Skip to main content

Execute SQL Commands

Hyper API is a wrapper around Hyper, a full-fledged SQL database. As such, you can use SQL queries and commands to interact with Hyper:

from tableauhyperapi import HyperProcess, Telemetry, Connection

with HyperProcess(telemetry=Telemetry.SEND_USAGE_DATA_TO_TABLEAU) as hyper:
with Connection(endpoint=hyper.endpoint) as connection:
connection.execute_command("""
CREATE TEMPORARY TABLE animals(name, legs) AS VALUES
('dog', 4),
('cat', 4),
('bird', 2),
('kangaroo', 2),
('centipede', 100)
""")

with connection.execute_query("SELECT name FROM animals") as results:
for row in results:
print(row)

bipeds = connection.execute_list_query(
"SELECT name FROM animals WHERE legs = 2")
print(bipeds)

max_legs = connection.execute_scalar_query(
"SELECT MAX(legs) FROM animals")
print("max legs: ", max_legs)

First, we need to start a Hyper process and connect to it. The HyperProcess and the Connection class handle those two aspects for us. Using the connection object, we can then send SQL commands and SQL queries to Hyper.

Functions for executing SQL queries

The Connection class provides methods for executing SQL statements and queries. There is one method for SQL commands, and three methods for queries which differ primarily in their return value:

MethodReturns
execute_commandThe count of affected rows, if available. None if not.
execute_queryA Hyper API result object. You can iterate over the returned rows using this object.
execute_list_queryA list of rows. (Python only)
execute_scalar_queryThe value from one row, one column.

execute_command is meant to be used for SQL commands like CREATE TABLE, COPY FROM, INSERT, UPDATE, DELETE etc., all of which don't produce any result tuples but instead are executed because we are interested in their side effects. execute_command returns the number of rows affected by the command. The different execute_query variants are meant for SQL queries, i.e. SQL statements that return actual tuples.

execute_query is the most versatile among the query functions: Through the returned result object, you can access both the result rows as well as metadata about the query result, such as the names and data types of the returned columns. To access the result rows, simply iterate over the result object using a for loop. Make sure to close the result object when it is no longer needed. In Python, this can be ensured by using a with block.

execute_list_query is a convenience method which reads the complete result of a query into a Python list.

execute_scalar_query is a convenience method meant for queries which return exactly one row consisting of a single column, and returns that single result value.

Constructing Hyper SQL statements

Using Hyper SQL you can, e.g., insert, update, and delete data from tables, import data from Parquet files or pose arbitrarily complex analytical queries. For a reference documentation of the supported commands, see Hyper SQL commands.

Because the SQL statements are passed to the Hyper API as strings, you need to ensure that identifiers and string values are properly encoded. As long as you are using hardcoding your query strings, this won't be a problem. You can simply make sure that your query is correctly written:

max_legs = connection.execute_scalar_query("SELECT MAX(legs) FROM animals")

You can use the full power of Python (or your preferred client language) to construct your SQL strings. E.g., in Python, formatted string literals (or "f-strings") are a very useful tool to build SQL commands:

# Create 10 tables, just for fun...
for id in range(0, 10):
connection.execute_command(f"""
CREATE TEMPORARY TABLE test_table_{id}(my_column int);
""")

However, you must be careful to correctly escape your names and strings. E.g., the following code will not work

table_name = "Guest Names"
value = "Francisco Eduardo"
# This will send an invalid command to Hyper
connection.execute_command(f"INSERT INTO {table_name} VALUES({value})")

because the SQL command sent to Hyper would be

INSERT INTO Guest Names VALUES(Francisco Eduardo)

which is incorrect. The correct query would be

INSERT INTO "Guest Names" VALUES('Francisco Eduardo')

The table name must be in double quotes and the string constant in single quotes.

Escaping for identifiers and strings is documented in General Syntax. Instead of reimplementing those escaping rules by yourself, you can use the escape_name and escape_string_literal functions to correctly format identifiers and strings in your SQL statements. Use escape_name for identifiers, such as column or table names. Use escape_string_literal when you need to use quoted string values. Furthermore, the utility classes TableName etc. are automatically escaped correctly when formatted as a string.

For example, if you have a table named Customers you could use {TableName('Customers')} in the SQL statement.

table = TableName("Customers")
for name in ["Dennis Kane", "Dorothe Hagen"]:
row_count = connection.execute_command(f"""
DELETE FROM {table}
WHERE "Name" = {escape_string_literal(name)}
""")