SnowConvert: Snowflake Scripting

Transação BEGIN e COMMIT

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Descrição

Snowflake SQL, uma transação pode ser iniciada explicitamente com a execução de uma instrução BEGIN. O Snowflake oferece suporte aos sinônimos BEGINWORK e BEGINTRANSACTION. O Snowflake recomenda usar BEGINTRANSACTION.

Uma transação pode ser encerrada explicitamente com a execução de COMMIT. Leia mais sobre as transações do Snowflake aqui.

Amostra de padrões de origem

Os exemplos a seguir detalham as instruções de transação BEGIN e COMMIT.

Transact-SQL

 CREATE PROCEDURE TestTransaction
AS
BEGIN
    DROP TABLE IF EXISTS NEWTABLE;
    CREATE TABLE NEWTABLE(COL1 INT, COL2 VARCHAR);
      BEGIN TRANSACTION;
         INSERT INTO NEWTABLE VALUES (1, 'MICHAEL');
         INSERT INTO NEWTABLE VALUES(2, 'JACKSON');
      COMMIT TRANSACTION;
END
Copy
 CREATE PROCEDURE TestTransaction
AS
BEGIN
    DROP TABLE IF EXISTS NEWTABLE;
    CREATE TABLE NEWTABLE(COL1 INT, COL2 VARCHAR);
      BEGIN TRANSACTION LabelA;
        INSERT INTO NEWTABLE VALUES (1, 'MICHAEL');
        INSERT INTO NEWTABLE VALUES(2, 'JACKSON');
      COMMIT TRANSACTION LabelA;
END
Copy
Snowflake SQL
 CREATE OR REPLACE PROCEDURE TestTransaction ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        DROP TABLE IF EXISTS NEWTABLE;
        CREATE OR REPLACE TABLE NEWTABLE (
            COL1 INT,
            COL2 VARCHAR
        );
            BEGIN TRANSACTION;
            INSERT INTO NEWTABLE VALUES (1, 'MICHAEL');
         INSERT INTO NEWTABLE VALUES(2, 'JACKSON');
            COMMIT;
    END;
$$;
Copy
 CREATE OR REPLACE PROCEDURE TestTransaction ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        DROP TABLE IF EXISTS NEWTABLE;
        CREATE OR REPLACE TABLE NEWTABLE (
            COL1 INT,
            COL2 VARCHAR
        );
            BEGIN TRANSACTION
            !!!RESOLVE EWI!!! /*** SSC-EWI-0101 - COMMENTED OUT TRANSACTION LABEL NAME BECAUSE IS NOT APPLICABLE IN SNOWFLAKE ***/!!!
            LabelA;
            INSERT INTO NEWTABLE VALUES (1, 'MICHAEL');
        INSERT INTO NEWTABLE VALUES(2, 'JACKSON');
            COMMIT;
    END;
$$;
Copy

Problemas conhecidos

  1. As transações aninhadas não são compatíveis com o Snowflake. Consulte a documentação a seguir para obter mais informações: https://docs.snowflake.com/en/sql-reference/transactions

CALL

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Descrição

A instrução CALL Snowflake Scripting, pois faz parte da API ODBC e não uma instrução SQL. Portanto, essa instrução não é convertida.

CASE

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

Descrição

O Transact-SQL tem dois formatos possíveis da expressão Case, ambos com a finalidade de avaliar expressões e obter resultados condicionalmente. O primeiro refere-se a uma expressão Case simples que será avaliada se uma expressão input_expression corresponder a uma ou mais expressões when_expression. O segundo avaliará cada expressão booliana de forma independente. A cláusula else é suportada em ambos os formatos.

De acordo com a documentação oficial de Transact-SQL Case:

CASE pode ser usado em qualquer instrução ou cláusula que permita uma expressão válida. Por exemplo, você pode usar CASE em instruções como SELECT, UPDATE, DELETE e SET, e em cláusulas como select_list, IN, WHERE, ORDER BY e HAVING.

Para obter mais informações sobre Transact-SQL Case, veja aqui.

 -- Simple CASE expression:   
CASE input_expression   
     WHEN when_expression THEN result_expression [ ...n ]   
     [ ELSE else_result_expression ]   
END   

-- Searched CASE expression:  
CASE  
     WHEN boolean_expression THEN result_expression [ ...n ]   
     [ ELSE else_result_expression ]   
END
Copy

Observação: o Transact-SQL permite encapsular opcionalmente a expressão input_expression e a expressão boolean_expression entre parênteses; o Snowflake Scripting também.

Amostra de padrões de origem

Os exemplos a seguir detalham dois cenários em que a expressão Case pode ser usada e suas diferenças em relação ao Snowflake Scripting.

Select usando Case

Transact-SQL
 CREATE OR ALTER PROCEDURE SelectCaseDemoProcedure
AS
      SELECT TOP 10
          LOGINID,
          CASE (MARITALSTATUS)
              WHEN 'S' THEN 'SINGLE'
              WHEN 'M' THEN 'MARIED'
              ELSE 'OTHER'
          END AS status
      FROM HUMANRESOURCES.EMPLOYEE;
GO

EXEC SelectCaseDemoProcedure;
Copy
 CREATE OR ALTER PROCEDURE SelectCaseDemoProcedure
AS
      SELECT TOP 10
          LOGINID,
          CASE
              WHEN MARITALSTATUS = 'S' THEN 'SINGLE'
              WHEN MARITALSTATUS = 'M' THEN 'MARIED'
              ELSE 'OTHER'
          END AS status
      FROM HUMANRESOURCES.EMPLOYEE;
GO

EXEC SelectCaseDemoProcedure;
Copy
 sqlLOGINID              |status|
------------------------+------+
adventure-works\ken0    |SINGLE|
adventure-works\terri0  |SINGLE|
adventure-works\roberto0|MARIED|
adventure-works\rob0    |SINGLE|
adventure-works\gail0   |MARIED|
adventure-works\jossef0 |MARIED|
adventure-works\dylan0  |MARIED|
adventure-works\diane1  |SINGLE|
adventure-works\gigi0   |MARIED|
adventure-works\michael6|MARIED|
Copy
Snowflake Scripting

Observe que, nesse cenário, não há diferenças em relação à expressão Case em si.

Aviso

A declaração e a atribuição da variável res servem para demonstrar a equivalência funcional entre as duas linguagens. Ela não aparece na saída real.

CREATE OR REPLACE PROCEDURE SelectCaseDemoProcedure ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
      DECLARE
            ProcedureResultSet RESULTSET;
      BEGIN
            ProcedureResultSet := (
            SELECT TOP 10
                  LOGINID,
                CASE (MARITALSTATUS)
                    WHEN 'S' THEN 'SINGLE'
                    WHEN 'M' THEN 'MARIED'
                    ELSE 'OTHER'
                END AS status
            FROM
                  HUMANRESOURCES.EMPLOYEE);
            RETURN TABLE(ProcedureResultSet);
      END;
$$;

CALL SelectCaseDemoProcedure();
Copy
 CREATE OR REPLACE PROCEDURE SelectCaseDemoProcedure ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
      DECLARE
            ProcedureResultSet RESULTSET;
      BEGIN
            ProcedureResultSet := (
            SELECT TOP 10
                  LOGINID,
                CASE
                    WHEN MARITALSTATUS = 'S' THEN 'SINGLE'
                    WHEN MARITALSTATUS = 'M' THEN 'MARIED'
                    ELSE 'OTHER'
                END AS status
            FROM
                  HUMANRESOURCES.EMPLOYEE);
            RETURN TABLE(ProcedureResultSet);
      END;
$$;

CALL SelectCaseDemoProcedure();
Copy
 LOGINID                |STATUS|
-----------------------+------+
adventure-worksken0    |SINGLE|
adventure-works erri0  |SINGLE|
adventure-worksoberto0 |MARIED|
adventure-worksob0     |SINGLE|
adventure-worksgail0   |MARIED|
adventure-worksjossef0 |MARIED|
adventure-worksdylan0  |MARIED|
adventure-worksdiane1  |SINGLE|
adventure-worksgigi0   |MARIED|
adventure-worksmichael6|MARIED|
Copy

Set usando Case

O banco de dados AdventureWorks2019 foi usado em ambas as linguagens para obter os mesmos resultados.

Transact-SQL
 CREATE OR ALTER PROCEDURE SetCaseDemoProcedure
AS
    DECLARE @value INT;
    DECLARE @result INT;
    SET @value = 5;
    
    SET @result =
        CASE @value
            WHEN 1 THEN @value * 10
            WHEN 3 THEN @value * 20
            WHEN 5 THEN @value * 30
            WHEN 7 THEN @value * 40
            ELSE -1
        END;
    
    RETURN @result
GO

DECLARE @result INT;
EXEC @result = SetCaseDemoProcedure;
PRINT @result;
Copy
 CREATE OR ALTER PROCEDURE SetCaseDemoProcedure
AS
    DECLARE @value INT;
    DECLARE @result INT;
    SET @value = 5;
    
    SET @result =
        CASE
            WHEN @value = 1 THEN @value * 10
            WHEN @value = 3 THEN @value * 20
            WHEN @value = 5 THEN @value * 30
            WHEN @value = 7 THEN @value * 40
            ELSE -1
        END;
    
    RETURN @result
GO

DECLARE @result INT;
EXEC @result = SetCaseDemoProcedure;
PRINT @result;
Copy
 |result|
|------|
|150   |
Copy
Snowflake Scripting

Aviso

O Snowflake Scripting não permite definir uma expressão Case diretamente em uma variável. Ambos os formatos de expressão Transact-SQL Case são convertidos para a seguinte gramática no Snowflake Scripting.

 CREATE OR REPLACE PROCEDURE SetCaseDemoProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        VALUE INT;
        RESULT INT;
    BEGIN
         
         
        VALUE := 5;
        CASE (:VALUE)
            WHEN 1 THEN
                RESULT := :VALUE * 10;
            WHEN 3 THEN
                RESULT := :VALUE * 20;
            WHEN 5 THEN
                RESULT := :VALUE * 30;
            WHEN 7 THEN
                RESULT := :VALUE * 40;
            ELSE
                RESULT := -1;
        END;
        RETURN :RESULT;
    END;
$$;

DECLARE
    RESULT INT;
BEGIN
    CALL SetCaseDemoProcedure();
    !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'Print' NODE ***/!!!
    PRINT @result;
END;
Copy
CREATE OR REPLACE PROCEDURE SetCaseDemoProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        VALUE INT;
        RESULT INT;
    BEGIN
         
         
        VALUE := 5;
        CASE
            WHEN :VALUE = 1 THEN
                RESULT := :VALUE * 10;
            WHEN :VALUE = 3 THEN
                RESULT := :VALUE * 20;
            WHEN :VALUE = 5 THEN
                RESULT := :VALUE * 30;
            WHEN :VALUE = 7 THEN
                RESULT := :VALUE * 40;
            ELSE
                RESULT := -1;
        END;
        RETURN :RESULT;
    END;
$$;

DECLARE
    RESULT INT;
BEGIN
    CALL SetCaseDemoProcedure();
    !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'Print' NODE ***/!!!
    PRINT @result;
END;
Copy
 |result|
|------|
|150   |
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs relacionados

  1. SSC-EWI-0073: Revisão de equivalência funcional pendente.

CREATE PROCEDURE

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

Descrição

A instrução create procedure permite a criação de procedimentos armazenados que podem:

  • Aceitar parâmetros de entrada e retornar vários valores na forma de parâmetros de saída para o procedimento de chamada ou lote.

  • Conter instruções de programação que executam operações no banco de dados, inclusive a chamada de outros procedimentos.

  • Retorna um valor de status para um procedimento de chamada ou lote para indicar sucesso ou falha (e o motivo da falha).

Para obter mais informações sobre Transact-SQL CREATE PROCEDURE, veja aqui.

 CREATE [ OR ALTER ] { PROC | PROCEDURE }
    [schema_name.] procedure_name [ ; number ]
    [ { @parameter [ type_schema_name. ] data_type }
        [ VARYING ] [ = default ] [ OUT | OUTPUT | [READONLY]
    ] [ ,...n ]
[ WITH <procedure_option> [ ,...n ] ]
[ FOR REPLICATION ]
AS { [ BEGIN ] sql_statement [;] [ ...n ] [ END ] }
[;]
Copy

Amostra de padrões da origem

Procedimento armazenado sem corpo

Um procedimento armazenado sem um corpo é um cenário incomum que é permitido no Transact-SQL. O Snowflake Scripting não permite definir procedimentos sem um corpo, mas o exemplo a seguir mostra a equivalência.

Transact-SQL
 CREATE PROC SampleProcedure AS;
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE SampleProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
   BEGIN
      RETURN '';
   END;
$$;
Copy

Procedimento armazenado básico

O exemplo a seguir detalha um procedimento armazenado simples que incluirá um novo departamento de privacidade no banco de dados AdventureWorks2019.

Transact-SQL
 CREATE OR ALTER PROCEDURE Add_Privacy_Department
AS
  EXECUTE ('INSERT INTO HumanResources.Department VALUES (''Privacy'', ''Executive General and Administration'', default)');
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE Add_Privacy_Department ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
  BEGIN
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE 'INSERT INTO HumanResources.Department VALUES ('Privacy', 'Executive General and Administration', default);';
  END;
$$;
Copy

Procedimento Alter

A transformação para o procedimento ALTER é equivalente ao procedimento básico.

Transact-SQL
 ALTER PROCEDURE procedureName
AS
SELECT 1 AS ThisDB;
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE procedureName ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
DECLARE
ProcedureResultSet RESULTSET;
BEGIN
ProcedureResultSet := (
SELECT 1 AS ThisDB);
RETURN TABLE(ProcedureResultSet);
END;
$$;
Copy

Usando parâmetros

Você pode usar parâmetros para conduzir sua lógica ou construir instruções dinâmicas SQL dentro do procedimento armazenado. No exemplo a seguir, é criado um procedimento armazenado SetNewPrice simples, que define um novo preço de produto com base nos argumentos enviados pelo chamador.

Transact-SQL
 CREATE OR ALTER PROCEDURE SetNewPrice @ProductID INT, @NewPrice MONEY
AS
  BEGIN
    DECLARE @dynSqlStatement AS VARCHAR(300);
    SET @dynSqlStatement = 'UPDATE Production.ProductListPriceHistory SET ListPrice = ' + CAST(@NewPrice AS VARCHAR(10)) + ' WHERE ProductID = ' + CAST(@ProductID AS VARCHAR(10)) + ' AND EndDate IS NULL';
    EXECUTE (@dynSqlStatement);
  END;
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE SetNewPrice (PRODUCTID INT, NEWPRICE NUMBER(38, 4))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    DYNSQLSTATEMENT VARCHAR(300);
  BEGIN
     
    DYNSQLSTATEMENT := 'UPDATE Production.ProductListPriceHistory
   SET
      ListPrice = ' || CAST(:NEWPRICE AS VARCHAR(10)) || '
   WHERE
      ProductID = ' || CAST(:PRODUCTID AS VARCHAR(10)) || '
      AND EndDate IS NULL;';
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE :DYNSQLSTATEMENT;
  END;
$$;
Copy

Parâmetros de saída

A palavra-chave output do Transact-SQL indica que o parâmetro é um parâmetro de saída, cujo valor será retornado ao chamador do procedimento armazenado. Por exemplo, o procedimento a seguir retornará o número de horas de férias de um funcionário específico.

Transact-SQL
 CREATE PROCEDURE GetVacationHours  
   @employeeId INT,  
   @vacationHours INT OUTPUT  
AS  
BEGIN  
   SELECT @vacationHours = VacationHours 
   FROM HumanResources.Employee
   WHERE NationalIDNumber = @employeeID
END;
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE GetVacationHours (EMPLOYEEID INT, VACATIONHOURS INT)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
   BEGIN
      SELECT
         VacationHours
      INTO
         :VACATIONHOURS
      FROM
         HumanResources.Employee
      WHERE
         NationalIDNumber = :EMPLOYEEID;
      RETURN VACATIONHOURS;
   END;
$$;
Copy

Aviso

Apenas um parâmetro de saída pode ser retornado de um procedimento armazenado do Snowflake Scripting.

Parâmetros opcionais

Um parâmetro é considerado opcional se tiver um valor padrão especificado quando for declarado. Não é necessário fornecer um valor para um parâmetro opcional em uma chamada de procedimento.

Transact-SQL
 CREATE PROCEDURE OPTIONAL_PARAMETER @VAR1 INT = 1, @VAR2 INT = 2
AS
    BEGIN
        RETURN NULL;
    END

GO

EXEC OPTIONAL_PARAMETER @VAR2 = 4
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE OPTIONAL_PARAMETER (VAR1 INT DEFAULT 1, VAR2 INT DEFAULT 2)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        RETURN NULL;
    END;
$$;

CALL OPTIONAL_PARAMETER(VAR2 => 4);
Copy

EXECUTE AS

A cláusula EXECUTE AS do Transact-SQL define o contexto de execução do procedimento armazenado, especificando qual conta de usuário o Mecanismo de Banco de Dados usa para validar as permissões dos objetos referenciados no procedimento. Por exemplo, podemos modificar o procedimento GetVacationHours anterior para definir diferentes contextos de execução.

  • Proprietário (padrão no Snowflake Scripting)

Transact-SQL
CREATE OR ALTER PROCEDURE GetVacationHours
   @employeeId INT,  
   @vacationHours INT OUTPUT
WITH EXECUTE AS OWNER
AS
BEGIN  
   SELECT @vacationHours = VacationHours 
   FROM HumanResources.Employee
   WHERE NationalIDNumber = @employeeID
END;
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE GetVacationHours (EMPLOYEEID INT, VACATIONHOURS INT)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS OWNER
AS
$$
   BEGIN
      SELECT
         VacationHours
      INTO
         :VACATIONHOURS
      FROM
         HumanResources.Employee
      WHERE
         NationalIDNumber = :EMPLOYEEID;
      RETURN VACATIONHOURS;
   END;
$$;
Copy
  • Chamador

Transact-SQL
 CREATE OR ALTER PROCEDURE GetVacationHours
   @employeeId INT,  
   @vacationHours INT OUTPUT
WITH EXECUTE AS CALLER
AS
BEGIN  
   SELECT @vacationHours = VacationHours 
   FROM HumanResources.Employee
   WHERE NationalIDNumber = @employeeID
END;
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE GetVacationHours (EMPLOYEEID INT, VACATIONHOURS INT)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
   BEGIN
      SELECT
         VacationHours
      INTO
         :VACATIONHOURS
      FROM
         HumanResources.Employee
      WHERE
         NationalIDNumber = :EMPLOYEEID;
      RETURN VACATIONHOURS;
   END;
$$;
Copy

Aviso

SELF e contextos de execução de usuários específicos («user_name») não são suportados no Snowflake Scripting.

READONLY AND VARYING PARAMETERS

O Snowflake não oferece suporte aos tipos de parâmetros READONLY e VARYING. Em vez disso, foi adicionado um FDM.

Transact-SQL
 CREATE OR ALTER PROCEDURE GetVacationHours
   @Param1 INT READONLY,  
   @Param2 INT VARYING
AS
BEGIN  
   SELECT * FROM Table1;
END;
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE GetVacationHours (PARAM1 INT !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'READONLY PARAMETERS' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!, PARAM2 INT !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'VARYING PARAMETERS' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!)
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
   DECLARE
      ProcedureResultSet RESULTSET;
   BEGIN
      ProcedureResultSet := (
      SELECT
         *
      FROM
         Table1);
      RETURN TABLE(ProcedureResultSet);
   END;
$$;
Copy

Problemas conhecidos

Argumentos opcionais não suportados

  • [VARYING] Aplica-se somente aos parâmetros cursor. Especifica o conjunto de resultados suportado como um parâmetro de saída. Esse parâmetro é construído dinamicamente pelo procedimento e seu conteúdo pode variar. O Snowflake Scripting não é compatível com CURSOR como um tipo de dados de retorno válido.

  • [= default] Torna um parâmetro opcional por meio da definição de um valor padrão. O Snowflake Scripting não suporta nativamente valores de parâmetros padrão.

  • [READONLY] Indica que o parâmetro não pode ser atualizado ou modificado no corpo do procedimento. Atualmente, não há suporte para o Snowflake Scripting.

  • [WITH RECOMPILE] Força o mecanismo de banco de dados a compilar o plano de consulta do procedimento armazenado sempre que ele for executado. Atualmente, não há suporte para o Snowflake Scripting.

  • [WITH ENCRYPTION] Usado para criptografar o texto de um procedimento armazenado. Somente usuários com acesso a tabelas do sistema ou arquivos de banco de dados (como usuários administradores do sistema) poderão acessar o texto do procedimento após sua criação. Atualmente, não há suporte para o Snowflake Scripting.

  • [FOR REPLICATION] Restringe o procedimento armazenado a ser executado somente durante a replicação. Atualmente, não há suporte para o Snowflake Scripting.

EWIS relacionados

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

  2. SSC-EWI-0058: No momento, a funcionalidade não é compatível com o Snowflake Scripting.

CURSOR

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

Descrição

As instruções Transact-SQL produzem um conjunto completo de resultados, mas há ocasiões em que os resultados são melhor processados uma linha de cada vez. A abertura de um cursor em um conjunto de resultados permite processar o conjunto de resultados uma linha de cada vez. Você pode atribuir um cursor a uma variável ou parâmetro com um tipo de dados cursor. Para obter mais informações, veja aqui.

 //ISO Syntax  
DECLARE cursor_name [ INSENSITIVE ] [ SCROLL ] CURSOR   
     FOR select_statement   
     [ FOR { READ ONLY | UPDATE [ OF column_name [ ,...n ] ] } ]  
[;]  

//Transact-SQL Extended Syntax  
DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ]   
     [ FORWARD_ONLY | SCROLL ]   
     [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]   
     [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]   
     [ TYPE_WARNING ]   
     FOR select_statement   
     [ FOR UPDATE [ OF column_name [ ,...n ] ] ]  
[;]  
Copy
 FETCH   
          [ [ NEXT | PRIOR | FIRST | LAST   
                    | ABSOLUTE { n | @nvar }   
                    | RELATIVE { n | @nvar }   
               ]   
               FROM   
          ]   
{ { [ GLOBAL ] cursor_name } | @cursor_variable_name }   
[ INTO @variable_name [ ,...n ] ] 
Copy
 OPEN { { [ GLOBAL ] cursor_name } | cursor_variable_name }  
Copy
 CLOSE { { [ GLOBAL ] cursor_name } | cursor_variable_name }
Copy
 DEALLOCATE { { [ GLOBAL ] cursor_name } | @cursor_variable_name }  
Copy

Amostra de padrões da origem

Transact-SQL

Observe que os parâmetros a seguir são inerentemente suportados pelo Snowflake Scripting.

  • [LOCAL].

  • \[FORWARD_ONLY].

  • [FAST_FORWARD] Especifica FORWARD_ONLY (somenteFETCH NEXT) e READ_ONLY

  • [READ_ONLY] o WHERE CURRENT OF não existe no Snowflake Scripting.

 CREATE TABLE vEmployee   (
    PersonID INT,
    LastName VARCHAR(255),
    FirstName VARCHAR(255),
);

INSERT INTO vEmployee(PersonID, LastName, FirstName) 
VALUES
    (1, 'AA', 'A'),
    (2, 'BB', 'B'),
    (3, 'CC', 'C'),
    (4, 'DD', 'D'),
    (5, 'EE', 'E'),
    (6, 'FF', 'F'),
    (7, 'GG', 'G');
	
CREATE OR ALTER PROCEDURE CursorExample
AS
    DECLARE 
        @CursorVar CURSOR, 
	@firstName VARCHAR;

    SET @CursorVar = CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY 
	FOR  
	SELECT FirstName
	FROM vEmployee;  

    OPEN @CursorVar;

    FETCH NEXT FROM @CursorVar INTO @firstName;
    FETCH NEXT FROM @CursorVar INTO @firstName;

    CLOSE @CursorVar;

    SELECT @firstName;
GO
Copy
B

Copy
Script Snowflake
 CREATE OR REPLACE TABLE vEmployee (
	PersonID INT,
	LastName VARCHAR(255),
	FirstName VARCHAR(255)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
;

INSERT INTO vEmployee (PersonID, LastName, FirstName)
VALUES
    (1, 'AA', 'A'),
    (2, 'BB', 'B'),
    (3, 'CC', 'C'),
    (4, 'DD', 'D'),
    (5, 'EE', 'E'),
    (6, 'FF', 'F'),
    (7, 'GG', 'G');

CREATE OR REPLACE PROCEDURE CursorExample ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
	DECLARE
		CURSORVAR CURSOR
		FOR
			SELECT FirstName
			FROM vEmployee;
		FIRSTNAME VARCHAR;
		ProcedureResultSet RESULTSET;
	BEGIN
		 
		 
		OPEN CURSORVAR;
		FETCH
			CURSORVAR
		INTO
			:FIRSTNAME;
		FETCH
			CURSORVAR
		INTO
			:FIRSTNAME;
		CLOSE CURSORVAR;
		ProcedureResultSet := (
		SELECT
			:FIRSTNAME);
		RETURN TABLE(ProcedureResultSet);
	END;
$$;
Copy
B

Copy

Problemas conhecidos

Não há suporte para os seguintes parâmetros:

DECLARE CURSOR

  • [ GLOBAL ] Permite fazer referência ao nome do cursor em qualquer procedimento armazenado ou lote executado pela conexão. O Snowflake Scripting só permite o uso do cursor localmente.

  • [ SCROLL ] O Snowflake Scripting suporta apenas FETCH NEXT.

  • [ KEYSET | DYNAMIC ] Se, após a abertura de um cursor, for feita uma atualização na tabela, essas opções poderão exibir algumas das alterações ao buscar o cursor. O Snowflake Scripting suporta apenas STATIC, ou seja, após a abertura do cursor, as alterações na tabela não são detectadas pelo cursor.

  • [SCROLL_LOCKS] Especifica que as atualizações ou exclusões posicionadas feitas por meio do cursor têm garantia de êxito; o Snowflake Scripting não pode garantir isso.

  • [OPTIMISTIC] Quando uma atualização ou exclusão é feita por meio do cursor, ele usa comparações de valores da coluna de carimbo de data/hora ou um valor de soma de verificação, se a tabela não tiver coluna de carimbo de data/hora, para determinar se a linha foi modificada depois de ter sido lida no cursor. O Snowflake Scripting não tem um processo interno para replicá-lo.

  • [TYPE_WARNING]

FETCH

  • [PRIOR | FIRST | LAST] O Snowscripting suporta apenas NEXT.

  • [ABSOLUTE] O Snowflake Scripting suporta apenas NEXT, mas o comportamento pode ser replicado.

  • [RELATIVE] Snowflake Scripting, mas o comportamento pode ser replicado.

  • [ GLOBAL ] Permite fazer referência ao nome do cursor em qualquer procedimento armazenado ou lote executado pela conexão. O Snowflake Scripting só permite o uso do cursor localmente.

  • FETCH sem INTO não é compatível.

  • Quando a instrução FETCH está localizada dentro de um loop, ela é considerada um padrão complexo, pois pode ter um impacto no desempenho do código convertido pelo Snowflake. Consulte a seção de problemas relacionados para obter mais informações.

Buscar amostra dentro do loop

 CREATE OR ALTER PROCEDURE cursor_procedure1
AS
BEGIN
DECLARE cursor1 CURSOR FOR SELECT col1 FROM my_table;
WHILE 1=0
   BEGIN
      FETCH NEXT FROM @cursor1 INTO @variable1;
   END
END;
Copy
 CREATE OR REPLACE PROCEDURE cursor_procedure1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
   DECLARE
      --** SSC-FDM-TS0013 - SNOWFLAKE SCRIPTING CURSOR ROWS ARE NOT MODIFIABLE **
      cursor1 CURSOR
      FOR
         SELECT
            col1
         FROM
            my_table;
   BEGIN
       
      WHILE (1=0) LOOP
         --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
         FETCH
            CURSOR1
            INTO
            :VARIABLE1;
      END LOOP;
   END;
$$;
Copy

OPEN

  • [ GLOBAL ] Permite fazer referência ao nome do cursor em qualquer procedimento armazenado ou lote executado pela conexão. O Snowflake Scripting só permite o uso do cursor localmente.

CLOSE

  • [ GLOBAL ] Permite fazer referência ao nome do cursor em qualquer procedimento armazenado ou lote executado pela conexão. O Snowflake Scripting só permite o uso do cursor localmente.

DEALLOCATED Remove uma referência de cursor e não há equivalente no Snowflake Scripting.

WHERE CURRENT OF o uso dessa instrução não é suportado, por exemplo:

 CREATE OR ALTER PROCEDURE CursorWithCurrent
AS
    DECLARE 
        @CursorVar CURSOR;

    SET @CursorVar = CURSOR 
	FOR  
	SELECT FirstName  
	FROM vEmployee;  

    OPEN @CursorVar;

    FETCH NEXT FROM @CursorVar;
    FETCH NEXT FROM @CursorVar;

    UPDATE vEmployee SET LastName = 'Changed' WHERE CURRENT OF @CursorVar;

    CLOSE @CursorVar;
GO
Copy

Variáveis de ambiente

  • @@CURSOR_ROWS

  • @@FETCH_STATUS

EWIs relacionados

  1. SSC-FDM-TS0013: As linhas de cursor do Snowflake Scripting não podem ser modificadas.

  2. SSC-PRF-0003: A busca dentro de um loop é considerada um padrão complexo, o que pode prejudicar o desempenho do Snowflake.

DECLARE

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Descrição

A instrução Transact-SQL DECLARE permite a criação de variáveis que podem ser usadas no escopo do lote ou de um procedimento armazenado. Para obter mais informações sobre Transact-SQL DECLARE, veja aqui.

 -- Syntax for SQL Server and Azure SQL Database  
  
DECLARE   
{   
    { @local_variable [AS] data_type  [ = value ] }  
  | { @cursor_variable_name CURSOR }  
} [,...n]   
| { @table_variable_name [AS] <table_type_definition> }   
  
<table_type_definition> ::=   
     TABLE ( { <column_definition> | <table_constraint> } [ ,...n] )   
  
<column_definition> ::=   
     column_name { scalar_data_type | AS computed_column_expression }  
     [ COLLATE collation_name ]   
     [ [ DEFAULT constant_expression ] | IDENTITY [ (seed ,increment ) ] ]   
     [ ROWGUIDCOL ]   
     [ <column_constraint> ]   
  
<column_constraint> ::=   
     { [ NULL | NOT NULL ]   
     | [ PRIMARY KEY | UNIQUE ]   
     | CHECK ( logical_expression )   
     | WITH ( <index_option > )  
     }   
  
<table_constraint> ::=   
     { { PRIMARY KEY | UNIQUE } ( column_name [ ,...n] )   
     | CHECK ( search_condition )   
     }
Copy

Amostra de padrões da origem

Declarar variáveis

As variáveis podem ser criadas de diferentes maneiras. As variáveis podem ou não ter um valor padrão e várias variáveis podem ser declaradas na mesma linha.

Observe que o Snowflake Scripting não permite a criação de mais de uma variável por linha.

Transact-SQL
 DECLARE @find VARCHAR(30);
DECLARE @find2 VARCHAR(30) = 'Default';
DECLARE @var VARCHAR(5), @var2 varchar(5);
Copy

Snowflake Scripting

 DECLARE
FIND VARCHAR(30);
FIND2 VARCHAR(30) := 'Default';
VAR VARCHAR(5);
VAR2 VARCHAR(5);
BEGIN
RETURN '';
END;
Copy

Declarar variáveis de tabela

O Transact-SQL permite a criação de variáveis de tabela que podem ser usadas como tabelas regulares. O Snowflake Scripting não suporta isso; em vez disso, uma tabela pode ser criada e descartada no final do procedimento.

Transact-SQL
 DECLARE @MyTableVar TABLE(  
    column1 varchar(10));
Copy

Snowflake Scripting

 BEGIN
    DECLARE
        T_MYTABLEVAR TABLE(
            column1 VARCHAR(10));
END;
Copy

Instrução DECLARE fora de rotinas (funções e procedimentos)

Ao contrário do Transact-SQL, o Snowflake não suporta a execução de instruções isoladas como DECLARE fora de rotinas como funções ou procedimentos. Para esse cenário, a instrução deve ser encapsulada em um bloco anônimo, conforme mostrado nos exemplos a seguir. Essa instrução geralmente é usada antes de um SET STATEMENT.

Transact-SQL
 DECLARE @Group nvarchar(50), @Sales MONEY;
SET @Group = N'North America';
SET @Sales = 2000000;
Copy

Snowflake Scripting

 DECLARE
_GROUP VARCHAR(50);
SALES NUMBER(38, 4);
BEGIN
_GROUP := 'North America';
SALES := 2000000;
END;
Copy

Se houver um cenário com apenas instruções DECLARE, o bloco BEGIN…END deverá ter uma instrução RETURN NULL para evitar erros, pois esse bloco não pode estar vazio.

Transact-SQL
 DECLARE @Group nvarchar(50), @Sales MONEY;
Copy

Snowflake Scripting

 DECLARE
_GROUP VARCHAR(50);
SALES NUMBER(38, 4);
BEGIN
RETURN '';
END;
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs relacionados

Sem EWIs relacionados.

EXECUTE

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

Descrição

A instrução Transact-SQL EXECUTE permite a execução de uma cadeia de comando ou cadeia de caracteres em um lote Transact-SQL, uma função definida pelo usuário com valor escalar ou um procedimento armazenado. Para obter mais informações sobre Transact-SQL EXECUTE, veja aqui.

 -- Execute a character string  
{ EXEC | EXECUTE }   
    ( { @string_variable | [ N ]'tsql_string' } [ + ...n ] )  
    [ AS { LOGIN | USER } = ' name ' ]  
[;]  

-- Execute a stored procedure or function  
[ { EXEC | EXECUTE } ]  
    {   
      [ @return_status = ]  
      { module_name [ ;number ] | @module_name_var }   
        [ [ @parameter = ] { value   
                           | @variable [ OUTPUT ]   
                           | [ DEFAULT ]   
                           }  
        ]  
      [ ,...n ]  
      [ WITH <execute_option> [ ,...n ] ]  
    }  
[;]  
Copy

Amostra de padrões da origem

Execução da cadeia de caracteres

EXECUTE pode ser usado para realizar operações SQL passadas diretamente como literais. No exemplo a seguir, ele é usado em um procedimento armazenado que insere um novo departamento de privacidade no banco de dados AdventureWorks2019.

Transact-SQL
 CREATE OR ALTER PROCEDURE AddPrivacyDepartment
AS 
EXECUTE ('INSERT INTO HumanResources.Department VALUES (''Privacy'', ''Executive General and Administration'', default)');
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE AddPrivacyDepartment ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
BEGIN
!!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
EXECUTE IMMEDIATE 'INSERT INTO HumanResources.Department VALUES ('Privacy', 'Executive General and Administration', default);';
END;
$$;
Copy

Execução do procedimento armazenado

EXECUTE também pode ser usado para chamar um procedimento armazenado existente. O exemplo a seguir chamará o procedimento AddPrivacyDepartment que foi criado acima. Em seguida, ele executará um SELECT para verificar se o novo departamento foi incluído com sucesso.

Transact-SQL
 EXECUTE AddPrivacyDepartment;
SELECT DepartmentID, Name, GroupName FROM HumanResources.Department; 
Copy
DepartmentID|Name                      |GroupName                           |ModifiedDate           |
------------+--------------------------+------------------------------------+-----------------------+
           1|Engineering               |Research and Development            |2008-04-30 00:00:00.000|
           2|Tool Design               |Research and Development            |2008-04-30 00:00:00.000|
           3|Sales                     |Sales and Marketing                 |2008-04-30 00:00:00.000|
           4|Marketing                 |Sales and Marketing                 |2008-04-30 00:00:00.000|
           5|Purchasing                |Inventory Management                |2008-04-30 00:00:00.000|
           6|Research and Development  |Research and Development            |2008-04-30 00:00:00.000|
           7|Production                |Manufacturing                       |2008-04-30 00:00:00.000|
           8|Production Control        |Manufacturing                       |2008-04-30 00:00:00.000|
           9|Human Resources           |Executive General and Administration|2008-04-30 00:00:00.000|
          10|Finance                   |Executive General and Administration|2008-04-30 00:00:00.000|
          11|Information Services      |Executive General and Administration|2008-04-30 00:00:00.000|
          12|Document Control          |Quality Assurance                   |2008-04-30 00:00:00.000|
          13|Quality Assurance         |Quality Assurance                   |2008-04-30 00:00:00.000|
          14|Facilities and Maintenance|Executive General and Administration|2008-04-30 00:00:00.000|
          15|Shipping and Receiving    |Inventory Management                |2008-04-30 00:00:00.000|
          16|Executive                 |Executive General and Administration|2008-04-30 00:00:00.000|
          17|Privacy                   |Executive General and Administration|2021-11-17 12:42:54.640|

Copy
Script Snowflake
 CALL AddPrivacyDepartment();

SELECT
DepartmentID,
Name,
GroupName
FROM
HumanResources.Department;
Copy
DEPARTMENTID|NAME                      |GROUPNAME                           |MODIFIEDDATE           |
------------+--------------------------+------------------------------------+-----------------------+
           1|Engineering               |Research and Development            |2021-11-17 10:29:36.963|
           2|Tool Design               |Research and Development            |2021-11-17 10:29:37.463|
           3|Sales                     |Sales and Marketing                 |2021-11-17 10:29:38.192|
           4|Marketing                 |Sales and Marketing                 |2021-11-17 10:29:38.733|
           5|Purchasing                |Inventory Management                |2021-11-17 10:29:39.298|
           6|Research and Development  |Research and Development            |2021-11-17 10:31:53.770|
           7|Production                |Manufacturing                       |2021-11-17 10:31:55.082|
           8|Production Control        |Manufacturing                       |2021-11-17 10:31:56.638|
           9|Human Resources           |Executive General and Administration|2021-11-17 10:31:57.507|
          10|Finance                   |Executive General and Administration|2021-11-17 10:31:58.473|
          11|Information Services      |Executive General and Administration|2021-11-17 10:34:35.200|
          12|Document Control          |Quality Assurance                   |2021-11-17 10:34:35.741|
          13|Quality Assurance         |Quality Assurance                   |2021-11-17 10:34:36.277|
          14|Facilities and Maintenance|Executive General and Administration|2021-11-17 10:34:36.832|
          15|Shipping and Receiving    |Inventory Management                |2021-11-17 10:34:37.373|
          16|Executive                 |Executive General and Administration|2021-11-17 10:34:37.918|
          17|Privacy                   |Executive General and Administration|2021-11-17 10:46:43.345|

Copy

Execução de variável local e uso de parâmetros

Um caso de uso comum para a instrução EXECUTE é quando são necessárias instruções SQL dinâmicas. Nesses casos, em vez de executar um literal de cadeia de caracteres, a instrução pode ser construída dinamicamente e atribuída a uma variável local, que será então executada. Um conjunto de argumentos pode ser enviado para o procedimento armazenado chamado para construir o comando dinâmico SQL.

No exemplo a seguir, é criado um procedimento armazenado SetNewPrice simples, que usa a instrução EXECUTE para definir um novo preço de produto com base nos argumentos enviados pelo chamador. Por fim, é realizado um SELECT para confirmar o novo preço do produto.

Transact-SQL
 CREATE OR ALTER PROCEDURE SetNewPrice @ProductID INT, @NewPrice MONEY
AS
  DECLARE @dynSqlStatement AS VARCHAR(300);
  SET @dynSqlStatement = 'UPDATE Production.ProductListPriceHistory SET ListPrice = ' + CAST(@NewPrice AS VARCHAR(10)) + ' WHERE ProductID = ' + CAST(@ProductID AS VARCHAR(10)) + ' AND EndDate IS NULL';
  EXECUTE (@dynSqlStatement);
GO

EXECUTE Set_New_Price @ProductID = 707, @NewPrice = 34.99;
SELECT ListPrice FROM Production.ProductListPriceHistory WHERE ProductID = 707 AND EndDate IS NULL;
Copy
ListPrice|
---------+
  34.9900|

Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE SetNewPrice (PRODUCTID INT, NEWPRICE NUMBER(38, 4))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    DYNSQLSTATEMENT VARCHAR(300);
  BEGIN
     
    DYNSQLSTATEMENT := 'UPDATE Production.ProductListPriceHistory
   SET
      ListPrice = ' || CAST(:NEWPRICE AS VARCHAR(10)) || '
   WHERE
      ProductID = ' || CAST(:PRODUCTID AS VARCHAR(10)) || '
      AND EndDate IS NULL;';
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE :DYNSQLSTATEMENT;
  END;
$$;

CALL Set_New_Price(707, 34.99);

SELECT
  ListPrice
FROM
  Production.ProductListPriceHistory
WHERE
  ProductID = 707 AND EndDate IS NULL;
Copy
LISTPRICE|
---------+
  34.9900|

Copy

Problemas conhecidos

Uso de códigos de retorno

A sintaxe do Transact-SQL EXECUTE contém o argumento opcional @return_status, que permite criar uma variável escalar para armazenar o status de retorno de uma função definida pelo usuário com valor escalar.

Ele também pode ser usado em procedimentos armazenados, embora o status de retorno seja limitado ao tipo de dados inteiro.

Para representar essa funcionalidade, poderíamos modificar um pouco o exemplo acima e criar uma função definida pelo usuário para calcular o preço do novo produto como uma média dos preços históricos. Em vez de passá-lo para o procedimento armazenado, poderíamos agora chamar a função CalculateAveragePrice para obter o novo preço e armazená-lo na variável de retorno para construir o SQL dinâmico.

Transact-SQL
 CREATE OR ALTER FUNCTION CalculateAveragePrice(@pid INT)
RETURNS MONEY
AS
BEGIN
  DECLARE @average AS MONEY;
  SELECT @average = AVG(LISTPRICE) FROM Production.ProductListPriceHistory WHERE ProductID = @pid;
  RETURN @average;
END;
GO

CREATE OR ALTER PROCEDURE SetNewPrice @ProductID INT
AS
  DECLARE @averageHistoricalPrice MONEY;
  EXECUTE @averageHistoricalPrice = [dbo].Calculate_Average_Price @pid=@ProductID;
  UPDATE Production.ProductListPriceHistory SET ListPrice = @averageHistoricalPrice WHERE ProductID =  @ProductID AND EndDate IS NULL;
GO

EXECUTE Set_New_Price @ProductID = 707;
SELECT ListPrice FROM Production.ProductListPriceHistory WHERE ProductID = 707 AND EndDate IS NULL;
Copy
ListPrice|
---------+
  34.0928|

Copy
Script Snowflake
 CREATE OR REPLACE FUNCTION CalculateAveragePrice (PID INT)
RETURNS NUMBER(38, 4)
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
AS
$$
  WITH CTE1 AS
  (
    SELECT
      AVG(LISTPRICE) AS AVERAGE FROM
      Production.ProductListPriceHistory
    WHERE
      ProductID = PID
  )
  SELECT
    AVERAGE
  FROM
    CTE1
$$;

CREATE OR REPLACE PROCEDURE SetNewPrice (PRODUCTID INT)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    AVERAGEHISTORICALPRICE NUMBER(38, 4);
  BEGIN
     
    CALL dbo.Calculate_Average_Price(:PRODUCTID);
    UPDATE Production.ProductListPriceHistory
      SET
        ListPrice = :AVERAGEHISTORICALPRICE
      WHERE
        ProductID = :PRODUCTID
        AND EndDate IS NULL;
  END;
$$;

CALL Set_New_Price(707);

SELECT
  ListPrice
FROM
  Production.ProductListPriceHistory
WHERE
  ProductID = 707 AND EndDate IS NULL;
Copy

Argumentos opcionais não suportados

  • @return_status

  • ;number

  • @module__name_v_ar

  • WITH RECOMPILE, WITH RESULT SETS NONE, WITH <definição do conjunto de resultados>

EWIs relacionados

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

IF

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Descrição

A cláusula IF permite que uma instrução SQL ou um bloco de instruções seja executado condicionalmente, desde que a expressão booliana seja verdadeira; caso contrário, as instruções da cláusula opcional ELSE serão executadas. O Transact-SQL também suporta a incorporação de várias cláusulas IF… ELSE caso sejam necessárias várias condições, ou a cláusula CASE também pode ser usada.

Para obter mais informações sobre o Transact-SQL IF…ELSE, veja aqui.

 IF Boolean_expression   
     { sql_statement | statement_block }   
[ ELSE   
     { sql_statement | statement_block } ]   
Copy

Observação: para definir um bloco de instruções, use as palavras-chave de controle de fluxo BEGIN e END.

Amostra de padrões de origem

Transact-SQL

O código a seguir refere-se a um IF… ELSE no Transact-SQL que condiciona a variável @value para identificar se ela é menor que 5, se está entre 5 e 10 ou se tem qualquer outro valor. Como @value é inicializado como 7, a segunda condição deve ser verdadeira e o resultado deve ser 200.

 CREATE OR ALTER PROCEDURE IfElseDemoProcedure
AS
    DECLARE @value INT;
    SET @value = 7;

    IF @value < 5
        SET @value = 100;
    ELSE IF @value >= 5 AND @value < 10
        BEGIN
            SET @value = 300;
            SET @value = @value - 100;
        END;
    ELSE  
        SET @value = -1;


    RETURN @value
GO


DECLARE @result INT;
EXEC @result = IfElseDemoProcedure;
PRINT @result;
Copy
 |result|
|------|
|200   |
Copy
Snowflake Scripting

Nota

Observe que, no Snowflake Scripting, a condição incorporada IF… ELSE é chamada de ELSEIF.

Além disso, a condição booliana é encapsulada entre parênteses, e a cláusula sempre termina com a expressão END IF.

Além disso, no Snowflake Scripting, não é necessário usar as palavras-chave BEGIN e END para definir um bloco de instruções, mas elas podem ser usadas se necessário.

 CREATE OR REPLACE PROCEDURE IfElseDemoProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        VALUE INT;
    BEGIN
         
        VALUE := 7;
        IF (:VALUE < 5) THEN
            VALUE := 100;
        ELSEIF (:VALUE >= 5 AND :VALUE < 10) THEN
            BEGIN
                VALUE := 300;
                VALUE := :VALUE - 100;
            END;
        ELSE
            VALUE := -1;
        END IF;
        RETURN :VALUE;
    END;
$$;

DECLARE
    RESULT INT;
BEGIN
    CALL IfElseDemoProcedure();
    !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'Print' NODE ***/!!!
    PRINT @result;
END;
Copy
|result|
|------|
|200   |

Copy

Instrução IF fora de rotinas (funções e procedimentos)

Ao contrário do Transact-SQL, o Snowflake não suporta a execução de instruções isoladas como IF…ELSE fora de rotinas como funções ou procedimentos. Para esse cenário, a instrução deve ser encapsulada em um bloco anônimo, conforme mostrado no exemplo a seguir. Você pode ler mais sobre como retornar corretamente os valores de saída na seção SELECT.

Transact-SQL
 DECLARE @maxWeight FLOAT, @productKey INTEGER  
SET @maxWeight = 100.00  
SET @productKey = 424  
IF @maxWeight <= 99  
    SELECT @productKey,  'This product is too heavy to ship and is only available for pickup.' 
ELSE  
    SELECT @productKey, 'This product is available for shipping or pickup.' 
Copy

Snowflake Scripting

 DECLARE
    MAXWEIGHT FLOAT;
    PRODUCTKEY INTEGER;
    BlockResultSet1 VARCHAR;
    BlockResultSet2 VARCHAR;
    return_arr ARRAY := array_construct();
BEGIN
    MAXWEIGHT := 100.00;
    PRODUCTKEY := 424;
    IF (:MAXWEIGHT <= 99) THEN
        BlockResultSet1 := 'RESULTSET_' || REPLACE(UPPER(UUID_STRING()), '-', '_');
        CREATE OR REPLACE TEMPORARY TABLE IDENTIFIER(:BlockResultSet1) AS
            SELECT
                :PRODUCTKEY,  'This product is too heavy to ship and is only available for pickup.';
        return_arr := array_append(return_arr, :BlockResultSet1);
    ELSE
        BlockResultSet2 := 'RESULTSET_' || REPLACE(UPPER(UUID_STRING()), '-', '_');
        CREATE OR REPLACE TEMPORARY TABLE IDENTIFIER(:BlockResultSet2) AS
            SELECT
                :PRODUCTKEY, 'This product is available for shipping or pickup.';
        return_arr := array_append(return_arr, :BlockResultSet2);
    END IF;
    --** SSC-FDM-0020 - MULTIPLE RESULT SETS ARE RETURNED IN TEMPORARY TABLES **
    RETURN return_arr;
END;
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs relacionados

  1. SSC-EWI-0073: Revisão de equivalência funcional pendente.

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

LABEL e GOTO

Applies to
  • [x] SQL Server

Descrição

O Snowflake SQL não é compatível com instruções GOTO LABEL. Atualmente, LABELS é comentado e um aviso é adicionado a todas as ocorrências.

Amostra de padrões de origem

Os exemplos a seguir detalham as instruções de transação BEGIN e COMMIT.

Transact-SQL

 CREATE PROCEDURE GoToProcedure
AS
BEGIN
DECLARE @TotalMaarks INT
SET @TotalMaarks = 49;
IF @TotalMaarks >= 50
    GOTO Pass
IF @TotalMaarks < 50
    GOTO Fail
Pass:
    SELECT 1;
    RETURN 1;
Fail:
    SELECT 2;
    RETURN 2;
END
Copy
Snowflake SQL
 CREATE OR REPLACE PROCEDURE GoToProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        TOTALMAARKS INT;
    BEGIN
         
        TOTALMAARKS := 49;
        IF (:TOTALMAARKS >= 50) THEN
            !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'GOTO' NODE ***/!!!
            GOTO Pass
        END IF;
        IF (:TOTALMAARKS < 50) THEN
            !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'GOTO' NODE ***/!!!
            GOTO Fail
        END IF;
        !!!RESOLVE EWI!!! /*** SSC-EWI-TS0045 - LABELED STATEMENT IS NOT SUPPORTED IN SNOWFLAKE SCRIPTING ***/!!!
        Pass:
        SELECT 1;
        RETURN 1;

        !!!RESOLVE EWI!!! /*** SSC-EWI-TS0045 - LABELED STATEMENT IS NOT SUPPORTED IN SNOWFLAKE SCRIPTING ***/!!!
        Fail:
        SELECT 2;
        RETURN 2;

    END;
$$;
Copy

Instrução LABEL e GOTO fora das rotinas (funções e procedimentos)

Transact-SQL

 CREATE TABLE T12(COL1 INT);
GOTO SecondStat
FirstStat:
    INSERT INTO T12 VALUES (1);
SecondStat:
    INSERT INTO T12 VALUES (2);
Copy

Snowflake Scripting

BEGIN
    CREATE OR REPLACE TABLE T12 (
        COL1 INT
    );
        !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'Goto' NODE ***/!!!
        GOTO SecondStat;
        !!!RESOLVE EWI!!! /*** SSC-EWI-TS0045 - LABELED STATEMENT IS NOT SUPPORTED IN SNOWFLAKE SCRIPTING ***/!!!
        FirstStat:
    INSERT INTO T12 VALUES (1);

        !!!RESOLVE EWI!!! /*** SSC-EWI-TS0045 - LABELED STATEMENT IS NOT SUPPORTED IN SNOWFLAKE SCRIPTING ***/!!!
        SecondStat:
    INSERT INTO T12 VALUES (2);

END;
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs relacionados

  1. SSC-EWI-TS0045: A instrução Labeled não é compatível com o Snowflake Scripting.

  2. SSC-EWI-0073: Revisão de equivalência funcional pendente.

OUTPUT PARAMETERS

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

Descrição

Um parâmetro de saída é um parâmetro cujo valor é passado para fora do procedimento armazenado, de volta para o bloco de chamada SQL. Como os parâmetros de saída não são compatíveis com o Snowflake Scripting, foi implementada uma solução para emular sua funcionalidade.

Amostra de padrões da origem

Parâmetro OUT único

O cenário mais básico para parâmetros OUT é quando o procedimento tem apenas um. Nesse caso, simplesmente retornamos o parâmetro OUT no final do corpo do procedimento.

O procedimento EXEC também precisa ser convertido. Para isso, é criado um CALL, os parâmetros são passados sem nenhum modificador («OUT» é removido) e, posteriormente, é feita uma atribuição para que o parâmetro seja associado ao respectivo valor resultante.

Transact-SQL
 -- Procedure with output parameter
CREATE PROCEDURE dbo.outmain
@name VARCHAR (255) OUTPUT
AS
SET @name = 'Jane';

-- Auxiliary procedure that calls the main procedure
CREATE PROCEDURE dbo.outaux
AS
DECLARE @name VARCHAR (255);
EXEC dbo.outmain
    @name = @name OUTPUT;
Copy
Script Snowflake
 -- Procedure with output parameter
CREATE OR REPLACE PROCEDURE dbo.outmain (NAME STRING)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        NAME := 'Jane';

        -- Auxiliary procedure that calls the main procedure
        !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'CREATE PROCEDURE' NODE ***/!!!
        CREATE PROCEDURE dbo.outaux
AS
DECLARE @name VARCHAR (255);
EXEC dbo.outmain
    @name = @name OUTPUT;
        RETURN NAME;
    END;
$$;
Copy

Múltiplos parâmetros OUT

Quando mais de um parâmetro OUT é encontrado, a cláusula RETURNS do procedimento muda para VARIANT. Isso é para acomodar o OBJECT_CONSTRUCT que será usado para armazenar os valores dos parâmetros OUT.

Além disso, uma instrução RETURN é adicionada ao final do corpo do procedimento. É aqui que o OBJECT_COSNTRUCT é criado e todos os valores de parâmetros do OUT são armazenados nele. Esse objeto será então usado pelo chamador para atribuir o valor dos parâmetros ao resultado correspondente.

Transact-SQL
 CREATE OR ALTER PROCEDURE basicProc (
    @col1 INT OUT,
    @col2 VARCHAR(10) OUT
) AS
BEGIN
    SET @col1 = 4;
    SET @col2 = 'test';
END;

CREATE OR ALTER PROCEDURE basicProcCall AS
BEGIN
    DECLARE @var1 INT = 0;
    DECLARE @var2 VARCHAR(10) = 'EMPTY';

    EXEC basicProc @var1 OUT, @var2 OUT;
    INSERT INTO TABLE1(col1, col2) VALUES (@var1, @var2);
END;

EXEC basicProcCall;
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE basicProc (COL1 INT, COL2 STRING)
RETURNS VARIANT
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        BEGIN
            COL1 := 4;
            COL2 := 'test';
        END;
        !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'CREATE PROCEDURE' NODE ***/!!!
        CREATE OR ALTER PROCEDURE basicProcCall AS
BEGIN
    DECLARE @var1 INT = 0;
    DECLARE @var2 VARCHAR(10) = 'EMPTY';

    EXEC basicProc @var1 OUT, @var2 OUT;
    INSERT INTO TABLE1(col1, col2) VALUES (@var1, @var2);
END;

EXEC basicProcCall;
        RETURN OBJECT_CONSTRUCT('COL1', :COL1, 'COL2', :COL2);
    END;
$$;
Copy

Parâmetros OUT e valores de retorno

O Transact-SQL permite que os procedimentos tenham valores de retorno. Quando um procedimento tem um valor de retorno e parâmetro(s) OUT, segue-se uma abordagem semelhante ao cenário Múltiplos parâmetros OUT. O valor de retorno original é tratado como um parâmetro OUT seria tratado, portanto, é armazenado dentro de OBJECT_CONSTRUCT e extraído dentro do procedimento do chamador.

Transact-SQL
 -- Procedure with multiple output parameters
CREATE PROCEDURE dbo.outmain
@name VARCHAR (255) OUTPUT
AS
SET @name = 'Jane';
RETURN 0;

-- Auxiliary procedure that calls the main procedure
CREATE PROCEDURE dbo.outaux
AS
DECLARE @name VARCHAR (255);
DECLARE @returnValue INT;
EXEC @returnValue = dbo.outmain
    @name = @name OUTPUT;
Copy
Script Snowflake
 -- Procedure with multiple output parameters
CREATE OR REPLACE PROCEDURE dbo.outmain (NAME STRING)
RETURNS VARIANT
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        NAME := 'Jane';
        RETURN OBJECT_CONSTRUCT('SC_RET_VALUE', 0, 'NAME', :NAME);

        -- Auxiliary procedure that calls the main procedure
        !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'CREATE PROCEDURE' NODE ***/!!!
        CREATE PROCEDURE dbo.outaux
AS
DECLARE @name VARCHAR (255);
DECLARE @returnValue INT;
EXEC @returnValue = dbo.outmain
    @name = @name OUTPUT;
    END;
$$;
Copy

Parâmetros de OUT para tipos de dados do cliente

Quando o parâmetro de saída é um tipo de cliente, o processo é semelhante ao de um tipo de dados normal.

Transact-SQL
 CREATE PROCEDURE procedure_udtype_out_params(
  @p_employee_id INT,
  @p_phone [dbo].[PhoneNumber] OUTPUT
) AS
BEGIN
  SELECT @p_phone = phone
  FROM employees
  WHERE employee_id = @p_employee_id;
END;
Copy
Script Snowflake
 CREATE OR REPLACE PROCEDURE procedure_udtype_out_params (P_EMPLOYEE_ID INT, P_PHONE VARIANT /*** SSC-FDM-TS0015 - DATA TYPE DBO.PHONENUMBER IS NOT SUPPORTED IN SNOWFLAKE ***/)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
  BEGIN
    SELECT
      phone
    INTO
      :P_PHONE
    FROM
      employees
    WHERE
      employee_id = :P_EMPLOYEE_ID;
    RETURN P_PHONE;
  END;
$$;
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs relacionados

  1. SSC-EWI-0073: Revisão de equivalência funcional pendente.

  2. SSC-FDM-TS0015: O tipo de dados não é compatível com o Snowflake.

SET

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Descrição

Define a variável local especificada, criada anteriormente com o uso da instrução DECLARE @local_variable, com o valor especificado. Para obter mais informações sobre o Transact-SQL SET, veja aqui.

Há quatro casos de SET, que são os seguintes:

 SET   
{ @local_variable  
    [ . { property_name | field_name } ] = { expression | udt_name { . | :: } method_name }  
}  
|  
{ @SQLCLR_local_variable.mutator_method  
}  
|  
{ @local_variable  
    {+= | -= | *= | /= | %= | &= | ^= | |= } expression  
}  
|   
  { @cursor_variable =   
    { @cursor_variable | cursor_name   
    | { CURSOR [ FORWARD_ONLY | SCROLL ]   
        [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]   
        [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]   
        [ TYPE_WARNING ]   
    FOR select_statement   
        [ FOR { READ ONLY | UPDATE [ OF column_name [ ,...n ] ] } ]   
      }   
    }  
}
Copy

Amostra de padrões de origem

Transact-SQL

 CREATE OR ALTER PROCEDURE SetProcedure
AS
    DECLARE @MyCounter INT;  
    DECLARE @FloatCounter FLOAT; 
	
    --Numerical operators
    SET @MyCounter = 3;  
    SET @MyCounter += 1;  --@MyCounter has 4
    SET @MyCounter -= 1;  --@MyCounter has 3
    SET @MyCounter *= 2;  --@MyCounter has 6
	
    SET @MyCounter /= 3;  --@MyCounter has 2
    SET @MyCounter = 6;  
    SET @MyCounter /= 5;  --@MyCounter has 1
    SET @MyCounter = 6;   
    SET @MyCounter /= 7;  --@MyCounter has 0
    SET @FloatCounter = 10;
    SET @FloatCounter /= 4;  --@FloatCounter has 2.5
    
    SET @MyCounter = 6;   
    SET @MyCounter %= 4;  --@MyCounter has 2
	
    --Logical operators
    SET @MyCounter &= 3;  --@MyCounter has 2
    SET @MyCounter ^= 2;  --@MyCounter has 0
    SET @MyCounter |= 0;  --@MyCounter has 0
		
    RETURN @MyCounter;
GO

DECLARE @result INT;
EXEC @result = SetProcedure;
PRINT @result;
Copy
 CREATE TABLE vEmployee (
    PersonID int,
    LastName varchar(255),
    FirstName varchar(255)
);

CREATE OR ALTER PROCEDURE SetCursor
AS
    DECLARE @CursorVar CURSOR; 
	
    SET @CursorVar = CURSOR SCROLL DYNAMIC  
        FOR  
	SELECT LastName, FirstName  
	FROM vEmployee  
	WHERE LastName like 'B%'; 
GO	
Copy
|Result   |
|---------|
|0        |

Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE SetProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        MYCOUNTER INT;
        FLOATCOUNTER FLOAT;
    BEGIN
         
         

        --Numerical operators
        MYCOUNTER := 3;
        MYCOUNTER := MYCOUNTER + 1;  --@MyCounter has 4

        MYCOUNTER := MYCOUNTER - 1;  --@MyCounter has 3

        MYCOUNTER := MYCOUNTER * 2;  --@MyCounter has 6

        MYCOUNTER := TRUNC(MYCOUNTER / 3);  --@MyCounter has 2

        MYCOUNTER := 6;
        MYCOUNTER := TRUNC(MYCOUNTER / 5);  --@MyCounter has 1

        MYCOUNTER := 6;
        MYCOUNTER := TRUNC(MYCOUNTER / 7);  --@MyCounter has 0

        FLOATCOUNTER := 10;
        FLOATCOUNTER := FLOATCOUNTER / 4;  --@FloatCounter has 2.5

        MYCOUNTER := 6;
        MYCOUNTER := MYCOUNTER % 4;  --@MyCounter has 2

    --Logical operators
        MYCOUNTER := BITAND(MYCOUNTER, 3);  --@MyCounter has 2

        MYCOUNTER := BITXOR(MYCOUNTER, 2);  --@MyCounter has 0

        MYCOUNTER := BITOR(MYCOUNTER, 0);  --@MyCounter has 0

        RETURN :MYCOUNTER;
    END;
$$;

DECLARE
    RESULT INT;
BEGIN
    CALL SetProcedure();
    !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'Print' NODE ***/!!!
    PRINT @result;
END;
Copy
 CREATE OR REPLACE TABLE vEmployee (
	PersonID INT,
	LastName VARCHAR(255),
	FirstName VARCHAR(255)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
;

CREATE OR REPLACE PROCEDURE SetCursor ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
	DECLARE
		!!!RESOLVE EWI!!! /*** SSC-EWI-TS0037 - SNOWFLAKE SCRIPTING CURSORS ARE NON-SCROLLABLE, ONLY FETCH NEXT IS SUPPORTED ***/!!!
		--** SSC-FDM-TS0013 - SNOWFLAKE SCRIPTING CURSOR ROWS ARE NOT MODIFIABLE **
		CURSORVAR CURSOR
		FOR
			SELECT LastName, FirstName
			FROM vEmployee
			WHERE LastName like 'B%';
	BEGIN
		 
		 
		RETURN '';
	END;
$$;
Copy
|Result   |
|---------|
|0        |

Copy

Instrução SET fora de rotinas (funções e procedimentos)

Ao contrário do Transact-SQL, o Snowflake não suporta a execução de instruções isoladas como SET fora de rotinas como funções ou procedimentos. Para esse cenário, a instrução deve ser encapsulada em um bloco anônimo, conforme mostrado nos exemplos a seguir. Essa instrução geralmente é usada depois de DECLARE STATEMENT.

Transact-SQL
 DECLARE @Group nvarchar(50), @Sales MONEY;
SET @Group = N'North America';
SET @Sales = 2000000;
Copy

Snowflake Scripting

 DECLARE
_GROUP VARCHAR(50);
SALES NUMBER(38, 4);
BEGIN
_GROUP := 'North America';
SALES := 2000000;
END;
Copy

Se houver um cenário com apenas instruções SET, o bloco DECLARE não será necessário. Provavelmente, esse cenário produzirá erros de tempo de execução se houver uma tentativa de definir um valor para uma variável que não foi declarada.

Transact-SQL
 SET @Group = N'North America';
Copy

Snowflake Scripting

 BEGIN
_GROUP := 'North America';
END;
Copy

Problemas conhecidos

1. SET of a local variable with property name

No momento, esse tipo de conjunto não é compatível com o Snowflake Scripting.

 // TSQL custom data type with properties example 
DECLARE @p Point;  
SET @p.X = @p.X + 1.1;  
Copy
2. SET of a local variable with mutator method

No momento, esse tipo de conjunto não é compatível com o Snowflake Scripting.

 // TSQL custom data type with mutator method
SET @p.SetXY(22, 23);   
Copy

EWIs relacionados

  1. SSC-EWI-TS0037: Os cursores do Snowflake Scripting não podem ser rolados.

  2. SSC-EWI-0073: Revisão de equivalência funcional pendente.

  3. SSC-FDM-TS0013: As linhas de cursor do Snowflake Scripting não podem ser modificadas.

TRY CATCH

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Descrição

Implementa o tratamento de erros para o Transact SQL. Um grupo de instruções Transact-SQL pode ser incluído em um bloco TRY. Se ocorrer um erro no bloco TRY, o controle geralmente é passado para outro grupo de instruções que está incluído em um bloco CATCH.

Amostra de padrões de origem

O exemplo a seguir detalha a transformação para TRY CATCH dentro de procedimentos.

Transact-SQL

 CREATE PROCEDURE ERROR_HANDLING_PROC
AS
BEGIN
    BEGIN TRY  
        -- Generate divide-by-zero error.  
        SELECT 1/0;  
    END TRY  
    BEGIN CATCH  
        -- Execute error retrieval routine.  
        SELECT 'error';
    END CATCH;   
END;
Copy
|error    |

Copy
Snowflake SQL
 CREATE OR REPLACE PROCEDURE ERROR_HANDLING_PROC ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        BEGIN
            -- Generate divide-by-zero error.  
            SELECT
                TRUNC( 1/0);
        EXCEPTION
            WHEN OTHER THEN
                -- Execute error retrieval routine.  
                SELECT 'error';
        END;
    END;
$$;
Copy
|error    |

Copy

Tentar capturar rotinas externas (funções e procedimentos)

Transact-SQL

 BEGIN TRY  
    SELECT 1/0;  
END TRY  
BEGIN CATCH  
    SELECT 'error';
END CATCH;
Copy

Snowflake Scripting

 DECLARE
    BlockResultSet1 VARCHAR;
    BlockResultSet2 VARCHAR;
    return_arr ARRAY := array_construct();
BEGIN
    BEGIN
        BlockResultSet1 := 'RESULTSET_' || REPLACE(UPPER(UUID_STRING()), '-', '_');
        CREATE OR REPLACE TEMPORARY TABLE IDENTIFIER(:BlockResultSet1) AS
            SELECT
                TRUNC( 1/0);
        return_arr := array_append(return_arr, :BlockResultSet1);
    EXCEPTION
        WHEN OTHER THEN
            BlockResultSet2 := 'RESULTSET_' || REPLACE(UPPER(UUID_STRING()), '-', '_');
            CREATE OR REPLACE TEMPORARY TABLE IDENTIFIER(:BlockResultSet2) AS
                SELECT 'error';
            return_arr := array_append(return_arr, :BlockResultSet2);
    END;
    --** SSC-FDM-0020 - MULTIPLE RESULT SETS ARE RETURNED IN TEMPORARY TABLES **
    RETURN return_arr;
END;
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs relacionados

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

WHILE

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Descrição

O comando While permite que uma instrução SQL ou um bloco de comandos seja executado repetidamente, desde que a condição especificada seja verdadeira. A execução das instruções no loop WHILE pode ser controlada de dentro do loop com as palavras-chave BREAK e CONTINUE.

Para obter mais informações sobre o Transact-SQL While, veja aqui.

 WHILE Boolean_expression   
     { sql_statement | statement_block | BREAK | CONTINUE }
Copy

Observação: para definir um bloco de instruções, use as palavras-chave de controle de fluxo BEGIN e END.

Amostra de padrões de origem

Código padrão de origem básico

Transact-SQL

O código a seguir refere-se a um While Loop no Transact-SQL que itera a variável @Iteration e controla o fluxo do loop para encerrar quando o valor de @Iteration for igual a 10.

Nota

As instruções após a palavra-chave CONTINUE não serão executadas.

 CREATE OR ALTER PROCEDURE WhileDemoProcedure
AS
    DECLARE @iteration INT;
    SET @iteration = 1;
    
    WHILE @iteration < 100
    BEGIN
        IF @iteration = 10
            BREAK;
        ELSE
            BEGIN
                SET @iteration = @iteration + 1;
                CONTINUE;
                SET @iteration = 2 * @iteration;
            END;
    END;
    RETURN @iteration;
GO



DECLARE @result INT;
EXEC @result = WhileDemoProcedure;
PRINT @result;
Copy
|iteration|
|---------|
|10       |

Copy
Snowflake Scripting

Nota

Assim como no Transact-SQL, no Snowflake Scripting as instruções após a palavra-chave CONTINUE não serão executadas.

Observe que, no Snowflake Scripting, não é necessário usar as palavras-chave BEGIN e END para definir um bloco de instruções, mas isso pode ser usado se necessário.

CREATE OR REPLACE PROCEDURE WhileDemoProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        ITERATION INT;
    BEGIN
         
        ITERATION := 1;
        WHILE (:ITERATION &#x3C; 100) LOOP
            IF (:ITERATION = 10) THEN
                BREAK;
            ELSE
                BEGIN
                    ITERATION := :ITERATION + 1;
                    CONTINUE;
                    ITERATION := 2 * :ITERATION;
                END;
            END IF;
        END LOOP;
        RETURN :ITERATION;
    END;
$$;

DECLARE
    RESULT INT;
BEGIN
    CALL WhileDemoProcedure();
    !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'Print' NODE ***/!!!
    PRINT @result;
END;
Copy

O Snowflake Scripting permite usar a palavra-chave LOOP em vez de DO e a expressão END LOOP em vez de END WHILE.

 WHILE (Boolean_expression) LOOP
    -- statement or statement block
END LOOP;
Copy
|Iteration|
|---------|
|10       |

Copy

While com padrão de origem de corpo vazio

Transact-SQL

Nota

Observe que este exemplo foi escrito quando não havia suporte para a instrução IF ELSE. As diferenças nos resultados devem desaparecer quando o suporte para a instrução for implementado.

 CREATE OR ALTER PROCEDURE WhileEmptyBodyProc
AS
BEGIN
    DECLARE @MyVar INT;
    SET @MyVar = 1;
    WHILE (@MyVar < 100)
        BEGIN
            IF @MyVar < 50
                SET @MyVar *= 5;
            ELSE
                SET @MyVar *= 3;
        END;
    RETURN @MyVar;
END;

DECLARE @result INT;
EXEC @result = WhileEmptyBodyProc;
PRINT @result;
Copy
|result|
|------|
|125   |

Copy
Script Snowflake

Esse comando não pode ter um corpo vazio no Snowflake Scripting. Para resolver esse caso, um comando BREAK padrão é adicionado quando um corpo vazio é detectado.

 CREATE OR REPLACE PROCEDURE WhileEmptyBodyProc ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        MYVAR INT;
        RESULT INT;
    BEGIN
        BEGIN
             
            MYVAR := 1;
            WHILE (:MYVAR < 100) LOOP
                IF (:MYVAR < 50) THEN
                    MYVAR := MYVAR * 5;
                ELSE
                    MYVAR := MYVAR * 3;
                END IF;
            END LOOP;
            RETURN :MYVAR;
        END;
         
        CALL WhileEmptyBodyProc();
        !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'PRINT' NODE ***/!!!
        PRINT @result;
    END;
$$;
Copy
|result|
|------|
|1     |

Copy

Instrução WHILE fora de rotinas (funções e procedimentos)

Ao contrário do Transact-SQL, o Snowflake não suporta a execução de instruções isoladas como WHILE fora de rotinas como funções ou procedimentos. Para esse cenário, a instrução deve ser encapsulada em um bloco anônimo, conforme mostrado no exemplo a seguir.

Transact-SQL
 DECLARE @iteration INT;
SET @iteration = 1;
 
WHILE @iteration < 100
BEGIN
    IF @iteration = 10
        BREAK;
    ELSE
        BEGIN
            SET @iteration = @iteration + 1;
            CONTINUE;
            SET @iteration = 2 * @iteration;
        END;
    END;
Copy

Snowflake Scripting

 DECLARE
    ITERATION INT;
BEGIN
    ITERATION := 1;
    WHILE (:ITERATION < 100) LOOP
        IF (:ITERATION = 10) THEN
            BREAK;
        ELSE
            BEGIN
                ITERATION := :ITERATION + 1;
                CONTINUE;
                ITERATION := 2 * :ITERATION;
            END;
        END IF;
    END LOOP;
END;
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs relacionados

  1. SSC-EWI-0073: Revisão de equivalência funcional pendente.