SnowConvert AI - Servidor SQL - Azure Synapse - Elementos gerais de linguagem

Nesta seção você encontra informações sobre instruções gerais do Transect-SQL.

COLLATE

Applies to
  • SQL Server

  • Azure Synapse Analytics

A transformação de Collate depende de seu valor, pois pode ser compatível ou não.

Atualmente, estes são os idiomas suportados na transformação; se forem encontrados em Collate, serão transformados em seu equivalente no Snowflake.

SQL Server

Snowflake

Latin1_General

EN

Modern_Spanish

ES

Francês

FR

Se o idioma não for um dos mencionados acima, Collate será comentado.

The collate in SQL Server comes with additional specifications, such as CI, CS, AI, and AS. If there are additional specifications that are unsupported, they will be commented in the result.

Fonte

SELECT 'a' COLLATE Latin1_General_CI_AS;

SELECT 'a' COLLATE Modern_Spanish_CI_AS;

SELECT 'a' COLLATE French_CI_AS;

SELECT 'a' COLLATE Albanian_BIN;

SELECT 'a' COLLATE Latin1_General_CI_AS_WS;

SELECT 'a' COLLATE Latin1_General_CI_AS_KS_WS;

SELECT 'a' COLLATE Albanian_CI_AI;

Esperado

SELECT 'a' COLLATE 'EN-CI-AS';

SELECT 'a' COLLATE 'ES-CI-AS';

SELECT 'a' COLLATE 'FR-CI-AS';

SELECT 'a'
--           !!!RESOLVE EWI!!! /*** SSC-EWI-TS0077 - COLLATION Albanian_BIN NOT SUPPORTED ***/!!!
-- COLLATE Albanian_BIN
                     ;

SELECT 'a' COLLATE 'EN-CI-AS' /*** SSC-FDM-TS0002 - COLLATION FOR VALUE WS NOT SUPPORTED ***/;

SELECT 'a' COLLATE 'EN-CI-AS' /*** SSC-FDM-TS0002 - COLLATION FOR VALUES KS,WS NOT SUPPORTED ***/;

SELECT 'a'
--           !!!RESOLVE EWI!!! /*** SSC-EWI-TS0077 - COLLATION Albanian_CI_AI NOT SUPPORTED ***/!!!
-- COLLATE Albanian_CI_AI
                       ;

Vejamos um exemplo de Collate em Create Table

Fonte

CREATE TABLE TABLECOLLATE
(
    COL1 VARCHAR COLLATE Latin1_General_CI_AS
);

Esperado

CREATE OR REPLACE TABLE TABLECOLLATE
(
    COL1 VARCHAR COLLATE 'EN-CI-AS' /*** SSC-PRF-0002 - CASE INSENSITIVE COLUMNS CAN DECREASE THE PERFORMANCE OF QUERIES ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
;

Como você pode ver, a transformação de Collate dentro de Select ou Table é a mesma.

COMPUTED COLUMN

Não foi possível transformar a expressão computada.

Applies to
  • SQL Server

  • Azure Synapse Analytics

Descrição

A expressão de uma coluna computada não pôde ser transformada.

Exemplo de código

Código de entrada:
CREATE TABLE [TestTable](
    [Col1] AS (CONVERT ([REAL], ExpressionValue))
);
Código de saída:
CREATE OR REPLACE TABLE TestTable (
    Col1 REAL AS (CAST(ExpressionValue AS REAL)) /*** SSC-FDM-TS0014 - COMPUTED COLUMN WAS TRANSFORMED TO ITS SNOWFLAKE EQUIVALENT, FUNCTIONAL EQUIVALENCE VERIFICATION PENDING. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
;

Recomendações

EWIs relacionados

  1. SSC-FDM-TS0014: Coluna computada transformada.

OUTER APPLY

Tradutor de equivalência de instrução de aplicação externa.

Applies to
  • SQL Server

  • Azure Synapse Analytics

Nota

Algumas partes do código de saída foram omitidas por motivos de clareza.

Descrição

Quando OUTER APPLY é especificado, uma linha é produzida para cada linha do conjunto de linhas à esquerda, mesmo quando a expressão do conjunto de linhas à direita retorna um conjunto de linhas vazio para essa linha. (Definição de OUTER APPLY)

Sintaxe

   Apply_Operator :=                                                                                   
       'CROSS' 'APPLY'
  |    'OUTER' 'APPLY'.

Equivalência no Snowflake

Apesar da instrução sem suporte OUTER APPLY no Snowflake, há uma instrução equivalente, que é LATERAL. Portanto, a conversão da instrução é realizada para obter a mesma funcionalidade por meio do uso de soluções alternativas.

No entanto, a instrução LATERAL no Snowflake tem duas variações de sintaxe. Na verdade, a variação INNER JOIN LATERAL é usada nessa conversão específica.

A gramática de INNER JOIN LATERAL do Snowflake é a seguinte:

 SELECT ...
FROM <left_hand_table_expression> INNER JOIN LATERAL ( <inline_view> )
...

Nota

_<inline\view> não pode ser um nome de tabela.

E a única instrução LATERAL é mostrada abaixo:

 SELECT ...
FROM <left_hand_table_expression>, LATERAL ( <inline_view> )
...

Amostra de origem

O exemplo a seguir mostra uma conversão geral entre OUTER APPLY e INNER JOIN LATERAL:

SQL Server

SELECT  p.ProjectName, e.ProjectName, e.FirstName
FROM Project p
OUTER APPLY (
    SELECT
        ProjectName,
        FirstName,
        LastName
    FROM Employees e
) e;

Saída

p.ProjectName

e.ProjectName

FirstName

Projeto A

Projeto A

John

Projeto A

Projeto A

Jane

Projeto A

Projeto B

Michael

Projeto B

Projeto A

John

Projeto B

Projeto A

Jane

Projeto B

Projeto B

Michael

Projeto C

Projeto A

John

Projeto C

Projeto A

Jane

Projeto C

Projeto B

Michael

Snowflake

 SELECT
    p.ProjectName,
    e.ProjectName,
    e.FirstName
FROM
    Project p
    INNER JOIN
        LATERAL (
                   SELECT
                       ProjectName,
                       FirstName,
                       LastName
                   FROM
                       Employees e
               ) e;

Saída

PROJECTNAME

PROJECTNAME_2

FIRSTNAME

Projeto A

Projeto A

John

Projeto A

Projeto A

Jane

Projeto A

Projeto B

Michael

Projeto B

Projeto A

John

Projeto B

Projeto A

Jane

Projeto B

Projeto B

Michael

Projeto C

Projeto A

John

Projeto C

Projeto A

Jane

Projeto C

Projeto B

Michael

Problemas conhecidos

Como a conversão é uma equivalência da entrada, há algumas limitações.

  • As instruções TOP e WHERE podem ser revisadas para otimizar o comportamento.

  • Pode ser necessário um nome de correlação no final da instrução. No Snowflake, a consulta não representa um problema se o nome da correlação não estiver na consulta, mas a funcionalidade pode mudar e não faz parte do padrão aceito no SQL Server.

SQL Server

SELECT
    SATT.UNIVERSAL_NAME
FROM
SAMPLE_ATLAS AS SATT
OUTER APPLY (
    SELECT
        TOP 1 UNIVERSAL_NAME,
        INTERNATIONAL_NAME,
        CODE_IDENTIFIER
    FROM
        SAMPLE_GLOBE AS SG
    WHERE
        SG.GLOBE_KEY = SATT.MbrPersGenKey
    ORDER BY
        GLOBE_KEY
);
Saída da tradução
SELECT
            UNIVERSAL_NAME
FROM
            SAMPLE_ATLAS
            AS SATT
            OUTER APPLY
                        /*** MSC-ERROR - MSCCP0001 - THE FOLLOWING SUBQUERY MATCHES AT LEAST ONE OF THE PATTERNS CONSIDERED INVALID AND MAY PRODUCE COMPILATION ERRORS ***/ (SELECT TOP 1
                                                UNIVERSAL_NAME,
                                                INTERNATIONAL_NAME,
                                                CODE_IDENTIFIER
                                    FROM
                                                SAMPLE_GLOBE AS SG
                                    WHERE
                                                SG.GLOBE_KEY = SATT.MbrPersGenKey
                                    ORDER BY GLOBE_KEY
                        );
  • Instruções específicas que não são compatíveis podem comentar todo o código do bloco (exemplo retirado de: Exemplo de JSON).

SQL Server
SELECT
    SATT.UNIVERSAL_NAME
FROM
SAMPLE_ATLAS AS SATT
INNER JOIN LATERAL (
    SELECT
        TOP 1 UNIVERSAL_NAME,
        INTERNATIONAL_NAME,
        CODE_IDENTIFIER
    FROM
        SAMPLE_GLOBE AS SG
    WHERE
        SG.GLOBE_KEY = SATT.MbrPersGenKey
    ORDER BY
        GLOBE_KEY
);
Saída da tradução
SELECT
	familyName,
	c.givenName AS childGivenName,
	c.firstName AS childFirstName,
	p.givenName AS petName
FROM
	Families f
	LEFT OUTER JOIN
		OPENJSON(f.doc) /*** MSC-WARNING - MSCEWI4030 - Equivalence from CROSS APPLY to LEFT OUTER JOIN must be checked. ***/;
-- ** MSC-ERROR - MSCEWI1001 - UNRECOGNIZED TOKEN ON LINE 7 OF THE SOURCE CODE. **
--		WITH (familyName nvarchar(100), children nvarchar(max) AS JSON)
--		CROSS APPLY OPENJSON(children)
--		WITH (givenName nvarchar(100), firstName nvarchar(100), pets nvarchar(max) AS JSON) as c
--			OUTER APPLY OPENJSON (pets)
--			WITH (givenName nvarchar(100))  as p

EWIs relacionados

Sem EWIs relacionados.

USE

Equivalente do Snowflake para a instrução Transact-SQL USE.

Applies to
  • SQL Server

A instrução USE tem seu próprio equivalente no Snowflake. A instrução será convertida para a instrução USE DATABASE no Snowflake.

Exemplos de conversão

Fonte

USE [MY DATABASE]

Saída

USE DATABASE "MY DATABASE";

Nome do banco de dados

O nome do banco de dados especificado na instrução USE poderá ser alterado se estiver entre colchetes ([ ]). O primeiro colchete e o último serão substituídos por aspas. Exemplo:

Fonte
[MYDATABASE]
[[[MYDATABASE]]
Saída
"MYDATABASE"
"[[MYDATABASE]"

Banco de dados definido pelo usuário

Se um usuário especificar na ferramenta de conversão um nome de banco de dados personalizado a ser aplicado a todos os objetos usando o parâmetro -d e quiser que as instruções USE sejam transformadas, o nome do banco de dados deverá ser aplicado apenas à instrução USE e não aos objetos. Isso substituirá o banco de dados especificado na instrução Use. Exemplo:

Fonte
-- Additional Params: -d MYCUSTOMDB
USE [MY DATABASE]

CREATE TABLE [TableName1].[TableName2](
	[ColumnName1] varchar NULL
);
Saída
-- Additional Params: -d MYCUSTOMDB
USE DATABASE MYCUSTOMDB;

CREATE OR REPLACE TABLE MYCUSTOMDB.TableName1.TableName2 (
	ColumnName1 VARCHAR NULL
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
;

Problemas conhecidos

Não foram encontrados problemas.

EWIs relacionados

Sem EWIs relacionados.

EXECUTE

Applies to
  • SQL Server

  • Azure Synapse Analytics

A conversão para as instruções Exec ou Execute não é compatível com o Snowflake, mas será convertida para a instrução CALL.

Nota

Algumas partes do código de saída foram omitidas por motivos de clareza.

Entrada

Exec db.sp1

Saída

CALL db.sp1();

Para mais informações sobre a execução, acesse: Executar dentro dos procedimentos

PRINT

Applies to
  • SQL Server

  • Azure Synapse Analytics


A instrução Print não tem suporte direto no Snowflake, mas será traduzida para o seu equivalente mais próximo, a função interna SYSTEM$LOG_INFO.

Entrada

PRINT 'My message';

Saída (dentro do SnowScript)

SYSTEM$LOG_INFO('My message');

Saída (fora do SnowScript)

Quando a instrução Print é usada fora de um procedimento armazenado, é necessário que ela seja chamada de um SnowConvert AI UDP.

CALL PUBLIC.LOG_INFO_UDP('My message');

Antes de começar a registrar mensagens, é necessário configurar uma tabela de eventos. Para mais informações, consulte: registro de mensagens no Snowflake Scripting

Procedimentos armazenados do sistema

SP_EXECUTESQL

Especificação de tradução para o procedimento do sistema SP_EXECUTESQL.

Applies to
  • SQL Server

  • Azure Synapse Analytics

Descrição

O procedimento armazenado do sistema SP_EXECUTESQL é usado para executar uma instrução ou um lote do Transact-SQL que pode ser reutilizado várias vezes ou que é criado dinamicamente. A instrução ou o lote pode conter parâmetros incorporados.

Essa funcionalidade pode ser emulada no Snowflake pela instrução EXECUTE IMMEDIATE e com uma função definida pelo usuário (UDF) para parâmetros incorporados.#x20;

Para mais informações sobre a função definida pelo usuário (UDF) usada para esta tradução, veja TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(STRING, STRING, ARRAY, ARRAY).

Sintaxe

Transact
 sp_executesql [ @stmt = ] N'statement'
[
    [ , [ @params = ] N'@parameter_name data_type [ { OUT | OUTPUT } ] [ , ...n ]' ]
    [ , [ @param1 = ] 'value1' [ , ...n ] ]
]

Amostra de padrões da origem

Todos os padrões transformarão SP_EXECUTESQL na instrução EXECUTE IMMEDIATE do Snowflake e somente modificarão a cadeia de caracteres SQL a ser executada ao usar parâmetros incorporados.

Aviso

SSC-EWI-0030 (Uso de SQL dinâmico) será adicionado a todos os padrões. Embora a conversão para SP_EXECUTESQL seja equivalente ao Snowflake, nesse contexto, esse EWI indica que a cadeia de caracteres SQL pode exigir correções manuais para que a conversão seja executada como pretendido.

Dados de configuração

Transact
 CREATE TABLE PERSONS(
  NAME VARCHAR(25),
  ID INT,
  AGE INT
);

-- DATA
INSERT 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);
Snowflake
 CREATE OR REPLACE TABLE PERSONS (
  NAME VARCHAR(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" }}'
;

-- DATA
INSERT 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);

Sem parâmetros incorporados

Quando nenhum parâmetro incorporado estiver sendo usado, SP_EXECUTESQL é transformado em uma instrução EXECUTE IMMEDIATE e usa a cadeia de caracteres SQL sem modificações.

Transact
 CREATE PROCEDURE SIMPLE_SINGLE_QUERY
AS
BEGIN
    DECLARE @SQLString NVARCHAR(500);
    SET @SQLString = N'SELECT * FROM PERSONS';
    EXECUTE sp_executesql @SQLString;
END

GO

EXEC SIMPLE_SINGLE_QUERY;
Resultados

Nome

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

Snowflake
CREATE OR REPLACE PROCEDURE SIMPLE_SINGLE_QUERY ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    SQLSTRING VARCHAR(500);
    ProcedureResultSet RESULTSET;
  BEGIN
     
    SQLSTRING := 'SELECT
   *
FROM
   PERSONS;';
    ProcedureResultSet := (
      !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
      EXECUTE IMMEDIATE :SQLSTRING
    );
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL SIMPLE_SINGLE_QUERY();
Resultados

Nome

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

Com parâmetros incorporados para vinculação de dados

Para parâmetros incorporados para vinculação de dados, o SP_EXECUTESQL é transformado em uma instrução EXECUTE IMMEDIATE e a cadeia de caracteres SQL é modificada pelo TRANSFORM_SP_EXECUTE_SQL_STRING_UDF.#x20;

O resultado de EXECUTE IMMEDIATE é atribuído à variável ProcedureResultSet e, posteriormente, retornado como TABLE(ProcedureResultSet).

Transact
 CREATE PROCEDURE QUERY_WITH_DATA_BINDING_PARAMS
AS
BEGIN
    DECLARE @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;
END

GO

EXEC QUERY_WITH_DATA_BINDING_PARAMS;
Resultados

Nome

ID

AGE

John Doe

2

21

Snowflake
CREATE OR REPLACE PROCEDURE QUERY_WITH_DATA_BINDING_PARAMS ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    INTVARIABLE INT;
    SQLSTRING VARCHAR(500);
    PARMDEFINITION VARCHAR(500);
    ProcedureResultSet RESULTSET;
  BEGIN
     
     
     
    INTVARIABLE := 21;
    SQLSTRING := 'SELECT
   *
FROM
   PERSONS
WHERE
   AGE = @age;';
    PARMDEFINITION := '@age INT';
    ProcedureResultSet := (
      !!!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(:INTVARIABLE))
    );
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL QUERY_WITH_DATA_BINDING_PARAMS();
Resultados

Nome

ID

AGE

John Doe

2

21

Com parâmetros incorporados OUTPUT

Para parâmetros OUTPUT incorporados, SP_EXECUTESQL é transformado em uma instrução EXECUTE IMMEDIATE e a cadeia de caracteres SQL é modificada por meio de TRANSFORM_SP_EXECUTE_SQL_STRING_UDF.

Além disso, SELECT $1, ..., $n INTO :outputParam1, ..., :outputParamN FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())) é adicionado ao resultado de cada coluna para o parâmetro OUTPUT correspondente.

Aviso

SSC-FDM-TS0028 é adicionado à instrução SELECT INTO. É essencial que os parâmetros da cláusula INTO apareçam na mesma ordem em que foram atribuídos na cadeia de caracteres SQL original.

Caso contrário, serão necessárias alterações manuais para atender a esse requisito.

Transact
CREATE PROCEDURE QUERY_WITH_OUTPUT_PARAMS
AS
BEGIN
    DECLARE @SQLString NVARCHAR(500);
    DECLARE @ParamDefinition NVARCHAR(500);
    DECLARE @MaxAge INT;

    SET @SQLString = N'SELECT @MaxAgeOUT = max(AGE) FROM PERSONS';
    SET @ParamDefinition = N'@MaxAgeOUT INT OUTPUT';
    EXECUTE sp_executesql @SQLString, @ParamDefinition, @MaxAgeOUT = @MaxAge OUTPUT;

    SELECT @MaxAge;
END

GO

EXEC QUERY_WITH_OUTPUT_PARAMS;
Resultados

<anônimo>

32

Snowflake
CREATE OR REPLACE PROCEDURE QUERY_WITH_OUTPUT_PARAMS ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "11/27/2024",  "domain": "test" }}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        SQLSTRING VARCHAR(500);
        PARAMDEFINITION VARCHAR(500);
        MAXAGE INT;
        ProcedureResultSet RESULTSET;
    BEGIN
         
         
         
        SQLSTRING := 'SELECT
   MAX(AGE) FROM
   PERSONS;';
        PARAMDEFINITION := '@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, :PARAMDEFINITION, ARRAY_CONSTRUCT('MAXAGEOUT'), ARRAY_CONSTRUCT(:MAXAGE));
        --** SSC-FDM-TS0028 - OUTPUT PARAMETERS MUST HAVE THE SAME ORDER AS THEY APPEAR IN THE EXECUTED CODE **
        SELECT
            $1
        INTO
            :MAXAGE
        FROM
            TABLE(RESULT_SCAN(LAST_QUERY_ID()));
        ProcedureResultSet := (
        SELECT
            :MAXAGE);
        RETURN TABLE(ProcedureResultSet);
    END;
$$;

CALL QUERY_WITH_OUTPUT_PARAMS();
Resultados

:MAXAGE::NUMBER(38,0)

32

Com os parâmetros incorporados OUTPUT e a vinculação de dados

A conversão é a mesma que para apenas parâmetros OUTPUT.

Transact
CREATE PROCEDURE QUERY_WITH_BOTH_PARAMS
AS
BEGIN
    DECLARE @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;
END

GO

EXEC QUERY_WITH_BOTH_PARAMS;
Resultados

<anônimo>

<anônimo>

24

4

Snowflake
CREATE OR REPLACE PROCEDURE QUERY_WITH_BOTH_PARAMS ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  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
   PERSONS
WHERE
   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,
      $2
    INTO
      :MAXAGE,
      :MAXID
    FROM
      TABLE(RESULT_SCAN(LAST_QUERY_ID()));
    ProcedureResultSet := (
    SELECT
      :MAXAGE,
      :MAXID);
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL QUERY_WITH_BOTH_PARAMS();
Resultados

:MAXAGE::NUMBER(38,0)

:MAXID::NUMBER(38,0)

24

4

Os parâmetros não estão em ordem de definição

Esse padrão segue as mesmas regras dos padrões anteriores. TRANSFORM_SP_EXECUTE_SQL_STRING_UDF substitui os valores dos parâmetros na ordem correta.

Transact
CREATE PROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF
AS
BEGIN
    DECLARE @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;
END

GO

EXEC QUERY_PARAMS_NOT_IN_ORDER_OF_DEF;

CREATE PROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2
AS
BEGIN
    DECLARE @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;
END

GO

EXEC QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2;
Resultados

<anônimo>

<anônimo>

24

4

<anônimo>

<anônimo>

24

4

Snowflake
CREATE OR REPLACE PROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  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
   PERSONS
WHERE
   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,
      $2
    INTO
      :MAXAGE,
      :MAXID
    FROM
      TABLE(RESULT_SCAN(LAST_QUERY_ID()));
    ProcedureResultSet := (
    SELECT
      :MAXAGE,
      :MAXID);
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL QUERY_PARAMS_NOT_IN_ORDER_OF_DEF();

CREATE OR REPLACE PROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2 ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  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
   PERSONS
WHERE
   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,
      $2
    INTO
      :MAXAGE,
      :MAXID
    FROM
      TABLE(RESULT_SCAN(LAST_QUERY_ID()));
    ProcedureResultSet := (
    SELECT
      :MAXAGE,
      :MAXID);
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2();
Resultados

:MAXAGE::NUMBER(38,0)

:MAXID::NUMBER(38,0)

24

4

:MAXAGE::NUMBER(38,0)

:MAXID::NUMBER(38,0)

24

4

Executar valores diretos

This translation also handles the cases where the values are directly assigned instead of using variables.

Transact
CREATE PROCEDURE QUERY_WITH_DIRECT_PARAMS_VALUES_ALL
AS
BEGIN
    DECLARE @MaxAge INT;
    DECLARE @MaxId INT;

    EXECUTE sp_executesql
        N'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;
END

GO

EXEC QUERY_WITH_DIRECT_PARAMS_VALUES_ALL;
Resultados

<anônimo>

<anônimo>

24

4

Snowflake
CREATE OR REPLACE PROCEDURE QUERY_WITH_DIRECT_PARAMS_VALUES_ALL ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/07/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    MAXAGE INT;
    MAXID INT;
    ProcedureResultSet RESULTSET;
  BEGIN
     
     
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF('SELECT
   MAX(AGE),
   MAX(ID) FROM
   PERSONS
WHERE
   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();
Resultados

:MAXAGE::NUMBER(38,0)

:MAXID::NUMBER(38,0)

24

4

Cadeia de caracteres SQL construída dinamicamente

Esse padrão segue as mesmas regras dos padrões anteriores. No entanto, a atribuição do resultado da instrução EXECUTE IMMEDIATE pode não ser adicionada se a cadeia de caracteres SQL não for uma consulta simples e única com ou sem parâmetros incorporados.

Além disso, a cadeia de caracteres SQL precisa começar com o valor literal 'SELECT' para SnowConvert AI para identificar corretamente que uma instrução SELECT será executada.

Transact
CREATE PROCEDURE DYNAMIC_WITH_PARAMS
AS
BEGIN
    DECLARE @IntVariable INT;
    DECLARE @SQLString NVARCHAR(500);
    DECLARE @ParmDefinition NVARCHAR(500);
    DECLARE  @where_clause nvarchar(100);

    SET @where_clause = 'WHERE AGE = @age';
    SET @IntVariable = 21;
    SET @SQLString = N'SELECT * FROM PERSONS ' + @where_clause;
    SET @ParmDefinition = N'@age INT';
    EXECUTE sp_executesql @SQLString, @ParmDefinition, @age = @IntVariable;
END

GO

EXEC DYNAMIC_WITH_PARAMS;
Resultados

Nome

ID

AGE

John Doe

2

21

Snowflake
CREATE OR REPLACE PROCEDURE DYNAMIC_WITH_PARAMS ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    INTVARIABLE INT;
    SQLSTRING VARCHAR(500);
    PARMDEFINITION VARCHAR(500);
    WHERE_CLAUSE VARCHAR(100);
    ProcedureResultSet RESULTSET;
  BEGIN
     
     
     
     
    WHERE_CLAUSE := 'WHERE AGE = @age';
    INTVARIABLE := 21;
    SQLSTRING := 'SELECT
   *
FROM
   PERSONS ' || :WHERE_CLAUSE || ';';
    PARMDEFINITION := '@age INT';
    ProcedureResultSet := (
      !!!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(:INTVARIABLE))
    );
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL DYNAMIC_WITH_PARAMS();
Resultados

Nome

ID

AGE

John Doe

2

21

Retorno de vários conjuntos de resultados

Os procedimentos do Snowflake Scripting permitem que apenas um conjunto de resultados seja retornado por procedimento.

Para replicar o comportamento do Transact-SQL, quando dois ou mais conjuntos de resultados devem ser retornados, eles são armazenados em tabelas temporárias. O procedimento Snowflake Scripting retornará uma matriz contendo os nomes das tabelas temporárias. Para obter mais informações, consulte SSC-FDM-0020.

Transact
CREATE PROCEDURE WITH_MULTIPLE_RETURNS
AS
BEGIN
    DECLARE @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;
END

GO

EXECUTE WITH_MULTIPLE_RETURNS;
Resultados

Nome

ID

AGE

John Doe

2

21

Nome

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

INSERT FIRST

1200

230

Snowflake
CREATE OR REPLACE PROCEDURE WITH_MULTIPLE_RETURNS ()
RETURNS ARRAY
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/07/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    SQLSTRING VARCHAR(500);
    PARMDEFINITION VARCHAR(500);
    ProcedureResultSet1 VARCHAR;
    ProcedureResultSet2 VARCHAR;
    return_arr ARRAY := array_construct();
  BEGIN
     
     
    SQLSTRING := 'SELECT
   *
FROM
   PERSONS
WHERE
   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));
    CREATE OR REPLACE TEMPORARY TABLE IDENTIFIER(:ProcedureResultSet1) AS
      SELECT
        *
      FROM
        TABLE(RESULT_SCAN(LAST_QUERY_ID()));
    return_arr := array_append(return_arr, :ProcedureResultSet1);
    SQLSTRING := 'INSERT INTO PERSONS VALUES ('INSERT FIRST', 1200, 230);';
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE :SQLSTRING;
    SQLSTRING := 'SELECT
   *
FROM
   PERSONS;';
    ProcedureResultSet2 := 'RESULTSET_' || REPLACE(UPPER(UUID_STRING()), '-', '_');
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE :SQLSTRING;
    CREATE OR REPLACE TEMPORARY TABLE IDENTIFIER(:ProcedureResultSet2) AS
      SELECT
        *
      FROM
        TABLE(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();
Resultados

WITH_MULTIPLE_RETURNS

[ «RESULTSET_88C35D7A_1E5B_455D_97A4_247806E583A5», «RESULTSET_B2345B61_A015_43CB_BA11_6D3E013EF262» ]

Problemas conhecidos

1. Invalid code is detected

SP_EXECUTESQL pode executar mais de uma instrução SQL dentro da cadeia de caracteres SQL. O Snowflake também oferece suporte à execução de várias instruções SQL, mas elas precisam estar em um bloco BEGIN END. Além disso, ao executar várias instruções de um bloco BEGIN END, o EXECUTE IMMEDIATE não retornará um conjunto de resultados. O SnowConvert AI ainda não oferece suporte para a tradução nesses casos. Para mais informações, veja SSC-EWI-0030.

Assim, quando esse caso for detectado, no código convertido, EXECUTE IMMEDIATE não será atribuído a ProcedureResultSet.

Transact
CREATE PROCEDURE WITH_INVALID_CODE_DETECTED
AS
BEGIN
    DECLARE @SQLString NVARCHAR(500);
    SET @SQLString = N'INSERT INTO PERSONS VALUES (''INSERT FIRST'', 1200, 230); SELECT * FROM PERSONS;';
    EXECUTE sp_executesql @SQLString;
END

GO

EXEC WITH_INVALID_CODE_DETECTED;
Resultados

Nome

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

INSERT FIRST

1200

230

Snowflake
CREATE OR REPLACE PROCEDURE WITH_INVALID_CODE_DETECTED ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    SQLSTRING VARCHAR(500);
  BEGIN
     
    SQLSTRING := 'INSERT INTO PERSONS VALUES ('INSERT FIRST', 1200, 230); SELECT
   *
FROM
   PERSONS;';
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE :SQLSTRING;
  END;
$$;

CALL WITH_INVALID_CODE_DETECTED();
Resultados
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

Se a cadeia de caracteres SQL for construída dinamicamente através de concatenações, pode ser que a SnowConvert AI não detecte qual instrução será executada. Assim, no código traduzido, EXECUTE IMMEDIATE não será atribuído ao ProcedureResultSet.

Transact
CREATE PROCEDURE WITH_INVALID_CODE_NOT_DETECTED
AS
BEGIN
    DECLARE @SQLString NVARCHAR(500);
    DECLARE @SQLInsert NVARCHAR(500);
    SET @SQLInsert = N'INSERT INTO PERSONS VALUES (''INSERT FIRST'', 1200, 230)';
    SET @SQLString = @SQLInsert + N'SELECT * FROM PERSONS;';
    EXECUTE sp_executesql @SQLString;
END

GO

EXEC WITH_INVALID_CODE_NOT_DETECTED;
Resultados

Nome

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

INSERT FIRST

1200

230

Snowflake
CREATE OR REPLACE PROCEDURE WITH_INVALID_CODE_NOT_DETECTED ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    SQLSTRING VARCHAR(500);
    SQLINSERT VARCHAR(500);
  BEGIN
     
     
    SQLINSERT := 'INSERT INTO PERSONS VALUES ('INSERT FIRST', 1200, 230);';
    SQLSTRING := :SQLINSERT || 'SELECT * FROM PERSONS;';
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE :SQLSTRING;
  END;
$$;

CALL WITH_INVALID_CODE_NOT_DETECTED();
Resultados
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

Se a cadeia de caracteres SQL começar com uma instrução SELECT e for seguida por mais instruções, a SnowConvert AI detectará isso como um código válido e tentará atribuir o resultado do EXECUTE IMMEDIATE para o ProcedureResultSet. Isso gera um erro de compilação. Para mais informações, veja SSC-EWI-0030.

Transact
CREATE PROCEDURE WITH_INVALID_CODE_MISTAKEN_AS_VALID
AS
BEGIN
    DECLARE @SQLString NVARCHAR(500);
    SET @SQLString = N'SELECT * FROM PERSONS; SELECT * FROM PERSONS;';
    EXECUTE sp_executesql @SQLString;
END

GO

EXEC WITH_INVALID_CODE_MISTAKEN_AS_VALID;
Resultados

Nome

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

Nome

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

Snowflake
CREATE OR REPLACE PROCEDURE WITH_INVALID_CODE_MISTAKEN_AS_VALID ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    SQLSTRING VARCHAR(500);
    ProcedureResultSet RESULTSET;
  BEGIN
     
    SQLSTRING := 'SELECT
   *
FROM
   PERSONS; SELECT
   *
FROM
   PERSONS;';
    ProcedureResultSet := (
      !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
      EXECUTE IMMEDIATE :SQLSTRING
    );
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL WITH_INVALID_CODE_MISTAKEN_AS_VALID();
Resultados
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.

EWIs relacionados

  1. SSC-EWI-0030: A instrução abaixo tem usos de SQL dinâmico

  2. SSC-FDM-TS0028: Os parâmetros de saída devem ter a mesma ordem em que aparecem no código executado.

  3. SSC-FDM-0020: Vários conjuntos de resultados são retornados em tabelas temporárias.

SP_RENAME

Stored Procedure to Rename certain objects in SQL Server

Applies to
  • SQL Server

  • Azure Synapse Analytics

O procedimento de armazenamento do sistema SP_RENAME pode ser emulado no Snowflake em determinados cenários. Em geral, o equivalente é EXECUTE IMMEDIATE, usando uma instrução dinâmica com ALTER TABLE e os parâmetros originais.

Exemplos de conversão para tabelas

Fonte

EXEC sp_rename 'TABLE1', 'TABLENEW1'

Saída

EXECUTE IMMEDIATE 'ALTER TABLE TABLE1 RENAME TO TABLENEW1';
Fonte
DECLARE @varname1 nvarchar(50) = 'previous_name'
DECLARE @varname2 nvarchar(50) = 'newer_name'
EXEC sp_rename @varname1, @varname2
Saída
DECLARE
VARNAME1 VARCHAR(50) := 'previous_name';
VARNAME2 VARCHAR(50) := 'newer_name';
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE ' || :VARNAME1 || ' RENAME TO ' || :VARNAME2;
END;

Exemplos de conversão para colunas

Fonte
EXEC sp_rename 'sample_BACKUP_2.column_old', 'column_new', 'COLUMN'
EXEC sp_rename 'database1.sample_BACKUP_3.column_old', 'column_new', 'COLUMN'
Saída
EXECUTE IMMEDIATE 'ALTER TABLE sample_BACKUP_2 RENAME COLUMN column_old TO column_new';

EXECUTE IMMEDIATE 'ALTER TABLE database1.sample_BACKUP_3 RENAME COLUMN column_old TO column_new';
Fonte
DECLARE @oldColumnName nvarchar(50) = 'previous_name'
DECLARE @newColumnName nvarchar(50) = 'newer_name'
DECLARE @tableName nvarchar(50) = 'TABLE'
EXEC sp_rename @objname = @tableName + '.' + @oldColumnName, @newname = @newColumnName, @objtype = 'COLUMN';
Saída
DECLARE
OLDCOLUMNNAME VARCHAR(50) := 'previous_name';
NEWCOLUMNNAME VARCHAR(50) := 'newer_name';
TABLENAME VARCHAR(50) := 'TABLE';
BEGIN
!!!RESOLVE EWI!!! /*** SSC-EWI-TS0075 - TRANSLATION FOR BUILT-IN PROCEDURE 'SP_RENAME' IS NOT CURRENTLY SUPPORTED. ***/!!!
EXEC sp_rename OBJNAME = :TABLENAME || '.' || :OLDCOLUMNNAME, NEWNAME = :NEWCOLUMNNAME, OBJTYPE = 'COLUMN';
END;

EWIs relacionados

  1. SSC-EWI-TS0075: A conversão para o procedimento interno não é suportada no momento.

WAITFOR DELAY

Applies to
  • SQL Server

  • Azure Synapse Analytics

Descrição

In SQL Server, WAITFOR DELAY pauses execution for a specified duration. SnowConvert AI transforms WAITFOR DELAY statements to Snowflake’s CALL SYSTEM$WAIT() function, which provides equivalent delay functionality.

The time string is parsed and converted to seconds (or milliseconds for sub-second precision). Variables and parameters are passed through directly with an EWI warning, since SYSTEM$WAIT expects a numeric value rather than a time string.

Nota

WAITFOR TIME (which pauses until a specific time of day) has no Snowflake equivalent and remains flagged with SSC-EWI-0073.

Exemplos de conversão

WAITFOR DELAY with literal time

Código de entrada:
 CREATE PROCEDURE proc1()
AS
BEGIN
  WAITFOR DELAY '00:00:30';
END
Generated Code:
 CREATE OR REPLACE PROCEDURE proc1 ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  BEGIN
    CALL SYSTEM$WAIT(30);
  END;
$$;

WAITFOR DELAY with sub-second precision

Código de entrada:
 CREATE PROCEDURE proc1()
AS
BEGIN
  WAITFOR DELAY '00:00:00.500';
END
Generated Code:
 CREATE OR REPLACE PROCEDURE proc1 ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  BEGIN
    CALL SYSTEM$WAIT(500, 'MILLISECONDS');
  END;
$$;

WAITFOR DELAY with variable

Código de entrada:
 CREATE PROCEDURE proc1(@WaitTime INT)
AS
BEGIN
  WAITFOR DELAY @WaitTime;
END
Generated Code:
 CREATE OR REPLACE PROCEDURE proc1 (WAITTIME INT)
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  BEGIN
    !!!RESOLVE EWI!!! /*** SSC-EWI-TS0094 - WAITFOR DELAY WITH VARIABLE ':WAITTIME' WAS CONVERTED TO SYSTEM$WAIT, BUT THE VARIABLE MAY CONTAIN A TIME STRING IN 'HH:MM:SS' FORMAT. SYSTEM$WAIT EXPECTS A NUMERIC VALUE IN SECONDS. ***/!!!
    CALL SYSTEM$WAIT(:WAITTIME);
  END;
$$;

WAITFOR DELAY at script level

Código de entrada:
 WAITFOR DELAY '00:00:30';
Generated Code:
 CALL SYSTEM$WAIT(30);

Known Limitations

  • WAITFOR TIME (pause until a specific time of day) has no Snowflake equivalent and is flagged with SSC-EWI-0073.

  • When a variable is used, SSC-EWI-TS0094 is emitted because SYSTEM$WAIT expects a numeric value but the variable may contain a time string in 'HH:MM:SS' format.

EWIs relacionados

  1. SSC-EWI-TS0094: WAITFOR DELAY variable may contain a time string incompatible with SYSTEM$WAIT.

  2. SSC-EWI-0073: Pending functional equivalence review (emitted for WAITFOR TIME).

CREATE STATISTICS

Applies to
  • SQL Server

  • Azure Synapse Analytics

Descrição

SnowConvert AI comments out CREATE STATISTICS statements because Snowflake automatically collects optimizer statistics and does not require this statement.

Translation Example

Código de entrada:

CREATE STATISTICS Stats1 ON dbo.Table1(col1);

Generated Code:

----** SSC-FDM-0037 - CREATE STATISTICS NOT NEEDED. SNOWFLAKE AUTOMATICALLY COLLECTS STATISTICS. **
--CREATE STATISTICS Stats1 ON dbo.Table1 (
--  col1
--);

Additional Example

Código de entrada:

CREATE STATISTICS NamePurchase ON AdventureWorks2022.Person.Person(BusinessEntityID, EmailPromotion) WITH FULLSCAN, NORECOMPUTE;

Generated Code:

----** SSC-FDM-0037 - CREATE STATISTICS NOT NEEDED. SNOWFLAKE AUTOMATICALLY COLLECTS STATISTICS. **
--CREATE STATISTICS NamePurchase ON AdventureWorks2022.Person.Person (
--  BusinessEntityID,
--  EmailPromotion
--) WITH FULLSCAN, NORECOMPUTE ;

Known Limitations

  • Any operational process that explicitly creates or refreshes statistics in SQL Server should be reviewed, because Snowflake manages optimizer statistics automatically.