Translation specification for the system procedure SP_EXECUTESQL.
Description
The SP_EXECUTESQL system stored procedure is used to execute a Transact-SQL statement or batch that can be reused many times, or one that is built dynamically. The statement or batch can contain embedded parameters.
This functionality can be emulated in Snowflake through the EXECUTE IMMEDIATE statement and with a user-defined function (UDF) for embedded parameters.
All patterns will transform SP_EXECUTESQL into Snowflake's EXECUTE IMMEDIATE statement and only modify the SQL string to be executed when using embedded parameters.
SSC-EWI-0030 (Usage of Dynamic SQL) will be added for all patterns. Even though the translation for SP_EXECUTESQL is equivalent to Snowflake, in this context, this EWI indicates that the SQL string might require manual fixes for the translation to execute as intended.
Setup Data
IN -> SqlServer_01.sql
CREATETABLEPERSONS(NAMEVARCHAR(25), ID INT, AGE INT);-- DATAINSERT INTO PERSONS VALUES ('John Smith', 1, 24);INSERT INTO PERSONS VALUES ('John Doe', 2, 21);INSERT INTO PERSONS VALUES ('Mary Keller', 3, 32);INSERT INTO PERSONS VALUES ('Mundane Man', 4, 18);
OUT -> SqlServer_01.sql
CREATE OR REPLACETABLEPERSONS (NAMEVARCHAR(25), ID INT, AGE INT)COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "transact", "convertedOn": "10/04/2024" }}'
;-- DATAINSERT INTO PERSONS VALUES ('John Smith', 1, 24);INSERT INTO PERSONS VALUES ('John Doe', 2, 21);INSERT INTO PERSONS VALUES ('Mary Keller', 3, 32);INSERT INTO PERSONS VALUES ('Mundane Man', 4, 18);
Without embedded parameters
When no embedded parameters are being used, the SP_EXECUTESQL is transformed into an EXECUTE IMMEDIATE statement and use the SQL string without modifications.
For embedded parameters for data binding, the SP_EXECUTESQL is transformed into an EXECUTE IMMEDIATE statement, and the SQL string is modified through the TRANSFORM_SP_EXECUTE_SQL_STRING_UDF.
The result of the EXECUTE IMMEDIATE is assigned to the ProcedureResultSet variable and later returned as TABLE(ProcedureResultSet).
Transact
IN -> SqlServer_03.sql
CREATEPROCEDURE QUERY_WITH_DATA_BINDING_PARAMSASBEGINDECLARE @IntVariable INT;DECLARE @SQLString NVARCHAR(500);DECLARE @ParmDefinition NVARCHAR(500);SET @IntVariable =21;SET @SQLString =N'SELECT * FROM PERSONS WHERE AGE = @age';SET @ParmDefinition =N'@age INT';EXECUTE sp_executesql @SQLString, @ParmDefinition, @age = @IntVariable;ENDGOEXEC QUERY_WITH_DATA_BINDING_PARAMS;
For embedded OUTPUT parameters, the SP_EXECUTESQL is transformed into an EXECUTE IMMEDIATE statement, and the SQL string is modified through the TRANSFORM_SP_EXECUTE_SQL_STRING_UDF.
Additionally, a SELECT $1, ..., $n INTO :outputParam1, ..., :outputParamN FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())) is added to the result of each column to the corresponding OUTPUT parameter.
SSC-FDM-TS0028 is added to the SELECT INTO statement. It is essential for the parameters in the INTO clause to appear in the same order as they were assigned in the original SQL String.
Otherwise, manual changes are required to meet this requirement.
CREATEORREPLACEPROCEDURE QUERY_WITH_OUTPUT_PARAMS ()RETURNSTABLE()LANGUAGESQLCOMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "transact", "convertedOn": "10/04/2024" }}'
EXECUTEASCALLERAS$$DECLARE INTVARIABLE INT; SQLSTRING VARCHAR(500); PARMDEFINITION VARCHAR(500); MAXAGE INT; ProcedureResultSet RESULTSET;BEGIN INTVARIABLE :=21; SQLSTRING :='SELECT MAX(AGE), MAX(ID) FROM PERSONS;'; PARMDEFINITION :='@MaxAgeOUT INT OUTPUT'; !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!! EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(:SQLSTRING, :PARMDEFINITION, ARRAY_CONSTRUCT('MAXAGEOUT'), ARRAY_CONSTRUCT(:MAXID, :MAXAGE));
--** SSC-FDM-TS0028 - OUTPUT PARAMETERS MUST HAVE THE SAME ORDER AS THEY APPEAR IN THE EXECUTED CODE **SELECT $1INTO :MAXAGEFROMTABLE(RESULT_SCAN(LAST_QUERY_ID())); ProcedureResultSet := (SELECT :MAXAGE);RETURNTABLE(ProcedureResultSet);END;$$;CALL QUERY_WITH_OUTPUT_PARAMS();
:MAXAGE::NUMBER(38,0)
32
With both embedded OUTPUT parameters and data binding
The translation is the same as for only OUTPUT parameters.
Transact
IN -> SqlServer_05.sql
CREATEPROCEDURE QUERY_WITH_BOTH_PARAMSASBEGINDECLARE @AgeVariable INT;DECLARE @IdVariable INT;DECLARE @SQLString NVARCHAR(500);DECLARE @ParmDefinition NVARCHAR(500);DECLARE @MaxAge INT;DECLARE @MaxId INT;SET @AgeVariable =30;SET @IdVariable =100;SET @SQLString =N'SELECT @MaxAgeOUT = max(AGE), @MaxIdOut = max(ID) FROM PERSONS WHERE AGE < @age AND ID < @id;';SET @ParmDefinition =N'@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT'; EXECUTE sp_executesql @SQLString, @ParmDefinition, @age = @AgeVariable, @id = @IdVariable, @MaxAgeOUT = @MaxAge OUTPUT, @MaxIdOUT = @MaxId OUTPUT;
SELECT @MaxAge, @MaxId;ENDGOEXEC QUERY_WITH_BOTH_PARAMS;
<anonymous>
<anonymous>
24
4
Snowflake
OUT -> SqlServer_05.sql
CREATEORREPLACEPROCEDURE QUERY_WITH_BOTH_PARAMS ()RETURNSTABLE()LANGUAGESQLCOMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "transact", "convertedOn": "10/04/2024" }}'
EXECUTEASCALLERAS$$DECLARE AGEVARIABLE INT; IDVARIABLE INT; SQLSTRING VARCHAR(500); PARMDEFINITION VARCHAR(500); MAXAGE INT; MAXID INT; ProcedureResultSet RESULTSET;BEGIN AGEVARIABLE :=30; IDVARIABLE :=100; SQLSTRING :='SELECT MAX(AGE), MAX(ID) FROM PERSONSWHERE AGE < @age AND ID < @id;'; PARMDEFINITION :='@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT'; !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!! EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(:SQLSTRING, :PARMDEFINITION, ARRAY_CONSTRUCT('AGE', 'ID', 'MAXAGEOUT', 'MAXIDOUT'), ARRAY_CONSTRUCT(:AGEVARIABLE, :IDVARIABLE, :MAXAGE, :MAXID));
--** SSC-FDM-TS0028 - OUTPUT PARAMETERS MUST HAVE THE SAME ORDER AS THEY APPEAR IN THE EXECUTED CODE **SELECT $1, $2INTO :MAXAGE, :MAXIDFROMTABLE(RESULT_SCAN(LAST_QUERY_ID())); ProcedureResultSet := (SELECT :MAXAGE, :MAXID);RETURNTABLE(ProcedureResultSet);END;$$;CALL QUERY_WITH_BOTH_PARAMS();
:MAXAGE::NUMBER(38,0)
:MAXID::NUMBER(38,0)
24
4
Parameters not in order of definition
This pattern follows the same rules as the previous patterns. TRANSFORM_SP_EXECUTE_SQL_STRING_UDF replaces the parameter values in the correct order.
Transact
IN -> SqlServer_06.sql
CREATEPROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEFASBEGINDECLARE @AgeVariable INT;DECLARE @IdVariable INT;DECLARE @SQLString NVARCHAR(500);DECLARE @ParmDefinition NVARCHAR(500);DECLARE @MaxAge INT;DECLARE @MaxId INT;SET @AgeVariable =30;SET @IdVariable =100;SET @SQLString =N'SELECT @MaxAgeOUT = max(AGE), @MaxIdOut = max(ID) FROM PERSONS WHERE AGE < @age AND ID < @id;';SET @ParmDefinition =N'@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT'; EXECUTE sp_executesql @SQLString, @ParmDefinition, @id = @IdVariable, @MaxAgeOUT = @MaxAge OUTPUT, @age = @AgeVariable, @MaxIdOUT = @MaxId OUTPUT;
SELECT @MaxAge, @MaxId;ENDGOEXEC QUERY_PARAMS_NOT_IN_ORDER_OF_DEF;CREATEPROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2ASBEGINDECLARE @AgeVariable INT;DECLARE @IdVariable INT;DECLARE @SQLString NVARCHAR(500);DECLARE @ParmDefinition NVARCHAR(500);DECLARE @MaxAge INT;DECLARE @MaxId INT;SET @AgeVariable =30;SET @IdVariable =100;SET @SQLString =N'SELECT @MaxAgeOUT = max(AGE), @MaxIdOut = max(ID) FROM PERSONS WHERE AGE < @age AND ID < @id;';SET @ParmDefinition =N'@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT'; EXECUTE sp_executesql @SQLString, @ParmDefinition, @AgeVariable, @MaxAgeOUT = @MaxAge OUTPUT, @id = @IdVariable, @MaxIdOUT = @MaxId OUTPUT;
SELECT @MaxAge, @MaxId;ENDGOEXEC QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2;
<anonymous>
<anonymous>
24
4
<anonymous>
<anonymous>
24
4
Snowflake
OUT -> SqlServer_06.sql
CREATEORREPLACEPROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF ()RETURNSTABLE()LANGUAGESQLCOMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "transact", "convertedOn": "10/04/2024" }}'
EXECUTEASCALLERAS$$DECLARE AGEVARIABLE INT; IDVARIABLE INT; SQLSTRING VARCHAR(500); PARMDEFINITION VARCHAR(500); MAXAGE INT; MAXID INT; ProcedureResultSet RESULTSET;BEGIN AGEVARIABLE :=30; IDVARIABLE :=100; SQLSTRING :='SELECT MAX(AGE), MAX(ID) FROM PERSONSWHERE AGE < @age AND ID < @id;'; PARMDEFINITION :='@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT'; !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!! EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(:SQLSTRING, :PARMDEFINITION, ARRAY_CONSTRUCT('ID', 'MAXAGEOUT', 'AGE', 'MAXIDOUT'), ARRAY_CONSTRUCT(:IDVARIABLE, :MAXAGE, :AGEVARIABLE, :MAXID));
--** SSC-FDM-TS0028 - OUTPUT PARAMETERS MUST HAVE THE SAME ORDER AS THEY APPEAR IN THE EXECUTED CODE **SELECT $1, $2INTO :MAXAGE, :MAXIDFROMTABLE(RESULT_SCAN(LAST_QUERY_ID())); ProcedureResultSet := (SELECT :MAXAGE, :MAXID);RETURNTABLE(ProcedureResultSet);END;$$;CALL QUERY_PARAMS_NOT_IN_ORDER_OF_DEF();CREATEORREPLACEPROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2 ()RETURNSTABLE()LANGUAGESQLCOMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "transact", "convertedOn": "10/04/2024" }}'
EXECUTEASCALLERAS$$DECLARE AGEVARIABLE INT; IDVARIABLE INT; SQLSTRING VARCHAR(500); PARMDEFINITION VARCHAR(500); MAXAGE INT; MAXID INT; ProcedureResultSet RESULTSET;BEGIN AGEVARIABLE :=30; IDVARIABLE :=100; SQLSTRING :='SELECT MAX(AGE), MAX(ID) FROM PERSONSWHERE AGE < @age AND ID < @id;'; PARMDEFINITION :='@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT'; !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!! EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(:SQLSTRING, :PARMDEFINITION, ARRAY_CONSTRUCT('', 'MAXAGEOUT', 'ID', 'MAXIDOUT'), ARRAY_CONSTRUCT(:AGEVARIABLE, :MAXAGE, :IDVARIABLE, :MAXID));
--** SSC-FDM-TS0028 - OUTPUT PARAMETERS MUST HAVE THE SAME ORDER AS THEY APPEAR IN THE EXECUTED CODE **SELECT $1, $2INTO :MAXAGE, :MAXIDFROMTABLE(RESULT_SCAN(LAST_QUERY_ID())); ProcedureResultSet := (SELECT :MAXAGE, :MAXID);RETURNTABLE(ProcedureResultSet);END;$$;CALL QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2();
:MAXAGE::NUMBER(38,0)
:MAXID::NUMBER(38,0)
24
4
:MAXAGE::NUMBER(38,0)
:MAXID::NUMBER(38,0)
24
4
Execute direct values
This translation also handles the cases where the values a directly assigned instead of using variables.
Transact
IN -> SqlServer_07.sql
CREATEPROCEDURE QUERY_WITH_DIRECT_PARAMS_VALUES_ALLASBEGINDECLARE @MaxAge INT;DECLARE @MaxId INT;EXECUTE sp_executesqlN'SELECT @MaxAgeOUT = max(AGE), @MaxIdOut = max(ID) FROM PERSONS WHERE ID < @id AND AGE < @age;',N'@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT',30,100, @MaxAge OUTPUT, @MaxId OUTPUT;SELECT @MaxAge, @MaxId;ENDGOEXEC QUERY_WITH_DIRECT_PARAMS_VALUES_ALL;
<anonymous>
<anonymous>
24
4
Snowflake
OUT -> SqlServer_07.sql
CREATEORREPLACEPROCEDURE QUERY_WITH_DIRECT_PARAMS_VALUES_ALL ()RETURNSTABLE()LANGUAGESQLCOMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "transact", "convertedOn": "10/07/2024" }}'
EXECUTEASCALLERAS$$DECLARE MAXAGE INT; MAXID INT; ProcedureResultSet RESULTSET;BEGIN !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!EXECUTEIMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF('SELECT MAX(AGE), MAX(ID) FROM PERSONSWHERE ID < @id AND AGE < @age;', '@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT', ARRAY_CONSTRUCT('', '', '', ''), ARRAY_CONSTRUCT(
30, 100, :MAXAGE, :MAXID)); --** SSC-FDM-TS0028 - OUTPUT PARAMETERS MUST HAVE THE SAME ORDER AS THEY APPEAR IN THE EXECUTED CODE ** SELECT $1, $2 INTO :MAXAGE, :MAXID FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())); ProcedureResultSet := ( SELECT :MAXAGE, :MAXID); RETURN TABLE(ProcedureResultSet); END;$$;CALL QUERY_WITH_DIRECT_PARAMS_VALUES_ALL();
:MAXAGE::NUMBER(38,0)
:MAXID::NUMBER(38,0)
24
4
SQL string dynamically built
This pattern follows the same rules as the previous patterns. However, assigning the result of the EXECUTE IMMEDIATE statement might not be added if the SQL string is not a simple single query with or without embedded parameters.
Furthermore, the SQL string must start with the literal value 'SELECT' for SnowConvert to correctly identify that a SELECT statement is going to be executed. For more information, check the Known Issues section.
Snowflake Scripting procedures only allow one result set to be returned per procedure.
To replicate Teradata behavior, when two or more result sets are to be returned, they are stored in temporary tables. The Snowflake Scripting procedure will return an array containing the names of the temporary tables. For more information, check SSC-FDM-0020.
Transact
IN -> SqlServer_09.sql
CREATEPROCEDURE WITH_MULTIPLE_RETURNSASBEGINDECLARE @SQLString NVARCHAR(500);DECLARE @ParmDefinition NVARCHAR(500);SET @SQLString =N'SELECT * FROM PERSONS WHERE AGE = @age';SET @ParmDefinition =N'@age INT';EXECUTE sp_executesql @SQLString, @ParmDefinition, @age =21;SET @SQLString =N'INSERT INTO PERSONS VALUES (''INSERT FIRST'', 1200, 230);';EXECUTE sp_executesql @SQLString;SET @SQLString =N'SELECT * FROM PERSONS';EXECUTE sp_executesql @SQLString;ENDGOEXECUTE WITH_MULTIPLE_RETURNS;
Name
ID
AGE
John Doe
2
21
Name
ID
AGE
John Smith
1
24
John Doe
2
21
Mary Keller
3
32
Mundane Man
4
18
INSERT FIRST
1200
230
Snowflake
OUT -> SqlServer_09.sql
CREATEORREPLACEPROCEDURE WITH_MULTIPLE_RETURNS ()RETURNSARRAYLANGUAGESQLCOMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "transact", "convertedOn": "10/07/2024" }}'
EXECUTEASCALLERAS$$DECLARE SQLSTRING VARCHAR(500); PARMDEFINITION VARCHAR(500); ProcedureResultSet1 VARCHAR; ProcedureResultSet2 VARCHAR; return_arr ARRAY := array_construct();BEGIN SQLSTRING :='SELECT *FROM PERSONSWHERE AGE = @age;'; PARMDEFINITION :='@age INT'; ProcedureResultSet1 :='RESULTSET_'||REPLACE(UPPER(UUID_STRING()), '-', '_'); !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!! EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(:SQLSTRING, :PARMDEFINITION, ARRAY_CONSTRUCT('AGE'), ARRAY_CONSTRUCT(21));
CREATEORREPLACE TEMPORARY TABLE IDENTIFIER(:ProcedureResultSet1) ASSELECT*FROMTABLE(RESULT_SCAN(LAST_QUERY_ID())); return_arr := array_append(return_arr, :ProcedureResultSet1); SQLSTRING :='INSERT INTO PERSONS VALUES ('INSERTFIRST', 1200, 230);'; !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!EXECUTEIMMEDIATE :SQLSTRING; SQLSTRING :='SELECT *FROM PERSONS;'; ProcedureResultSet2 :='RESULTSET_'||REPLACE(UPPER(UUID_STRING()), '-', '_'); !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!EXECUTEIMMEDIATE :SQLSTRING;CREATEORREPLACE TEMPORARY TABLE IDENTIFIER(:ProcedureResultSet2) ASSELECT*FROMTABLE(RESULT_SCAN(LAST_QUERY_ID())); return_arr := array_append(return_arr, :ProcedureResultSet2);--** SSC-FDM-0020 - MULTIPLE RESULT SETS ARE RETURNED IN TEMPORARY TABLES **RETURN return_arr;END;$$;CALL WITH_MULTIPLE_RETURNS();
SP_EXECUTESQL can execute more than one SQL statement inside the SQL string. Snowflake also supports executing multiple SQL statements, but need to be enclosed in a BEGIN ... END block. Furthermore, when executing multiple statements from a BEGIN ... END block, the EXECUTE IMMEDIATE will not return a resultset. The translation for these cases is not yet supported by SnowConvert. For more information, check SSC-EWI-0030.
Thus, when this case is detected, in the translated code, the EXECUTE IMMEDIATE will not be assigned to the ProcedureResultSet.
Transact
IN -> SqlServer_10.sql
CREATEPROCEDURE WITH_INVALID_CODE_DETECTEDASBEGINDECLARE @SQLString NVARCHAR(500);SET @SQLString =N'INSERT INTO PERSONS VALUES (''INSERT FIRST'', 1200, 230); SELECT * FROM PERSONS;';EXECUTE sp_executesql @SQLString;ENDGOEXEC WITH_INVALID_CODE_DETECTED;
000006 (0A000): Uncaught exception of type 'STATEMENT_ERROR' on line 10 at position 4 : Multiple SQL statements in a single API call are not supported; use one API call per statement instead.
2. Valid or Invalid code is not detected
When the SQL string is built dynamically through concatenations, SnowConvert might not detect what statement is going to be executed. Thus, in the translated code, the EXECUTE IMMEDIATE will not be assigned to the ProcedureResultSet.
000006 (0A000): Uncaught exception of type 'STATEMENT_ERROR' on line 10 at position 4 : Multiple SQL statements in a single API call are not supported; use one API call per statement instead.
3. Invalid code is mistaken as valid
If the SQL string starts with a SELECT statement and is followed by more statements, SnowConvert will detect this as a valid code and try to assign the result of the EXECUTE IMMEDIATE to theProcedureResultSet. This leads to a compilation error. For more information, check SSC-EWI-0030.
Transact
IN -> SqlServer_12.sql
CREATEPROCEDURE WITH_INVALID_CODE_MISTAKEN_AS_VALIDASBEGINDECLARE @SQLString NVARCHAR(500);SET @SQLString =N'SELECT * FROM PERSONS; SELECT * FROM PERSONS;';EXECUTE sp_executesql @SQLString;ENDGOEXEC WITH_INVALID_CODE_MISTAKEN_AS_VALID;
000006 (0A000): Uncaught exception of type 'STATEMENT_ERROR' on line 10 at position 4 : Multiple SQL statements in a single API call are not supported; use one API call per statement instead.
Related EWIs
SSC-EWI-0030: The statement below has usages of dynamic SQL
SSC-FDM-TS0028: Output parameters must have the same order as they appear in the executed code.
SSC-FDM-0020: Multiple result sets are returned in temporary tables.