SnowConvert: DMLs do Transact

Between

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

Código-fonte

 -- Additional Params: -t JavaScript
CREATE PROCEDURE ProcBetween
AS
BEGIN
declare @aValue int = 1;
IF(@aValue BETWEEN 1 AND 2)
   return 1
END;
GO
Copy

Código esperado

 CREATE OR REPLACE PROCEDURE ProcBetween ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
   // SnowConvert Helpers Code section is omitted.

   let AVALUE = 1;
   if (SELECT(`   ? BETWEEN 1 AND 2`,[AVALUE])) {
      return 1;
   }
$$;
Copy

Problemas conhecidos

Não foram encontrados problemas.

Bulk Insert

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

A conversão direta para BULK INSERT é a instrução do Snowflake COPY INTO. COPY INTO não usa diretamente o caminho do arquivo para recuperar os valores. O arquivo deve existir antes em um STAGE. Além disso, as opções usadas em BULK INSERT devem ser especificadas em um Snowflake FILE FORMAT que será consumido pelo STAGE ou diretamente pelo COPY INTO.

Para adicionar um arquivo a algum STAGE, você deve usar o comando PUT . Observe que o comando só pode ser executado a partir do SnowSQL CLI. Aqui está um exemplo das etapas que devemos seguir antes de executar um COPY INTO:

 -- Additional Params: -t JavaScript
CREATE PROCEDURE PROCEDURE_SAMPLE
AS

CREATE TABLE #temptable  
 ([col1] varchar(100),  
  [col2] int,  
  [col3] varchar(100))  

BULK INSERT #temptable FROM 'C:\test.txt'  
WITH   
(  
   FIELDTERMINATOR ='\t',  
   ROWTERMINATOR ='\n'
); 

GO
Copy
 CREATE OR REPLACE FILE FORMAT FILE_FORMAT_638434968243607970
FIELD_DELIMITER = '\t'
RECORD_DELIMITER = '\n';

CREATE OR REPLACE STAGE STAGE_638434968243607970
FILE_FORMAT = FILE_FORMAT_638434968243607970;

--** SSC-FDM-TS0004 - PUT STATEMENT IS NOT SUPPORTED ON WEB UI. YOU SHOULD EXECUTE THE CODE THROUGH THE SNOWFLAKE CLI **
PUT file://C:\test.txt @STAGE_638434968243607970 AUTO_COMPRESS = FALSE;

CREATE OR REPLACE PROCEDURE PROCEDURE_SAMPLE ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
 // SnowConvert Helpers Code section is omitted.

 EXEC(`CREATE OR REPLACE TEMPORARY TABLE T_temptable
(
   col1 VARCHAR(100),
   col2 INT,
   col3 VARCHAR(100))`);
 EXEC(`COPY INTO T_temptable FROM @STAGE_638434968243607970/test.txt`);
$$
Copy

Como você vê no código acima, o SnowConvert identifica todos os BULK INSERTS no código e, para cada instância, um novo STAGE e FILE FORMAT serão criados antes da cópia em execução. Além disso, após a criação do STAGE, um comando PUT também será criado para adicionar o arquivo ao estágio.

Os nomes das instruções geradas são gerados automaticamente usando o carimbo de data/hora atual em segundos, a fim de evitar colisões entre seus usos.

Por fim, todas as opções para a inserção em massa estão sendo mapeadas para opções de formato de arquivo, se aplicável. Se a opção não for compatível com o Snowflake, ela será comentada e um aviso será adicionado. Consulte também SSC-FDM-TS0004.

Opções de massa suportadas

SQL Server

Snowflake

FORMAT

TYPE

FIELDTERMINATOR

FIELD_DELIMITER

FIRSTROW

SKIP_HEADER

ROWTERMINATOR

RECORD_DELIMITER

FIELDQUOTE

FIELD_OPTIONALLY_ENCLOSED_BY

EWIs relacionados

  1. SSC-FDM-TS0004: PUT STATEMENT IS NOT SUPPORTED ON WEB UI.

Expressão de tabela comum (CTE)

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

As expressões de tabela comuns são compatíveis com o Snowflake SQL por padrão.

Sintaxe do Snowflake SQL

Subconsulta:

 [ WITH
       <cte_name1> [ ( <cte_column_list> ) ] AS ( SELECT ...  )
   [ , <cte_name2> [ ( <cte_column_list> ) ] AS ( SELECT ...  ) ]
   [ , <cte_nameN> [ ( <cte_column_list> ) ] AS ( SELECT ...  ) ]
]
SELECT ...
Copy

CTE recursivo:

 [ WITH [ RECURSIVE ]
       <cte_name1> ( <cte_column_list> ) AS ( anchorClause UNION ALL recursiveClause )
   [ , <cte_name2> ( <cte_column_list> ) AS ( anchorClause UNION ALL recursiveClause ) ]
   [ , <cte_nameN> ( <cte_column_list> ) AS ( anchorClause UNION ALL recursiveClause ) ]
]
SELECT ...
Copy

Onde:

 anchorClause ::=
     SELECT <anchor_column_list> FROM ...

 recursiveClause ::=
     SELECT <recursive_column_list> FROM ... [ JOIN ... ]
Copy

Detalhes dignos de nota

A palavra-chave RECURSIVE não existe em T-SQL, e a transformação não adiciona ativamente a palavra-chave ao resultado. Um aviso é adicionado ao código de saída para indicar esse comportamento.

Expressão de tabela comum com SELECT INTO

A transformação a seguir ocorre quando a expressão WITH é seguida por uma instrução SELECT INTO e será transformada em uma expressão TEMPORARY TABLE.

SQL Server:

 WITH ctetable(col1, col2) AS
    (
        SELECT	col1, col2 FROM	t1 poh WHERE poh.col1 = 16 and poh.col2 = 4
    ),
    employeeCte AS
    (
	SELECT BUSINESSENTITYID, VACATIONHOURS FROM employee WHERE BUSINESSENTITYID = (SELECT col1 FROM ctetable)
    ),
    finalCte AS
    (
        SELECT BUSINESSENTITYID, VACATIONHOURS FROM employeeCte  
    ) SELECT * INTO #table2 FROM finalCte;

SELECT * FROM #table2;
Copy

Snowflake:

 CREATE OR REPLACE TEMPORARY TABLE T_table2 AS
	WITH ctetable (
		col1,
		col2
	) AS
		   (
		       SELECT
		   		col1,
		   		col2
		       FROM
		   		t1 poh
		       WHERE
		   		poh.col1 = 16 and poh.col2 = 4
		   ),
		   		employeeCte AS
		   		    (
		   			SELECT
		   		BUSINESSENTITYID,
		   		VACATIONHOURS
		       FROM
		   		employee
		       WHERE
		   		BUSINESSENTITYID = (SELECT
		   						col1
		   					FROM
		   						ctetable
		   		)
		   		    ),
		   		finalCte AS
		   		    (
		   		        SELECT
		   		BUSINESSENTITYID,
		   		VACATIONHOURS
		       FROM
		   		employeeCte
		   		    )
		   		SELECT
		       *
		       FROM
		       finalCte;

		       SELECT
		       *
		       FROM
		       T_table2;
Copy

Expressão de tabela comum com outras expressões

A transformação a seguir ocorre quando a expressão WITH é seguida por instruções INSERT ou DELETE.

SQL Server:

 WITH CTE AS( SELECT * from table1)
INSERT INTO Table2 (a,b,c,d)
SELECT a,b,c,d
FROM CTE
WHERE e IS NOT NULL;
Copy

Snowflake:

 INSERT INTO Table2 (a, b, c, d)
WITH CTE AS( SELECT
*
from
table1
)
SELECT
a,
b,
c,
d
FROM
CTE AS CTE
WHERE
e IS NOT NULL;
Copy

Expressão de tabela comum com Delete From

Para essa transformação, ela só se aplicará a uma CTE (Expressão de tabela comum) com um Delete From, no entanto, somente para algumas especificidades CTE. Ele deve ter apenas um CTE, e deve ter dentro dele uma função de ROW_NUMBER ou RANK.

O objetivo do CTE com Delete deve ser remover duplicatas de uma tabela. Caso o CTE com Delete pretenda remover outro tipo de dados, essa transformação não se aplicará.

Vejamos um exemplo. Para um exemplo prático, precisamos primeiro criar uma tabela com alguns dados.

 CREATE TABLE WithQueryTest
(
    ID BIGINT,
    Value BIGINT,
    StringValue NVARCHAR(258)
);

Insert into WithQueryTest values(100, 100, 'First');
Insert into WithQueryTest values(200, 200, 'Second');
Insert into WithQueryTest values(300, 300, 'Third');
Insert into WithQueryTest values(400, 400, 'Fourth');
Insert into WithQueryTest values(100, 100, 'First');
Copy

Observe que há um valor duplicado. As linhas 8 e 12 inserem o mesmo valor. Agora vamos eliminar as linhas duplicadas em uma tabela.

 WITH Duplicated AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) AS RN
FROM WithQueryTest
)
DELETE FROM Duplicated
WHERE Duplicated.RN > 1
Copy

Se executarmos um Select da tabela, ele mostrará o seguinte resultado

Observe que não há linhas duplicadas. Para conservar a funcionalidade desses CTE com Delete no Snowflake, ele será transformado em

 CREATE OR REPLACE TABLE PUBLIC.WithQueryTest AS SELECT
*
FROM PUBLIC.WithQueryTest
QUALIFY ROW_NUMBER()
OVER (PARTITION BY ID ORDER BY ID) = 1 ;
Copy

Como você pode ver, a consulta é transformada em uma tabela Create Or Replace.

Vamos testá-la no Snowflake. Para testá-la, precisamos da tabela também.

 CREATE OR REPLACE TABLE PUBLIC.WithQueryTest
(
ID BIGINT,
Value BIGINT,
StringValue VARCHAR(258)
);

Insert into PUBLIC.WithQueryTest values(100, 100, 'First');
Insert into PUBLIC.WithQueryTest values(200, 200, 'Second');
Insert into PUBLIC.WithQueryTest values(300, 300, 'Third');
Insert into PUBLIC.WithQueryTest values(400, 400, 'Fourth');
Insert into PUBLIC.WithQueryTest values(100, 100, 'First');
Copy

Agora, se executarmos o resultado da transformação e, em seguida, um Select para verificar se as linhas duplicadas foram excluídas, este será o resultado.

Expressão de tabela comum com a instrução MERGE

A seguinte transformação ocorre quando a expressão WITH é seguida pela instrução MERGE e será transformada em uma expressão MERGE INTO.

SQL Server:

 WITH ctetable(col1, col2) as 
    (
        SELECT col1, col2
        FROM t1 poh
        where poh.col1 = 16 and poh.col2 = 88
    ),
    finalCte As
    (
        SELECT col1 FROM ctetable  
    )  
    MERGE  
  table1 AS target
  USING finalCte AS source  
  ON (target.ID = source.COL1)
  WHEN MATCHED THEN UPDATE SET target.ID = source.Col1
  WHEN NOT MATCHED THEN INSERT (ID, col1) VALUES (source.COL1, source.COL1 );
Copy

Snowflake:

 MERGE INTO table1 AS target
USING (
  --** SSC-PRF-TS0001 - PERFORMANCE WARNING - RECURSION FOR CTE NOT CHECKED. MIGHT REQUIRE RECURSIVE KEYWORD **
  WITH ctetable (
    col1,
    col2
  ) as
       (
           SELECT
           col1,
           col2
           FROM
           t1 poh
           where
           poh.col1 = 16 and poh.col2 = 88
       ),
           finalCte As
               (
                   SELECT
           col1
           FROM
           ctetable
               )
           SELECT
           *
           FROM
           finalCte
) AS source
ON (target.ID = source.COL1)
WHEN MATCHED THEN
           UPDATE SET
           target.ID = source.Col1
WHEN NOT MATCHED THEN
           INSERT (ID, col1) VALUES (source.COL1, source.COL1);
Copy

Expressão de tabela comum com a instrução UPDATE

A transformação a seguir ocorre quando a expressão WITH é seguida por uma instrução UPDATE e será transformada em uma instrução UPDATE.

SQL Server:

 WITH ctetable(col1, col2) AS 
    (
        SELECT col1, col2
        FROM table2 poh
        WHERE poh.col1 = 5 and poh.col2 = 4
    )
UPDATE tab1
SET ID = 8, COL1 = 8
FROM table1 tab1
INNER JOIN ctetable CTE ON tab1.ID = CTE.col1;
Copy

Snowflake:

 UPDATE dbo.table1 tab1
    SET
        ID = 8,
        COL1 = 8
    FROM
        (
            WITH ctetable (
                col1,
                col2
            ) AS
                   (
                       SELECT
                           col1,
                           col2
                       FROM
                           table2 poh
                       WHERE
                           poh.col1 = 5 and poh.col2 = 4
                   )
                   SELECT
                       *
                   FROM
                       ctetable
        ) AS CTE
    WHERE
        tab1.ID = CTE.col1;
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs relacionados

  1. SSC-EWI-0108: A subconsulta a seguir corresponde a pelo menos um dos padrões considerados inválidos e pode produzir erros de compilação.

  2. SSC-PRF-TS0001: Aviso de desempenho - recursão para CTE não verificada. Pode exigir uma palavra-chave recursiva.

Delete

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

Remove uma ou mais linhas de uma tabela ou visualização no SQL Server. Para obter mais informações sobre o SQL Server Delete, veja aqui.

 [ WITH <common_table_expression> [ ,...n ] ]  
DELETE   
    [ TOP ( expression ) [ PERCENT ] ]   
    [ FROM ]   
    { { table_alias  
      | <object>   
      | rowset_function_limited   
      [ WITH ( table_hint_limited [ ...n ] ) ] }   
      | @table_variable  
    }  
    [ <OUTPUT Clause> ]  
    [ FROM table_source [ ,...n ] ]   
    [ WHERE { <search_condition>   
            | { [ CURRENT OF   
                   { { [ GLOBAL ] cursor_name }   
                       | cursor_variable_name   
                   }   
                ]  
              }  
            }   
    ]   
    [ OPTION ( <Query Hint> [ ,...n ] ) ]   
[; ]  
  
<object> ::=  
{   
    [ server_name.database_name.schema_name.   
      | database_name. [ schema_name ] .   
      | schema_name.  
    ]  
    table_or_view_name   
}  
Copy

Amostra de padrões de origem

A transformação para a instrução DELETE é bastante simples, com algumas ressalvas. Uma dessas ressalvas é a forma como o Snowflake oferece suporte a várias fontes na cláusula FROM. No entanto, há um equivalente no Snowflake, conforme mostrado abaixo.

SQL Server

 DELETE T1 FROM TABLE2 T2, TABLE1 T1 WHERE T1.ID = T2.ID
Copy

Snowflake

 DELETE FROM
TABLE1 T1
USING TABLE2 T2
WHERE
T1.ID = T2.ID;
Copy

Nota

Observe que, como o DELETE original era para T1, a presença de TABLE2 T2 na cláusula FROM exige a criação da cláusula USING.

Excluir duplicatas de uma tabela

A documentação a seguir explica um padrão comum usado para remover linhas duplicadas de uma tabela no SQL Server. Essa abordagem usa a função ROW_NUMBER para particionar os dados com base no key_value, que pode ser uma ou mais colunas separadas por vírgulas. Em seguida, exclua todos os registros que receberam um valor de número de linha maior que 1. Esse valor indica que os registros são duplicados. Você pode ler a documentação referenciada para entender o comportamento desse método e recriá-lo.

DELETE T
FROM
(
SELECT *
, DupRank = ROW_NUMBER() OVER (
              PARTITION BY key_value
              ORDER BY ( {expression} )
            )
FROM original_table
) AS T
WHERE DupRank > 1 

Copy

O exemplo a seguir usa essa abordagem para remover duplicatas de uma tabela e seu equivalente no Snowflake. A transformação consiste em executar uma instrução INSERT OVERWRITE que trunca a tabela (remove todos os dados) e, em seguida, insere novamente as linhas na mesma tabela, ignorando as duplicadas. O código de saída é gerado considerando as mesmas cláusulas PARTITION BY e ORDER BY usadas no código original.

SQL Server

Criar uma tabela com linhas duplicadas

 create table duplicatedRows(
    someID int,
    col2 bit,
    col3 bit,
    col4 bit,
    col5 bit
);

insert into duplicatedRows VALUES(10, 1, 0, 0, 1);
insert into duplicatedRows VALUES(10, 1, 0, 0, 1);
insert into duplicatedRows VALUES(11, 1, 1, 0, 1);
insert into duplicatedRows VALUES(12, 0, 0, 1, 1);
insert into duplicatedRows VALUES(12, 0, 0, 1, 1);
insert into duplicatedRows VALUES(13, 1, 0, 1, 0);
insert into duplicatedRows VALUES(14, 1, 0, 1, 0);
insert into duplicatedRows VALUES(14, 1, 0, 1, 0);

select * from duplicatedRows;
Copy
someID  | col2  | col3  | col4  | col5 |

 10     | true  | false | false | true  |
 10     | true  | false | false | true  |
 11     | true  | true  | false | true  |
 12     | false | false | true  | true  |
 12     | false | false | true  | true  |
 13     | true  | false | true  | false |
 14     | true  | false | true  | false |
 14     | true  | false | true  | false |


Copy

Remover linhas duplicadas

 DELETE f FROM (
	select  someID, row_number() over (
		partition by someID, col2
		order by
			case when COL3 = 1 then 1 else 0 end
			+ case when col4 = 1 then 1 else 0 end
			+ case when col5 = 1 then 1 else 0 end
			asc
		) as rownum
	from
		duplicatedRows
	) f where f.rownum > 1;
	
select * from duplicatedRows;
Copy
someID  | col2  | col3  | col4  | col5 |

 10     | true  | false | false | true  |
 11     | true  | true  | false | true  |
 12     | false | false | true  | true  |
 13     | true  | false | true  | false |
 14     | true  | false | true  | false |


Copy

Snowflake

Criar uma tabela com linhas duplicadas

 create table duplicatedRows(
    someID int,
    col2 BOOLEAN,
    col3 BOOLEAN,
    col4 BOOLEAN,
    col5 BOOLEAN
);

insert into duplicatedRows VALUES(10, 1, 0, 0, 1);
insert into duplicatedRows VALUES(10, 1, 0, 0, 1);
insert into duplicatedRows VALUES(11, 1, 1, 0, 1);
insert into duplicatedRows VALUES(12, 0, 0, 1, 1);
insert into duplicatedRows VALUES(12, 0, 0, 1, 1);
insert into duplicatedRows VALUES(13, 1, 0, 1, 0);
insert into duplicatedRows VALUES(14, 1, 0, 1, 0);
insert into duplicatedRows VALUES(14, 1, 0, 1, 0);

select * from duplicatedRows;
Copy
someID  | col2  | col3  | col4  | col5 |

 10     | true  | false | false | true  |
 10     | true  | false | false | true  |
 11     | true  | true  | false | true  |
 12     | false | false | true  | true  |
 12     | false | false | true  | true  |
 13     | true  | false | true  | false |
 14     | true  | false | true  | false |
 14     | true  | false | true  | false |


Copy

Remover linhas duplicadas

   insert overwrite into duplicatedRows
            SELECT
                *
            FROM
                duplicatedRows
            QUALIFY
                ROW_NUMBER()
                over
                (partition by someID, col2
		    order by
			case when COL3 = 1 then 1 else 0 end
			+ case when col4 = 1 then 1 else 0 end
			+ case when col5 = 1 then 1 else 0 end
			asc) = 1;
	
select * from duplicatedRows;
Copy
someID  | col2  | col3  | col4  | col5 |

 10     | true  | false | false | true  |
 11     | true  | true  | false | true  |
 12     | false | false | true  | true  |
 13     | true  | false | true  | false |
 14     | true  | false | true  | false |


Copy

Aviso

Considere que pode haver diversas variações desse padrão, mas todas elas se baseiam no mesmo princípio e têm a mesma estrutura.

Problemas conhecidos

Não foram encontrados problemas.

EWIs relacionados

Sem EWIs relacionados.

Descartes

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

DROP TABLE

Sintaxe no Transact-SQL

 DROP TABLE [ IF EXISTS ] <table_name> [ ,...n ]  
[ ; ]  
Copy
Sintaxe no Snowflake
 DROP TABLE [ IF EXISTS ] <name> [ CASCADE | RESTRICT ]
Copy

Conversão

A conversão para instruções DROP TABLE únicas é muito simples. Desde que haja apenas uma tabela sendo descartada na instrução, ela será deixada como está.

Por exemplo:

 DROP TABLE IF EXISTS [table_name]
Copy
 DROP TABLE IF EXISTS table_name;
Copy

A única diferença digna de nota entre o SQL Server e o Snowflake aparece quando a instrução de entrada descarta mais de uma tabela. Nesses cenários, uma instrução DROP TABLE diferente é criada para cada tabela que está sendo descartada.

Por exemplo:

 DROP TABLE IF EXISTS [table_name], [table_name2], [table_name3]
Copy
 DROP TABLE IF EXISTS table_name;

DROP TABLE IF EXISTS table_name2;

DROP TABLE IF EXISTS table_name3;
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs Relacionados

Sem EWIs relacionados.

Exists

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

Tipos de subconsultas

As subconsultas podem ser categorizadas como correlacionadas ou não correlacionadas:

Uma subconsulta correlacionada refere-se a uma ou mais colunas de fora da subconsulta. (As colunas são normalmente referenciadas dentro da cláusula WHERE da subconsulta). Uma subconsulta correlacionada pode ser pensada como um filtro na tabela a que se refere, como se a subconsulta fosse avaliada em cada linha da tabela na consulta externa.

Uma subconsulta não correlacionada não tem tais referências de colunas externas. É uma consulta independente, cujos resultados são retornados e utilizados pela consulta externa uma vez (não por linha).

A instrução EXISTS é considerada uma subconsulta correlacionada.

Código-fonte

 -- Additional Params: -t JavaScript
CREATE PROCEDURE ProcExists
AS
BEGIN
IF(EXISTS(Select AValue from ATable))
  return 1;
END;
Copy

Código esperado

 CREATE OR REPLACE PROCEDURE ProcExists ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
  // SnowConvert Helpers Code section is omitted.

  if (SELECT(`   EXISTS(Select
         AValue
      from
         ATable
   )`)) {
    return 1;
  }
$$;
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs Relacionados

Sem EWIs relacionados.

IN

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

O operador IN verifica se uma expressão está incluída nos valores retornados por uma subconsulta.

Código-fonte

 -- Additional Params: -t JavaScript
CREATE PROCEDURE dbo.SP_IN_EXAMPLE
AS
	DECLARE @results as VARCHAR(50);

	SELECT @results = COUNT(*) FROM TABLE1

	IF @results IN (1,2,3)
		SELECT 'is IN';
	ELSE
		SELECT 'is NOT IN';
	
	return
GO

-- =============================================
-- Example to execute the stored procedure
-- =============================================
EXECUTE dbo.SP_IN_EXAMPLE
GO
                              
Copy

Código esperado

 CREATE OR REPLACE PROCEDURE dbo.SP_IN_EXAMPLE ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
	// SnowConvert Helpers Code section is omitted.

	let RESULTS;
	SELECT(`   COUNT(*) FROM
   TABLE1`,[],(value) => RESULTS = value);
	if ([1,2,3].includes(RESULTS)) {
	} else {
	}
	return;
$$;

-- =============================================
-- Example to execute the stored procedure
-- =============================================
CALL dbo.SP_IN_EXAMPLE();
Copy

Problemas conhecidos

Não foram encontrados problemas.

EWIs Relacionados

Sem EWIs relacionados.

Insert

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

Adiciona uma ou mais linhas a uma tabela ou a uma visualização no SQL Server. Para obter mais informações sobre o SQL Server Insert, veja aqui.

Comparação de sintaxe

A gramática básica de inserção é equivalente em ambas as linguagens SQL. No entanto, ainda existem alguns outros elementos de sintaxe no SQL Server que mostram diferenças, por exemplo, um deles permite que o desenvolvedor adicione um valor a uma coluna usando o operador assign. A sintaxe mencionada também será transformada na sintaxe básica de inserção.

Snowflake

 INSERT [ OVERWRITE ] INTO <target_table> [ ( <target_col_name> [ , ... ] ) ]
       {
         VALUES ( { <value> | DEFAULT | NULL } [ , ... ] ) [ , ( ... ) ]  |
         <query>
       }
Copy

SQL Server

 [ WITH <common_table_expression> [ ,...n ] ]  
INSERT   
{  
        [ TOP ( expression ) [ PERCENT ] ]   
        [ INTO ]   
        { <object> | rowset_function_limited   
          [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]  
        }  
    {  
        [ ( column_list ) ]   
        [ <OUTPUT Clause> ]  
        { VALUES ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n     ]   
        | derived_table   
        | execute_statement  
        | <dml_table_source>  
        | DEFAULT VALUES   
        }  
    }  
}  
[;]  
  
<object> ::=  
{   
    [ server_name . database_name . schema_name .   
      | database_name .[ schema_name ] .   
      | schema_name .   
    ]  
  table_or_view_name  
}  
  
<dml_table_source> ::=  
    SELECT <select_list>  
    FROM ( <dml_statement_with_output_clause> )   
      [AS] table_alias [ ( column_alias [ ,...n ] ) ]  
    [ WHERE <search_condition> ]  
        [ OPTION ( <query_hint> [ ,...n ] ) ] 
Copy

Amostra de padrões de origem

INSERT Básico

SQL Server
 INSERT INTO TABLE1 VALUES (1, 2, 123, 'LiteralValue');
Copy
Snowflake
 INSERT INTO TABLE1 VALUES (1, 2, 123, 'LiteralValue');
Copy

INSERT com operador de montagem

SQL Server
 INSERT INTO aTable (columnA = 'varcharValue', columnB = 1);
Copy
Snowflake
 INSERT INTO aTable (columnA = 'varcharValue', columnB = 1);
Copy

INSERT sem INTO

SQL Server
 INSERT exampleTable VALUES ('Hello', 23);
Copy
Snowflake
 INSERT INTO exampleTable VALUES ('Hello', 23);
Copy

INSERT com expressão de tabela comum

SQL Server
 WITH ctevalues (textCol, numCol) AS (SELECT 'cte string', 155)
INSERT INTO exampleTable SELECT * FROM ctevalues;
Copy
Snowflake
 INSERT INTO exampleTable
WITH ctevalues (
textCol,
numCol
) AS (SELECT 'cte string', 155)
SELECT
*
FROM
ctevalues AS ctevalues;
Copy

INSERT com fator DML de tabela com MERGE como DML

Esse caso é tão específico que a instrução INSERT tem uma consulta SELECT e a cláusula FROM do SELECT mencionado contém uma instrução MERGE DML. Procurando um equivalente no Snowflake, as próximas instruções são criadas: uma tabela temporária, a instrução merge convertida e, por fim, a instrução insert.

SQL Server
 INSERT INTO T3
SELECT
  col1,
  col2
FROM (
  MERGE T1 USING T2
  	ON T1.col1 = T2.col1
  WHEN NOT MATCHED THEN
    INSERT VALUES ( T2.col1, T2.col2 )
  WHEN MATCHED THEN
    UPDATE SET T1.col2 = t2.col2
  OUTPUT
  	$action ACTION_OUT,
    T2.col1,
    T2.col2
) AS MERGE_OUT
 WHERE ACTION_OUT='UPDATE';
Copy
Snowflake
 --** SSC-FDM-TS0026 - DELETE CASE IS NOT BEING CONSIDERED, PLEASE CHECK IF THE ORIGINAL MERGE PERFORMS IT **
CREATE OR REPLACE TEMPORARY TABLE MERGE_OUT AS
SELECT
	CASE WHEN T1.$1 IS NULL THEN 'INSERT' ELSE 'UPDATE' END ACTION_OUT,
	T2.col1,
	T2.col2
FROM T2 LEFT JOIN T1 ON T1.col1 = T2.col1;

MERGE INTO T1
USING T2
ON T1.col1 = T2.col1
WHEN NOT MATCHED THEN INSERT VALUES (T2.col1, T2.col2)
WHEN MATCHED THEN UPDATE SET T1.col2 = t2.col2
!!!RESOLVE EWI!!! /*** SSC-EWI-0021 - OUTPUT CLAUSE NOT SUPPORTED IN SNOWFLAKE ***/!!!
OUTPUT
	$action ACTION_OUT,
	T2.col1,
	T2.col2 ;

INSERT INTO T3
SELECT col1, col2
FROM MERGE_OUT
WHERE ACTION_OUT ='UPDATE';
Copy

Aviso

NOTE: Como o nome do padrão sugere, ele é usado apenas em casos em que a inserção vem com um select… do qual o corpo contém uma instrução MERGE.

Problemas conhecidos

1. Elementos de sintaxe que exigem mapeamentos especiais:

  • [INTO]: Essa palavra-chave é obrigatória no Snowflake e deve ser adicionada se não estiver presente.

  • [DEFAULT VALUES]: Insere o valor padrão em todas as colunas especificadas na inserção. Deve ser transformado em VALUES (DEFAULT, DEFAULT, …), a quantidade de DEFAULTs adicionada é igual ao número de colunas que a inserção modificará. Por enquanto, há um aviso sendo adicionado.

    SQL Server

 INSERT INTO exampleTable DEFAULT VALUES;
Copy
#### Snowflake


Copy
 !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'INSERT WITH DEFAULT VALUES' NODE ***/!!!
INSERT INTO exampleTable DEFAULT VALUES;
Copy

2. Elementos de sintaxe não suportados ou irrelevantes:

  • [TOP (expressão) [PERCENT]]: Indica a quantidade ou o percentual de linhas que serão inseridas. Sem suporte.

  • [rowset_function\_limited]: É OPENQUERY() ou OPENROWSET(), usado para ler dados de servidores remotos. Sem suporte.

  • [WITH table_hint_limited]: São usados para obter bloqueios de leitura/gravação em tabelas. Não é relevante no Snowflake.

  • [<OUTPUT Clause>]: Especifica uma tabela ou um conjunto de resultados em que as linhas inseridas também serão inseridas. Sem suporte.

  • [execute_statement]: Pode ser usado para executar uma consulta para obter dados. Sem suporte.

  • [dml_table\_source]: Um conjunto de resultados temporários gerado pela cláusula OUTPUT de outra instrução DML. Sem suporte.

3. O caso DELETE não está sendo considerado.

  • Para o padrão INSERT with Table DML Factor with MERGE as DML, o caso DELETE não está sendo considerado na solução, portanto, se a instrução de mesclagem do código-fonte tiver um caso DELETE, considere que ele pode não funcionar como esperado.

EWIs relacionados

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

  2. SSC-FDM-TS0026: o caso DELETE não está sendo considerado.

Merge

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Comparação de sintaxe

Sintaxe do Snowflake SQL:

 MERGE
    INTO <target_table>
    USING <source>
    ON <join_expr>
    { matchedClause | notMatchedClause } [ ... ]
Copy

Sintaxe do Transact-SQL:

 -- SQL Server and Azure SQL Database
[ WITH <common_table_expression> [,...n] ]  
MERGE
    [ TOP ( expression ) [ PERCENT ] ]
    [ INTO ] <target_table> [ WITH ( <merge_hint> ) ] [ [ AS ] table_alias ]  
    USING <table_source> [ [ AS ] table_alias ]
    ON <merge_search_condition>  
    [ WHEN MATCHED [ AND <clause_search_condition> ]  
        THEN <merge_matched> ] [ ...n ]  
    [ WHEN NOT MATCHED [ BY TARGET ] [ AND <clause_search_condition> ]  
        THEN <merge_not_matched> ]  
    [ WHEN NOT MATCHED BY SOURCE [ AND <clause_search_condition> ]  
        THEN <merge_matched> ] [ ...n ]  
    [ <output_clause> ]  
    [ OPTION ( <query_hint> [ ,...n ] ) ]
;  
Copy

Exemplo

Dado o código-fonte a seguir:

 MERGE
INTO
  targetTable WITH(KEEPIDENTITY, KEEPDEFAULTS, HOLDLOCK, IGNORE_CONSTRAINTS, IGNORE_TRIGGERS, NOLOCK, INDEX(value1, value2, value3)) as tableAlias
USING
  tableSource AS tableAlias2
ON
  mergeSetCondition > mergeSetCondition
WHEN MATCHED BY TARGET AND pi.Quantity - src.OrderQty >= 0
  THEN UPDATE SET pi.Quantity = pi.Quantity - src.OrderQty
OUTPUT $action, DELETED.v AS DELETED, INSERTED.v INSERTED INTO @localVar(col, list)
OPTION(RECOMPILE);
Copy

Você pode esperar obter algo parecido com isto:

 MERGE INTO targetTable as tableAlias
USING tableSource AS tableAlias2
ON mergeSetCondition > mergeSetCondition
WHEN MATCHED AND pi.Quantity - src.OrderQty >= 0 THEN
  UPDATE SET
    pi.Quantity = pi.Quantity - src.OrderQty
    !!!RESOLVE EWI!!! /*** SSC-EWI-0021 - OUTPUT CLAUSE NOT SUPPORTED IN SNOWFLAKE ***/!!!
   OUTPUT $action, DELETED.v AS DELETED, INSERTED.v INSERTED INTO @localVar(col, list);
Copy

EWIs relacionados

  1. SSC-EWI-0021: A sintaxe não é compatível com o Snowflake.

Seleção

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

Permite a seleção de uma ou mais linhas ou colunas de uma ou mais tabelas no SQL Server.

Para obter mais informações sobre o SQL Server Select, veja aqui.

 <SELECT statement> ::=    
    [ WITH { [ XMLNAMESPACES ,] [ <common_table_expression> [,...n] ] } ]  
    <query_expression>   
    [ ORDER BY <order_by_expression> ] 
    [ <FOR Clause>]   
    [ OPTION ( <query_hint> [ ,...n ] ) ]   
<query_expression> ::=   
    { <query_specification> | ( <query_expression> ) }   
    [  { UNION [ ALL ] | EXCEPT | INTERSECT }  
        <query_specification> | ( <query_expression> ) [...n ] ]   
<query_specification> ::=   
SELECT [ ALL | DISTINCT ]   
    [TOP ( expression ) [PERCENT] [ WITH TIES ] ]   
    < select_list >   
    [ INTO new_table ]   
    [ FROM { <table_source> } [ ,...n ] ]   
    [ WHERE <search_condition> ]   
    [ <GROUP BY> ]   
    [ HAVING < search_condition > ]   
Copy

Amostra de padrões de origem

SELECT WITH COLUMN ALIASES

O exemplo a seguir demonstra como usar aliases de coluna no Snowflake. Espera-se que as duas primeiras colunas, do código do SQL Server, sejam transformadas de um formulário de atribuição em um formulário normalizado usando a palavra-chave AS. A terceira e a quarta colunas estão usando formatos válidos do Snowflake.

SQL Server

 SELECT
    MyCol1Alias = COL1,
    MyCol2Alias = COL2,
    COL3 AS MyCol3Alias,
    COL4 MyCol4Alias
FROM TABLE1;
Copy

Snowflake

 SELECT
    COL1 AS MyCol1Alias,
    COL2 AS MyCol2Alias,
    COL3 AS MyCol3Alias,
    COL4 MyCol4Alias
FROM
    TABLE1;
Copy

SELECT TOP

O caso básico do SQL Server Select Top é suportado pelo Snowflake. No entanto, existem mais três casos que não são suportados. Você pode verificá-los na seção Problemas conhecidos.

SQL Server

SELECT TOP 1 * from ATable;
Copy

Snowflake

 SELECT TOP 1
*
from
ATable;
Copy

SELECT INTO

O exemplo a seguir mostra que SELECT INTO é transformado em um CREATE TABLE AS, isso ocorre porque no Snowflake não há equivalente para SELECT INTO e para criar uma tabela com base em uma consulta tem que ser com CREATE TABLE AS.

SQL Server

 SELECT * INTO NEWTABLE FROM TABLE1;
Copy

Snowflake

 CREATE OR REPLACE TABLE NEWTABLE AS
SELECT
*
FROM
TABLE1;
Copy

Outro caso é quando você inclui operadores de conjunto, como EXCEPT e INTERSECT. A transformação é basicamente a mesma que a anterior.

SQL Server

 SELECT * INTO NEWTABLE FROM TABLE1
EXCEPT
SELECT * FROM TABLE2
INTERSECT
SELECT * FROM TABLE3;
Copy

Snowflake

 CREATE OR REPLACE TABLE NEWTABLE AS
SELECT
*
FROM
TABLE1
EXCEPT
SELECT
*
FROM
TABLE2
INTERSECT
SELECT
*
FROM
TABLE3;
Copy

Problemas conhecidos

Argumentos adicionais de SELECT TOP

Como as palavras-chave PERCENT e WITH TIES afetam o resultado e não são compatíveis com o Snowflake, elas serão comentadas e adicionadas como um erro.

SQL Server

 SELECT TOP 1 PERCENT * from ATable;
SELECT TOP 1 WITH TIES * from ATable;
SELECT TOP 1 PERCENT WITH TIES * from ATable;
Copy

Snowflake

 SELECT
TOP 1 !!!RESOLVE EWI!!! /*** SSC-EWI-0040 - THE STATEMENT IS NOT SUPPORTED IN SNOWFLAKE ***/!!!
*
from
ATable;

SELECT
TOP 1 !!!RESOLVE EWI!!! /*** SSC-EWI-0040 - THE STATEMENT IS NOT SUPPORTED IN SNOWFLAKE ***/!!!
*
from
ATable;

SELECT
TOP 1 !!!RESOLVE EWI!!! /*** SSC-EWI-0040 - THE STATEMENT IS NOT SUPPORTED IN SNOWFLAKE ***/!!!
*
from
ATable;
Copy

SELECT FOR

Como a cláusula FOR não é compatível com o Snowflake, ela é comentada e adicionada como um erro durante a transformação.

SQL Server

 SELECT column1, column2 FROM my_table FOR XML PATH('');
Copy

Snowflake

 SELECT
--** SSC-FDM-TS0016 - XML COLUMNS IN SNOWFLAKE MIGHT HAVE A DIFFERENT FORMAT **
FOR_XML_UDF(OBJECT_CONSTRUCT('column1', column1, 'column2', column2), '')
FROM
my_table;
Copy

SELECT OPTION

A cláusula OPTION não é suportada pelo Snowflake. Ela será comentada e adicionada como um aviso durante a transformação.

Aviso

Observe que a instrução OPTION foi removida da transformação porque não é relevante ou não é necessária no Snowflake.

SQL Server

 SELECT column1, column2 FROM my_table OPTION (HASH GROUP, FAST 10);
Copy

Snowflake

 SELECT
column1,
column2
FROM
my_table;
Copy

SELECT WITH

A cláusula WITH não é suportada pelo Snowflake. Ela será comentada e adicionada como um aviso durante a transformação.

Aviso

Observe que a instrução WITH(NOLOCK, NOWAIT) foi removida da transformação porque não é relevante ou não é necessária no Snowflake.

SQL Server

 SELECT AValue from ATable WITH(NOLOCK, NOWAIT);
Copy

Snowflake

 SELECT
AValue
from
ATable;
Copy

EWIs relacionados

  1. SSC-EWI-0040: Instrução não suportada.

  2. SSC-FDM-TS0016: Colunas XML no Snowflake podem ter um formato diferente

Operadores de conjuntos

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Os operadores de conjunto no TSQL e no Snowflake apresentam a mesma sintaxe e cenários compatíveis (EXCEPT, INTERSECT, UNION e UNION ALL), com exceção do MINUS que não é compatível com TSQL, resultando no mesmo código durante a conversão.

 SELECT LastName, FirstName FROM employees
UNION ALL
SELECT FirstName, LastName FROM contractors;

SELECT ...
INTERSECT
SELECT ...

SELECT ...
EXCEPT
SELECT ...
Copy

Truncate

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Nota

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

Código-fonte

 TRUNCATE TABLE TABLE1;
Copy

Código convertido

 TRUNCATE TABLE TABLE1;
Copy

EWIs relacionados

Sem EWIs relacionados.

Update

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

Altera os dados existentes em uma tabela ou visualização no SQL Server. Para obter mais informações sobre o SQL Server Update, veja aqui.

 [ WITH <common_table_expression> [...n] ]  
UPDATE   
    [ TOP ( expression ) [ PERCENT ] ]   
    { { table_alias | <object> | rowset_function_limited   
         [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]  
      }  
      | @table_variable      
    }  
    SET  
        { column_name = { expression | DEFAULT | NULL }  
          | { udt_column_name.{ { property_name = expression  
                                | field_name = expression }  
                                | method_name ( argument [ ,...n ] )  
                              }  
          }  
          | column_name { .WRITE ( expression , @Offset , @Length ) }  
          | @variable = expression  
          | @variable = column = expression  
          | column_name { += | -= | *= | /= | %= | &= | ^= | |= } expression  
          | @variable { += | -= | *= | /= | %= | &= | ^= | |= } expression  
          | @variable = column { += | -= | *= | /= | %= | &= | ^= | |= } expression  
        } [ ,...n ]   
  
    [ <OUTPUT Clause> ]  
    [ FROM{ <table_source> } [ ,...n ] ]   
    [ WHERE { <search_condition>   
            | { [ CURRENT OF   
                  { { [ GLOBAL ] cursor_name }   
                      | cursor_variable_name   
                  }   
                ]  
              }  
            }   
    ]   
    [ OPTION ( <query_hint> [ ,...n ] ) ]  
[ ; ]  
  
<object> ::=  
{   
    [ server_name . database_name . schema_name .   
    | database_name .[ schema_name ] .   
    | schema_name .  
    ]  
    table_or_view_name}  
Copy

Amostra de padrões de origem

UPDATE Básico

A conversão para uma instrução regular em UPDATE é muito simples. Como a estrutura básica do UPDATE é suportada por padrão no Snowflake, os outliers são as partes em que você verá algumas diferenças; verifique-as na seção Problemas conhecidos.

SQL Server
 Update UpdateTest1
Set Col1 = 5;
Copy

Snowflake

 Update UpdateTest1
Set
Col1 = 5;
Copy

Produtos cartesianos

O SQL Server permite adicionar referências circulares entre a tabela de destino da instrução Update e a cláusula FROM/ Em tempo de execução, o otimizador de banco de dados remove qualquer produto cartesiano gerado. Caso contrário, o Snowflake atualmente não otimiza esse cenário, produzindo um produto cartesiano que pode ser verificado no Plano de Execução.\

Para resolver isso, se houver um JOIN em que uma de suas tabelas seja a mesma que o destino da atualização, essa referência será removida e adicionada à cláusula WHERE, e será usada apenas para filtrar os dados e evitar uma operação de conjunto.

SQL Server
 UPDATE [HumanResources].[EMPLOYEEDEPARTMENTHISTORY_COPY]
SET
	BusinessEntityID = b.BusinessEntityID ,
	DepartmentID = b.DepartmentID,
	ShiftID = b.ShiftID,
	StartDate = b.StartDate,
	EndDate = b.EndDate,
	ModifiedDate = b.ModifiedDate
	FROM [HumanResources].[EMPLOYEEDEPARTMENTHISTORY_COPY] AS a
	RIGHT OUTER JOIN [HumanResources].[EmployeeDepartmentHistory] AS b
	ON a.BusinessEntityID = b.BusinessEntityID and a.ShiftID = b.ShiftID;
Copy

Snowflake

 UPDATE HumanResources.EMPLOYEEDEPARTMENTHISTORY_COPY a
	SET
		BusinessEntityID = b.BusinessEntityID,
		DepartmentID = b.DepartmentID,
		ShiftID = b.ShiftID,
		StartDate = b.StartDate,
		EndDate = b.EndDate,
		ModifiedDate = b.ModifiedDate
	FROM
		HumanResources.EmployeeDepartmentHistory AS b
	WHERE
		HumanResources.EMPLOYEEDEPARTMENTHISTORY_COPY.BusinessEntityID = b.BusinessEntityID(+)
		AND HumanResources.EMPLOYEEDEPARTMENTHISTORY_COPY.ShiftID = b.ShiftID(+);
Copy

Problemas conhecidos

Cláusula OUTPUT

A cláusula OUTPUT não é suportada pelo Snowflake.

SQL Server
 Update UpdateTest2
Set Col1 = 5
OUTPUT
	deleted.Col1,
	inserted.Col1
	into ValuesTest;
Copy

Snowflake

 Update UpdateTest2
	Set
		Col1 = 5
!!!RESOLVE EWI!!! /*** SSC-EWI-0021 - OUTPUT CLAUSE NOT SUPPORTED IN SNOWFLAKE ***/!!!
OUTPUT
	deleted.Col1,
	inserted.Col1
	into ValuesTest;
Copy

CTE

A cláusula WITH CTE é movida para a consulta interna na instrução Update para ser suportada pelo Snowflake.

SQL Server
 With ut as (select * from UpdateTest3)
Update x
Set Col1 = 5 
from ut as x;
Copy

Snowflake

 UPDATE UpdateTest3
Set
Col1 = 5
FROM
(
WITH ut as (select
*
from
UpdateTest3
)
SELECT
*
FROM
ut
) AS x;
Copy

Cláusula TOP

A cláusula TOP não é suportada pelo Snowflake.

SQL Server
 Update TOP(10) UpdateTest4
Set Col1 = 5;
Copy

Snowflake

 Update
--       !!!RESOLVE EWI!!! /*** SSC-EWI-0021 - TOP CLAUSE NOT SUPPORTED IN SNOWFLAKE ***/!!!
-- TOP(10)
         UpdateTest4
Set
Col1 = 5;
Copy

WITH TABLE HINT LIMITED

A cláusula Update WITH não é suportada pelo Snowflake.

SQL Server
 Update UpdateTest5 WITH(TABLOCK)
Set Col1 = 5;
Copy

Snowflake

 Update UpdateTest5
Set
Col1 = 5;
Copy

EWIs relacionados

  1. SSC-EWI-0021: A sintaxe não é compatível com o Snowflake.

Alternativa para UPDATE com JOIN

Este é um trabalho em andamento e pode mudar no futuro.

Description

O padrão UPDATE FROM é usado para atualizar dados com base em dados de outras tabelas. Esta documentação do SQLServer fornece um exemplo simples.

Analise a seguinte sintaxe do SQL Server da documentação.

Sintaxe do SQL Server

 UPDATE [table_name] 
SET column_name = expression [, ...]
[FROM <table_source> [, ...]]
[WHERE <search_condition>]
[OPTION (query_hint)]
Copy
  • table_name: A tabela ou visualização que você está atualizando.

  • SET: Especifica as colunas e seus novos valores. A cláusula SET atribui um novo valor (ou expressão) a uma ou mais colunas.

  • FROM: Usado para especificar uma ou mais tabelas de origem (como uma junção). Isso ajuda a definir de onde vêm os dados para realizar a atualização.

  • WHERE: Especifica quais linhas devem ser atualizadas com base na(s) condição(ões). Sem essa cláusula, todas as linhas da tabela seriam atualizadas.

  • OPTION (query_hint): Especifica dicas para otimização de consultas.

Sintaxe do Snowflake

A sintaxe do Snowflake também pode ser revisada na documentação do Snowflake.

Nota

O Snowflake não é compatível com JOINs na cláusula UPDATE.

 UPDATE <target_table>
       SET <col_name> = <value> [ , <col_name> = <value> , ... ]
        [ FROM <additional_tables> ]
        [ WHERE <condition> ]
Copy

Parâmetros obrigatórios

  • _ target_table: _especifica a tabela a ser atualizada.

  • _ col_name: especifica o nome de uma coluna em _ target_table. Não inclua o nome da tabela. Por exemplo, UPDATE t1 SET t1.col = 1 é inválido.

  • _ value :especifica o novo valor a ser definido em _ col_name.

Parâmetros opcionais

  • FROM`` _ additional_tables: _ Especifica uma ou mais tabelas a serem usadas para selecionar linhas a serem atualizadas ou para definir novos valores. observe que a repetição da tabela de destino resulta em uma junção automática

  • WHERE`` _ condition: _Ta expressão que especifica as linhas da tabela de destino a serem atualizadas. Padrão: sem valor (todas as linhas da tabela de destino são atualizadas)

Resumo da conversão

SQL Server JOIN typeSnowflake Best Alternative
Single INNER JOINUse the target table in the FROM clause to emulate an INNER JOIN.
Multiple INNER JOINUse the target table in the FROM clause to emulate an INNER JOIN.
Multiple INNER JOIN + Agregate conditionUse subquery + IN Operation
Single LEFT JOINUse subquery + IN Operation
Multiple LEFT JOIN

Use Snowflake UPDATE reordering the statements as needed.
UPDATE [target_table_name]

SET [all_set_statements]

FROM [all_left_join_tables_separated_by_comma]

WHERE [all_clauses_into_the_ON_part]

Multiple RIGHT JOIN

Use Snowflake UPDATE reordering the statements as needed.
UPDATE [target_table_name]

SET [all_set_statements]

FROM [all_right_join_tables_separated_by_comma]

WHERE [all_clauses_into_the_ON_part]

Single RIGHT JOINUse the table in the FROM clause and add filters in the WHERE clause as needed.

_Nota 1: JOIN simples pode usar a tabela na cláusula FROM e adicionar filtros na cláusula WHERE, conforme necessário

Nota 2: Outras abordagens podem incluir o operando (+) para definir JOINs.

Amostra de padrões de origem

Dados de configuração

 CREATE TABLE Orders (
    OrderID INT PRIMARY KEY,
    CustomerID INT,
    ProductID INT,
    Quantity INT,
    OrderDate DATE
);

CREATE TABLE Customers (
    CustomerID INT PRIMARY KEY,
    CustomerName VARCHAR(100)
);

CREATE TABLE Products (
    ProductID INT PRIMARY KEY,
    ProductName VARCHAR(100),
    Price DECIMAL(10, 2)
);
Copy
 CREATE OR REPLACE TABLE Orders (
    OrderID INT PRIMARY KEY,
    CustomerID INT,
    ProductID INT,
    Quantity INT,
    OrderDate DATE
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "11/12/2024",  "domain": "test" }}'
;

CREATE OR REPLACE TABLE Customers (
    CustomerID INT PRIMARY KEY,
    CustomerName VARCHAR(100)
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "11/12/2024",  "domain": "test" }}'
;

CREATE OR REPLACE TABLE Products (
    ProductID INT PRIMARY KEY,
    ProductName VARCHAR(100),
    Price DECIMAL(10, 2)
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "11/12/2024",  "domain": "test" }}'
;
Copy
Data Insertion for samples
-- Insert Customer Data
INSERT INTO Customers (CustomerID, CustomerName) VALUES (1, 'John Doe');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (2, 'Jane Smith');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (3, 'Alice Johnson');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (4, 'Bob Lee');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (5, 'Charlie Brown');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (6, 'David White');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (7, 'Eve Black');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (8, 'Grace Green');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (9, 'Hank Blue');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (10, 'Ivy Red');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (11, 'Jack Grey');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (12, 'Kim Yellow');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (13, 'Leo Purple');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (14, 'Mona Pink');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (15, 'Nathan Orange');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (16, 'Olivia Cyan');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (17, 'Paul Violet');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (18, 'Quincy Brown');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (19, 'Rita Silver');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (20, 'Sam Green');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (21, 'Tina Blue');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (22, 'Ursula Red');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (23, 'Vince Yellow');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (24, 'Wendy Black');
INSERT INTO Customers (CustomerID, CustomerName) VALUES (25, 'Xander White');

-- Insert Product Data
INSERT INTO Products (ProductID, ProductName, Price) VALUES (1, 'Laptop', 999.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (2, 'Smartphone', 499.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (3, 'Tablet', 299.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (4, 'Headphones', 149.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (5, 'Monitor', 199.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (6, 'Keyboard', 49.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (7, 'Mouse', 29.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (8, 'Camera', 599.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (9, 'Printer', 99.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (10, 'Speaker', 129.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (11, 'Charger', 29.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (12, 'TV', 699.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (13, 'Smartwatch', 199.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (14, 'Projector', 499.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (15, 'Game Console', 399.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (16, 'Speaker System', 299.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (17, 'Earphones', 89.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (18, 'USB Drive', 15.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (19, 'External Hard Drive', 79.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (20, 'Router', 89.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (21, 'Printer Ink', 49.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (22, 'Flash Drive', 9.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (23, 'Gamepad', 34.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (24, 'Webcam', 49.99);
INSERT INTO Products (ProductID, ProductName, Price) VALUES (25, 'Docking Station', 129.99);

-- Insert Orders Data
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (1, 1, 1, 2, '2024-11-01');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (2, 2, 2, 1, '2024-11-02');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (3, 3, 3, 5, '2024-11-03');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (4, 4, 4, 3, '2024-11-04');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (5, NULL, 5, 7, '2024-11-05');  -- NULL Customer
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (6, 6, 6, 2, '2024-11-06');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (7, 7, NULL, 4, '2024-11-07');  -- NULL Product
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (8, 8, 8, 1, '2024-11-08');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (9, 9, 9, 3, '2024-11-09');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (10, 10, 10, 2, '2024-11-10');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (11, 11, 11, 5, '2024-11-11');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (12, 12, 12, 2, '2024-11-12');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (13, NULL, 13, 8, '2024-11-13');  -- NULL Customer
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (14, 14, NULL, 4, '2024-11-14');  -- NULL Product
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (15, 15, 15, 3, '2024-11-15');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (16, 16, 16, 2, '2024-11-16');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (17, 17, 17, 1, '2024-11-17');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (18, 18, 18, 4, '2024-11-18');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (19, 19, 19, 3, '2024-11-19');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (20, 20, 20, 6, '2024-11-20');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (21, 21, 21, 3, '2024-11-21');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (22, 22, 22, 5, '2024-11-22');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (23, 23, 23, 2, '2024-11-23');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (24, 24, 24, 4, '2024-11-24');
INSERT INTO Orders (OrderID, CustomerID, ProductID, Quantity, OrderDate) VALUES (25, 25, 25, 3, '2024-11-25');
Copy

Caso 1: Atualização de INNER JOIN única

Para INNER JOIN, se a tabela for usada dentro das instruções FROM, ela se transformará automaticamente em INNER JOIN. Observe que há várias abordagens para dar suporte a JOINs em instruções UPDATE no Snowflake. Esse é um dos padrões mais simples para garantir a legibilidade.

SQL Server
 UPDATE Orders
SET Quantity = 10
FROM Orders O
INNER JOIN Customers C ON O.CustomerID = C.CustomerID
WHERE C.CustomerName = 'John Doe';

-- Select the changes
SELECT Orders.CustomerID, Orders.Quantity, Customers.CustomerName
FROM Orders, Customers
WHERE Orders.CustomerID = Customers.CustomerID
AND Customers.CustomerName = 'John Doe';
Copy

CustomerID

Quantidade

CustomerName

1

10

John Doe

Snowflake
 UPDATE Orders O
SET O.Quantity = 10
FROM 
  Customers C
WHERE 
  C.CustomerName = 'John Doe'
  AND O.CustomerID = C.CustomerID;


-- Select the changes
SELECT Orders.CustomerID, Orders.Quantity, Customers.CustomerName
FROM Orders, Customers
WHERE Orders.CustomerID = Customers.CustomerID
AND Customers.CustomerName = 'John Doe';
Copy

CustomerID

Quantidade

CustomerName

1

10

John Doe

Outras abordagens:

MERGE INTO
 MERGE INTO Orders O
USING Customers C
ON O.CustomerID = C.CustomerID
WHEN MATCHED AND C.CustomerName = 'John Doe' THEN
  UPDATE SET O.Quantity = 10;
Copy
IN Operation
 UPDATE Orders O
SET O.Quantity = 10
WHERE O.CustomerID IN 
  (SELECT CustomerID FROM Customers WHERE CustomerName = 'John Doe');
Copy

Caso 2: Atualização de múltiplos INNER JOIN

SQL Server
 UPDATE Orders
SET Quantity = 5
FROM Orders O
INNER JOIN Customers C ON O.CustomerID = C.CustomerID
INNER JOIN Products P ON O.ProductID = P.ProductID
WHERE C.CustomerName = 'Alice Johnson' AND P.ProductName = 'Tablet';

-- Select the changes
SELECT Orders.CustomerID, Orders.Quantity, Customers.CustomerName FROM Orders, Customers
WHERE Orders.CustomerID = Customers.CustomerID
AND Customers.CustomerName = 'Alice Johnson';
Copy

CustomerID

Quantidade

CustomerName

3

5

Alice Johnson

Snowflake
 UPDATE Orders O
SET O.Quantity = 5
FROM Customers C, Products P
WHERE O.CustomerID = C.CustomerID
  AND C.CustomerName = 'Alice Johnson'
  AND P.ProductName = 'Tablet'
  AND O.ProductID = P.ProductID;

-- Select the changes
SELECT Orders.CustomerID, Orders.Quantity, Customers.CustomerName FROM Orders, Customers
WHERE Orders.CustomerID = Customers.CustomerID
AND Customers.CustomerName = 'Alice Johnson';
Copy

CustomerID

Quantidade

CustomerName

3

5

Alice Johnson

Caso 3: Atualização de múltiplos INNER JOIN com condição agregada

SQL Server
 UPDATE Orders
SET Quantity = 6
FROM Orders O
INNER JOIN Customers C ON O.CustomerID = C.CustomerID
INNER JOIN Products P ON O.ProductID = P.ProductID
WHERE C.CustomerID IN (SELECT CustomerID FROM Orders WHERE Quantity > 3)
AND P.Price < 200;

SELECT C.CustomerID, C.CustomerName, O.Quantity, P.Price FROM Orders O
INNER JOIN Customers C ON O.CustomerID = C.CustomerID
INNER JOIN Products P ON O.ProductID = P.ProductID
WHERE C.CustomerID IN (SELECT CustomerID FROM Orders WHERE Quantity > 3)
AND P.Price < 200;
Copy

CustomerID

CustomerName

Quantidade

Price

11

Jack Grey

6

29,99

18

Quincy Brown

6

15,99

20

Sam Green

6

89,99

22

Ursula Red

6

9,99

24

Wendy Black

6

49,99

Snowflake
 UPDATE Orders O
SET Quantity = 6
WHERE O.CustomerID IN (SELECT CustomerID FROM Orders WHERE Quantity > 3)
AND O.ProductID IN (SELECT ProductID FROM Products WHERE Price < 200);

-- Select changes
SELECT C.CustomerID, C.CustomerName, O.Quantity, P.Price FROM Orders O
INNER JOIN Customers C ON O.CustomerID = C.CustomerID
INNER JOIN Products P ON O.ProductID = P.ProductID
WHERE C.CustomerID IN (SELECT CustomerID FROM Orders WHERE Quantity > 3)
AND P.Price < 200;
Copy

CustomerID

CustomerName

Quantidade

Price

11

Jack Grey

6

29,99

18

Quincy Brown

6

15,99

20

Sam Green

6

89,99

22

Ursula Red

6

9,99

24

Wendy Black

6

49,99

Caso 4: Atualização de LEFT JOIN única

SQL Server
 UPDATE Orders
SET Quantity = 13
FROM Orders O
LEFT JOIN Customers C ON O.CustomerID = C.CustomerID
WHERE C.CustomerID IS NULL AND O.ProductID = 13;

-- Select the changes
SELECT * FROM orders
WHERE CustomerID IS NULL;
Copy

OrderID

CustomerID

ProductID

Quantidade

OrderDate

5

nulo

5

7

2024-11-05

13

nulo

13

13

2024-11-13

Snowflake
 UPDATE Orders
SET Quantity = 13
WHERE OrderID IN (
  SELECT O.OrderID
  FROM Orders O
  LEFT JOIN Customers C ON O.CustomerID = C.CustomerID
  WHERE C.CustomerID IS NULL AND O.ProductID = 13
);


-- Select the changes
SELECT * FROM orders
WHERE CustomerID IS NULL;
Copy

OrderID

CustomerID

ProductID

Quantidade

OrderDate

5

nulo

5

7

2024-11-05

13

nulo

13

13

2024-11-13

Nota

Essa abordagem no Snowflake não funcionará porque não atualiza as linhas necessárias:

UPDATE Orders O SET O.Quantity = 13 FROM Customers C WHERE O.CustomerID = C.CustomerID AND C.CustomerID IS NULL AND O.ProductID = 13;

Caso 5: Múltiplos LEFT JOIN e RIGHT JOIN Update

Esse é um padrão mais complexo. Para converter vários LEFT JOINs, consulte o padrão a seguir:

Nota

LEFT JOIN e RIGHT JOIN dependerão da ordem na cláusula FROM.

 UPDATE [target_table_name]
SET [all_set_statements]
FROM [all_left_join_tables_separated_by_comma]
WHERE [all_clauses_into_the_ON_part]
Copy
SQL Server
 UPDATE Orders
SET
    Quantity = C.CustomerID
FROM Orders O
LEFT JOIN Customers C ON C.CustomerID = O.CustomerID
LEFT JOIN Products P ON P.ProductID = O.ProductID
WHERE C.CustomerName = 'Alice Johnson'
  AND P.ProductName = 'Tablet';

SELECT O.OrderID, O.CustomerID, O.ProductID, O.Quantity, O.OrderDate
FROM Orders O
LEFT JOIN Customers C ON C.CustomerID = O.CustomerID
LEFT JOIN Products P ON P.ProductID = O.ProductID
WHERE C.CustomerName = 'Alice Johnson'
  AND P.ProductName = 'Tablet';
Copy

OrderID

CustomerID

ProductID

Quantidade

OrderDate

3

3

3

3

2024-11-12

Snowflake
 UPDATE Orders O
SET O.Quantity = C.CustomerID
FROM Customers C, Products P
WHERE O.CustomerID = C.CustomerID
  AND C.CustomerName = 'Alice Johnson'
  AND P.ProductName = 'Tablet'
  AND O.ProductID = P.ProductID;

  SELECT O.OrderID, O.CustomerID, O.ProductID, O.Quantity, O.OrderDate
FROM Orders O
LEFT JOIN Customers C ON C.CustomerID = O.CustomerID
LEFT JOIN Products P ON P.ProductID = O.ProductID
WHERE C.CustomerName = 'Alice Johnson'
  AND P.ProductName = 'Tablet';
Copy

OrderID

CustomerID

ProductID

Quantidade

OrderDate

3

3

3

3

2024-11-12

Caso 6: Atualização de INNER JOIN e LEFT JOIN mistos

SQL Server
 UPDATE Orders
SET Quantity = 4
FROM Orders O
INNER JOIN Products P ON O.ProductID = P.ProductID
LEFT JOIN Customers C ON O.CustomerID = C.CustomerID
WHERE C.CustomerID IS NULL AND P.ProductName = 'Monitor';

-- Select changes
SELECT O.CustomerID, C.CustomerName, O.Quantity FROM Orders O
INNER JOIN Products P ON O.ProductID = P.ProductID
LEFT JOIN Customers C ON O.CustomerID = C.CustomerID
WHERE C.CustomerID IS NULL AND P.ProductName = 'Monitor';
Copy

CustomerID

CustomerName

Quantidade

nulo

nulo

4

Snowflake
 UPDATE Orders O
SET Quantity = 4
WHERE O.ProductID IN (SELECT ProductID FROM Products WHERE ProductName = 'Monitor')
AND O.CustomerID IS NULL;

-- Select changes
SELECT O.CustomerID, C.CustomerName, O.Quantity FROM Orders O
INNER JOIN Products P ON O.ProductID = P.ProductID
LEFT JOIN Customers C ON O.CustomerID = C.CustomerID
WHERE C.CustomerID IS NULL AND P.ProductName = 'Monitor';
Copy

CustomerID

CustomerName

Quantidade

nulo

nulo

4

Caso 7: Atualização de RIGHT JOIN único

SQL Server
 UPDATE O
SET O.Quantity = 1000
FROM Orders O
RIGHT JOIN Customers C ON O.CustomerID = C.CustomerID
WHERE C.CustomerName = 'Alice Johnson';

-- Select changes 
SELECT
    O.OrderID,
    O.CustomerID,
    O.ProductID,
    O.Quantity,
    O.OrderDate,
    C.CustomerName
FROM
    Orders O
RIGHT JOIN Customers C ON O.CustomerID = C.CustomerID
WHERE
    C.CustomerName = 'Alice Johnson';
Copy
OrderIDCustomerIDProductIDQuantityCustomerName
3331000Alice Johnson
Snowflake
 UPDATE Orders O
SET O.Quantity = 1000
FROM Customers C
WHERE O.CustomerID = C.CustomerID
  AND C.CustomerName = 'Alice Johnson';


  -- Select changes 
SELECT
    O.OrderID,
    O.CustomerID,
    O.ProductID,
    O.Quantity,
    O.OrderDate,
    C.CustomerName
FROM
    Orders O
RIGHT JOIN Customers C ON O.CustomerID = C.CustomerID
WHERE
    C.CustomerName = 'Alice Johnson';
Copy
OrderIDCustomerIDProductIDQuantityCustomerName
3331000Alice Johnson

Problemas conhecidos

  • Como UPDATE no Snowflake não permite o uso de JOINs diretamente, pode haver casos que não correspondam aos padrões descritos.

UPDATE com LEFT e RIGHT JOIN

Applies to
  • [x] SQL Server

  • [x] Azure Synapse Analytics

Aviso

Parcialmente suportado no Snowflake

Descrição

O padrão UPDATE FROM é usado para atualizar dados com base em dados de outras tabelas. Esta documentação do SQLServer fornece um exemplo simples.

Analise a seguinte sintaxe do SQL Server da documentação.

Sintaxe do SQL Server

 UPDATE [table_name] 
SET column_name = expression [, ...]
[FROM <table_source> [, ...]]
[WHERE <search_condition>]
[OPTION (query_hint)]
Copy
  • table_name: A tabela ou visualização que você está atualizando.

  • SET: Especifica as colunas e seus novos valores. A cláusula SET atribui um novo valor (ou expressão) a uma ou mais colunas.

  • FROM: Usado para especificar uma ou mais tabelas de origem (como uma junção). Isso ajuda a definir de onde vêm os dados para realizar a atualização.

  • WHERE: Especifica quais linhas devem ser atualizadas com base na(s) condição(ões). Sem essa cláusula, todas as linhas da tabela seriam atualizadas.

  • OPTION (query_hint): Especifica dicas para otimização de consultas.

Sintaxe do Snowflake

A sintaxe do Snowflake também pode ser revisada na documentação do Snowflake.

Nota

O Snowflake não é compatível com JOINs na cláusula UPDATE.

 UPDATE <target_table>
       SET <col_name> = <value> [ , <col_name> = <value> , ... ]
        [ FROM <additional_tables> ]
Copy

Parâmetros obrigatórios

  • _ target_table: _especifica a tabela a ser atualizada.

  • _ col_name: especifica o nome de uma coluna em _ target_table. Não inclua o nome da tabela. Por exemplo, UPDATE t1 SET t1.col = 1 é inválido.

  • _ value :especifica o novo valor a ser definido em _ col_name.

Parâmetros opcionais

  • FROM`` _ additional_tables: _ Especifica uma ou mais tabelas a serem usadas para selecionar linhas a serem atualizadas ou para definir novos valores. observe que a repetição da tabela de destino resulta em uma junção automática

  • WHERE`` _ condition: _Ta expressão que especifica as linhas da tabela de destino a serem atualizadas. Padrão: sem valor (todas as linhas da tabela de destino são atualizadas)

Resumo da conversão

Como explicado na descrição da gramática, não há uma solução equivalente direta para JOINs dentro do cluster UPDATE. Por esse motivo, a abordagem para transformar essas instruções é adicionar o operador (+) na coluna que logicamente adicionará os dados necessários à tabela. Esse operador (+) é adicionado aos casos em que as tabelas são referenciadas na seção LEFT/RIGHT JOIN.

Observe que há outras linguagens que usam esse operador (+) e que a posição do operador pode determinar o tipo de junção. Nesse caso específico, no Snowflake, a posição não determinará o tipo de junção, mas sim a associação com as tabelas e colunas logicamente necessárias.

Mesmo quando há outras alternativas, como a cláusula MERGE ou os usos de um CTE, essas alternativas tendem a se tornar difíceis de ler quando há consultas complexas e se tornam extensas.

Amostra de padrões de origem

Dados de configuração

 CREATE TABLE GenericTable1 (
    Col1 INT,
    Col2 VARCHAR(10),
    Col3 VARCHAR(10),
    Col4 VARCHAR(10),
    Col5 VARCHAR(10),
    Col6 VARCHAR(100)
);

CREATE TABLE GenericTable2 (
    Col1 VARCHAR(10),
    Col2 VARCHAR(10),
    Col3 VARCHAR(10),
    Col4 VARCHAR(10),
    Col5 VARCHAR(10)
);

CREATE TABLE GenericTable3 (
    Col1 VARCHAR(10),
    Col2 VARCHAR(100),
    Col3 CHAR(1)
);

INSERT INTO GenericTable1 (Col1, Col2, Col3, Col4, Col5, Col6)
VALUES
(1, 'A1', 'B1', 'C1', NULL, NULL),
(2, 'A2', 'B2', 'C2', NULL, NULL),
(3, 'A3', 'B3', 'C3', NULL, NULL);

INSERT INTO GenericTable2 (Col1, Col2, Col3, Col4, Col5)
VALUES
('1', 'A1', 'B1', 'C1', 'X1'),
('2', 'A2', 'B2', 'C2', 'X2'),
('3', 'A3', 'B3', 'C3', 'X3');

INSERT INTO GenericTable3 (Col1, Col2, Col3)
VALUES
('X1', 'Description1', 'A'),
('X2', 'Description2', 'A'),
('X3', 'Description3', 'A');
Copy
 CREATE OR REPLACE TABLE GenericTable1 (
    Col1 INT,
    Col2 VARCHAR(10),
    Col3 VARCHAR(10),
    Col4 VARCHAR(10),
    Col5 VARCHAR(10),
    Col6 VARCHAR(100)
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "12/18/2024",  "domain": "test" }}'
;

CREATE OR REPLACE TABLE GenericTable2 (
    Col1 VARCHAR(10),
    Col2 VARCHAR(10),
    Col3 VARCHAR(10),
    Col4 VARCHAR(10),
    Col5 VARCHAR(10)
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "12/18/2024",  "domain": "test" }}'
;

CREATE OR REPLACE TABLE GenericTable3 (
    Col1 VARCHAR(10),
    Col2 VARCHAR(100),
    Col3 CHAR(1)
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "12/18/2024",  "domain": "test" }}'
;

INSERT INTO GenericTable1 (Col1, Col2, Col3, Col4, Col5, Col6)
VALUES
(1, 'A1', 'B1', 'C1', NULL, NULL),
(2, 'A2', 'B2', 'C2', NULL, NULL),
(3, 'A3', 'B3', 'C3', NULL, NULL);

INSERT INTO GenericTable2 (Col1, Col2, Col3, Col4, Col5)
VALUES
('1', 'A1', 'B1', 'C1', 'X1'),
('2', 'A2', 'B2', 'C2', 'X2'),
('3', 'A3', 'B3', 'C3', 'X3');

INSERT INTO GenericTable3 (Col1, Col2, Col3)
VALUES
('X1', 'Description1', 'A'),
('X2', 'Description2', 'A'),
('X3', 'Description3', 'A');
Copy

LEFT JOIN

SQL Server

 UPDATE T1
SET
    T1.Col5 = T2.Col5,
    T1.Col6 = T3.Col2
FROM GenericTable1 T1
LEFT JOIN GenericTable2 T2 ON
    T2.Col1 COLLATE SQL_Latin1_General_CP1_CI_AS = T1.Col1
    AND T2.Col2 = T1.Col2
    AND T2.Col3 = T1.Col3
    AND T2.Col4 = T1.Col4
LEFT JOIN GenericTable3 T3 ON
    T3.Col1 = T2.Col5 AND T3.Col3 = 'A';
Copy

Col1

Col2

Col3

Col4

Col5

Col6

1

A1

B1

C1

null

null

2

A2

B2

C2

null

null

3

A3

B3

C3

null

null

Col1Col2Col3Col4Col5Col6
1A1B1C1X1Description1
2A2B2C2X2Description2
3A3B3C3X3Description3

Snowflake

 UPDATE dbo.GenericTable1 T1
    SET
        T1.Col5 = T2.Col5,
        T1.Col6 = T3.Col2
    FROM
        GenericTable2 T2,
        GenericTable3 T3
    WHERE
        T2.Col1(+) COLLATE 'EN-CI-AS' /*** SSC-FDM-TS0002 - COLLATION FOR VALUE CP1 NOT SUPPORTED ***/ = T1.Col1
        AND T2.Col2(+) = T1.Col2
        AND T2.Col3(+) = T1.Col3
        AND T2.Col4(+) = T1.Col4
        AND T3.Col1(+) = T2.Col5
        AND T3.Col3 = 'A';
Copy

Col1

Col2

Col3

Col4

Col5

Col6

1

A1

B1

C1

null

null

2

A2

B2

C2

null

null

3

A3

B3

C3

null

null

Col1Col2Col3Col4Col5Col6
1A1B1C1X1Description1
2A2B2C2X2Description2
3A3B3C3X3Description3

RIGHT JOIN

SQL Server

 UPDATE T1
SET
    T1.Col5 = T2.Col5
FROM GenericTable2 T2
RIGHT JOIN GenericTable1 T1 ON
    T2.Col1 COLLATE SQL_Latin1_General_CP1_CI_AS = T1.Col1
    AND T2.Col2 = T1.Col2
    AND T2.Col3 = T1.Col3
    AND T2.Col4 = T1.Col4;
Copy

Col1

Col2

Col3

Col4

Col5

Col6

1

A1

B1

C1

null

null

2

A2

B2

C2

null

null

3

A3

B3

C3

null

null

Col1

Col2

Col3

Col4

Col5

Col6

1

A1

B1

C1

X1

null

2

A2

B2

C2

X2

null

3

A3

B3

C3

X3

null

Snowflake

 UPDATE dbo.GenericTable1 T1
    SET
        T1.Col5 = T2.Col5
    FROM
        GenericTable2 T2,
        GenericTable1 T1
    WHERE
        T2.Col1 COLLATE 'EN-CI-AS' /*** SSC-FDM-TS0002 - COLLATION FOR VALUE CP1 NOT SUPPORTED ***/ = T1.Col1
        AND T2.Col2 = T1.Col2(+)
        AND T2.Col3 = T1.Col3(+)
        AND T2.Col4 = T1.Col4(+);
Copy

Col1

Col2

Col3

Col4

Col5

Col6

1

A1

B1

C1

null

null

2

A2

B2

C2

null

null

3

A3

B3

C3

null

null

Col1

Col2

Col3

Col4

Col5

Col6

1

A1

B1

C1

X1

null

2

A2

B2

C2

X2

null

3

A3

B3

C3

X3

null

Problemas conhecidos

  • Pode haver padrões que não podem ser convertidos devido a diferenças na lógica.

  • Se seu padrão de consulta se aplicar, examine as linhas não determinísticas: «Quando uma cláusula FROM contém uma cláusula JOIN entre tabelas (por exemplo, t1 e t2), uma linha de destino em t1 pode se unir a (ou seja, corresponder a) mais de uma linha na tabela t2. Quando isso ocorre, a linha de destino é chamada de multi-joined row. Ao atualizar uma linha com várias junções, o parâmetro de sessão ERROR_ON_NONDETERMINISTIC_UPDATE controla o resultado da atualização (Documentação do Snowflake).