SnowConvert AI - SQL Server-Azure Synapse - 프로시저

이 섹션에서는 구문 및 프로시저의 TSQL 문을 Snowflake Javascript로 변환하는 작업을 설명합니다

Applies to
  • SQL 서버

  • Azure 시냅스 분석

참고

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

1. CREATE PROCEDURE Translation

Snowflake CREATE PROCEDURE 는 SQL 구문에서 정의되는 반면 내부 문은 JavaScript 에 정의됩니다.

Transact

 -- Additional Params: -t JavaScript
CREATE PROCEDURE HumanResources.uspGetAllEmployees
     @FirstName NVARCHAR(50),
     @Age INT
AS
    -- TSQL Statements and queries...
GO
Copy

Snowflake

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

매개 변수의 DATA TYPE

매개 변수 데이터 타입은 Snowflake에 해당하는 데이터 타입으로 변환됩니다. 데이터 타입도 참조하세요.

EXEC 헬퍼

SnowFlake 환경에서 프로시저에서 문을 실행하려면 이러한 문을 사전 처리하고 소스 언어에 특정한 여러 변수에 실행이 반영되도록 조정해야 합니다.

SnowConvert AI는 지원되는 문을 자동으로 변환하고 EXEC 헬퍼를 사용합니다. 이 헬퍼는 이러한 문이 네이티브 환경에서 실행되는 방식을 시뮬레이션하는 많은 변수를 액세스 및 업데이트하는 기능을 제공합니다.

예를 들어, 마이그레이션된 프로시저에서 항상 추가되는 코드 블록이 있는 것을 볼 수 있습니다. 다음 섹션에서 이 코드의 기본 구조에 대해 설명하겠습니다. 저희는 항상 변형을 간소화할 수 있는 새롭고 개선된 방법과 요구 사항이 있는 헬퍼를 평가하고 찾고 있다는 점을 명심하십시오.

구조

EXEC 헬퍼의 기본 구조는 다음과 같습니다.

  1. 변수 선언 섹션: 프로시저 내부에서 문의 실행과 관련된 값을 담을 다양한 변수나 오브젝트를 선언합니다. 여기에는 문의 영향을 받는 행 수 또는 결과 세트 자체와 같은 값이 포함됩니다.

  2. fixBind 함수 선언: 바인딩이 날짜 유형일 때 수정하는 데 사용되는 보조 함수입니다.

  3. EXEC 함수 선언: 기본 EXEC 헬퍼 함수입니다. 실행할 문, 바인드 배열(기본적으로 실행에 의해 수정될 수 있고 프로시저 실행 내내 데이터 영속성을 요구하는 변수 또는 매개 변수), ERROR_HANDLERS 를 사용해야 하는지 여부를 결정하는 noCatch 플래그, 문 실행에 예외가 있을 때 사용자 정의 코드를 실행하기 위한 catchFunction 함수를 받습니다. EXEC함수의 본문은 매우 간단합니다. 문을 실행하고 그 실행으로 생성된 모든 중요한 데이터를 오류 처리 블록에 저장합니다.

  4. ERROR VARS: EXEC 캐치 블록은 SQL 서버_LINE](https://docs.microsoft.com/en-us/sql/t-sql/functions/error-line-transact-sql?view=sql-server-ver15),_MESSAGE](https://docs.microsoft.com/en-us/sql/t-sql/functions/error-message-transact-sql?view=sql-server-ver15),_NUMBER](https://docs.microsoft.com/en-us/sql/t-sql/functions/error-number-transact-sql?view=sql-server-ver15),_](https://docs.microsoft.com/en-us/sql/t-sql/functions/error-procedure-transact-sql?view=sql-server-ver15)및_](https://docs.microsoft.com/en-us/sql/t-sql/functions/error-state-transact-sql?view=sql-server-ver15) 내장 함수 동작을 에뮬레이션하기 위해 사용자 정의 함수에서 변수를 가져오기 위해 사용할 수 있는 MESSAGE_TEXT, SQLCODE, SQLSTATE, PROC_NAME, ERROR_LINE 같은 오류 변수 목록을 설정합니다. 이러한 모든 변수가 1개의 값으로 설정된 후 UPDATE_ERROR_VARS 사용자 정의 함수는 SQL 범위에서 액세스하기 위해 일부 환경 변수를 오류 값으로 업데이트하는 작업을 담당합니다.

코드

다음 코드 블록은 프로시저 내부의 EXEC 헬퍼를 나타냅니다.

   var _RS, ROW_COUNT, _ROWS, MESSAGE_TEXT, SQLCODE = 0, SQLSTATE = '00000', ERROR_HANDLERS, NUM_ROWS_AFFECTED, INTO;
   var fixBind = function (arg) {
      arg = arg == undefined ? null : arg instanceof Date ? arg.toISOString() : arg;
      return arg;
   };
   var fetch = (count,rows,stmt) => (count && rows.next() && Array.apply(null,Array(stmt.getColumnCount())).map((_,i) => rows.getColumnValue(i + 1))) || [];
   var EXEC = (stmt,binds = [],noCatch = false) => {
      binds = binds ? binds.map(fixBind) : binds;
      for(var stmt of stmt.split(";").filter((_) => _)) {
         try {
            _RS = snowflake.createStatement({
                  sqlText : stmt,
                  binds : binds
               });
            _ROWS = _RS.execute();
            ROW_COUNT = _RS.getRowCount();
            NUM_ROWS_AFFECTED = _RS.getNumRowsAffected();
            return {
               THEN : (action) => !SQLCODE && action(fetch(_ROWS))
            };
         } catch(error) {
            let rStack = new RegExp('At .*, line (\\d+) position (\\d+)');
            let stackLine = error.stackTraceTxt.match(rStack) || [0,-1];
            MESSAGE_TEXT = error.message.toString();
            SQLCODE = error.code.toString();
            SQLSTATE = error.state.toString();
            snowflake.execute({sqlText: `SELECT UPDATE_ERROR_VARS_UDF(?,?,?,?,?)`,binds: [stackLine[1], SQLCODE, SQLSTATE, MESSAGE_TEXT, PROC_NAME]});
            throw error;
         }
      }
   };
Copy

간단한 EXEC 예제

다음은 저장 프로시저 내부의 EXEC 호출의 간단한 예입니다

소스 코드

 -- Additional Params: -t JavaScript
CREATE PROCEDURE dbo.EXEC_EXAMPLE_1
AS
   EXECUTE('SELECT 1 AS Message');
GO
Copy
 -- =============================================
-- Example to execute the stored procedure
-- =============================================
EXECUTE dbo.EXEC_EXAMPLE_1
GO
Copy

예상 코드

CREATE OR REPLACE PROCEDURE dbo.EXEC_EXAMPLE_1 ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
	// REGION SnowConvert AI Helpers Code
	var _RS, ROW_COUNT, _ROWS, MESSAGE_TEXT, SQLCODE = 0, SQLSTATE = '00000', OBJECT_SCHEMA_NAME  = 'dbo', ERROR_HANDLERS, NUM_ROWS_AFFECTED, PROC_NAME = arguments.callee.name, DOLLAR_DOLLAR = '$' + '$';
	function* sqlsplit(sql) {
		var part = '';
		var ismark = () => sql[i] == '$' && sql[i + 1] == '$';
		for(var i = 0;i < sql.length;i++) {
			if (sql[i] == ';') {
				yield part + sql[i];
				part = '';
			} else if (ismark()) {
				part += sql[i++] + sql[i++];
				while ( i < sql.length && !ismark() ) {
					part += sql[i++];
				}
				part += sql[i] + sql[i++];
			} else part += sql[i];
		}
		if (part.trim().length) yield part;
	};
	var formatDate = (arg) => (new Date(arg - (arg.getTimezoneOffset() * 60000))).toISOString().slice(0,-1);
	var fixBind = function (arg) {
		arg = arg == undefined ? null : arg instanceof Date ? formatDate(arg) : arg;
		return arg;
	};
	var EXEC = (stmt,binds = [],severity = "16",noCatch = false) => {
		binds = binds ? binds.map(fixBind) : binds;
		for(var stmt of sqlsplit(stmt)) {
			try {
				_RS = snowflake.createStatement({
						sqlText : stmt,
						binds : binds
					});
				_ROWS = _RS.execute();
				ROW_COUNT = _RS.getRowCount();
				NUM_ROWS_AFFECTED = _RS.getNumRowsAffected();
				return {
					THEN : (action) => !SQLCODE && action(fetch(_ROWS))
				};
			} catch(error) {
				let rStack = new RegExp('At .*, line (\\d+) position (\\d+)');
				let stackLine = error.stackTraceTxt.match(rStack) || [0,-1];
				MESSAGE_TEXT = error.message.toString();
				SQLCODE = error.code.toString();
				SQLSTATE = error.state.toString();
				snowflake.execute({
					sqlText : `SELECT UPDATE_ERROR_VARS_UDF(?,?,?,?,?,?)`,
					binds : [stackLine[1],SQLCODE,SQLSTATE,MESSAGE_TEXT,PROC_NAME,severity]
				});
				throw error;
			}
		}
	};
	// END REGION

	EXEC(`SELECT 1 AS Message;`);
$$;
Copy

매개 변수가 있는 저장 프로시저 내의 EXEC

이 예제에서 EXEC 명령은 저장 프로시저 내부에 있으며 매개 변수 값을 받습니다

소스 코드

 -- Additional Params: -t JavaScript
CREATE PROCEDURE dbo.EXEC_EXAMPLE_2
	@p1 varchar(50) = N''
AS
	EXEC ('SELECT ' + @p1);
GO
Copy
 -- =============================================
-- Example to execute the stored procedure
-- =============================================
EXECUTE dbo.EXEC_EXAMPLE_2 N'''Hello World!'''
GO
Copy

예상 코드

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

	EXEC(`SELECT
   ${P1};`);
$$;
Copy

EXEC 매개 변수를 사용하여 저장 프로시저 호출하기

이 예제에서 EXEC 은 다른 저장 프로시저를 호출하고 매개 변수를 추가합니다

소스 코드

 -- Additional Params: -t JavaScript
CREATE PROCEDURE dbo.EXEC_EXAMPLE_3
	@p1 varchar(50) = N''
AS
	EXEC EXEC_EXAMPLE_2 @p1
GO
Copy
 -- =============================================
-- Example to execute the stored procedure
-- =============================================
EXECUTE dbo.EXEC_EXAMPLE_3 N'''Hello World!'''
GO
Copy

예상 코드

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

	EXEC(`CALL EXEC_EXAMPLE_2(?)`,[P1]);
$$;
Copy

기본값이 있는 매개 변수.

SqlServer 에서는 프로시저가 호출될 때 지정되지 않은 경우 기본값이 있는 매개 변수가 있을 수 있습니다.

SQL 서버

CREATE PROCEDURE PROC_WITH_DEFAULT_PARAMS1
@PARAM1 INT = 0, @PARAM2 INT = 0, @PARAM3 INT = 0, @PARAM4 INT = 0
AS
BEGIN
    .
    .
    .
END
Copy

Snowflake

CREATE OR REPLACE PROCEDURE PROC_WITH_DEFAULT_PARAMS1(param1 int default 0, param2 int default 0, param3 int default 0, param4 int default 0)
RETURNS TABLE()
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
    .
    .
    .
$$;
Copy
CALL PROC_WITH_DEFAULT_PARAMS1(param2 => 10, param4 => 15);
Copy

CURSOR 헬퍼

CREATE OR REPLACE PROCEDURE PROC1()
RETURNS STRING
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
	  var CURSOR = function (stmt, binds) {
	  var statementObj, result_set, total_rows, isOpen = false, self = this, row_count;
	
	  this.CURRENT = new Object;
	
	  var fetch = (count,rows,stmt) => (count && rows.next() && Array.apply(null,Array(stmt.getColumnCount())).map((_,i) => rows.getColumnValue(i + 1))) || [];
	
	  var fixBind = function (arg) {
	      arg = arg == undefined ? null : arg instanceof Date ? formatDate(arg) : arg;
	      return arg;
	   };
	
	  this.OPEN = function(openParameters) {
		  if (result_set == undefined) {
			try {
				if (openParameters) binds = openParameters;
				if (binds instanceof Function) binds = binds();
				var finalBinds = binds && binds.map(fixBind);
				var finalStmt = stmt instanceof Function ? stmt() : stmt;
				statementObj = snowflake.createStatement({
					sqlText : finalStmt,
					binds : finalBinds
				});
				result_set = statementObj.execute();
				total_rows = statementObj.getRowCount();
				isOpen = true;
				row_count = 0;
			} catch(error) {
				RAISE(error.code,"error",error.message);
			}
			else {
				isOpen = true;
			}
		  }
	          
	      return this;
	  };
	      
	  this.CURSOR_ROWS = function () {
	      return total_rows;
	  };
	
	  this.FETCH_STATUS = function() {
	      if(total_rows > row_count)
	          return 0;
	      else
	          return -1;
	  };
	
	  this.FETCH_NEXT = function() {
		  self.res = [];
	      if (isOpen) {
			  self.res = fetch(total_rows,result_set,statementObj);
			  if (self.res)
				  row_count++;
		  }
		  return self.res && self.res.length > 0;
	  };
	
	  this.INTO = function () {
	      return self.res;
	  };
	
	  this.CLOSE = function () {
	      isOpen = false;
	  };
	
	  this.DEALLOCATE = function() {
	      this.CURRENT = row_count = result_set_table = total_rows = result_set = statementObj = self = undefined;
	  };
  };
  
  var COL1, COL2;
  var sql_stmt = ``;
	
  let c = new CURSOR(`SELECT COL1, COL2 FROM TABLE1;`,() => []);
    
  c.OPEN();
  c.FETCH_NEXT();
  [COL1, COL2] = c.INTO();
  while ( c.FETCH_STATUS()) {
        
        
        sql_stmt = `INSERT INTO TABLE2 (COL1, COL2) VALUES (` + COL1+ `, ` + COL2 + `)`;
		
        snowflake.createStatement({
            sqlText : sql_stmt
         }).execute();
  }

  c.CLOSE();
  c.DEALLOCATE();

  return 'sucess';
$$;
Copy

EXEC 헬퍼에 삽입

Exec에 삽입 헬퍼는 Insert insertIntoTemporaryTable(sql) 이라는 함수를 생성합니다. 이 함수를 사용하면INSERT INTO TABLE_NAME EXEC(...) 을 TSQL 에서 Snowflake 로 변환하여 해당 데이터를 임시 테이블에 삽입한 다음 원래 Insert 에 다시 추가함으로써 원래 문의 동작을 모방할 수 있습니다.

이 문의 코드가 어떻게 수정되는지에 대한 자세한 내용은 실행에 삽입 섹션을 참조하십시오

참고

INSERT INTO EXEC 에 대해 생성된 코드는 내부에 여러 쿼리가 포함된 EXECUTE 문을 처리할 때 성능 문제가 발생할 수 있습니다.

   function insertIntoTemporaryTable(sql) {
    var table = "SnowConvertPivotTemporaryTable";
    return EXEC('CREATE OR REPLACE TEMPORARY TABLE ${table} AS ${sql}');
  }
  
  insertIntoTemporaryTable(`${DBTABLES}`)
  EXEC(`INSERT INTO MYDB.PUBLIC.T_Table SELECT * FROM MYDB.PUBLIC.SnowConvertPivotTemporaryTable`);
  EXEC(`DROP TABLE SnowConvertPivotTemporaryTable`)
Copy

LIKE 헬퍼

프로시저에서 다음과 같은 식이 발견되는 경우, 예를 들어

CREATE PROCEDURE ProcedureLike @VariableValue VARCHAR(50) AS
BEGIN
	IF @VariableValue like '%c%'
	BEGIN
		Select AValue from ATable;
	END;
END;
Copy

프로시저의 내부가 Javascript로 변환되므로 같은 식은 오류를 throw합니다. 이 기능을 방지 및 유지하기 위해 프로시저를 시작할 때 같은 식이 발견되면 함수가 추가됩니다.

   function LIKE(expr,pattern,esc,cs) {
    function fixPattern(pattern,esc) {
      const specials = '/.*+?|(){}[]\\'.split('');
      var newPattern = "";
      var fix = (c) => specials.includes(c) ? '\\' + c : c;
      for(var i = 0;i < pattern.length;i++) {
        var c = pattern[i];
        if (c === esc) {
          newPattern += pattern[i + 1]
          i++
        } else if (c === '%') {
          newPattern += ".*?"
        } else if (c === '_') {
          newPattern += "."
        } else if (c === '[' || ']') {
          newPattern += c
        } else newPattern += fix(c)
      }
      return newPattern;
    }
    return new RegExp(`^${fixPattern(pattern,esc)}$`,cs ? '' : 'i').exec(expr) != null;
  }
Copy

이 함수를 사용하면 SQL의 like 식의 기능을 복제할 수 있습니다. 이 기능을 사용할 수 있는 다양한 케이스를 살펴보겠습니다

 -- Additional Params: -t JavaScript
CREATE PROCEDURE ProcedureLike @VariableValue VARCHAR(50) AS
BEGIN
	IF @VariableValue like '%c%'
	BEGIN
		Select AValue from ATable;
	END;
	IF @VariableValue not like '%c%'
	BEGIN
		Select BValue from BTable;
	END;
  IF @VariableValue like '%c!%%' escape '!'
	BEGIN
		Select CValue from CTable;
	END;
END;
Copy

마지막 코드에는 normal like, not like 및 like with escape가 있습니다. 변환은 다음과 같습니다

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

	if (LIKE(VARIABLEVALUE,`%c%`)) {
		{
			EXEC(`		Select
		   AValue
		from
		   ATable`);
		}
	}
	if (!LIKE(VARIABLEVALUE,`%c%`)) {
		{
			EXEC(`		Select
		   BValue
		from
		   BTable`);
		}
	}
	if (LIKE(VARIABLEVALUE,`%c!%%`,`!`)) {
		{
			EXEC(`		Select
		   CValue
		from
		   CTable`);
		}
	}
$$;
Copy

like는 함수 호출로 변환됩니다

LIKE(VARIABLEVALUE,`%c%`)
!LIKE(VARIABLEVALUE,`%c%`)
LIKE(VARIABLEVALUE,`%c!%%`,`!`)
Copy

LIKE 함수가 수신하는 매개 변수는 다음과 같습니다.

  • 평가 중인 식입니다.

  • 비교 패턴

  • 이스케이프 문자가 있는 경우 이스케이프 문자는 선택적 매개 변수입니다.

헬퍼 선택

스칼라 값을 변수로 설정해야 할 때 SELECT 라는 함수를 생성합니다

 -- Additional Params: -t JavaScript
CREATE PROCEDURE MAX_EMPLOYEE_ID
AS
BEGIN
   DECLARE @VARIABLE INT 
   SET @VARIABLE = (SELECT MAX(EMPLOYEE_ID) FROM EMPLOYEES);
   RETURN @VARIABLE
END;
Copy

이 경우 SELECT 헬퍼를 사용하여 다음 코드를 생성합니다

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

   let VARIABLE;
   VARIABLE = EXEC(`SELECT
   MAX(EMPLOYEE_ID) FROM
   EMPLOYEES`);
   return VARIABLE;
$$;
Copy

SELECT 헬퍼를 사용하여 쿼리에서 검색된 값을 로컬 값에 삽입할 수도 있습니다. 이 헬퍼는SQL 서버 SELECT @local_variable 와 동일한 동작을 지원하도록 특별히 설계되었습니다. args 매개 변수는 선택 내부의 모든 로컬 변수에 적용되는 각 작업을 나타냅니다. SELECT @Variable도 참조하십시오. 예:

 -- Additional Params: -t JavaScript
CREATE PROCEDURE [PROCEDURE1] AS

DECLARE @VAR1 int;
DECLARE @VAR2 int;
select @VAR1 = col1 + col2, @VAR2 += col1 from table1;

GO
Copy

이 경우 변수 할당은 SQL 서버 동작을 에뮬레이션하기 위해 JavaScript lambdas로 변환됩니다.

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

let VAR1;
let VAR2;
SELECT(`   col1 + col2,
   col1
   from
   table1`,[],(value) => VAR1 = value,(value) => VAR2 += value);
$$;
Copy

RAISERROR 헬퍼

이 헬퍼는 소스 코드에RAISERROR호출의 사용처가 있을 때 생성됩니다. 예:

 var RAISERROR = (message,severity,state) => {
    snowflake.execute({
      sqlText : `SELECT UPDATE_ERROR_VARS_UDF(?,?,?)`,
      binds : [message,severity,state]
    });
    var msg = `Message: ${message}, Level: ${severity}, State: ${state}`;
    throw msg;
  };
Copy

RAISERROR 는 __UPDATE_ERROR_VARS_UDF_를 실행하여 오류 메시지, 심각도, 상태 값을 환경 변수로 저장하여 ERROR 기본 제공 함수 중 하나를 호출하여 사용해야 할 경우를 대비합니다. 마지막으로 SQL 서버와 동일한 형식으로 오류 메시지가 throw됩니다.

ID 함수 헬퍼

이 헬퍼는 프로시저 내부의 Select Into에서 ID 함수 를 사용할 때마다 생성됩니다.

  var IdentityHelper = (seed,increment) => {
      var sequenceString = "`CREATE OR REPLACE SEQUENCE SnowConvert_Temp_Seq START = ${seed} INCREMENT = ${increment}`";
      return EXEC(sequenceString);
Copy

이 헬퍼의 매개 변수는 원래 함수와 동일하며, TSQL 에서 ID 함수 동작을 모방하는 시퀀스를 생성하기 위해 생성되며, 원본 코드의 변경 사항은 다음과 같습니다.

  • 소스 코드에 있는 것과 동일한 매개 변수를 사용하여 IdentityHelper 함수에 대한 추가 메서드 호출입니다.

  • 그리고 IDENTITY_UDF 함수를 호출하여 시퀀스의 다음 값을 가져옵니다.

   IdentityHelper(1,1)
   EXEC(`CREATE TABLE PUBLIC.department_table3 AS SELECT IDENTITY_UDF() /*** MSC-WARNING - MSCEWI1046 - 'identity' FUNCTION MAPPED TO 'IDENTITY_UDF', FUNCTIONAL EQUIVALENCE VERIFICATION PENDING ***/ as Primary_Rank
from PUBLIC.department_table`);
Copy

TSQL 에서와 마찬가지로 매개 변수를 지정하지 않으면 1,1이 기본값이 됩니다.

CALL 프로시저 헬퍼

이 헬퍼는 이전에는 사용자 정의 함수였지만 이제는 변환 프로세스의 결과로 프로시저가 된 함수에 대한 호출이 있을 때마다 생성됩니다.

    var CALL = (sql,binds = [],...args) => {
      EXEC("CALL " + sql,binds);
      _ROWS.next();
      return (_ROWS.getColumnValue(1))[0];
   };
Copy

이 도우미의 목적은 프로시저를 호출하는 데 필요한 논리를 함수처럼 캡슐화하기 위한 것입니다.

SELECT 같은 쿼리 내에서는 프로시저를 호출할 수 없으므로 이 기능은 제한된다는 점에 유의하십시오.

FooSelfAssign(@PAR INT) 를 프로시저로 변환했다고 가정한 사용 예시입니다.

 // Input code
DECLARE @VAR1 INT = FooSelfAssign(1);
DECLARE @VAR4 INT = FooSelfAssign(FooSelfAssign(FooSelfAssign(FooSelfAssign(4))));
Copy
 // Output code
let VAR1 = CALL(`FooSelfAssign(1)`)
let VAR4 = CALL(`FooSelfAssign(?)`,[CALL(`FooSelfAssign(?)`,[CALL(`FooSelfAssign(?)`,[CALL(`FooSelfAssign(4)`)])])]);
Copy

VAR1 의 변환은 매우 간단하지만, VAR4 의 경우 가장 바깥쪽 CALL 에 나머지 CALLs 이 바인딩된 목록이 포함되어 있다는 점에 유의하십시오.

연속되는 각 CALL 은 다른 CALL 안에 포함되어 있는 경우 바인딩으로 변환됩니다.

2. Variables

DECLARE @변수

SQL 서버

DECLARE @product_list VARCHAR(MAX) = ' ';
DECLARE @Variable1 AS VARCHAR(100), @Variable2 AS VARCHAR(100);
Copy

Snowflake

let PRODUCT_LIST = ` `;
let VARIABLE1;
let VARIABLE2;
Copy

DECLARE 변수 테이블

이 경우 DECLARE 를 사용하여 변수 테이블을 선언합니다 예를 살펴보겠습니다.

 -- Additional Params: -t JavaScript
CREATE PROCEDURE PROC1
AS
BEGIN
DECLARE @VariableNameTable TABLE   
 ( 
 [Col1] INT NOT NULL,
 [Col2] INT NOT NULL 
 );
INSERT INTO @VariableNameTable Values(111,222);
Select * from @VariableNameTable;
END

Exec PROC1;
Copy

Sql 서버에서 해당 코드를 실행하면 다음과 같은 결과를 얻을 수 있습니다

col1

col2

111

222

이제 Snowflake의 변화를 살펴 보겠습니다

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

 {
  EXEC(`CREATE OR REPLACE TEMPORARY TABLE T_VariableNameTable
(
   Col1 INT NOT NULL,
   Col2 INT NOT NULL
)`);
  EXEC(`INSERT INTO T_VariableNameTable Values(111,222)`);
  EXEC(`Select
   *
from
   T_VariableNameTable`);
 }
 EXEC(`CALL PROC1()`);
$$;
Copy

61 ~ 67 라인은 프로시저 내부의 해당 문의 결과입니다.

변수 선언 테이블이 임시 테이블로 바뀝니다. 이름에서 @ 문자가 T_로 대체되었다는 점에 유의하십시오.

Snowflake에서 해당 코드를 실행하면 아무런 결과도 얻지 못합니다. null만 표시됩니다. 그 이유는 마지막 Select가 이제 EXEC 헬퍼에 있기 때문입니다. 그렇다면 테이블이 있는지 어떻게 알 수 있을까요?

EXEC 의 프로시저 내부에 임시 테이블로 생성되었으므로 프로시저 외부에서 해당 테이블에 대한 선택을 수행할 수 있습니다.

 Select * from PUBLIC.T_VariableNameTable;
Copy

해당 문을 실행하면 다음과 같은 결과가 표시됩니다

col1

col2

111

222

SET @변수

지금은 오른쪽에 있는 식에 따라 설정 변수가 변환됩니다.

식에 변환이 있는 경우 JavaScript 에 해당하는 값으로 변환됩니다.

 -- Additional Params: -t JavaScript
CREATE PROCEDURE PROC1
AS
BEGIN
	SET @product_list2 = '';
    SET @product_list = '';
    SET @var1 += '';
    SET @var2 &= '';
    SET @var3 ^= '';
    SET @var4 |= '';
    SET @var5 /= '';
    SET @var6 %= '';
    SET @var7 *= '';
    SET @var8 -= '';
    SET @ProviderStatement = 'SELECT * FROM TABLE1
WHERE COL1 = '+@PARAM1+ ' AND COL2 = ' + @LOCALVAR1;
    SET @NotSupported = functionValue(a,b,c);
END
    
Copy

Snowflake

CREATE OR REPLACE PROCEDURE PROC1 ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'
EXECUTE AS CALLER
AS
$$
	// SnowConvert AI Helpers Code section is omitted.
	
	PRODUCT_LIST2 = ``;
	PRODUCT_LIST = ``;
	VAR1 += ``;
	VAR2 &= ``;
	VAR3 ^= ``;
	VAR4 |= ``;
	VAR5 /= ``;
	VAR6 %= ``;
	VAR7 *= ``;
	VAR8 -= ``;
	PROVIDERSTATEMENT = `SELECT
   *
FROM
   TABLE1
WHERE
   COL1 = ${PARAM1}
   AND COL2 = ${LOCALVAR1};`;
	NOTSUPPORTED = SELECT(`   functionValue(a,b,c) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'functionValue' NODE ***/!!!`);
$$;
Copy

예제에서 볼 수 있듯이 NOTSUPPORTED 변수의 값은 당분간 변환되지 않으므로 설명되어 있습니다. 이는 아직 변환이 완료되지 않았음을 의미합니다.

다른 종류의 세트는 다음과 같이 설명됩니다

SQL 서버

 -- Additional Params: -t JavaScript
CREATE PROCEDURE PROC1
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
;

SET NOCOUNT ON
;

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
;

SET NOCOUNT OFF
;
END
Copy

Snowflake

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

/*** SSC-EWI-0040 - THE 'SET' CLAUSE IS NOT SUPPORTED IN SNOWFLAKE ***/
/*SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED*/
;
/*** SSC-EWI-0040 - THE 'SET' CLAUSE IS NOT SUPPORTED IN SNOWFLAKE ***/
/*SET NOCOUNT ON*/
;
/*** SSC-EWI-0040 - THE 'SET' CLAUSE IS NOT SUPPORTED IN SNOWFLAKE ***/
/*SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED*/
;
/*** SSC-EWI-0040 - THE 'SET' CLAUSE IS NOT SUPPORTED IN SNOWFLAKE ***/
/*SET NOCOUNT OFF*/
;
$$;
Copy

SELECT @변수

지금은 SELECT @variable 를 단순 선택으로 변환하여 변수 할당을 제거하고 연산자 오른쪽에 식을 유지합니다. 선택에서 로컬 변수의 할당 작업은 SQL Server 에서 로컬 변수 할당 중에 수행되는 작업과 동일한 동작을 나타내는 화살표 함수로 대체됩니다.

SQL 서버

 -- Additional Params: -t JavaScript
CREATE PROCEDURE PROC1 AS
DECLARE @VAR1 int;
DECLARE @VAR2 int;
SELECT @VAR1 = COL1 + COL2, @VAR2 = COL3 FROM TABLE1;
GO
Copy

Snowflake

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

let VAR1;
let VAR2;
SELECT(`   COL1 + COL2,
   COL3
   FROM
   TABLE1`,[],(value) => VAR1 = value,(value) => VAR2 = value);
$$;
Copy

3. Statements translation

SELECT

기본 양식

기본 SELECT 형식에는 바인딩이 없으므로 변환 중에 하나의 매개 변수를 사용하여 EXEC 헬퍼 함수가 호출됩니다. 예:

 -- Source code:
SELECT * FROM DEMO_TABLE_1;
Copy
 // Translated code:
EXEC(`SELECT * FROM DEMO_TABLE_1`);
Copy

IF

SQL 서버

IF Conditional_Expression
   -- SQL Statement
ELSE IF Conditiona_Expression2
   -- SQL Statement
ELSE
   -- SQL Statement
Copy

Snowflake

 if (Conditional_Expression) {
    // SQL Statement
} else if (Conditional_Expression2) {
    // SQL Statement
} else{
    // SQL Statement
}
Copy

WHILE

SQL 서버

WHILE ( Conditional_Expression )
BEGIN
   -- SQL STATEMENTS
END;
Copy

Snowflake

while ( Conditional_Expression )
{
  // SQL STATEMENTS
}
Copy

EXEC / EXECUTE

SQL 서버

 -- Execute simple statement
Exec('Select 1');

-- Execute statement using Dynamic Sql
Exec('Select ' + @par1 + ' from [db].[t1]');

-- Execute Procedure with parameter
EXEC db.sp2 'Create proc [db].[p3] AS', @par1, 1
Copy

Snowflake

 -- Execute simple statement
EXEC(`Select 1`);

-- Execute statement using Dynamic Sql
EXEC(`Select ${PAR1} from MYDB.db.t1`);

-- Execute Procedure with parameter
EXEC(`CALL db.sp2(/*** SSC-EWI-0038 - THIS STATEMENT MAY BE A DYNAMIC SQL THAT COULD NOT BE RECOGNIZED AND CONVERTED ***/
'Select * from MYDB.db.t1', ?, 1, Default)`,[PAR1]);
Copy

THROW

THROW 에 대한 변환은 오류를 수신하는 캐치 블록이 원래 문에 지정된 정보에 액세스할 수 있도록 합니다.

SQL 서버

 -- Case 1
THROW

-- Case 2
THROW 123, 'The error message', 1

-- Case 3
THROW @var1, @var2, @var3
Copy

Snowflake

 // Case 1
throw {};

// Case 2
throw { code: 123, message: "The error message", status: 1 };

// Case 3
throw { code: VAR1, message: VAR2, status: VAR3 };
Copy

RAISERROR

SQL ServerRAISERROR 함수는 Snowflake에서 지원되지 않습니다. SnowConvert AI는 원래 동작을 에뮬레이션하는 헬퍼를 생성하기 위해 모든 사용을 식별합니다. 예:

SQL 서버

 -- Additional Params: -t JavaScript
CREATE OR ALTER PROCEDURE  RAISERRORTEST AS
BEGIN
    DECLARE @MessageTXT VARCHAR = 'ERROR MESSAGE';
    RAISERROR (N'E_INVALIDARG', 16, 1);
    RAISERROR ('Diagram does not exist or you do not have permission.', 16, 1);
    RAISERROR(@MessageTXT, 16, 1);
END
GO
Copy

Snowflake

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

    let MESSAGETXT = `ERROR MESSAGE`;
    RAISERROR("E_INVALIDARG","16","1");
    RAISERROR("Diagram does not exist or you do not have permission.","16","1");
    RAISERROR(MESSAGETXT,"16","1");
$$;
Copy

BREAK/CONTINUE

중단/계속 변환을 사용하면 코드의 플로우를 중단하거나 다른 블록으로 계속할 수 있습니다.

SQL 서버

-- Additional Params: -t JavaScript
CREATE PROCEDURE ProcSample
AS
BEGIN
IF @@ROWCOUNT > 0
  Continue;
ELSE
  BREAK;
END
Copy

Snowflake

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

  if (ROW_COUNT > 0) {
    continue;
  } else {
    break;
  }
$$;
Copy

INSERT INTO EXEC

INSERT INTO[테이블] EXEC(...) 문은 Snowflake에서 지원되지 않기 때문에 코드를 약간 수정하여 몇 라인의 코드를 추가하여 동작을 복제할 수 있습니다.

  • 추가된 첫 번째 라인은 EXEC 내부의 인자에서 추출된 코드가 있는 insertIntoTemporaryTable 로 호출하여 결과 세트를 임시 테이블에 삽입합니다. 함수에 대한 자세한 내용은 EXEC 헬퍼에 삽입하기 섹션을 참조하십시오.

  • 코드에서 삽입의 Exec이 제거되고 임시 테이블에서 EXEC 의 결과를 검색하는 쿼리가 생성됩니다.

SELECT * FROM MYDB.PUBLIC.SnowConvertPivotTemporaryTable    
Copy
  • 추가된 마지막 줄은 추가된 임시 테이블에 대한 DROP TABLE 문입니다.

   DROP TABLE SnowConvertPivotTemporaryTable    
Copy

SQL 서버

INSERT INTO #Table1
EXEC ('SELECT
Table1.ID
FROM Population');

INSERT INTO #Table1
EXEC (@DBTables);
Copy

Snowflake

  insertIntoTemporaryTable(`SELECT Table1.ID FROM MYDB.PUBLIC.Population)
  EXEC(`INSERT INTO MYDB.PUBLIC.T_Table1 SELECT * FROM MYDB.PUBLIC.SnowConvertPivotTemporaryTable`);
  EXEC(`DROP TABLE SnowConvertPivotTemporaryTable`)
  
  insertIntoTemporaryTable(`${DBTABLES}`)
  EXEC(`INSERT INTO MYDB.PUBLIC.T_Table1 SELECT * FROM MYDB.PUBLIC.SnowConvertPivotTemporaryTable`);
  EXEC(`DROP TABLE SnowConvertPivotTemporaryTable`)
Copy

BEGIN TRANSACTION

BEGIN TRANSACTION 을 Snowflake의 BEGIN 명령으로 변환하여 EXEC 헬퍼 호출에 삽입합니다.

헬퍼는 결과 BEGIN 을 실제로 실행하는 역할을 담당합니다.

SQL 서버

 -- Input code
BEGIN TRAN @transaction_name;
Copy

Snowflake

 // Output code
EXEC(`BEGIN`, []);
Copy

COMMIT TRANSACTION

COMMIT TRANSACTION 을 Snowflake의 COMMIT 명령으로 변환하여 EXEC 헬퍼 호출에 삽입합니다.

헬퍼는 결과 COMMIT 를 실제로 실행하는 역할을 담당합니다.

SQL 서버

 -- Input code
COMMIT TRAN @transaction_name;
Copy

Snowflake

 // Output code
EXEC(`COMMIT`, []);
Copy

ROLLBACK TRANSACTION

ROLLBACK TRANSACTION 을 Snowflake의 ROLLBACK 명령으로 변환하여 EXEC 헬퍼 호출에 삽입합니다.

헬퍼는 결과물인 ROLLBACK 을 실제로 실행하는 역할을 담당합니다.

SQL 서버

 -- Input code
ROLLBACK TRAN @transaction_name;
Copy

Snowflake

 // Output code
EXEC(`ROLLBACK`, []);
Copy

WAITFOR DELAY

WAITFOR DELAY 절은 Snowflake의 SYSTEM$WAIT함 수로 변환됩니다. DELAY의 _time_to_pass_매개 변수는 SYSTEM$WAIT 함수의 매개 변수로 사용하기 위해 초 단위로 변환됩니다.

WAITFOR 절의 다른 베리언트는 Snowflake에서 지원되지 않으므로 해당 메시지가 표시됩니다.

SQL 서버

 -- Input code
1) WAITFOR DELAY '02:00';
2) WAITFOR TIME '13:30';
3) WAITFOR (RECEIVE TOP (1)
   @dh = conversation_handle,
   @mt = message_type_name,
   @body = message_body
   FROM [eqe]), TIMEOUT 5000;
Copy

Snowflake

 // Output code
1) EXEC(`SYSTEM$WAIT(120)`,[]);
2) /*** SSC-EWI-0040 - THE 'WAIT FOR' CLAUSE IS NOT SUPPORTED IN SNOWFLAKE ***/
   /*WAITFOR TIME '13:30'*/
   ;
3) /*** SSC-EWI-0040 - THE 'WAIT FOR' CLAUSE IS NOT SUPPORTED IN SNOWFLAKE ***/
   /*WAITFOR (RECEIVE TOP (1)
      @dh = conversation_handle,
      @mt = message_type_name,
      @body = message_body
      FROM [eqe]), TIMEOUT 5000*/
   ;
Copy

3. Cursors

CURSORS는 Snowflake에서 지원되지 않으므로 SnowConvert AI는 해당 기능을 대상 플랫폼에서 원래 동작을 에뮬레이션하는 JavaScript 헬퍼에 매핑합니다. 예:

SQL 서버

 -- Additional Params: -t JavaScript
CREATE PROCEDURE [procCursorHelper] AS

DECLARE vendor_cursor CURSOR FOR   
    SELECT VendorID, Name  
    FROM Purchasing.Vendor  
    WHERE PreferredVendorStatus = 1  
    ORDER BY VendorID;
GO
Copy

Snowflake

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

    var VENDOR_CURSOR = new CURSOR(`SELECT
       VendorID,
       Name
    FROM
       Purchasing.Vendor
    WHERE
       PreferredVendorStatus = 1
    ORDER BY VendorID`,[],false);
$$;
Copy

DECLARE CURSOR

SQL 서버

DECLARE myCursor1 CURSOR FOR SELECT COL1 FROM TABLE1
Copy

Snowflake

let myCursor1 = new CURSOR(`SELECT COL1 FROM TABLE1`,() => []);
Copy

OPEN

SQL 서버

OPEN myCursor1
OPEN GLOBAL myCursor2
Copy

Snowflake

myCursor1.OPEN();
myCursor2.OPEN()
Copy

FETCH

SQL 서버

DECLARE @VALUE1 INT
FETCH NEXT FROM myCursor1 into @VALUE1
Copy

Snowflake

var VALUE1;
myCursor1.FETCH_NEXT();
VALUE1 = myCursor1.INTO();
Copy

CLOSE

SQL 서버

CLOSE myCursor1
CLOSE GLOBAL myCursor2
Copy

Snowflake

myCursor1.CLOSE()
myCursor2.CLOSE()
Copy

DEALLOCATE

SQL 서버

DEALLOCATE myCursor1
DEALLOCATE GLOBAL myCursor2
Copy

Snowflake

myCursor1.DEALLOCATE()
myCursor2.DEALLOCATE()
Copy

@@FETCH_STATUS

SQL 서버

 @@FETCH_STATUS
Copy

Snowflake

myCursor1.FETCH_STATUS()
Copy

@@CURSOR_ROWS

SQL 서버

 @@CURSOR_ROWS
Copy

Snowflake

myCursor1.FETCH_STATUS()
Copy

4. Expressions

이진 연산

SQL 서버

SET @var1 = 1 + 1;
SET @var1 = 1 - 1;
SET @var1 = 1 / 1;
SET @var1 = 1 * 1;
SET @var1 = 1 OR 1;
SET @var1 = 1 AND 1;
Copy

Snowflake

VAR1 = 1 + 1;
VAR1 = 1 - 1;
VAR1 = 1 / 1;
VAR1 = 1 * 1;
VAR1 = 1 || 1;
VAR1 = 1 && 1;
Copy

조건부

SQL 서버

@var1 > 0
@var1 = 0
@var1 < 0
@var1 <> 0
Copy

Snowflake

VAR1 > 0
VAR1 = 0
VAR1 < 0
VAR1 != 0
Copy

NULL 조건자

SQL 서버
@var1 is null
@var2 is not null
Copy
Snowflake
VAR1 == null
VAR2 != null
Copy

5. Labels and Goto

레이블 은 SQL Server에서 JavaScript 와 동일하게 동작하지 않습니다. 동작을 시뮬레이션하기 위해 함수 로 변환하고 있습니다. 그 사용법은 레이블의 모든 논리이 포함된 생성된 함수의 호출로 대체되고 있습니다. 예:

소스 코드

 -- Additional Params: -t JavaScript
CREATE PROCEDURE [procWithLabels] 
AS
SUCCESS_EXIT:
	SET @ErrorStatus = 0
	RETURN @ErrorStatus

ERROR_EXIT:
	RETURN @ErrorStatus
Copy

Snowflake

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

	SUCCESS_EXIT();
	ERROR_EXIT();
	function SUCCESS_EXIT() {
		ERRORSTATUS = 0;
		return ERRORSTATUS;
	}
	function ERROR_EXIT() {
		return ERRORSTATUS;
	}
$$;
Copy

위의 예제에서 볼 수 있듯이 소스 코드의 레이블이었던 함수 선언을 코드 끝에 배치하여 코드를 더 깔끔하게 생성할 수 있습니다.

GOTO 는 JavaScript 에는 존재하지 않는 또 다른 명령입니다. 동작을 시뮬레이션하기 위해 참조되는 함수(레이블)에 대한 호출로 변환하고 그 앞에 반환 문을 붙였습니다. 예:

SQL 서버

 -- Additional Params: -t JavaScript
CREATE PROCEDURE [procWithLabels] 
AS
DECLARE @ErrorStatus int = 0;
IF @ErrorStatus <> 0 GOTO ERROR_EXIT
	
SUCCESS_EXIT:
	SET @ErrorStatus = 0
	RETURN @ErrorStatus

ERROR_EXIT:
	RETURN @ErrorStatus
Copy

Snowflake

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

	let ERRORSTATUS = 0;
	if (ERRORSTATUS != 0) {
		return ERROR_EXIT();
	}
	SUCCESS_EXIT();
	ERROR_EXIT();
	function SUCCESS_EXIT() {
		ERRORSTATUS = 0;
		return ERRORSTATUS;
	}
	function ERROR_EXIT() {
		return ERRORSTATUS;
	}
$$;
Copy

위의 예제에서 볼 수 있듯이 SQL 서버가 GOTO 에서와 같이 코드 플로우를 중단하기 위해 함수 호출에 return 이 추가되었습니다.