SnowConvert: Transact DMLs

Between

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

소스 코드

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

예상 코드

 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

알려진 문제

문제가 발견되지 않았습니다.

대량 삽입

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

BULK INSERT 의 직접적인 변환은 Snowflake COPY INTO 문입니다. COPY INTO 는 파일 경로를 직접 사용하여 값을 검색하지 않습니다. 파일은 STAGE 앞에 위치해야 합니다. 또한 BULK INSERT 에서 사용되는 옵션은 STAGE 또는 COPY INTO 에 의해 직접 소비될 Snowflake FILE FORMAT 에 지정되어야 합니다.

STAGE 에 파일을 추가하려면 PUT 명령을 사용해야 합니다. 이 명령은 오직 SnowSQL CLI 에서만 실행될 수 있습니다.. 다음은 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

위의 코드에서 볼 수 있듯이 SnowConvert 는 코드의 모든 BULK INSERTS 를 식별하고 각 인스턴스마다 복사본이 실행되기 전에 STAGEFILE FORMAT 을 새로 생성합니다. 또한 STAGE 를 생성한 후 PUT 명령도 생성되어 스테이지에 파일을 추가할 수 있습니다.

생성된 문의 이름은 사용 간의 충돌을 방지하기 위해 현재 타임스탬프(초)를 사용하여 자동으로 생성됩니다.

마지막으로 대량 삽입에 대한 모든 옵션이 적용되는 경우 파일 형식 옵션에 매핑됩니다. 해당 옵션이 Snowflake에서 지원되지 않는 경우 설명과 함께 경고가 추가됩니다. SSC-FDM-TS0004도 참조하십시오.

지원되는 대량 옵션

SQL 서버

Snowflake

FORMAT

TYPE

FIELDTERMINATOR

FIELD_DELIMITER

FIRSTROW

SKIP_HEADER

ROWTERMINATOR

RECORD_DELIMITER

FIELDQUOTE

FIELD_OPTIONALLY_ENCLOSED_BY

관련 EWIs

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

공통 테이블 식 (CTE)

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

일반적인 테이블 식은 기본적으로 Snowflake SQL 에서 지원됩니다.

Snowflake SQL 구문

하위 쿼리:

 [ 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:

 [ 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

여기서

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

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

주목할 만한 세부 정보

RECURSIVE 키워드는 T-SQL 에 존재하지 않으며, 변환이 해당 키워드를 결과에 적극적으로 추가하지 않습니다. 이 동작을 설명하기 위해 출력 코드에 경고가 추가됩니다.

SELECT INTO 를 사용한 일반적인 테이블 식

WITH 식 뒤에 SELECT INTO 문이 오면 다음과 같이 변환되며, 이는 TEMPORARY TABLE 러 변환됩니다.

SQL 서버:

 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

다른 식과 공통 테이블 표현식

WITH 식 뒤에 INSERT 또는 DELETE 문이 오는 경우 다음과 같은 변환이 발생합니다.

SQL 서버:

 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

삭제 위치가 있는 일반적인 테이블 식

이 변환의 경우CTE (공통 테이블 식)에 삭제자가 있는 경우에만 적용되지만 일부 세부 사항 CTE 에 대해서만 적용됩니다. 1개의 CTE 만 있어야 하며 ROW_NUMBER 또는 RANK 의 함수 내에 있어야 합니다.

삭제가 포함된 CTE 의 목적은 테이블에서 중복을 제거하는 것이어야 합니다. 삭제가 포함된 CTE 에서 다른 종류의 데이터를 제거하려는 경우에는 이 변환이 적용되지 않습니다.

예를 살펴보겠습니다. 작동하는 예제를 보려면 먼저 일부 데이터가 있는 테이블을 생성해야 합니다.

 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

중복된 값이 있다는 점에 유의하십시오. 8라인과 12라인에 동일한 값을 삽입합니다. 이제 테이블에서 중복 행을 제거해 보겠습니다.

 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

테이블에서 선택을 실행하면 다음과 같은 결과가 표시됩니다

중복된 행이 없다는 점에 유의하십시오. 이러한 CTE 의 기능을 보존하기 위해 Snowflake에서 Delete를 사용하면 다음과 같이 변환됩니다

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

보시다시피 쿼리는 테이블 생성하기 또는 바꾸기로 변환됩니다.

Snowflake에서 테스트해 보겠습니다. 테스트하려면 테이블도 필요합니다.

 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

이제 변환 결과를 실행한 다음 선택을 클릭하여 중복된 행이 삭제되었는지 확인하면 다음과 같은 결과가 표시됩니다.

MERGE 문을 사용한 일반적인 테이블 식

WITH 식 뒤에 MERGE 문이 오면 다음과 같은 변환이 발생하며, 이는 MERGEINTO 호 해결할 수 있습니다..

SQL 서버:

 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

UPDATE 문을 사용한 일반적인 테이블 식

WITH 식 뒤에 UPDATE 문이 오는 경우 다음과 같은 변환이 발생하며, 이는 UPDATE 문으로 변환됩니다.

SQL 서버:

 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

알려진 문제

문제가 발견되지 않았습니다.

관련 EWIs

  1. SSC-EWI-0108: 다음 하위 쿼리는 유효하지 않은 것으로 간주되는 패턴 중 하나 이상과 일치하며 컴파일 오류가 발생할 수 있습니다.

  2. SSC-PRF-TS0001: 성능 경고 - CTE 에 대한 재귀가 확인되지 않았습니다. 재귀 키워드가 필요할 수 있습니다.

삭제

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

SQL 서버의 테이블 또는 뷰에서 1개 이상의 행을 제거합니다. SQL 서버 삭제에 대한 자세한 내용은 여기 를 참조하십시오.

 [ 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

샘플 소스 패턴

DELETE 문을 변환하는 방법은 매우 간단하지만 몇 가지 주의 사항이 있습니다. 이러한 주의 사항 중 하나는 FROM 절에서 여러 소스를 지원하는 방식인데, 아래 그림과 같이 Snowflake에도 이에 상응하는 방식이 있습니다.

SQL 서버

 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

참고

원래 DELETE 는 T1 용이므로 FROM 절에 TABLE2 T2 가 있으면 USING 절을 생성해야 합니다.

테이블에서 중복 삭제하기

다음 설명서에서는 SQL 서버의 테이블에서 중복된 행을 제거하는 데 사용되는 일반적인 패턴 에 대해 설명합니다. 이 접근법은 ROW_NUMBER 함수를 사용하여 쉼표로 구분된 1개 이상의 열일 수 있는 key_value 를 기준으로 데이터를 파티션합니다. 그런 다음 1보다 큰 행 번호 값을 받은 모든 레코드를 삭제합니다. 이 값은 레코드가 중복되어 있음을 나타냅니다. 참조된 설명서를 읽고 이 메서드의 동작을 이해하고 다시 만들 수 있습니다.

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

Copy

다음 예제에서는 이 접근법을 사용하여 테이블과 이에 해당하는 Snowflake에서 중복을 제거합니다. 변환은 테이블을 잘라내는(모든 데이터를 제거) INSERT OVERWRITE 문을 수행한 다음 중복된 행을 무시하고 동일한 테이블에 다시 행을 삽입하는 것으로 구성됩니다. 출력 코드는 원본 코드에 사용되는 PARTITION BYORDER BY 절을 동일하게 고려하여 생성됩니다.

SQL 서버

행이 중복된 테이블 생성하기

 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

중복된 행 제거하기

 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

행이 중복된 테이블 생성하기

 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

중복된 행 제거하기

   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

경고

이 패턴에는 여러 가지 변형이 있을 수 있지만 모두 동일한 원리를 기반으로 하며 동일한 구조를 가지고 있습니다.

Known Issues

문제가 발견되지 않았습니다.

관련 EWIs

관련 EWIs 없음.

방울

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

DROP TABLE

Transact-SQL 의 구문

 DROP TABLE [ IF EXISTS ] <table_name> [ ,...n ]  
[ ; ]  
Copy
Snowflake의 구문
 DROP TABLE [ IF EXISTS ] <name> [ CASCADE | RESTRICT ]
Copy

변환

단일 DROP TABLE 문에 대한 변환은 매우 간단합니다. 문 내에 삭제되는 테이블이 하나만 있는 경우 그대로 유지됩니다.

예:

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

SQL 서버와 Snowflake의 유일한 주목할 만한 차이점은 입력 문이 둘 이상의 테이블을 삭제할 때 표시됩니다. 이러한 시나리오에서는 삭제되는 각 테이블에 대해 서로 다른 DROP TABLE 문이 생성됩니다.

예:

 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

알려진 문제

문제가 발견되지 않았습니다.

관련 EWIs

관련 EWIs 없음.

존재

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

하위 쿼리의 타입

하위 쿼리는 상관관계가 있거나 상관관계가 없는 것으로 분류할 수 있습니다.

상관 하위 쿼리는 하위 쿼리 외부에서 1개 이상의 열을 참조합니다. (열은 일반적으로 하위 쿼리의 WHERE 절 내에서 참조됩니다.) 상관 하위 쿼리는 하위 쿼리가 외부 쿼리에 위치한 테이블의 각 행에서 평가된 것처럼 참조하는 테이블의 필터로 생각할 수 있습니다.

비상관 하위 쿼리는 이러한 외부 열 참조가 없습니다. 그리고 독립적인 쿼리로, 쿼리의 결과는 외부 쿼리에 한 번만 반환 및 사용됩니다(행당 아님).

EXISTS 문은 상관 하위 쿼리로 간주됩니다.

소스 코드

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

예상 코드

 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

알려진 문제

문제가 발견되지 않았습니다.

관련 EWIs

관련 EWIs 없음.

IN

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

IN 연산자는 하위 쿼리에서 반환된 값에 식이 포함되어 있는지 확인합니다.

소스 코드

 -- 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

예상 코드

 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

알려진 문제

문제가 발견되지 않았습니다.

관련 EWIs

관련 EWIs 없음.

삽입

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

SQL 서버의 테이블 또는 뷰에 1개 이상의 행을 추가합니다. SQL 서버 삽입에 대한 자세한 내용은 여기 에서 확인할 수 있습니다.

구문 비교

기본 삽입 문법은 SQL 언어 모두에서 동일합니다. 그러나 SQL 서버에는 여전히 차이점을 보여주는 몇 가지 다른 구문 요소가 있습니다. 예를 들어, 개발자가 할당 연산자를 사용하여 열에 값을 추가할 수 있는 구문 요소가 있습니다. 언급된 구문도 기본 삽입 구문으로 변환됩니다.

Snowflake

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

SQL 서버

 [ 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

샘플 소스 패턴

기본 INSERT

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

assing 연산자가 있는 INSERT

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

INTO 가 없는 INSERT

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

공통 테이블 식이 있는 INSERT

SQL 서버
 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

MERGE 를 DML 로 사용한 테이블 DML 요소가 있는 INSERT

이 경우는 INSERT 문에 SELECT 쿼리가 있고, SELECTFROM 절에 MERGE DML 문이 포함되어 있는 매우 구체적인 경우입니다. Snowflake에서 이에 상응하는 문을 찾으면 다음 문이 생성됩니다. 임시 테이블, the merge 문 converted 및 마지막으로 삽입 문이 생성됩니다.

SQL 서버
 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

경고

참고: 패턴의 이름에서 알 수 있듯이 본문에 MERGE 문이 포함된 select…가 삽입된 경우만 해당합니다.

Known Issues

1. 특수 매핑이 필요한 구문 요소입니다.

  • [INTO]: 이 키워드는 Snowflake에서 필수이며 없는 경우 추가해야 합니다.

  • [DEFAULT VALUES]: 삽입에 지정된 모든 열에 기본값을 삽입합니다. VALUES (DEFAULT, DEFAULT, …)로 변환되어야 하며, 추가된 DEFAULTs 의 양은 삽입이 수정할 열의 수와 같습니다. 현재로서는 경고가 추가되고 있습니다.

    SQL 서버

 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. 지원되지 않거나 관련 없는 구문 요소:

  • [TOP (expression) [PERCENT]]: 삽입할 행의 양 또는 백분율을 나타냅니다. 지원 안 됨.

  • [rowset_function_limited]: OPENQUERY() 또는 OPENROWSET()이며, 원격 서버에서 데이터를 읽는 데 사용됩니다. 지원 안 됨.

  • [WITH table_hint_limited]: 테이블에 대한 읽기/쓰기 잠금을 설정하는 데 사용됩니다. Snowflake와 관련이 없습니다.

  • [<OUTPUT 절>]: 삽입된 행이 삽입될 테이블 또는 결과 세트를 지정합니다. 지원 안 됨.

  • [execute_statement]: 데이터를 가져오는 쿼리를 실행하는 데 사용할 수 있습니다. 지원 안 됨.

  • [dml_table_source]: 다른 DML 문의 OUTPUT 절에 의해 생성된 임시 결과 세트입니다. 지원 안 됨.

3. DELETE 케이스는 고려되지 않고 있습니다.

  • MERGE 를 DML 로 사용한 테이블 DML 요소가 있는 INSERT 패턴의 경우 솔루션에서 DELETE 케이스는 고려하지 않으므로 소스 코드 병합 문에 DELETE 케이스가 있는 경우 예상대로 작동하지 않을 수 있음을 고려하십시오.

관련 EWIs

  1. SSC-EWI-0073: 보류 중 함수 동등성 검토.

  2. SSC-FDM-TS0026: DELETE 케이스는 고려되지 않고 있습니다.

병합

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

구문 비교

Snowflake SQL 구문:

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

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

다음 소스 코드가 주어집니다.

 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

다음과 같은 결과를 기대할 수 있습니다.

 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

  1. SSC-EWI-0021: Snowflake에서 지원되지 않는 구문입니다.

선택

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

SQL 서버에서 1개 이상의 테이블의 행 또는 열을 1개 이상 선택할 수 있습니다.

SQL Server Select에 대한 자세한 내용은 여기 에서 확인할 수 있습니다.

 <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

샘플 소스 패턴

SELECT WITH COLUMN ALIASES

다음 예제는 Snowflake에서 열 별칭을 사용하는 방법을 보여줍니다. SQL 서버 코드의 처음 두 열은 AS 키워드를 사용하여 할당 양식에서 정규화된 양식으로 변환될 것으로 예상됩니다. 세 번째 및 네 번째 열은 유효한 Snowflake 형식을 사용하고 있습니다.

SQL 서버

 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

SQL Server Select Top의 기본 케이스는 Snowflake에서 지원됩니다. 그러나 지원되지 않는 경우가 세 가지 더 있으며, 알려진 문제 섹션에서 확인할 수 있습니다.

SQL 서버

SELECT TOP 1 * from ATable;
Copy

Snowflake

 SELECT TOP 1
*
from
ATable;
Copy

SELECT INTO

다음 예제에서는 SELECT INTOCREATE TABLE AS 로 변환된 것을 볼 수 있는데, 이는 Snowflake에서 SELECT INTO 에 해당하는 것이 없고 쿼리를 기반으로 테이블을 생성하려면 CREATE TABLE AS 를 사용해야 하기 때문입니다.

SQL 서버

 SELECT * INTO NEWTABLE FROM TABLE1;
Copy

Snowflake

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

또 다른 경우는 EXCEPTINTERSECT 과 같은 세트 연산자를 포함하는 경우입니다. 변환은 기본적으로 이전 변환과 동일합니다.

SQL 서버

 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

Known Issues

SELECT TOP 추가 인자

PERCENTWITH TIES 키워드는 결과에 영향을 미치며, Snowflake에서 지원하지 않으므로 오류로 설명되어 추가됩니다.

SQL 서버

 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

FOR 절은 Snowflake에서 지원되지 않으므로 변환 중에 오류로 설명되어 추가됩니다.

SQL 서버

 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

OPTION 절은 Snowflake에서 지원되지 않습니다. 변환하는 동안 설명이 추가되고 경고로 추가됩니다.

경고

OPTION 문은 관련성이 없거나 필요하지 않으므로 변환에서 제거되었음을 참고하십시오.

SQL 서버

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

Snowflake

 SELECT
column1,
column2
FROM
my_table;
Copy

SELECT WITH

WITH 절은 Snowflake에서 지원되지 않습니다. 변환하는 동안 설명이 추가되고 경고로 추가됩니다.

경고

WITH(NOLOCK, NOWAIT) 문은 관련성이 없거나 필요하지 않으므로 변환에서 제거되었습니다.

SQL 서버

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

Snowflake

 SELECT
AValue
from
ATable;
Copy

관련 EWIs

  1. SSC-EWI-0040: 문은 지원되지 않습니다.

  2. SSC-FDM-TS0016: XML 열의 형식은 다를 수 있습니다

세트 연산자

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

TSQL 과 Snowflake의 설정 연산자는 TSQL 에서 지원되지 않는 MINUS 를 제외하고 동일한 구문과 지원 시나리오(EXCEPT, INTERSECT, UNION, UNION ALL)를 제공하므로 변환 시 동일한 코드가 생성됩니다.

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

SELECT ...
INTERSECT
SELECT ...

SELECT ...
EXCEPT
SELECT ...
Copy

잘라내기

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

소스 코드

 TRUNCATE TABLE TABLE1;
Copy

변환된 코드

 TRUNCATE TABLE TABLE1;
Copy

관련 EWIs

관련 EWIs 없음.

업데이트

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

SQL 서버에서 테이블 또는 뷰의 기존 데이터를 변경합니다. SQL 서버 업데이트에 대한 자세한 내용은 여기 를 참조하십시오.

 [ 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

샘플 소스 패턴

기본 UPDATE

일반 UPDATE 문으로 변환하는 방법은 매우 간단합니다. 기본 UPDATE 구조는 Snowflake에서 기본적으로 지원되므로 이상값은 약간의 차이가 있는 부분으로, 알려진 문제 섹션에서 확인하십시오.

SQL 서버
 Update UpdateTest1
Set Col1 = 5;
Copy

Snowflake

 Update UpdateTest1
Set
Col1 = 5;
Copy

데카르트 곱

SQL 서버는 업데이트 문의 대상 테이블과 FROM 절 사이에 순환 참조를 추가할 수 있습니. 실행 시 데이터베이스 최적화 도구는 생성된 데카르트 곱을 제거합니다. 그렇지 않으면, Snowflake는 현재 이 시나리오를 최적화하지 않고 실행 계획에서 확인할 수 있는 데카르트 곱을 생성합니다.\

이를 해결하기 위해 테이블 중 하나가 업데이트 대상과 동일한 JOIN 이 있는 경우 이 참조를 제거하고 WHERE 절에 추가하여 데이터를 필터링하고 세트 작업을 하지 않는 데 사용합니다.

SQL 서버
 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

Known Issues

OUTPUT 절

OUTPUT 절은 Snowflake에서 지원되지 않습니다.

SQL 서버
 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

WITH CTE 절을 업데이트 문의 내부 쿼리로 이동하여 Snowflake에서 지원하도록 합니다.

SQL 서버
 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

TOP 절

TOP 절은 Snowflake에서 지원되지 않습니다.

SQL 서버
 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

업데이트 WITH 절은 Snowflake에서 지원되지 않습니다.

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

Snowflake

 Update UpdateTest5
Set
Col1 = 5;
Copy

관련 EWIs

  1. SSC-EWI-0021: Snowflake에서 지원되지 않는 구문입니다.

JOIN 이 있는 UPDATE 의 대안

이 내용은 진행 중이며 향후 변경될 수 있습니다.

Description

UPDATE FROM 패턴은 다른 테이블의 데이터를 기반으로 데이터를 업데이트하는 데 사용됩니다. 이 SQLServer 설명서 는 간단한 샘플을 제공합니다.

설명서 에서 다음 SQL 서버 구문을 검토하십시오.

SQL 서버 구문

 UPDATE [table_name] 
SET column_name = expression [, ...]
[FROM <table_source> [, ...]]
[WHERE <search_condition>]
[OPTION (query_hint)]
Copy
  • table_name: 업데이트하려는 테이블 또는 뷰입니다.

  • SET: 열과 새 값을 지정합니다. SET 절은 1개 이상의 열에 새 값(또는 식)을 할당합니다.

  • FROM: 1개 이상의 소스 테이블을 지정하는 데 사용됩니다(예: join). 업데이트를 수행하기 위한 데이터의 출처를 정의하는 데 도움이 됩니다.

  • WHERE: 조건에 따라 업데이트할 행을 지정합니다. 이 절이 없으면 테이블의 모든 행이 업데이트됩니다.

  • OPTION (query_hint): 쿼리 최적화를 위한 힌트를 지정합니다.

Snowflake 구문

Snowflake 구문은 Snowflake 설명서 에서도 확인할 수 있습니다.

참고

Snowflake는 UPDATE 절의 JOINs 을 지원하지 않습니다.

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

필수 매개 변수

  • _ target_table: 업데이트할 테이블을 지정합니다.

  • _ col_name: _ target_table_. 에서 열의 이름을 지정합니다. 테이블 이름을 포함하지 마십시오. 예: UPDATE t1 SET t1.col = 1 은 유효하지 않습니다.

  • _ value :_ _ col_name_ 에 설정할 새 값을 지정합니다.

선택적 매개 변수

  • FROM`` _ additional_tables: _ 업데이트할 행을 선택하거나 새 값을 설정하는 데 사용할 1개 이상의 테이블을 지정합니다. 대상 테이블을 반복하면 셀프 조인이 발생한다는 점에 유의하십시오.

  • WHERE`` _ condition: _: 업데이트할 대상 테이블의 행을 지정하는 식입니다. 기본값: 값 없음(대상 테이블의 모든 행이 업데이트됨)

변환 요약

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.

참고-1: 간단한 JOIN 은 FROM 절의 테이블을 사용하고 필요에 따라 WHERE 절에 필터를 추가할 수 있습니다

참고-2: 다른 접근법은 JOINs_을 정의하기 위해 (+) 피연산자를 포함할 수 있습니다

샘플 소스 패턴

설정 데이터

 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

케이스 1: 단일 INNER JOIN 업데이트

INNER JOIN 의 경우 테이블이 FROM 문 내에 사용되면 자동으로 INNER JOIN 으로 바뀝니다. UPDATE 문에서 JOINs 을 지원하는 방법에는 여러 가지가 있습니다. 이는 가독성을 보장하는 가장 간단한 패턴 중 하나입니다.

SQL 서버
 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

수량

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

수량

CustomerName

1

10

John Doe

다른 접근법:

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

케이스 2: 다중 INNER JOIN 업데이트

SQL 서버
 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

수량

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

수량

CustomerName

3

5

Alice Johnson

케이스 3: 집계 조건이 있는 여러 INNER JOIN 업데이트

SQL 서버
 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

수량

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

수량

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

케이스 4: 단일 LEFT JOIN 업데이트

SQL 서버
 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

수량

OrderDate

5

Null

5

7

2024-11-05

13

Null

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

수량

OrderDate

5

Null

5

7

2024-11-05

13

Null

13

13

2024-11-13

참고

Snowflake의 이 접근법은 필요한 행을 업데이트하지 않으므로 작동하지 않습니다.

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

케이스 5: 여러 LEFT JOINRIGHT JOIN 업데이트

이는 더 복잡한 패턴입니다. 여러 LEFT JOINs 을 변환하려면 다음 패턴을 검토하십시오.

참고

LEFT JOINRIGHT JOINFROM 절의 순서에 따라 종속성을 갖습니다.

 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 서버
 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

수량

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

수량

OrderDate

3

3

3

3

2024-11-12

케이스 6: INNER JOINLEFT JOIN 업데이트 혼합

SQL 서버
 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

수량

Null

Null

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

수량

Null

Null

4

케이스 7: 단일 RIGHT JOIN 업데이트

SQL 서버
 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

문제 파악

  • UPDATE 에서 JOINs 을 직접 사용할 수 없으므로 설명된 패턴과 일치하지 않는 경우가 있을 수 있습니다.

UPDATELEFT 및 RIGHTJOIN

Applies to
  • [x] SQL 서버

  • [x] Azure 시냅스 분석

경고

Snowflake에서 부분적으로 지원됨

설명

UPDATE FROM 패턴은 다른 테이블의 데이터를 기반으로 데이터를 업데이트하는 데 사용됩니다. 이 SQLServer 설명서 는 간단한 샘플을 제공합니다.

설명서 에서 다음 SQL 서버 구문을 검토하십시오.

SQL 서버 구문

 UPDATE [table_name] 
SET column_name = expression [, ...]
[FROM <table_source> [, ...]]
[WHERE <search_condition>]
[OPTION (query_hint)]
Copy
  • table_name: 업데이트하려는 테이블 또는 뷰입니다.

  • SET: 열과 새 값을 지정합니다. SET 절은 1개 이상의 열에 새 값(또는 식)을 할당합니다.

  • FROM: 1개 이상의 소스 테이블을 지정하는 데 사용됩니다(예: join). 업데이트를 수행하기 위한 데이터의 출처를 정의하는 데 도움이 됩니다.

  • WHERE: 조건에 따라 업데이트할 행을 지정합니다. 이 절이 없으면 테이블의 모든 행이 업데이트됩니다.

  • OPTION (query_hint): 쿼리 최적화를 위한 힌트를 지정합니다.

Snowflake 구문

Snowflake 구문은 Snowflake 설명서 에서도 확인할 수 있습니다.

참고

Snowflake는 UPDATE 절의 JOINs 을 지원하지 않습니다.

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

필수 매개 변수

  • _ target_table: 업데이트할 테이블을 지정합니다.

  • _ col_name: _ target_table_. 에서 열의 이름을 지정합니다. 테이블 이름을 포함하지 마십시오. 예: UPDATE t1 SET t1.col = 1 은 유효하지 않습니다.

  • _ value :_ _ col_name_ 에 설정할 새 값을 지정합니다.

선택적 매개 변수

  • FROM`` _ additional_tables: _ 업데이트할 행을 선택하거나 새 값을 설정하는 데 사용할 1개 이상의 테이블을 지정합니다. 대상 테이블을 반복하면 셀프 조인이 발생한다는 점에 유의하십시오.

  • WHERE`` _ condition: _: 업데이트할 대상 테이블의 행을 지정하는 식입니다. 기본값: 값 없음(대상 테이블의 모든 행이 업데이트됨)

변환 요약

문법 설명에 설명되어 있듯이 UPDATE 클래스 내에 JOINs 에 대한 직접적인 동등한 솔루션은 없습니다. 따라서 이 문을 변환하는 방법은 필수 권한을 테이블에 논리적으로 추가하는 열에 연산자(+)를 추가하는 것입니다. 이 연산자(+)는 LEFT/RIGHT JOIN 섹션에서 테이블이 참조되는 케이스에 추가됩니다.

이 연산자 (+)를 사용하는 다른 언어가 있으며 연산자의 위치에 따라 조인 유형이 결정될 수 있다는 점에 유의하십시오. 이 특정 경우 Snowflake에서는 위치가 조인 유형을 결정하는 것이 아니라 논리적으로 필요한 테이블 및 열과의 연결에 따라 결정됩니다.

MERGE 케이스 또는 CTE 의 사용법과 같은 다른 대안이 있더라도 쿼리가 복잡하고 방대해지면 이러한 대안은 읽기 어려워지는 경향이 있습니다.

샘플 소스 패턴

설정 데이터

 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 서버

 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 서버

 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

Known Issues

  • 논리의 차이로 인해 변환할 수 없는 패턴이 있을 수 있습니다.

  • 쿼리 패턴이 적용되는 경우 비결정적 행을 검토하십시오. “FROM 절에 테이블 사이(예: t1t2)에 JOIN 이 포함된 경우, t1 의 대상 행은 테이블 t2 의 하나 이상의 행에 조인(즉, 일치)될 수 있습니다. 이 경우 대상 행을 _다중 조인 행_이라고 합니다. 다중 조인 행을 업데이트할 때 ERROR_ON_NONDETERMINISTIC_UPDATE 세션 매개 변수는 업데이트 결과를 제어합니다” (Snowflake 설명서).