<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>article Building SQL with SQL: An introduction to EXECUTE IMMEDIATE in Technical Blog</title>
    <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/ba-p/59620</link>
    <description>&lt;H1&gt;&lt;SPAN&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="execute_immediate.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/6324i19DF14826BFB4CF8/image-size/medium?v=v2&amp;amp;px=400" role="button" title="execute_immediate.png" alt="execute_immediate.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/H1&gt;
&lt;H1&gt;&lt;SPAN&gt;Motivation&lt;/SPAN&gt;&lt;/H1&gt;
&lt;P&gt;&lt;SPAN&gt;In Databricks, you have many means to compose and execute queries. You can:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Incrementally build a query and execute it using the DataFrame API&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Use Python, Scala, or some supported other language to glue together a SQL string and use &lt;FONT face="andale mono,times"&gt;spark.sql()&lt;/FONT&gt; to compile and execute the SQL&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;In a variation of the above, you can also protect against SQL injection by using &lt;FONT face="andale mono,times"&gt;spark.sql()&lt;/FONT&gt; to pass different values to a parameterized SQL statement string.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;All these solutions, however, require you to use a language outside of SQL to build the query.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;If you prefer Python or Scala, this may be fine, but if you are into SQL you’re probably looking for a native solution. EXECUTE IMMEDIATE allows you to do just that.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Note:&lt;/STRONG&gt; You can find a notebook with all the SQL &lt;A title="here" href="https://github.com/srielau/notebooks/blob/main/EXECUTE%20IMMEDIATE%20BLOG.sql" target="_blank" rel="noopener"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;H1&gt;&lt;SPAN&gt;A concrete problem: Finding PRIMARY KEY violations&lt;/SPAN&gt;&lt;/H1&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;STRONG&gt;Note:&lt;/STRONG&gt; PRIMARY KEY is&lt;EM&gt; Delta Tables&lt;/EM&gt; feature, and the INFORMATION SCHEMA is a &lt;EM&gt;Unity Catalog&lt;/EM&gt; feature.&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;Given a set of Delta tables in Unity Catalog with primary keys, and given only the name of the table as input:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="comic sans ms,sans-serif"&gt;&lt;SPAN&gt;Generate and execute a query that returns all the duplicate keys in a table.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;What do we need to pull this of?&lt;/SPAN&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;We need to run queries against the Information Schema to find the list of columns composing the primary key&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;We need to collect the list of columns, so we can use it in a GROUP BY&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;We need to compose a query that then groups by the key columns and selects only those with a count greater one.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;We finally need to execute this query.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;But can we do all this without leaving SQL?&lt;BR /&gt;Using session variables as glue we certainly can!&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Let’s get started.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Binding in the "input"&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;First, we need a variable to hold the table name. Remember that a table name has three parts:&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tableId&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRUCT&lt;/FONT&gt;&amp;lt;catalog &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;, schema &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;, name &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;&amp;gt;;&lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;Here, for simplicity, I’m going to hardcode the name, but of course you can bind it in using widgets in a notebook.&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;SET VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;table&lt;/FONT&gt; = named_struct(&lt;FONT color="#0000FF"&gt;'catalog'&lt;/FONT&gt;, current_catalog(),&lt;BR /&gt;&lt;FONT color="#0000FF"&gt;                             'schema' &lt;/FONT&gt;, current_schema() ,&lt;BR /&gt;&lt;FONT color="#0000FF"&gt;                             'name'   &lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'persons'        &lt;/FONT&gt;);&lt;/PRE&gt;
&lt;H2&gt;Collecting the primary key columns&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;Now we have hunt for the primary key columns.&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;Two tables are in play here:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;SPAN&gt;&lt;FONT face="andale mono,times"&gt;TABLE_CONSTRAINTS&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;tells us what constraints exist on the table and what their types are.&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;So we need to find the name of the constraint that relates to the primary key.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;&lt;FONT face="andale mono,times"&gt;CONSTRAINT_COLUMN_USAGE&lt;/FONT&gt;&lt;BR /&gt;tells us which columns a given constraint depends on.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;That’s all we need. We don’t need to know the column types, the order of the key columns, or anything else more detailed.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;pkColumns&lt;/FONT&gt; &lt;FONT color="#008000"&gt;ARRAY&amp;lt;STRING&amp;gt;&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SET VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;pkColumns&lt;/FONT&gt; =&lt;BR /&gt;  (&lt;FONT color="#008000"&gt;SELECT&lt;/FONT&gt; array_agg(&lt;FONT color="#FF9900"&gt;ccu.column_name&lt;/FONT&gt;)&lt;BR /&gt;&lt;FONT color="#008000"&gt;     FROM&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;INFORMATION_SCHEMA.TABLE_CONSTRAINTS&lt;/FONT&gt; &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tc&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;     NATURAL JOIN&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE&lt;/FONT&gt; &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;ccu&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;     WHERE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tableId.catalog&lt;/FONT&gt;    = &lt;FONT color="#FF9900"&gt;tc.table_catalog&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;       AND&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tableId.schema &lt;/FONT&gt;    = &lt;FONT color="#FF9900"&gt;tc.table_schema&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;       AND&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tableId.name&lt;/FONT&gt;       = &lt;FONT color="#FF9900"&gt;tc.table_name&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;       AND&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tc.constraint_type&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'PRIMARY KEY'&lt;/FONT&gt;);&lt;/SPAN&gt; &lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;Let’s be nice and throw in some error handling:&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;SELECT CASE WHEN&lt;/FONT&gt; array_size(&lt;FONT color="#FF9900"&gt;pkColumns&lt;/FONT&gt;) == 0&lt;BR /&gt;            &lt;FONT color="#008000"&gt;THEN&lt;/FONT&gt; raise_error(&lt;FONT color="#0000FF"&gt;'No primary key found for: `'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.catalog&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'`.`'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.schema&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'`.`'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.name&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'`'&lt;/FONT&gt;)&lt;BR /&gt;&lt;FONT color="#008000"&gt;       END&lt;/FONT&gt;;&lt;/PRE&gt;
&lt;H2&gt;Building the query&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;Now it’s time to compose the query. We need to turn the primary key column array into a comma separated list. Lambda functions are great for this sort of work.&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SET VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; =&lt;BR /&gt;&lt;FONT color="#0000FF"&gt;  'SELECT '&lt;/FONT&gt; || aggregate(&lt;FONT color="#FF9900"&gt;pkColumns&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;''&lt;/FONT&gt;, (&lt;FONT color="#FF9900"&gt;list&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;col&lt;/FONT&gt;) -&amp;gt; &lt;FONT color="#FF9900"&gt;list&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;col&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;', '&lt;/FONT&gt;) || &lt;FONT color="#0000FF"&gt;' count(1) AS num_dups '&lt;/FONT&gt;&lt;BR /&gt;  &lt;FONT color="#0000FF"&gt;'  FROM `'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.catalog&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'`. `'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.schema&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'`. `'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.name&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'` '&lt;/FONT&gt;&lt;BR /&gt;  '&lt;FONT color="#0000FF"&gt;  GROUP BY ALL HAVING COUNT(1) &amp;gt; 1'&lt;/FONT&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;H2&gt;&lt;SPAN&gt;Run it!&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;Now all that’s left is to execute the query.&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;We do this by using the new EXECUTE IMMEDIATE statement in DBR 14.3.&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;EXECUTE IMMEDIATE takes a STRING literal or a variable, treats it as a query to compile and runs it.&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt;;&lt;BR /&gt;[&lt;FONT color="#993366"&gt;USER_RAISED_EXCEPTION] No primary key found for: `main`.`srielau`.`t` SQLSTATE: P0001&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Oh, well, I guess we need a table:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;SET CATALOG&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;main&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SET SCHEMA&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;srielau&lt;/FONT&gt;; &lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;CREATE TABLE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;persons(firstname&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRING NOT NULL&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;lastname&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRING NOT NULL&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;);&lt;BR /&gt;&lt;FONT color="#008000"&gt;ALTER TABLE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;persons&lt;/FONT&gt; &lt;FONT color="#008000"&gt;ADD CONSTRAINT&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;persons_pk&lt;/FONT&gt; &lt;FONT color="#008000"&gt;PRIMARY KEY&lt;/FONT&gt; (&lt;FONT color="#FF9900"&gt;firstname&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;lastname&lt;/FONT&gt;);&lt;BR /&gt;&lt;FONT color="#008000"&gt;INSERT INTO&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;persons&lt;/FONT&gt; &lt;FONT color="#008000"&gt;VALUES&lt;/FONT&gt;&lt;BR /&gt;  (&lt;FONT color="#0000FF"&gt;'Tom'&lt;/FONT&gt;      , &lt;FONT color="#0000FF"&gt;'Sawyer' &lt;/FONT&gt;     , '&lt;FONT color="#0000FF"&gt;St. Petersburg'&lt;/FONT&gt;       ),&lt;BR /&gt;  (&lt;FONT color="#0000FF"&gt;'Benjamin'&lt;/FONT&gt; , &lt;FONT color="#0000FF"&gt;'Bluemchen'&lt;/FONT&gt;   , &lt;FONT color="#0000FF"&gt;'Neustadt' &lt;/FONT&gt;            ),&lt;BR /&gt;  (&lt;FONT color="#0000FF"&gt;'Benjamin'&lt;/FONT&gt; , &lt;FONT color="#0000FF"&gt;'Bluemchen'&lt;/FONT&gt;   , &lt;FONT color="#0000FF"&gt;'Neustaedter Zoo'&lt;/FONT&gt;      ),&lt;BR /&gt;  (&lt;FONT color="#0000FF"&gt;'Emil'&lt;/FONT&gt;     , &lt;FONT color="#0000FF"&gt;'Svensson'&lt;/FONT&gt;    , &lt;FONT color="#0000FF"&gt;'Loenneberga'&lt;/FONT&gt;          ),&lt;BR /&gt;  (&lt;FONT color="#0000FF"&gt;'Pippi'&lt;/FONT&gt;    , &lt;FONT color="#0000FF"&gt;'Longstocking'&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Villa Villekulla'&lt;/FONT&gt;     ),&lt;BR /&gt;  ('&lt;FONT color="#0000FF"&gt;Pippi'&lt;/FONT&gt;    , &lt;FONT color="#0000FF"&gt;'Longstocking'&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Kurrekurredutt Island'&lt;/FONT&gt;);&lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;Next try:&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;firstname      lastname num_dups&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;---------  ------------ --------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;Benjamin   Bluemchen           2&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;Pippi      Longstocking        2&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Nice!&lt;/P&gt;
&lt;P&gt;Let's look into EXECUTE IMMEDIATE in more detail.&lt;/P&gt;
&lt;H1&gt;EXECUTE IMMEDIATE tear down&lt;/H1&gt;
&lt;P&gt;Having hopefully sufficiently motivated the use of EXECUTE IMMEDIATE let's dive deeper into what it can do.&lt;/P&gt;
&lt;P&gt;The syntax is pretty straight forward:&lt;/P&gt;
&lt;PRE&gt;EXECUTE IMMEDIATE sql_string&lt;BR /&gt;  [ INTO var_name [, ...] ]&lt;BR /&gt;  [ USING { arg_expr [ AS ] [alias] } [, ...] ]&lt;/PRE&gt;
&lt;H2&gt;What statements can be run?&lt;/H2&gt;
&lt;P&gt;sql_string must be a string literal or a session variable of a string type. There are no limitations about which SQL statement you can run, except that you cannot execute an EXECUTE IMMEDIATE. So you can run a DML statement:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;SET&lt;/FONT&gt; &lt;FONT color="#008000"&gt;VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'INSERT INTO persons'&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#0000FF"&gt;                   ' VALUES (\'Josefine\', \'Mausekind\', \'Sprotten vor dem Wind\')'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE&lt;/FONT&gt; &lt;FONT color="#008000"&gt;IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;num_affected_rows num_inserted_rows&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;----------------- -----------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;                1                 1&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SET&lt;/FONT&gt; &lt;FONT color="#008000"&gt;VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'UPDATE persons SET location = \'Leuchtturm Josefine\''&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#0000FF"&gt;                   ' WHERE firstname =\'Josefine\' AND lastname =\'Mausekind\''&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE&lt;/FONT&gt; &lt;FONT color="#008000"&gt;IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;num_affected_rows&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;-----------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;                1&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE&lt;/FONT&gt; &lt;FONT color="#008000"&gt;IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'DELETE FROM persons WHERE location = \'Leuchtturm Josefine\''&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;num_affected_rows&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;-----------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;                1&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;Or you can do DDL:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'ALTER TABLE persons ADD COLUMN dob DATE'&lt;/FONT&gt;;&lt;/PRE&gt;
&lt;P&gt;You can do grants and revokes:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'GRANT MODIFY ON TABLE persons TO `alf@melmak.et`'&lt;/FONT&gt;;&lt;/PRE&gt;
&lt;P&gt;and of course queries as shows in the example above.&lt;/P&gt;
&lt;P&gt;Some users store a their SQL statements in tables, look them up some form of statement ID and execute them using EXECUTE IMMEDIATE.&lt;/P&gt;
&lt;H2&gt;Statement Parameters&lt;/H2&gt;
&lt;P&gt;Obviously you can compose any SQL statement using the sql_string. However it can be advantageous to parameterize the string just like you want to parameterized SQL statements in Scala or Python when executing spark.sql(). The purpose is to provide values, often coming directly from the end user without risking SQL injection.&lt;/P&gt;
&lt;P&gt;EXECUTE IMMEDIATE supports both named and unnamed parameters:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'SELECT location FROM persons WHERE firstname = ? AND lastname = ?'&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;  USING&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'Tom'&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Sawyer'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;--------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;St. Petersburg&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'SELECT location FROM persons WHERE firstname = :first AND lastname = :last'&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;  USING&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'Tom'&lt;/FONT&gt; &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;first&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Sawyer'&lt;/FONT&gt; &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;--------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;St. Petersburg&lt;/FONT&gt;&amp;nbsp;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;Of course you can use session variables:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'SELECT location FROM persons WHERE firstname = ? AND lastname = ?'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;first&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'Tom'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'Sawyer'&lt;/FONT&gt;;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; &lt;FONT color="#008000"&gt;USING &lt;FONT color="#FF9900"&gt;first &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; first&lt;/FONT&gt;&lt;/FONT&gt;, &lt;FONT color="#008000"&gt;&lt;FONT color="#FF9900"&gt;last &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; last&lt;/FONT&gt;;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;--------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;St. Petersburg&lt;/FONT&gt;&amp;nbsp;&lt;BR /&gt;&lt;FONT color="#008000"&gt;&lt;BR /&gt;SET VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'SELECT location FROM persons WHERE firstname = :first AND lastname = :last'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; &lt;FONT color="#008000"&gt;USING&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last &lt;FONT color="#008000"&gt;AS last&lt;/FONT&gt;&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;first&lt;FONT color="#008000"&gt; AS first&lt;/FONT&gt;&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;--------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;St. Petersburg&lt;/FONT&gt;&amp;nbsp;&lt;/PRE&gt;
&lt;P&gt;You can also use variables directly instead of using formal parameter passing. This may be considered rather sloppy.&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;SET VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'SELECT location FROM persons WHERE firstname = first AND lastname = last'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE &lt;/FONT&gt;&lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;--------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;St. Petersburg&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&lt;/PRE&gt;
&lt;H2&gt;Where do the results go?&lt;/H2&gt;
&lt;P&gt;By default EXECUTE IMMEDIATE will return the same results as the SQL Statement passed to it. For queries that is the query result. For INSERT statement it is the meta data:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'INSERT INTO persons(firstname, lastname, location)  (?, ?, ?)'&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;  USING&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'Bibi'&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Blocksberg'&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Neustadt'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;num_affected_rows num_inserted_rows&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;----------------- -----------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;                1                 1&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;But for queries only there is another options. If the query returns at most one row you can instruct EXECUTE IMMEDIATE to assign the result to a list of session variables.&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SET&lt;/FONT&gt; &lt;FONT color="#008000"&gt;VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;first&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'Emil'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'SELECT lastname, location FROM persons WHERE firstname = ?'&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;INTO&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;USING&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;first&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SELECT&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;last     location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;-------- -----------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;Svensson Loenneberga&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;If the query returns no rows NULL is assigned:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'SELECT lastname, location FROM persons WHERE firstname = ?'&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;INTO&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;USING&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'Huckleberry'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;last location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;---- --------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;null     null&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;If there is more than one row EXECUTE IMMEDIATE returns an error:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'SELECT lastname, location FROM persons WHERE firstname = ?'&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;INTO&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;USING&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'Benjamin'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;[ROW_SUBQUERY_TOO_MANY_ROWS] More than one row returned by a subquery used as a row. SQLSTATE: 21000&lt;/FONT&gt;&lt;/PRE&gt;
&lt;H1&gt;Conclusion&lt;/H1&gt;
&lt;P&gt;EXECUTE IMMEDIATE is a powerful new statement introduced in Databricks Runtime 14.3. It allows you to compose SQL out of SQL operations and pass session state via SQL variables. This allows for linear scripting in SQL which otherwise would have required you to utilize a host language such as Python.&lt;/P&gt;
&lt;H1&gt;Related&lt;/H1&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="https://github.com/srielau/notebooks/blob/main/EXECUTE%20IMMEDIATE%20BLOG.sql" target="_self"&gt;Notebook with examples above&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="Blog: SQL Session Variables: Stash your state, and use it, too." href="https://community.databricks.com/t5/technical-blog/sql-session-variables-stash-your-state-and-use-it-too/ba-p/58737" target="_blank" rel="noopener"&gt;Blog: SQL Session Variables: Stash your state, and use it, too.&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="Blog: Parameterized queries with PySpark" href="https://www.databricks.com/blog/parameterized-queries-pyspark" target="_blank" rel="noopener"&gt;Blog: Parameterized queries with PySpark&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://www.databricks.com/blog/2018/11/16/introducing-new-built-in-functions-and-higher-order-functions-for-complex-data-types-in-apache-spark.html" target="_self"&gt;Blog: New built in functions and higher order functions in Apache Spark&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://www.databricks.com/blog/2017/05/24/working-with-nested-data-using-higher-order-functions-in-sql-on-databricks.html" target="_self"&gt;Blog: Working with nested data using higher order functions in Databricks with SQL&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="SQL Reference: EXECUTE IMMEDIATE" href="https://docs.databricks.com/en/sql/language-manual/sql-ref-syntax-aux-execute-immediate.html" target="_blank" rel="noopener"&gt;SQL Reference: EXECUTE IMMEDIATE&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="SQL Reference: Variables" href="https://docs.databricks.com/en/sql/language-manual/sql-ref-variables.html" target="_blank" rel="noopener"&gt;SQL Reference: Variables&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="SQL Reference: Parameter Markers" href="https://docs.databricks.com/en/sql/language-manual/sql-ref-parameter-marker.html" target="_blank" rel="noopener"&gt;SQL Reference: Parameter Markers&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="SQL Reference: Information schema" href="https://docs.databricks.com/en/sql/language-manual/sql-ref-information-schema.html" target="_blank" rel="noopener"&gt;SQL Reference: Information schema&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Tue, 27 Feb 2024 19:04:03 GMT</pubDate>
    <dc:creator>SergeRielau</dc:creator>
    <dc:date>2024-02-27T19:04:03Z</dc:date>
    <item>
      <title>Building SQL with SQL: An introduction to EXECUTE IMMEDIATE</title>
      <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/ba-p/59620</link>
      <description>&lt;H1&gt;&lt;SPAN&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="execute_immediate.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/6324i19DF14826BFB4CF8/image-size/medium?v=v2&amp;amp;px=400" role="button" title="execute_immediate.png" alt="execute_immediate.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/H1&gt;
&lt;H1&gt;&lt;SPAN&gt;Motivation&lt;/SPAN&gt;&lt;/H1&gt;
&lt;P&gt;&lt;SPAN&gt;In Databricks, you have many means to compose and execute queries. You can:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Incrementally build a query and execute it using the DataFrame API&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Use Python, Scala, or some supported other language to glue together a SQL string and use &lt;FONT face="andale mono,times"&gt;spark.sql()&lt;/FONT&gt; to compile and execute the SQL&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;In a variation of the above, you can also protect against SQL injection by using &lt;FONT face="andale mono,times"&gt;spark.sql()&lt;/FONT&gt; to pass different values to a parameterized SQL statement string.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;All these solutions, however, require you to use a language outside of SQL to build the query.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;If you prefer Python or Scala, this may be fine, but if you are into SQL you’re probably looking for a native solution. EXECUTE IMMEDIATE allows you to do just that.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Note:&lt;/STRONG&gt; You can find a notebook with all the SQL &lt;A title="here" href="https://github.com/srielau/notebooks/blob/main/EXECUTE%20IMMEDIATE%20BLOG.sql" target="_blank" rel="noopener"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;H1&gt;&lt;SPAN&gt;A concrete problem: Finding PRIMARY KEY violations&lt;/SPAN&gt;&lt;/H1&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;STRONG&gt;Note:&lt;/STRONG&gt; PRIMARY KEY is&lt;EM&gt; Delta Tables&lt;/EM&gt; feature, and the INFORMATION SCHEMA is a &lt;EM&gt;Unity Catalog&lt;/EM&gt; feature.&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;Given a set of Delta tables in Unity Catalog with primary keys, and given only the name of the table as input:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="comic sans ms,sans-serif"&gt;&lt;SPAN&gt;Generate and execute a query that returns all the duplicate keys in a table.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;What do we need to pull this of?&lt;/SPAN&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;We need to run queries against the Information Schema to find the list of columns composing the primary key&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;We need to collect the list of columns, so we can use it in a GROUP BY&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;We need to compose a query that then groups by the key columns and selects only those with a count greater one.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;We finally need to execute this query.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;But can we do all this without leaving SQL?&lt;BR /&gt;Using session variables as glue we certainly can!&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Let’s get started.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Binding in the "input"&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;First, we need a variable to hold the table name. Remember that a table name has three parts:&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tableId&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRUCT&lt;/FONT&gt;&amp;lt;catalog &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;, schema &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;, name &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;&amp;gt;;&lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;Here, for simplicity, I’m going to hardcode the name, but of course you can bind it in using widgets in a notebook.&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;SET VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;table&lt;/FONT&gt; = named_struct(&lt;FONT color="#0000FF"&gt;'catalog'&lt;/FONT&gt;, current_catalog(),&lt;BR /&gt;&lt;FONT color="#0000FF"&gt;                             'schema' &lt;/FONT&gt;, current_schema() ,&lt;BR /&gt;&lt;FONT color="#0000FF"&gt;                             'name'   &lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'persons'        &lt;/FONT&gt;);&lt;/PRE&gt;
&lt;H2&gt;Collecting the primary key columns&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;Now we have hunt for the primary key columns.&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;Two tables are in play here:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;SPAN&gt;&lt;FONT face="andale mono,times"&gt;TABLE_CONSTRAINTS&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;tells us what constraints exist on the table and what their types are.&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;So we need to find the name of the constraint that relates to the primary key.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;&lt;FONT face="andale mono,times"&gt;CONSTRAINT_COLUMN_USAGE&lt;/FONT&gt;&lt;BR /&gt;tells us which columns a given constraint depends on.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;That’s all we need. We don’t need to know the column types, the order of the key columns, or anything else more detailed.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;pkColumns&lt;/FONT&gt; &lt;FONT color="#008000"&gt;ARRAY&amp;lt;STRING&amp;gt;&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SET VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;pkColumns&lt;/FONT&gt; =&lt;BR /&gt;  (&lt;FONT color="#008000"&gt;SELECT&lt;/FONT&gt; array_agg(&lt;FONT color="#FF9900"&gt;ccu.column_name&lt;/FONT&gt;)&lt;BR /&gt;&lt;FONT color="#008000"&gt;     FROM&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;INFORMATION_SCHEMA.TABLE_CONSTRAINTS&lt;/FONT&gt; &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tc&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;     NATURAL JOIN&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE&lt;/FONT&gt; &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;ccu&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;     WHERE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tableId.catalog&lt;/FONT&gt;    = &lt;FONT color="#FF9900"&gt;tc.table_catalog&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;       AND&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tableId.schema &lt;/FONT&gt;    = &lt;FONT color="#FF9900"&gt;tc.table_schema&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;       AND&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tableId.name&lt;/FONT&gt;       = &lt;FONT color="#FF9900"&gt;tc.table_name&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;       AND&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;tc.constraint_type&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'PRIMARY KEY'&lt;/FONT&gt;);&lt;/SPAN&gt; &lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;Let’s be nice and throw in some error handling:&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;SELECT CASE WHEN&lt;/FONT&gt; array_size(&lt;FONT color="#FF9900"&gt;pkColumns&lt;/FONT&gt;) == 0&lt;BR /&gt;            &lt;FONT color="#008000"&gt;THEN&lt;/FONT&gt; raise_error(&lt;FONT color="#0000FF"&gt;'No primary key found for: `'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.catalog&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'`.`'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.schema&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'`.`'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.name&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'`'&lt;/FONT&gt;)&lt;BR /&gt;&lt;FONT color="#008000"&gt;       END&lt;/FONT&gt;;&lt;/PRE&gt;
&lt;H2&gt;Building the query&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;Now it’s time to compose the query. We need to turn the primary key column array into a comma separated list. Lambda functions are great for this sort of work.&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SET VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; =&lt;BR /&gt;&lt;FONT color="#0000FF"&gt;  'SELECT '&lt;/FONT&gt; || aggregate(&lt;FONT color="#FF9900"&gt;pkColumns&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;''&lt;/FONT&gt;, (&lt;FONT color="#FF9900"&gt;list&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;col&lt;/FONT&gt;) -&amp;gt; &lt;FONT color="#FF9900"&gt;list&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;col&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;', '&lt;/FONT&gt;) || &lt;FONT color="#0000FF"&gt;' count(1) AS num_dups '&lt;/FONT&gt;&lt;BR /&gt;  &lt;FONT color="#0000FF"&gt;'  FROM `'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.catalog&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'`. `'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.schema&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'`. `'&lt;/FONT&gt; || &lt;FONT color="#FF9900"&gt;tableId.name&lt;/FONT&gt; || &lt;FONT color="#0000FF"&gt;'` '&lt;/FONT&gt;&lt;BR /&gt;  '&lt;FONT color="#0000FF"&gt;  GROUP BY ALL HAVING COUNT(1) &amp;gt; 1'&lt;/FONT&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;H2&gt;&lt;SPAN&gt;Run it!&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;Now all that’s left is to execute the query.&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;We do this by using the new EXECUTE IMMEDIATE statement in DBR 14.3.&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;EXECUTE IMMEDIATE takes a STRING literal or a variable, treats it as a query to compile and runs it.&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt;;&lt;BR /&gt;[&lt;FONT color="#993366"&gt;USER_RAISED_EXCEPTION] No primary key found for: `main`.`srielau`.`t` SQLSTATE: P0001&lt;/FONT&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Oh, well, I guess we need a table:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;SET CATALOG&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;main&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SET SCHEMA&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;srielau&lt;/FONT&gt;; &lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;CREATE TABLE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;persons(firstname&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRING NOT NULL&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;lastname&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRING NOT NULL&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;);&lt;BR /&gt;&lt;FONT color="#008000"&gt;ALTER TABLE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;persons&lt;/FONT&gt; &lt;FONT color="#008000"&gt;ADD CONSTRAINT&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;persons_pk&lt;/FONT&gt; &lt;FONT color="#008000"&gt;PRIMARY KEY&lt;/FONT&gt; (&lt;FONT color="#FF9900"&gt;firstname&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;lastname&lt;/FONT&gt;);&lt;BR /&gt;&lt;FONT color="#008000"&gt;INSERT INTO&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;persons&lt;/FONT&gt; &lt;FONT color="#008000"&gt;VALUES&lt;/FONT&gt;&lt;BR /&gt;  (&lt;FONT color="#0000FF"&gt;'Tom'&lt;/FONT&gt;      , &lt;FONT color="#0000FF"&gt;'Sawyer' &lt;/FONT&gt;     , '&lt;FONT color="#0000FF"&gt;St. Petersburg'&lt;/FONT&gt;       ),&lt;BR /&gt;  (&lt;FONT color="#0000FF"&gt;'Benjamin'&lt;/FONT&gt; , &lt;FONT color="#0000FF"&gt;'Bluemchen'&lt;/FONT&gt;   , &lt;FONT color="#0000FF"&gt;'Neustadt' &lt;/FONT&gt;            ),&lt;BR /&gt;  (&lt;FONT color="#0000FF"&gt;'Benjamin'&lt;/FONT&gt; , &lt;FONT color="#0000FF"&gt;'Bluemchen'&lt;/FONT&gt;   , &lt;FONT color="#0000FF"&gt;'Neustaedter Zoo'&lt;/FONT&gt;      ),&lt;BR /&gt;  (&lt;FONT color="#0000FF"&gt;'Emil'&lt;/FONT&gt;     , &lt;FONT color="#0000FF"&gt;'Svensson'&lt;/FONT&gt;    , &lt;FONT color="#0000FF"&gt;'Loenneberga'&lt;/FONT&gt;          ),&lt;BR /&gt;  (&lt;FONT color="#0000FF"&gt;'Pippi'&lt;/FONT&gt;    , &lt;FONT color="#0000FF"&gt;'Longstocking'&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Villa Villekulla'&lt;/FONT&gt;     ),&lt;BR /&gt;  ('&lt;FONT color="#0000FF"&gt;Pippi'&lt;/FONT&gt;    , &lt;FONT color="#0000FF"&gt;'Longstocking'&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Kurrekurredutt Island'&lt;/FONT&gt;);&lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;Next try:&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;firstname      lastname num_dups&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;---------  ------------ --------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;Benjamin   Bluemchen           2&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;Pippi      Longstocking        2&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Nice!&lt;/P&gt;
&lt;P&gt;Let's look into EXECUTE IMMEDIATE in more detail.&lt;/P&gt;
&lt;H1&gt;EXECUTE IMMEDIATE tear down&lt;/H1&gt;
&lt;P&gt;Having hopefully sufficiently motivated the use of EXECUTE IMMEDIATE let's dive deeper into what it can do.&lt;/P&gt;
&lt;P&gt;The syntax is pretty straight forward:&lt;/P&gt;
&lt;PRE&gt;EXECUTE IMMEDIATE sql_string&lt;BR /&gt;  [ INTO var_name [, ...] ]&lt;BR /&gt;  [ USING { arg_expr [ AS ] [alias] } [, ...] ]&lt;/PRE&gt;
&lt;H2&gt;What statements can be run?&lt;/H2&gt;
&lt;P&gt;sql_string must be a string literal or a session variable of a string type. There are no limitations about which SQL statement you can run, except that you cannot execute an EXECUTE IMMEDIATE. So you can run a DML statement:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;SET&lt;/FONT&gt; &lt;FONT color="#008000"&gt;VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'INSERT INTO persons'&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#0000FF"&gt;                   ' VALUES (\'Josefine\', \'Mausekind\', \'Sprotten vor dem Wind\')'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE&lt;/FONT&gt; &lt;FONT color="#008000"&gt;IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;num_affected_rows num_inserted_rows&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;----------------- -----------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;                1                 1&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SET&lt;/FONT&gt; &lt;FONT color="#008000"&gt;VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'UPDATE persons SET location = \'Leuchtturm Josefine\''&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#0000FF"&gt;                   ' WHERE firstname =\'Josefine\' AND lastname =\'Mausekind\''&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE&lt;/FONT&gt; &lt;FONT color="#008000"&gt;IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;num_affected_rows&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;-----------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;                1&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE&lt;/FONT&gt; &lt;FONT color="#008000"&gt;IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'DELETE FROM persons WHERE location = \'Leuchtturm Josefine\''&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;num_affected_rows&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;-----------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;                1&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;Or you can do DDL:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'ALTER TABLE persons ADD COLUMN dob DATE'&lt;/FONT&gt;;&lt;/PRE&gt;
&lt;P&gt;You can do grants and revokes:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'GRANT MODIFY ON TABLE persons TO `alf@melmak.et`'&lt;/FONT&gt;;&lt;/PRE&gt;
&lt;P&gt;and of course queries as shows in the example above.&lt;/P&gt;
&lt;P&gt;Some users store a their SQL statements in tables, look them up some form of statement ID and execute them using EXECUTE IMMEDIATE.&lt;/P&gt;
&lt;H2&gt;Statement Parameters&lt;/H2&gt;
&lt;P&gt;Obviously you can compose any SQL statement using the sql_string. However it can be advantageous to parameterize the string just like you want to parameterized SQL statements in Scala or Python when executing spark.sql(). The purpose is to provide values, often coming directly from the end user without risking SQL injection.&lt;/P&gt;
&lt;P&gt;EXECUTE IMMEDIATE supports both named and unnamed parameters:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'SELECT location FROM persons WHERE firstname = ? AND lastname = ?'&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;  USING&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'Tom'&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Sawyer'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;--------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;St. Petersburg&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'SELECT location FROM persons WHERE firstname = :first AND lastname = :last'&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;  USING&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'Tom'&lt;/FONT&gt; &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;first&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Sawyer'&lt;/FONT&gt; &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;--------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;St. Petersburg&lt;/FONT&gt;&amp;nbsp;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;Of course you can use session variables:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'SELECT location FROM persons WHERE firstname = ? AND lastname = ?'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;first&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'Tom'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'Sawyer'&lt;/FONT&gt;;&lt;BR /&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; &lt;FONT color="#008000"&gt;USING &lt;FONT color="#FF9900"&gt;first &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; first&lt;/FONT&gt;&lt;/FONT&gt;, &lt;FONT color="#008000"&gt;&lt;FONT color="#FF9900"&gt;last &lt;FONT color="#008000"&gt;AS&lt;/FONT&gt; last&lt;/FONT&gt;;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;--------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;St. Petersburg&lt;/FONT&gt;&amp;nbsp;&lt;BR /&gt;&lt;FONT color="#008000"&gt;&lt;BR /&gt;SET VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'SELECT location FROM persons WHERE firstname = :first AND lastname = :last'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; &lt;FONT color="#008000"&gt;USING&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last &lt;FONT color="#008000"&gt;AS last&lt;/FONT&gt;&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;first&lt;FONT color="#008000"&gt; AS first&lt;/FONT&gt;&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;--------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;St. Petersburg&lt;/FONT&gt;&amp;nbsp;&lt;/PRE&gt;
&lt;P&gt;You can also use variables directly instead of using formal parameter passing. This may be considered rather sloppy.&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;SET VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'SELECT location FROM persons WHERE firstname = first AND lastname = last'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE &lt;/FONT&gt;&lt;FONT color="#FF9900"&gt;queryStr&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;--------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;St. Petersburg&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&lt;/PRE&gt;
&lt;H2&gt;Where do the results go?&lt;/H2&gt;
&lt;P&gt;By default EXECUTE IMMEDIATE will return the same results as the SQL Statement passed to it. For queries that is the query result. For INSERT statement it is the meta data:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'INSERT INTO persons(firstname, lastname, location)  (?, ?, ?)'&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#008000"&gt;  USING&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'Bibi'&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Blocksberg'&lt;/FONT&gt;, &lt;FONT color="#0000FF"&gt;'Neustadt'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;num_affected_rows num_inserted_rows&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;----------------- -----------------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;                1                 1&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;But for queries only there is another options. If the query returns at most one row you can instruct EXECUTE IMMEDIATE to assign the result to a list of session variables.&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;DECLARE&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt; &lt;FONT color="#008000"&gt;STRING&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SET&lt;/FONT&gt; &lt;FONT color="#008000"&gt;VAR&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;first&lt;/FONT&gt; = &lt;FONT color="#0000FF"&gt;'Emil'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'SELECT lastname, location FROM persons WHERE firstname = ?'&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;INTO&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;USING&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;first&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#008000"&gt;SELECT&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;last     location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;-------- -----------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;Svensson Loenneberga&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;If the query returns no rows NULL is assigned:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'SELECT lastname, location FROM persons WHERE firstname = ?'&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;INTO&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;USING&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'Huckleberry'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;last location&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;---- --------&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT color="#993366"&gt;null     null&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;If there is more than one row EXECUTE IMMEDIATE returns an error:&lt;/P&gt;
&lt;PRE&gt;&lt;FONT color="#008000"&gt;EXECUTE IMMEDIATE&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'SELECT lastname, location FROM persons WHERE firstname = ?'&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;INTO&lt;/FONT&gt; &lt;FONT color="#FF9900"&gt;last&lt;/FONT&gt;, &lt;FONT color="#FF9900"&gt;location&lt;/FONT&gt;&lt;BR /&gt;   &lt;FONT color="#008000"&gt;USING&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;'Benjamin'&lt;/FONT&gt;;&lt;BR /&gt;&lt;FONT color="#993366"&gt;[ROW_SUBQUERY_TOO_MANY_ROWS] More than one row returned by a subquery used as a row. SQLSTATE: 21000&lt;/FONT&gt;&lt;/PRE&gt;
&lt;H1&gt;Conclusion&lt;/H1&gt;
&lt;P&gt;EXECUTE IMMEDIATE is a powerful new statement introduced in Databricks Runtime 14.3. It allows you to compose SQL out of SQL operations and pass session state via SQL variables. This allows for linear scripting in SQL which otherwise would have required you to utilize a host language such as Python.&lt;/P&gt;
&lt;H1&gt;Related&lt;/H1&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="https://github.com/srielau/notebooks/blob/main/EXECUTE%20IMMEDIATE%20BLOG.sql" target="_self"&gt;Notebook with examples above&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="Blog: SQL Session Variables: Stash your state, and use it, too." href="https://community.databricks.com/t5/technical-blog/sql-session-variables-stash-your-state-and-use-it-too/ba-p/58737" target="_blank" rel="noopener"&gt;Blog: SQL Session Variables: Stash your state, and use it, too.&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="Blog: Parameterized queries with PySpark" href="https://www.databricks.com/blog/parameterized-queries-pyspark" target="_blank" rel="noopener"&gt;Blog: Parameterized queries with PySpark&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://www.databricks.com/blog/2018/11/16/introducing-new-built-in-functions-and-higher-order-functions-for-complex-data-types-in-apache-spark.html" target="_self"&gt;Blog: New built in functions and higher order functions in Apache Spark&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://www.databricks.com/blog/2017/05/24/working-with-nested-data-using-higher-order-functions-in-sql-on-databricks.html" target="_self"&gt;Blog: Working with nested data using higher order functions in Databricks with SQL&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="SQL Reference: EXECUTE IMMEDIATE" href="https://docs.databricks.com/en/sql/language-manual/sql-ref-syntax-aux-execute-immediate.html" target="_blank" rel="noopener"&gt;SQL Reference: EXECUTE IMMEDIATE&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="SQL Reference: Variables" href="https://docs.databricks.com/en/sql/language-manual/sql-ref-variables.html" target="_blank" rel="noopener"&gt;SQL Reference: Variables&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="SQL Reference: Parameter Markers" href="https://docs.databricks.com/en/sql/language-manual/sql-ref-parameter-marker.html" target="_blank" rel="noopener"&gt;SQL Reference: Parameter Markers&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;&lt;A title="SQL Reference: Information schema" href="https://docs.databricks.com/en/sql/language-manual/sql-ref-information-schema.html" target="_blank" rel="noopener"&gt;SQL Reference: Information schema&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 27 Feb 2024 19:04:03 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/ba-p/59620</guid>
      <dc:creator>SergeRielau</dc:creator>
      <dc:date>2024-02-27T19:04:03Z</dc:date>
    </item>
    <item>
      <title>Re: Building SQL with SQL: An introduction to EXECUTE IMMEDIATE</title>
      <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/76124#M208</link>
      <description>&lt;P&gt;Thanks for posting this, it's quite useful!&lt;/P&gt;&lt;P&gt;I am having trouble using the INTO command to assign the result of the query into a variable. This is only happening on &lt;STRONG&gt;SQL Serverless&lt;/STRONG&gt;, while using &lt;STRONG&gt;all-purpose compute&lt;/STRONG&gt; (DBR 14.3 LTS) works.&lt;/P&gt;&lt;P&gt;Code sample:&lt;/P&gt;&lt;LI-CODE lang="c"&gt;DECLARE OR REPLACE sum INT;
DECLARE OR REPLACE sqlStr = 'SELECT 10';
EXECUTE IMMEDIATE sqlStr INTO sum;
SELECT sum;&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;Running this on&amp;nbsp;&lt;STRONG&gt;all-purpose compute&lt;/STRONG&gt; I get the correct output of 10:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="iamgoda_0-1719602229185.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/9021i8889E76AAD4A50B7/image-size/medium/is-moderation-mode/true?v=v2&amp;amp;px=400" role="button" title="iamgoda_0-1719602229185.png" alt="iamgoda_0-1719602229185.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;Running it on SQL Serverless, the value of sum is null:&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="iamgoda_1-1719602345251.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/9022i46D370FA298A56ED/image-size/medium/is-moderation-mode/true?v=v2&amp;amp;px=400" role="button" title="iamgoda_1-1719602345251.png" alt="iamgoda_1-1719602345251.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;This was run on a SQL notebook, but same issue happens when running in SQL Editor:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="iamgoda_2-1719602538338.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/9023i07F6FD0EBD8B5823/image-size/medium/is-moderation-mode/true?v=v2&amp;amp;px=400" role="button" title="iamgoda_2-1719602538338.png" alt="iamgoda_2-1719602538338.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;Any idea why this is happening?&lt;/P&gt;&lt;P&gt;Thanks!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 28 Jun 2024 19:27:07 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/76124#M208</guid>
      <dc:creator>iamgoda</dc:creator>
      <dc:date>2024-06-28T19:27:07Z</dc:date>
    </item>
    <item>
      <title>Re: Building SQL with SQL: An introduction to EXECUTE IMMEDIATE</title>
      <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/76144#M209</link>
      <description>&lt;P&gt;&lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/92666"&gt;@iamgoda&lt;/a&gt;&amp;nbsp;I can reproduce that. And it looks like a bug.&lt;BR /&gt;Are you able to open a support ticket?&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
      <pubDate>Sat, 29 Jun 2024 04:55:46 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/76144#M209</guid>
      <dc:creator>SergeRielau</dc:creator>
      <dc:date>2024-06-29T04:55:46Z</dc:date>
    </item>
    <item>
      <title>Re: Building SQL with SQL: An introduction to EXECUTE IMMEDIATE</title>
      <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/76154#M210</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/82608"&gt;@SergeRielau&lt;/a&gt;&amp;nbsp;thanks for confirming! I will open a ticket through Microsoft Support and also inform our Databricks contact.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 29 Jun 2024 13:56:45 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/76154#M210</guid>
      <dc:creator>iamgoda</dc:creator>
      <dc:date>2024-06-29T13:56:45Z</dc:date>
    </item>
    <item>
      <title>Re: Building SQL with SQL: An introduction to EXECUTE IMMEDIATE</title>
      <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/76160#M211</link>
      <description>&lt;P&gt;FYI - Databricks support ticket&amp;nbsp;&lt;STRONG&gt;00495455&amp;nbsp;&lt;/STRONG&gt;has been created for this issue.&lt;/P&gt;</description>
      <pubDate>Sat, 29 Jun 2024 19:11:26 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/76160#M211</guid>
      <dc:creator>iamgoda</dc:creator>
      <dc:date>2024-06-29T19:11:26Z</dc:date>
    </item>
    <item>
      <title>Re: Building SQL with SQL: An introduction to EXECUTE IMMEDIATE</title>
      <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/76166#M212</link>
      <description>&lt;P&gt;Thanks&amp;nbsp;&lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/92666"&gt;@iamgoda&lt;/a&gt;&amp;nbsp;we'll get that fixed.&lt;/P&gt;</description>
      <pubDate>Sat, 29 Jun 2024 20:10:32 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/76166#M212</guid>
      <dc:creator>SergeRielau</dc:creator>
      <dc:date>2024-06-29T20:10:32Z</dc:date>
    </item>
    <item>
      <title>Re: Building SQL with SQL: An introduction to EXECUTE IMMEDIATE</title>
      <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/95995#M334</link>
      <description>&lt;P&gt;Is the question mark notation meant to work in SQL Serverless? That doesn't seem to work for me. Works fine on a 14.3 cluster. EXECUTE IMMEDIATE works, it just doesn't seem to work with parameterized queries.&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="BlaneCS_0-1729779411123.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/12257iA2B2B80FCE5C42D7/image-size/medium?v=v2&amp;amp;px=400" role="button" title="BlaneCS_0-1729779411123.png" alt="BlaneCS_0-1729779411123.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="BlaneCS_1-1729779430925.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/12258iF960FA20B015B494/image-size/medium?v=v2&amp;amp;px=400" role="button" title="BlaneCS_1-1729779430925.png" alt="BlaneCS_1-1729779430925.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="BlaneCS_2-1729779493052.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/12259i7345E09BFAE4C0C1/image-size/medium?v=v2&amp;amp;px=400" role="button" title="BlaneCS_2-1729779493052.png" alt="BlaneCS_2-1729779493052.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 24 Oct 2024 14:18:45 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/95995#M334</guid>
      <dc:creator>BlaneCS</dc:creator>
      <dc:date>2024-10-24T14:18:45Z</dc:date>
    </item>
    <item>
      <title>Re: Building SQL with SQL: An introduction to EXECUTE IMMEDIATE</title>
      <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/96018#M336</link>
      <description>&lt;P&gt;I can reproduce this &lt;span class="lia-unicode-emoji" title=":disappointed_face:"&gt;😞&lt;/span&gt;&lt;BR /&gt;Have raised a support ticket ES-129055, but it would help if you (as a customer) contact support as well.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-10-24 at 9.16.10 AM.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/12264iD119FC4AF7A8838E/image-size/large?v=v2&amp;amp;px=999" role="button" title="Screenshot 2024-10-24 at 9.16.10 AM.png" alt="Screenshot 2024-10-24 at 9.16.10 AM.png" /&gt;&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 24 Oct 2024 16:22:42 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/96018#M336</guid>
      <dc:creator>SergeRielau</dc:creator>
      <dc:date>2024-10-24T16:22:42Z</dc:date>
    </item>
    <item>
      <title>Re: Building SQL with SQL: An introduction to EXECUTE IMMEDIATE</title>
      <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/149418#M940</link>
      <description>&lt;P&gt;Thank you for this excellent deep dive into &lt;STRONG&gt;EXECUTE IMMEDIATE&lt;/STRONG&gt;!&lt;/P&gt;&lt;P&gt;I’m currently writing an article for data engineers migrating from traditional RDBMS environments to Databricks, and it would be great to to have your perspective on a specific architectural behavior regarding variable scope and session state.&lt;/P&gt;&lt;P&gt;I have observed that if you dynamically declare a variable using &lt;STRONG&gt;EXECUTE IMMEDIATE&lt;/STRONG&gt; inside a &lt;STRONG&gt;BEGIN...END&lt;/STRONG&gt; block, it bypasses the local script scope and creates a session variable, but I could not find a direct reference on Databricks documentation regarding this behavior. In fact, coming from a traditional RDBMS background my self, I am trying to understand the mechanics of the&amp;nbsp;&lt;STRONG&gt;BEGIN...END&lt;/STRONG&gt;&amp;nbsp;statement.&lt;/P&gt;&lt;P&gt;For example:&lt;/P&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;DIV class=""&gt;&lt;PRE&gt;&lt;SPAN class=""&gt;BEGIN&lt;/SPAN&gt;
  &lt;SPAN class=""&gt;EXECUTE&lt;/SPAN&gt; IMMEDIATE &lt;SPAN class=""&gt;'DECLARE V_VAR INT = 1'&lt;/SPAN&gt;; 
&lt;SPAN class=""&gt;END&lt;/SPAN&gt;;

&lt;SPAN class=""&gt;SELECT&lt;/SPAN&gt; &lt;SPAN class=""&gt;V_VAR&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;I have the following two questions:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;P&gt;Is this&amp;nbsp;a deliberate architectural decision? And is my assumption correct, that &lt;STRONG&gt;EXECUTE IMMEDIATE&lt;/STRONG&gt; hands the evaluated string directly to the global Catalyst parser as a standalone statement, meaning it evaluates the &lt;STRONG&gt;DECLARE&lt;/STRONG&gt; keyword using "outside-the-block" rules&amp;nbsp;rather than the local compound block memory.&amp;nbsp;&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;If we are dynamically generating a &lt;STRONG&gt;TEMP VIEW&lt;/STRONG&gt; inside a script that relies on a variable, is dynamically generating a session variable via &lt;STRONG&gt;EXECUTE IMMEDIATE&lt;/STRONG&gt; the recommended approach? Or is it better to construct the&amp;nbsp;&lt;STRONG&gt;TEMP VIEW&lt;/STRONG&gt;&amp;nbsp;statement using the&amp;nbsp;&lt;STRONG&gt;EXECUTE IMMEDIATE&lt;/STRONG&gt; command, passing local variables with the&amp;nbsp;&lt;STRONG&gt;USING&lt;/STRONG&gt; keyword? (Accepting the "difficulties" in creating the statement, e.g. string handling)&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;Any insights would be greatly appreciated!&lt;/P&gt;</description>
      <pubDate>Thu, 26 Feb 2026 19:30:55 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/149418#M940</guid>
      <dc:creator>bojito</dc:creator>
      <dc:date>2026-02-26T19:30:55Z</dc:date>
    </item>
    <item>
      <title>Re: Building SQL with SQL: An introduction to EXECUTE IMMEDIATE</title>
      <link>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/149427#M941</link>
      <description>&lt;P&gt;&lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/217900"&gt;@bojito&lt;/a&gt;&amp;nbsp;Great questions!&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;DECLARE [VARIABLE] executed in the EXECUTE IMMEDIATE is a top level statement. It can only ever produce session varaibles.&lt;/LI&gt;
&lt;LI&gt;DECLARE variable in a compound statement is part of the BEGIN .. END block. It can only ever declare local variables.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;So this is by design.&lt;BR /&gt;Local variables are invisible to the statement inside EXECUTE IMMEDIATE. That statement can only see session variables. You must pass local variables in via USING.&lt;BR /&gt;&lt;BR /&gt;Hope that helps&lt;BR /&gt;Serge&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 26 Feb 2026 21:02:23 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/building-sql-with-sql-an-introduction-to-execute-immediate/bc-p/149427#M941</guid>
      <dc:creator>SergeRielau</dc:creator>
      <dc:date>2026-02-26T21:02:23Z</dc:date>
    </item>
  </channel>
</rss>

