SnowConvert AI - SQL Server-Azure Synapse - 일반 언어 요소

이 섹션에서는 Transact-SQL의 일반 문에 대한 정보를 찾을 수 있습니다.

COLLATE

Applies to
  • SQL 서버

  • Azure 시냅스 분석

데이터 정렬의 변환은 지원되거나 지원되지 않을 수 있으므로 그 값에 따라 달라집니다.

현재 변환이 지원되는 언어는 다음과 같으며, 데이터 정렬에서 해당 언어가 발견되면 해당 언어에 해당하는 Snowflake로 변환됩니다.

SQL 서버

Snowflake

Latin1_General

EN

Modern_Spanish

ES

프랑스어

FR

언어가 위의 언어 중 하나가 아닌 경우 데이터 정렬에 설명이 추가됩니다.

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

원본

SELECT 'a' COLLATE Latin1_General_CI_AS;

SELECT 'a' COLLATE Modern_Spanish_CI_AS;

SELECT 'a' COLLATE French_CI_AS;

SELECT 'a' COLLATE Albanian_BIN;

SELECT 'a' COLLATE Latin1_General_CI_AS_WS;

SELECT 'a' COLLATE Latin1_General_CI_AS_KS_WS;

SELECT 'a' COLLATE Albanian_CI_AI;

예상

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

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

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

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

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

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

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

Create Table에서 데이터 정렬의 예를 보겠습니다

원본

CREATE TABLE TABLECOLLATE
(
    COL1 VARCHAR COLLATE Latin1_General_CI_AS
);

예상

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

보시다시피 Select 또는 Table 내에서 데이터 정렬의 변환은 동일합니다.

COMPUTED COLUMN

계산된 식을 변환할 수 없습니다.

Applies to
  • SQL 서버

  • Azure 시냅스 분석

설명

계산된 열의 식을 변환할 수 없습니다.

코드 예제

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

권장 사항

  • 변환되지 않은 식에 수동 변경 사항을 추가합니다.

  • 추가 지원이 필요한 경우 snowconvert-support@snowflake.com으로 이메일을 보내주세요.

관련 EWIs

  1. SSC-FDM-TS0014: 계산된 열이 변환되었습니다.

OUTER APPLY

동등한 문으로 외부 apply 문 변환.

Applies to
  • SQL 서버

  • Azure 시냅스 분석

참고

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

설명

OUTER APPLY 를 지정하면 오른쪽 행 집합 식이 해당 행에 대해 빈 행 집합을 반환하더라도 왼쪽 행 집합의 각 행에 대해 1개의 행이 생성됩니다. (OUTER APPLY 정의)

구문

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

Snowflake 등가성

지원되지 않는 문이 OUTER APPLY 에 있지만, 이에 상응하는 문이 LATERAL 입니다. 따라서 문에 대한 변환은 대체 솔루션을 사용하여 동일한 기능을 얻기 위해 수행됩니다.

그럼에도 불구하고 Snowflake의 LATERAL 문은 구문에서 두 가지 변형이 있습니다. 실제로 이 특정 변환에서는 INNER JOIN LATERAL 변형이 사용됩니다.

Snowflake의 INNER JOIN LATERAL 문법은 다음과 같습니다.

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

참고

_<inline_view>_는 테이블 이름이 아니어야 합니다.

그리고 단일 LATERAL 문은 아래와 같습니다.

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

샘플 소스

다음 예제는 OUTER APPLY 와 INNER JOIN LATERAL 사이의 일반적인 변환을 보여줍니다.

SQL 서버

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

출력

p.ProjectName

e.ProjectName

FirstName

Project A

Project A

John

Project A

Project A

Jane

Project A

Project B

Michael

Project B

Project A

John

Project B

Project A

Jane

Project B

Project B

Michael

Project C

Project A

John

Project C

Project A

Jane

Project C

Project B

Michael

Snowflake

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

출력

PROJECTNAME

PROJECTNAME_2

FIRSTNAME

Project A

Project A

John

Project A

Project A

Jane

Project A

Project B

Michael

Project B

Project A

John

Project B

Project A

Jane

Project B

Project B

Michael

Project C

Project A

John

Project C

Project A

Jane

Project C

Project B

Michael

알려진 문제

변환은 입력된 내용을 그대로 옮기는 것이므로 몇 가지 제한이 있습니다.

  • TOP 및 WHERE 문을 검토하여 동작을 최적화할 수 있습니다.

  • 문 끝에 상관관계 이름이 필요할 수 있습니다. Snowflake에서는 상관 관계 이름이 쿼리에 없는 경우 문제가 되지 않지만 기능이 변경되어 SQL 서버에서 허용되는 패턴의 일부를 형성하지 않을 수 있습니다.

SQL 서버

SELECT
    SATT.UNIVERSAL_NAME
FROM
SAMPLE_ATLAS AS SATT
OUTER APPLY (
    SELECT
        TOP 1 UNIVERSAL_NAME,
        INTERNATIONAL_NAME,
        CODE_IDENTIFIER
    FROM
        SAMPLE_GLOBE AS SG
    WHERE
        SG.GLOBE_KEY = SATT.MbrPersGenKey
    ORDER BY
        GLOBE_KEY
);
변환 출력
SELECT
            UNIVERSAL_NAME
FROM
            SAMPLE_ATLAS
            AS SATT
            OUTER APPLY
                        /*** MSC-ERROR - MSCCP0001 - THE FOLLOWING SUBQUERY MATCHES AT LEAST ONE OF THE PATTERNS CONSIDERED INVALID AND MAY PRODUCE COMPILATION ERRORS ***/ (SELECT TOP 1
                                                UNIVERSAL_NAME,
                                                INTERNATIONAL_NAME,
                                                CODE_IDENTIFIER
                                    FROM
                                                SAMPLE_GLOBE AS SG
                                    WHERE
                                                SG.GLOBE_KEY = SATT.MbrPersGenKey
                                    ORDER BY GLOBE_KEY
                        );
  • 지원되지 않는 특정 문은 모든 블록 코드를 설명할 수 있습니다(예: JSON 예시) .

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

관련 EWIs

관련 EWIs 없음.

USE

Snowflake의 동등한 Transact-SQL USE 문

Applies to
  • SQL 서버

USE 문은 Snowflake에 해당하는 문이 있습니다. 문은 Snowflake의 USE DATABASE문으로 변환됩니다.

변환 예시

원본

USE [MY DATABASE]

출력

USE DATABASE "MY DATABASE";

데이터베이스 이름

USE 문에 지정된 데이터베이스 이름대괄호 ([ ]) 내에 들어올 경우 변경될 수 있습니다. 첫 번째 괄호와 마지막 괄호는 _따옴표_로 바뀝니다. 예:

원본
[MYDATABASE]
[[[MYDATABASE]]
출력
"MYDATABASE"
"[[MYDATABASE]"

사용자 정의 데이터베이스

사용자가 변환 도구에 -d 매개 변수를 사용하여 모든 오브젝트에 적용할 사용자 정의 데이터베이스 이름을 지정하고 USE 문을 변환하려는 경우 데이터베이스 이름은 오브젝트가 아닌 USE 문에만 적용되어야 합니다. 이렇게 하면 사용 문에서 지정된 데이터베이스가 재정의됩니다. 예:

원본
-- Additional Params: -d MYCUSTOMDB
USE [MY DATABASE]

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

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

Known Issues

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

관련 EWIs

관련 EWIs 없음.

EXECUTE

Applies to
  • SQL 서버

  • Azure 시냅스 분석

실행 또는 실행 문에 대한 변환은 Snowflake에서 지원되지 않지만, CALL 문으로 변환됩니다.

참고

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

입력

Exec db.sp1

출력

CALL db.sp1();

Execute에 대한 자세한 내용은 프로시저 내부 실행을 참조하세요.

PRINT

Applies to
  • SQL 서버

  • Azure 시냅스 분석


Print 문은 Snowflake에서 직접 지원되지 않지만, 가장 가까운 문인 SYSTEM$LOG_INFO 기본 제공 함수로 변환됩니다.

입력

PRINT 'My message';

출력(SnowScript 내부)

SYSTEM$LOG_INFO('My message');

출력(SnowScript 외부)

Print 문이 저장 프로시저 외부에서 사용되는 경우, SnowConvert AI UDP에서 호출해야 합니다.

CALL PUBLIC.LOG_INFO_UDP('My message');

메시지 로깅을 시작하려면 먼저 이벤트 테이블을 설정해야 합니다. 자세한 내용은 Snowflake Scripting에서 메시지 로깅을 참조하세요.

시스템 저장 프로시저

SP_EXECUTESQL

시스템 프로시저 SP_EXECUTESQL에 대한 변환 사양.

Applies to
  • SQL 서버

  • Azure 시냅스 분석

설명

SP_EXECUTESQL 시스템 저장 프로시저는 Transact-SQL 문 또는 여러 번 재사용할 수 있는 배치 또는 동적으로 빌드된 배치를 실행하는 데 사용됩니다. 문 또는 배치에는 임베디드 매개 변수가 포함될 수 있습니다.

이 기능은 EXECUTE IMMEDIATE 문과 임베디드 매개 변수에 대한 UDF(사용자 정의 함수)를 사용하여 Snowflake에서 에뮬레이션할 수 있습니다.

이 변환에 사용된 UDF(사용자 정의 함수)에 대한 자세한 내용은 TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(STRING, STRING, ARRAY, ARRAY)를 확인하세요.

구문

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

샘플 소스 패턴

모든 패턴은 SP_EXECUTESQL 을 Snowflake의 EXECUTE IMMEDIATE 문으로 변환하고 임베디드 매개 변수를 사용할 때만 SQL 문자열이 실행되도록 수정했습니다.

경고

SSC-EWI-0030 (동적 SQL 사용)이 모든 패턴에 추가됩니다. SP_EXECUTESQL 변환은 Snowflake와 동일하지만, 이 문맥에서 EWI 는 SQL 문자열이 의도한 대로 실행되려면 수동 수정이 필요할 수 있음을 나타냅니다.

설정 데이터

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

-- DATA
INSERT INTO PERSONS VALUES ('John Smith', 1, 24);
INSERT INTO PERSONS VALUES ('John Doe', 2, 21);
INSERT INTO PERSONS VALUES ('Mary Keller', 3, 32);
INSERT INTO PERSONS VALUES ('Mundane Man', 4, 18);
Snowflake
 CREATE OR REPLACE TABLE PERSONS (
  NAME VARCHAR(25),
  ID INT,
  AGE INT
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
;

-- DATA
INSERT INTO PERSONS VALUES ('John Smith', 1, 24);
INSERT INTO PERSONS VALUES ('John Doe', 2, 21);
INSERT INTO PERSONS VALUES ('Mary Keller', 3, 32);
INSERT INTO PERSONS VALUES ('Mundane Man', 4, 18);

내장된 매개 변수 없음

임베디드 매개 변수가 사용되지 않는 경우 SP_EXECUTESQL 은 EXECUTE IMMEDIATE 문으로 변환되고 수정 없이 SQL 문자열을 사용합니다.

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

GO

EXEC SIMPLE_SINGLE_QUERY;
결과

이름

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

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

CALL SIMPLE_SINGLE_QUERY();
결과

이름

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

데이터 바인딩을 위한 내장 매개 변수 포함

데이터 바인딩을 위한 임베디드 매개 변수의 경우, SP_EXECUTESQL은 EXECUTE IMMEDIATE 문으로 변환되고 SQL 문자열은 TRANSFORM_SP_EXECUTE_SQL_STRING_UDF를 통해 수정됩니다.

EXECUTE IMMEDIATE 의 결과는 ProcedureResultSet 변수에 할당되고 나중에 TABLE(ProcedureResultSet) 로 반환됩니다.

Transact
 CREATE PROCEDURE QUERY_WITH_DATA_BINDING_PARAMS
AS
BEGIN
    DECLARE @IntVariable INT;
    DECLARE @SQLString NVARCHAR(500);
    DECLARE @ParmDefinition NVARCHAR(500);

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

GO

EXEC QUERY_WITH_DATA_BINDING_PARAMS;
결과

이름

ID

AGE

John Doe

2

21

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

CALL QUERY_WITH_DATA_BINDING_PARAMS();
결과

이름

ID

AGE

John Doe

2

21

내장된 OUTPUT 매개 변수 포함

임베디드 OUTPUT 매개 변수의 경우 SP_EXECUTESQL 은EXECUTE IMMEDIATE 문으로 변환되고 SQL 문자열은 TRANSFORM_SP_EXECUTE_SQL_STRING_UDF 을 통해 수정됩니다.

또한 SELECT $1, ..., $n INTO :outputParam1, ..., :outputParamN FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())) 이 각 열의 결과에 해당 OUTPUT 매개 변수에 추가됩니다.

경고

SSC-FDM-TS0028 은 SELECT INTO 문에 추가됩니다. INTO 절의 매개 변수는 원래 SQL 문자열에 할당된 것과 동일한 순서로 표시되어야 합니다.

그렇지 않으면 이 필수 권한을 충족하기 위해 수동으로 변경해야 합니다.

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

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

    SELECT @MaxAge;
END

GO

EXEC QUERY_WITH_OUTPUT_PARAMS;
결과

<anonymous>

32

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

CALL QUERY_WITH_OUTPUT_PARAMS();
결과

:MAXAGE::NUMBER(38,0)

32

임베디드 OUTPUT 매개 변수 및 데이터 바인딩 모두 포함

변환은 OUTPUT 매개 변수만 변환하는 것과 동일합니다.

Transact
CREATE PROCEDURE QUERY_WITH_BOTH_PARAMS
AS
BEGIN
    DECLARE @AgeVariable INT;
    DECLARE @IdVariable INT;
    DECLARE @SQLString NVARCHAR(500);
    DECLARE @ParmDefinition NVARCHAR(500);
    DECLARE @MaxAge INT;
    DECLARE @MaxId INT;

    SET @AgeVariable = 30;
    SET @IdVariable = 100;
    SET @SQLString = N'SELECT @MaxAgeOUT = max(AGE), @MaxIdOut = max(ID) FROM PERSONS WHERE AGE < @age AND ID < @id;';
    SET @ParmDefinition = N'@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT';
    EXECUTE sp_executesql @SQLString, @ParmDefinition, @age = @AgeVariable, @id = @IdVariable, @MaxAgeOUT = @MaxAge OUTPUT, @MaxIdOUT = @MaxId OUTPUT;

    SELECT @MaxAge, @MaxId;
END

GO

EXEC QUERY_WITH_BOTH_PARAMS;
결과

<anonymous>

<anonymous>

24

4

Snowflake
CREATE OR REPLACE PROCEDURE QUERY_WITH_BOTH_PARAMS ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    AGEVARIABLE INT;
    IDVARIABLE INT;
    SQLSTRING VARCHAR(500);
    PARMDEFINITION VARCHAR(500);
    MAXAGE INT;
    MAXID INT;
    ProcedureResultSet RESULTSET;
  BEGIN
     
     
     
     
     
     
    AGEVARIABLE := 30;
    IDVARIABLE := 100;
    SQLSTRING := 'SELECT
   MAX(AGE),
   MAX(ID) FROM
   PERSONS
WHERE
   AGE < @age AND ID < @id;';
    PARMDEFINITION := '@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT';
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(:SQLSTRING, :PARMDEFINITION, ARRAY_CONSTRUCT('AGE', 'ID', 'MAXAGEOUT', 'MAXIDOUT'), ARRAY_CONSTRUCT(:AGEVARIABLE, :IDVARIABLE, :MAXAGE, :MAXID));
    --** SSC-FDM-TS0028 - OUTPUT PARAMETERS MUST HAVE THE SAME ORDER AS THEY APPEAR IN THE EXECUTED CODE **
    SELECT
      $1,
      $2
    INTO
      :MAXAGE,
      :MAXID
    FROM
      TABLE(RESULT_SCAN(LAST_QUERY_ID()));
    ProcedureResultSet := (
    SELECT
      :MAXAGE,
      :MAXID);
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL QUERY_WITH_BOTH_PARAMS();
결과

:MAXAGE::NUMBER(38,0)

:MAXID::NUMBER(38,0)

24

4

정의 순서가 아닌 매개 변수

이 패턴은 이전 패턴과 동일한 규칙을 따릅니다. TRANSFORM_SP_EXECUTE_SQL_STRING_UDF 매개 변수 값을 올바른 순서로 바꿉니다.

Transact
CREATE PROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF
AS
BEGIN
    DECLARE @AgeVariable INT;
    DECLARE @IdVariable INT;
    DECLARE @SQLString NVARCHAR(500);
    DECLARE @ParmDefinition NVARCHAR(500);
    DECLARE @MaxAge INT;
    DECLARE @MaxId INT;

    SET @AgeVariable = 30;
    SET @IdVariable = 100;
    SET @SQLString = N'SELECT @MaxAgeOUT = max(AGE), @MaxIdOut = max(ID) FROM PERSONS WHERE AGE < @age AND ID < @id;';
    SET @ParmDefinition = N'@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT';
    EXECUTE sp_executesql @SQLString, @ParmDefinition, @id = @IdVariable, @MaxAgeOUT = @MaxAge OUTPUT, @age = @AgeVariable, @MaxIdOUT = @MaxId OUTPUT;

    SELECT @MaxAge, @MaxId;
END

GO

EXEC QUERY_PARAMS_NOT_IN_ORDER_OF_DEF;

CREATE PROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2
AS
BEGIN
    DECLARE @AgeVariable INT;
    DECLARE @IdVariable INT;
    DECLARE @SQLString NVARCHAR(500);
    DECLARE @ParmDefinition NVARCHAR(500);
    DECLARE @MaxAge INT;
    DECLARE @MaxId INT;

    SET @AgeVariable = 30;
    SET @IdVariable = 100;
    SET @SQLString = N'SELECT @MaxAgeOUT = max(AGE), @MaxIdOut = max(ID) FROM PERSONS WHERE AGE < @age AND ID < @id;';
    SET @ParmDefinition = N'@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT';
    EXECUTE sp_executesql @SQLString, @ParmDefinition, @AgeVariable, @MaxAgeOUT = @MaxAge OUTPUT, @id = @IdVariable, @MaxIdOUT = @MaxId OUTPUT;

    SELECT @MaxAge, @MaxId;
END

GO

EXEC QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2;
결과

<anonymous>

<anonymous>

24

4

<anonymous>

<anonymous>

24

4

Snowflake
CREATE OR REPLACE PROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    AGEVARIABLE INT;
    IDVARIABLE INT;
    SQLSTRING VARCHAR(500);
    PARMDEFINITION VARCHAR(500);
    MAXAGE INT;
    MAXID INT;
    ProcedureResultSet RESULTSET;
  BEGIN
     
    AGEVARIABLE := 30;
    IDVARIABLE := 100;
    SQLSTRING := 'SELECT
   MAX(AGE),
   MAX(ID) FROM
   PERSONS
WHERE
   AGE < @age AND ID < @id;';
    PARMDEFINITION := '@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT';
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(:SQLSTRING, :PARMDEFINITION, ARRAY_CONSTRUCT('ID', 'MAXAGEOUT', 'AGE', 'MAXIDOUT'), ARRAY_CONSTRUCT(:IDVARIABLE, :MAXAGE, :AGEVARIABLE, :MAXID));
    --** SSC-FDM-TS0028 - OUTPUT PARAMETERS MUST HAVE THE SAME ORDER AS THEY APPEAR IN THE EXECUTED CODE **
    SELECT
      $1,
      $2
    INTO
      :MAXAGE,
      :MAXID
    FROM
      TABLE(RESULT_SCAN(LAST_QUERY_ID()));
    ProcedureResultSet := (
    SELECT
      :MAXAGE,
      :MAXID);
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL QUERY_PARAMS_NOT_IN_ORDER_OF_DEF();

CREATE OR REPLACE PROCEDURE QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2 ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/04/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    AGEVARIABLE INT;
    IDVARIABLE INT;
    SQLSTRING VARCHAR(500);
    PARMDEFINITION VARCHAR(500);
    MAXAGE INT;
    MAXID INT;
    ProcedureResultSet RESULTSET;
  BEGIN
     
     
     
     
     
     
    AGEVARIABLE := 30;
    IDVARIABLE := 100;
    SQLSTRING := 'SELECT
   MAX(AGE),
   MAX(ID) FROM
   PERSONS
WHERE
   AGE < @age AND ID < @id;';
    PARMDEFINITION := '@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT';
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(:SQLSTRING, :PARMDEFINITION, ARRAY_CONSTRUCT('', 'MAXAGEOUT', 'ID', 'MAXIDOUT'), ARRAY_CONSTRUCT(:AGEVARIABLE, :MAXAGE, :IDVARIABLE, :MAXID));
    --** SSC-FDM-TS0028 - OUTPUT PARAMETERS MUST HAVE THE SAME ORDER AS THEY APPEAR IN THE EXECUTED CODE **
    SELECT
      $1,
      $2
    INTO
      :MAXAGE,
      :MAXID
    FROM
      TABLE(RESULT_SCAN(LAST_QUERY_ID()));
    ProcedureResultSet := (
    SELECT
      :MAXAGE,
      :MAXID);
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL QUERY_PARAMS_NOT_IN_ORDER_OF_DEF_2();
결과

:MAXAGE::NUMBER(38,0)

:MAXID::NUMBER(38,0)

24

4

:MAXAGE::NUMBER(38,0)

:MAXID::NUMBER(38,0)

24

4

직접 값 실행

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

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

    EXECUTE sp_executesql
        N'SELECT @MaxAgeOUT = max(AGE), @MaxIdOut = max(ID) FROM PERSONS WHERE ID < @id AND AGE < @age;',
        N'@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT',
        30,
        100,
        @MaxAge OUTPUT,
        @MaxId OUTPUT;

    SELECT @MaxAge, @MaxId;
END

GO

EXEC QUERY_WITH_DIRECT_PARAMS_VALUES_ALL;
결과

<anonymous>

<anonymous>

24

4

Snowflake
CREATE OR REPLACE PROCEDURE QUERY_WITH_DIRECT_PARAMS_VALUES_ALL ()
RETURNS TABLE()
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/07/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    MAXAGE INT;
    MAXID INT;
    ProcedureResultSet RESULTSET;
  BEGIN
     
     
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF('SELECT
   MAX(AGE),
   MAX(ID) FROM
   PERSONS
WHERE
   ID < @id AND AGE < @age;', '@age INT, @id INT, @MaxAgeOUT INT OUTPUT, @MaxIdOUT INT OUTPUT', ARRAY_CONSTRUCT('', '', '', ''), ARRAY_CONSTRUCT(
    30,
    100, :MAXAGE, :MAXID));
    --** SSC-FDM-TS0028 - OUTPUT PARAMETERS MUST HAVE THE SAME ORDER AS THEY APPEAR IN THE EXECUTED CODE **
    SELECT
      $1,
      $2
    INTO
      :MAXAGE,
      :MAXID
    FROM
      TABLE(RESULT_SCAN(LAST_QUERY_ID()));
    ProcedureResultSet := (
    SELECT
      :MAXAGE,
      :MAXID);
    RETURN TABLE(ProcedureResultSet);
  END;
$$;

CALL QUERY_WITH_DIRECT_PARAMS_VALUES_ALL();
결과

:MAXAGE::NUMBER(38,0)

:MAXID::NUMBER(38,0)

24

4

SQL 동적으로 작성된 문자열

이 패턴은 이전 패턴과 동일한 규칙을 따릅니다. 그러나 SQL 문자열이 매개 변수가 포함되거나 포함되지 않은 단순한 단일 쿼리가 아닌 경우 EXECUTE IMMEDIATE 문의 결과를 할당하지 않을 수 있습니다.

또한, SnowConvert AI가 SELECT 문이 실행될 것이라는 사실을 올바르게 식별하려면 SQL 문자열은 리터럴 값 'SELECT'로 시작해야 합니다.

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

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

GO

EXEC DYNAMIC_WITH_PARAMS;
결과

이름

ID

AGE

John Doe

2

21

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

CALL DYNAMIC_WITH_PARAMS();
결과

이름

ID

AGE

John Doe

2

21

여러 결과 세트 반환하기

Snowflake Scripting 프로시저에서는 프로시저당 1개의 결과 세트만 반환할 수 있습니다.

Transact-SQL 동작을 복제하려면 2개 이상의 결과 세트가 반환되어야 하는 경우 임시 테이블에 저장됩니다. Snowflake Scripting 프로시저는 임시 테이블의 이름이 포함된 배열을 반환합니다. 자세한 내용은 SSC-FDM-0020 섹션을 참조하십시오.

Transact
CREATE PROCEDURE WITH_MULTIPLE_RETURNS
AS
BEGIN
    DECLARE @SQLString NVARCHAR(500);
    DECLARE @ParmDefinition NVARCHAR(500);

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

    SET @SQLString = N'INSERT INTO PERSONS VALUES (''INSERT FIRST'', 1200, 230);';
    EXECUTE sp_executesql @SQLString;

    SET @SQLString = N'SELECT * FROM PERSONS';
    EXECUTE sp_executesql @SQLString;
END

GO

EXECUTE WITH_MULTIPLE_RETURNS;
결과

이름

ID

AGE

John Doe

2

21

이름

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

INSERT FIRST

1200

230

Snowflake
CREATE OR REPLACE PROCEDURE WITH_MULTIPLE_RETURNS ()
RETURNS ARRAY
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "transact",  "convertedOn": "10/07/2024" }}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    SQLSTRING VARCHAR(500);
    PARMDEFINITION VARCHAR(500);
    ProcedureResultSet1 VARCHAR;
    ProcedureResultSet2 VARCHAR;
    return_arr ARRAY := array_construct();
  BEGIN
     
     
    SQLSTRING := 'SELECT
   *
FROM
   PERSONS
WHERE
   AGE = @age;';
    PARMDEFINITION := '@age INT';
    ProcedureResultSet1 := 'RESULTSET_' || REPLACE(UPPER(UUID_STRING()), '-', '_');
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE TRANSFORM_SP_EXECUTE_SQL_STRING_UDF(:SQLSTRING, :PARMDEFINITION, ARRAY_CONSTRUCT('AGE'), ARRAY_CONSTRUCT(21));
    CREATE OR REPLACE TEMPORARY TABLE IDENTIFIER(:ProcedureResultSet1) AS
      SELECT
        *
      FROM
        TABLE(RESULT_SCAN(LAST_QUERY_ID()));
    return_arr := array_append(return_arr, :ProcedureResultSet1);
    SQLSTRING := 'INSERT INTO PERSONS VALUES ('INSERT FIRST', 1200, 230);';
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE :SQLSTRING;
    SQLSTRING := 'SELECT
   *
FROM
   PERSONS;';
    ProcedureResultSet2 := 'RESULTSET_' || REPLACE(UPPER(UUID_STRING()), '-', '_');
    !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
    EXECUTE IMMEDIATE :SQLSTRING;
    CREATE OR REPLACE TEMPORARY TABLE IDENTIFIER(:ProcedureResultSet2) AS
      SELECT
        *
      FROM
        TABLE(RESULT_SCAN(LAST_QUERY_ID()));
    return_arr := array_append(return_arr, :ProcedureResultSet2);
    --** SSC-FDM-0020 - MULTIPLE RESULT SETS ARE RETURNED IN TEMPORARY TABLES **
    RETURN return_arr;
  END;
$$;

CALL WITH_MULTIPLE_RETURNS();
결과

WITH_MULTIPLE_RETURNS

[ “RESULTSET_88C35D7A_1E5B_455D_97A4_247806E583A5”, “RESULTSET_B2345B61_A015_43CB_BA11_6D3E013EF262” ]

Known Issues

1. Invalid code is detected

SP_EXECUTESQL은 SQL 문자열 내부에서 둘 이상의 SQL 문을 실행할 수 있습니다. 또한 Snowflake는 여러 SQL 문을 실행하도록 지원하지만 BEGIN ... END 블록으로 묶어야 합니다. 또한, BEGIN ... END 블록에서 여러 문을 실행할 때 EXECUTE IMMEDIATE는 결과 세트를 반환하지 않습니다. 이러한 사례에 대한 변환은 SnowConvert AI에서 아직 지원되지 않습니다. 자세한 내용은 SSC-EWI-0030을 참조하세요.

따라서 이 경우가 감지되면 변환된 코드에서 EXECUTE IMMEDIATEProcedureResultSet 에 할당되지 않습니다.

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

GO

EXEC WITH_INVALID_CODE_DETECTED;
결과

이름

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

INSERT FIRST

1200

230

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

CALL WITH_INVALID_CODE_DETECTED();
결과
000006 (0A000): Uncaught exception of type 'STATEMENT_ERROR' on line 10 at position 4 : Multiple SQL statements in a single API call are not supported; use one API call per statement instead.

2. Valid or Invalid code is not detected

SQL 문자열이 연결을 통해 동적으로 빌드되면 SnowConvert AI는 실행할 문을 감지하지 못할 수 있습니다. 따라서 변환된 코드에서 EXECUTE IMMEDIATEProcedureResultSet에 할당되지 않습니다.

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

GO

EXEC WITH_INVALID_CODE_NOT_DETECTED;
결과

이름

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

INSERT FIRST

1200

230

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

CALL WITH_INVALID_CODE_NOT_DETECTED();
결과
000006 (0A000): Uncaught exception of type 'STATEMENT_ERROR' on line 10 at position 4 : Multiple SQL statements in a single API call are not supported; use one API call per statement instead.

3. Invalid code is mistaken as valid

SQL 문자열이 SELECT 문으로 시작되고 뒤에 더 많은 문이 오는 경우 SnowConvert AI는 이를 유효한 코드로 감지하고 EXECUTE IMMEDIATE의 결과를 ProcedureResultSet에 할당하려고 시도합니다. 이로 인해 컴파일 오류가 발생합니다. 자세한 내용은 SSC-EWI-0030을 참조하세요.

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

GO

EXEC WITH_INVALID_CODE_MISTAKEN_AS_VALID;
결과

이름

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

이름

ID

AGE

John Smith

1

24

John Doe

2

21

Mary Keller

3

32

Mundane Man

4

18

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

CALL WITH_INVALID_CODE_MISTAKEN_AS_VALID();
결과
000006 (0A000): Uncaught exception of type 'STATEMENT_ERROR' on line 10 at position 4 : Multiple SQL statements in a single API call are not supported; use one API call per statement instead.

관련 EWIs

  1. SSC-EWI-0030: 아래 문에는 동적 SQL 의 사용법이 설명되어 있습니다.

  2. SSC-FDM-TS0028: 출력 매개 변수는 실행된 코드에 표시되는 순서와 동일해야 합니다.

  3. SSC-FDM-0020: 여러 결과 세트가 임시 테이블에 반환됩니다.

SP_RENAME

Stored Procedure to Rename certain objects in SQL Server

Applies to
  • SQL 서버

  • Azure 시냅스 분석

특정 시나리오에서는 SP_RENAME 시스템 저장소 프로시저를 Snowflake에서 에뮬레이션할 수 있습니다. 일반적으로 ALTER TABLE 및 원래 매개 변수와 동적 문을 사용하는 EXECUTE IMMEDIATE를 통해 동등한 기능을 얻을 수 있습니다.

테이블 변환 예제

원본

EXEC sp_rename 'TABLE1', 'TABLENEW1'

출력

EXECUTE IMMEDIATE 'ALTER TABLE TABLE1 RENAME TO TABLENEW1';
원본
DECLARE @varname1 nvarchar(50) = 'previous_name'
DECLARE @varname2 nvarchar(50) = 'newer_name'
EXEC sp_rename @varname1, @varname2
출력
DECLARE
VARNAME1 VARCHAR(50) := 'previous_name';
VARNAME2 VARCHAR(50) := 'newer_name';
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE ' || :VARNAME1 || ' RENAME TO ' || :VARNAME2;
END;

열의 변환 예제

원본
EXEC sp_rename 'sample_BACKUP_2.column_old', 'column_new', 'COLUMN'
EXEC sp_rename 'database1.sample_BACKUP_3.column_old', 'column_new', 'COLUMN'
출력
EXECUTE IMMEDIATE 'ALTER TABLE sample_BACKUP_2 RENAME COLUMN column_old TO column_new';

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

관련 EWIs

  1. SSC-EWI-TS0075: 기본 제공 프로시저에 대한 변환은 현재 지원되지 않습니다.

WAITFOR DELAY

Applies to
  • SQL 서버

  • Azure 시냅스 분석

설명

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

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

참고

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

변환 예시

WAITFOR DELAY with literal time

입력 코드:
 CREATE PROCEDURE proc1()
AS
BEGIN
  WAITFOR DELAY '00:00:30';
END
Generated Code:
 CREATE OR REPLACE PROCEDURE proc1 ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  BEGIN
    CALL SYSTEM$WAIT(30);
  END;
$$;

WAITFOR DELAY with sub-second precision

입력 코드:
 CREATE PROCEDURE proc1()
AS
BEGIN
  WAITFOR DELAY '00:00:00.500';
END
Generated Code:
 CREATE OR REPLACE PROCEDURE proc1 ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  BEGIN
    CALL SYSTEM$WAIT(500, 'MILLISECONDS');
  END;
$$;

WAITFOR DELAY with variable

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

WAITFOR DELAY at script level

입력 코드:
 WAITFOR DELAY '00:00:30';
Generated Code:
 CALL SYSTEM$WAIT(30);

Known Limitations

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

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

관련 EWIs

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

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

CREATE STATISTICS

Applies to
  • SQL 서버

  • Azure 시냅스 분석

설명

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

Translation Example

입력 코드:

CREATE STATISTICS Stats1 ON dbo.Table1(col1);

Generated Code:

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

Additional Example

입력 코드:

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

Generated Code:

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

Known Limitations

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