SnowConvert AI – SQL Server – Azure Synapse – Prozeduren

In diesem Abschnitt wird die Transformation der Syntax und TSQL-Anweisungen der Prozedur für Snowflake-JavaScript erläutert.

Applies to
  • SQL Server

  • Azure Synapse Analytics

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

1. CREATE PROCEDURE Translation

Snowflake CREATE PROCEDURE ist in SQL-Syntax definiert, während seine inneren Anweisungen in JavaScript definiert sind.

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

Die Datentypen des Parameters werden in die entsprechenden Snowflake-Datentypen übersetzt. Siehe auch Datentypen.

EXEC-Hilfsfunktion

Um Anweisungen aus einer Prozedur in der Umgebung SnowFlake ausführen zu können, müssen diese Anweisungen vorverarbeitet und so angepasst werden, dass sie ihre Ausführung in mehreren Variablen widerspiegeln, die für die Ausgangssprache spezifisch sind.

SnowConvert AI übersetzt die unterstützten Anweisungen automatisch und verwendet eine EXEC-Hilfsfunktion. Diese Hilfsfunktion bietet Zugriffs- und Aktualisierungsmöglichkeiten für viele Variablen, die simulieren, wie die Ausführung dieser Anweisungen in ihrer nativen Umgebung aussehen würde.

Sie können zum Beispiel feststellen, dass in den migrierten Prozeduren ein Codeblock immer hinzugefügt wird. Im nächsten Abschnitt werden wir die Grundstruktur dieses Codes erklären. Bitte denken Sie daran, dass wir ständig nach neuen und verbesserten Möglichkeiten suchen, um die Transformationen und alle benötigten Hilfsfunktionen zu rationalisieren.

Struktur

Die Grundstruktur der Hilfsfunktion EXEC ist wie folgt:

  1. Abschnitt Variablendeklaration: Hier werden die verschiedenen Variablen oder Objekte deklariert, die Werte im Zusammenhang mit der Ausführung der Anweisungen innerhalb der Prozedur enthalten. Dazu gehören Werte wie die Anzahl der Zeilen, die von einer Anweisung betroffen sind, oder sogar das Resultset selbst.

  2. fixBind-Funktionsdeklaration: Dies ist eine Hilfsfunktion, die verwendet wird, um Bindungen zu fixieren, wenn sie vom Typ „Date“Funktion sind.

  3. EXEC-Funktionsdeklaration: Dies ist die wichtigste EXEC-Hilfsfunktion. Sie erhält die auszuführende Anweisung, das Array der Bindungen (im Grunde die Variablen oder Parameter, die durch die Ausführung geändert werden können und während der Ausführung der Prozedur Datenpermanenz erfordern), das noCatch-Flag, das bestimmt, ob ERROR_HANDLERS verwendet werden muss, und die catchFunction-Funktion zur Ausführung von benutzerdefiniertem Code, wenn bei der Ausführung der Anweisung eine Ausnahme auftritt. Der Body der Funktion EXEC ist sehr einfach: Führen Sie die Anweisung aus und speichern Sie alle wertvollen Daten, die bei ihrer Ausführung anfallen, innerhalb eines Fehlerbehandlungsblocks.

  4. ERROR VARS: Der EXEC-Catch-Block richtet eine Liste von Fehlervariablen ein, wie z. B. MESSAGE_TEXT, SQLCODE, SQLSTATE, PROC_NAME und ERROR_LINE, die zum Abrufen von Werten aus benutzerdefinierten Funktionen verwendet werden können, um die Verhaltensweise der integrierten SQL Server-Funktionen ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR\_PROCEDURE und ERROR\_STATE zu emulieren. Nachdem alle diese Variablen auf einen Wert gesetzt wurden, ist die benutzerdefinierte Funktion UPDATE_ERROR_VARS dafür zuständig, einige Umgebungsvariablen mit den Fehlerwerten zu aktualisieren, um im SQL-Bereich Zugriff auf sie zu haben.

Code

Der folgende Codeblock stellt die EXEC-Hilfsfunktion innerhalb einer Prozedur dar:

   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

Einfaches EXEC-Beispiel

Dies ist ein einfaches Beispiel für einen EXEC-Aufruf innerhalb einer gespeicherten Prozedur

Quellcode

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

Erwarteter Code

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 innerhalb einer gespeicherten Prozedur mit einem Parameter

In diesem Beispiel befindet sich der EXEC-Befehl innerhalb einer gespeicherten Prozedur und erhält einen Parameterwert

Quellcode

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

Erwarteter Code

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 ruft eine gespeicherte Prozedur mit einem Parameter auf

In diesem Beispiel ruft EXEC eine andere gespeicherte Prozedur auf und fügt einen Parameter hinzu

Quellcode

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

Erwarteter Code

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

Parameter mit Standardwert.

In SqlServer kann es Parameter mit einem Standardwert geben, falls diese beim Aufruf einer Prozedur nicht angegeben werden.

SQL Server

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

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

Insert Into EXEC-Hilfsfunktion

Die Insert Into Exec-Hilfsfunktion erzeugt eine Funktion namens Insert insertIntoTemporaryTable(SQL). Mit dieser Funktion kann die Transformation für INSERT INTO TABLE_NAME EXEC(...) von TSQL in Snowflake die Verhaltensweise der ursprünglichen Anweisung imitieren, indem die Daten in eine temporäre Tabelle eingefügt und dann wieder in die ursprüngliche INSERT-Anweisung eingefügt werden.

Weitere Informationen darüber, wie der Code für diese Anweisung geändert wird, finden Sie im Abschnitt „Insert Into Exec“

Bemerkung

Dieser generierte Code für INSERT INTO EXEC kann bei der Verarbeitung von EXECUTE-Anweisungen, die mehrere Abfragen enthalten, Leistungsprobleme verursachen.

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

Für den Fall, dass ein ähnlicher Ausdruck in einer Prozedur gefunden wird, zum Beispiel

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

Da das Innere der Prozedur in Javascript umgewandelt wird, wird der LIKE-Ausdruck einen Fehler auslösen. Um dies zu vermeiden und die Funktionalität zu erhalten, wird eine Funktion am Anfang der Prozedur hinzugefügt, wenn ein ähnlicher Ausdruck gefunden wird.

   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

Mit dieser Funktion können wir die Funktionalität des LIKE-Ausdrucks von SQL replizieren. Schauen wir uns die verschiedenen Anwendungsfälle an

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

Im letzten Code gibt es ein normales „Like“, ein „Not Like“ und ein „Like“ mit Escape. Die Transformation ist

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

Beachten Sie, dass die Likes in Funktionsaufrufe umgewandelt werden

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

Die in der Funktion LIKE enthaltenen Parameter sind die folgenden:

  • Der Ausdruck, der gerade ausgewertet wird.

  • Das Vergleichsmuster

  • Wenn vorhanden, ist das Escape-Zeichen ein optionaler Parameter.

Select-Hilfsfunktion

Erzeugt eine Funktion namens SELECT, wenn ein skalarer Wert auf eine Variable gesetzt werden muss

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

In diesem Fall wird der folgende Code mit der SELECT-Hilfsfunktion erzeugt

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

Die SELECT-Hilfsfunktion kann auch verwendet werden, um einen aus einer Abfrage abgerufenen Wert in einen lokalen Wert einzufügen. Die Hilfsfunktion wurde speziell entwickelt, um die gleiche Verhaltensweise des SQL Servers SELECT @local_variable zu unterstützen. Der Parameter args steht für jede Operation, die auf alle lokalen Variablen innerhalb des „Select“ angewendet wird. Siehe auch SELECT @Variable. Beispiel:

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

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

GO
Copy

In diesem Fall werden die Variablenzuweisungen in JavaScript Lambdas übersetzt, um die Verhaltensweise von SQL Server zu emulieren.

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

Dieses Hilfsmittel wird generiert, wenn ein RAISERROR-Aufruf im Quellcode verwendet wird. Beispiel:

 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 führt das Programm UPDATE_ERROR_VARS_UDF aus, um den Wert der Fehlermeldung, den Schweregrad und den Status als Umgebungsvariablen zu speichern, für den Fall, dass sie durch den Aufruf einer der in ERROR eingebauten Funktionen verwendet werden müssen. Schließlich wird die Fehlermeldung in demselben Format ausgegeben wie bei SQL Server.

Identitätsfunktion-Hilfsfunktion

Dieses Hilfsfunktion wird immer dann generiert, wenn die Identitätsfunktion für ein „Select Into“ innerhalb einer Prozedur verwendet wird.

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

Die Parameter für diese Hilfsfunktion sind die gleichen wie die der Originalfunktion. Es wurde erstellt, um eine Sequenz zu erzeugen, die die Verhaltensweise der Identitätsfunktion in TSQL nachahmt. Die Änderungen am ursprünglichen Code sind:

  • Ein zusätzlicher Methodenaufruf der Funktion IdentityHelper mit denselben Parametern, die im Quellcode zu finden sind.

  • Und der Aufruf der IDENTITY_UDF ein Funktionsentwurf, um den nächsten Wert in der Folge zu erhalten.

   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

Genau wie in TSQL werden die Standardwerte (1,1) verwendet, wenn keine Parameter angegeben werden.

CALL Prozedur-Hilfsfunktion

Diese Hilfsfunktion wird immer dann generiert, wenn ein Aufruf einer zuvor benutzerdefinierten Funktion erfolgt, die durch den Übersetzungsprozess nun zu einer Prozedur geworden ist.

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

Der Zweck dieser Hilfsfunktion ist es, die Logik für den Aufruf von Prozeduren so zu kapseln, als ob sie Funktionen wären.

Bitte bedenken Sie, dass diese Funktionalität eingeschränkt ist, da Prozeduren nicht innerhalb von Abfragen wie SELECT aufgerufen werden können.

Anwendungsbeispiel, unter der Annahme, dass FooSelfAssign(@PAR INT) in eine Prozedur übersetzt wurde:

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

Beachten Sie, dass die Übersetzung für VAR1 sehr einfach ist, während bei VAR4 der äußerste CALL eine Liste mit den restlichen CALLs als Bindungen enthält.

Jeder nachfolgende CALL wird in eine Bindung übersetzt, wenn er in einem anderen CALL enthalten ist.

2. Variables

DECLARE @Variable

SQL Server

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 @Variable Tabelle

In diesem Fall wird DECLARE verwendet, um eine Variablentabelle zu deklarieren. Sehen wir uns ein Beispiel an.

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

Wenn wir diesen Code in SQL Server ausführen, erhalten wir das folgende Ergebnis

col1

col2

111

222

Sehen wir uns nun die Transformation in Snowflake an

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

Beachten Sie, dass die Zeilen 61 bis 67 die Ergebnisse der Anweisungen innerhalb der Prozedur sind.

Die Tabelle Deklarationsvariable wird in eine temporäre Tabelle umgewandelt. Beachten Sie, dass im Namen das Zeichen @ durch T_ ersetzt wurde.

Wenn wir diesen Code in Snowflake ausführen, erhalten wir kein Ergebnis. Es wird lediglich „null“ angezeigt. Das liegt daran, dass das letzte Select jetzt in der Hilfsfunktion von EXEC enthalten ist. Woher wissen wir also, dass die Tabelle vorhanden ist?

Da sie als temporäre Tabelle innerhalb der Prozedur in einem EXEC erstellt wurde, können wir einen Select auf diese Tabelle außerhalb der Prozedur ausführen.

 Select * from PUBLIC.T_VariableNameTable;
Copy

Wenn wir diese Anweisung ausführen, erhalten wir das folgende Ergebnis

col1

col2

111

222

SET @Variable

Jetzt wird die Set-Variable je nach dem Ausdruck, der auf der rechten Seite steht, umgewandelt.

Wenn der Ausdruck eine Transformation hat, wird er in seine JavaScript-Entsprechung umgewandelt.

Beispiel

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

Wie Sie im Beispiel sehen können, ist der Wert der NOTSUPPORTED-Variable kommentiert, da sie vorerst nicht umgewandelt wird. Beachten Sie, dass dies bedeutet, dass die Transformation noch nicht abgeschlossen ist.

Andere Arten von Sets werden kommentiert, zum Beispiel die folgenden

SQL Server

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

Im Moment wird die SELECT @variable in ein einfaches Select umgewandelt, wobei die Variablenzuweisungen entfernt werden und die Ausdrücke auf der rechten Seite des Operators bleiben. Die Zuweisungsoperationen der lokalen Variablen im Select werden durch arrow-Funktionen ersetzt, die die gleiche Verhaltensweise der Operation repräsentieren, die bei der Zuweisung der lokalen Variablen in SQL Server durchgeführt wird.

SQL Server

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

Grundform

Die grundlegende SELECT-Form hat keine Bindungen, sodass die Übersetzung die Erstellung eines Aufrufs zur EXEC-Hilfsfunktion mit einem Parameter impliziert. Beispiel:

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

IF

SQL Server

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 Server

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

Snowflake

while ( Conditional_Expression )
{
  // SQL STATEMENTS
}
Copy

EXEC / EXECUTE

SQL Server

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

Die Transformation für THROW stellt sicher, dass der Catch-Block, der den Fehler empfängt, Zugriff auf die in der ursprünglichen Anweisung angegebenen Informationen hat.

SQL Server

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

Die SQL Server RAISERROR-Funktion wird in Snowflake nicht unterstützt. SnowConvert AI identifiziert alle Verwendungen, um eine Hilfsfunktion zu generieren, die das ursprüngliche Verhalten emuliert. Beispiel:

SQL Server

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

Die Transformation „break/continue“ sorgt dafür, dass der Codefluss angehalten oder mit einem anderen Block fortgesetzt wird.

SQL Server

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

Der Code wurde geringfügig geändert, da die Anweisung INSERT INTO [Table] EXEC(...) in Snowflake nicht unterstützt wird. Dies ermöglicht es uns, die Verhaltensweise durch Hinzufügen einiger Codezeilen zu replizieren:

  • Die erste hinzugefügte Zeile ist ein Aufruf der Funktion insertIntoTemporaryTable, in die der aus dem Argument innerhalb von EXEC extrahierte Code eingefügt wird. Dadurch wird das Resultset in eine temporäre Tabelle eingefügt. Weitere Informationen zu dieser Funktion finden Sie im Abschnitt Insert Into EXEC-Hilfsfunktion.

  • Exec von Insert wird aus dem Code entfernt und eine Abfrage, die die Ergebnisse des EXEC aus der temporären Tabelle abruft.

SELECT * FROM MYDB.PUBLIC.SnowConvertPivotTemporaryTable    
Copy
  • Die letzte hinzugefügte Zeile ist eine DROP TABLE-Anweisung für die hinzugefügte temporäre Tabelle.

   DROP TABLE SnowConvertPivotTemporaryTable    
Copy

SQL Server

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 wird in den Snowflake-Befehl BEGIN umgewandelt und in einen EXEC-Hilfsaufruf eingefügt.

Die Hilfsfunktion ist für die tatsächliche Ausführung der resultierenden BEGIN zuständig.

SQL Server

 -- Input code
BEGIN TRAN @transaction_name;
Copy

Snowflake

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

COMMIT TRANSACTION

COMMIT TRANSACTION wird in den Snowflake-Befehl COMMIT umgewandelt und in einen EXEC-Hilfsaufruf eingefügt.

Die Hilfsfunktion ist für die tatsächliche Ausführung der resultierenden COMMIT zuständig.

SQL Server

 -- Input code
COMMIT TRAN @transaction_name;
Copy

Snowflake

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

ROLLBACK TRANSACTION

ROLLBACK TRANSACTION wird in den Snowflake-Befehl ROLLBACK umgewandelt und in einen EXEC-Hilfsaufruf eingefügt.

Die Hilfsfunktion ist für die tatsächliche Ausführung der resultierenden ROLLBACK zuständig.

SQL Server

 -- Input code
ROLLBACK TRAN @transaction_name;
Copy

Snowflake

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

WAITFOR DELAY

WAITFOR DELAY-Klausel wird in die Funktion SYSTEM$WAIT von Snowflake umgewandelt. Der Parameter _time_to\pass der Funktion DELAY wird in Sekunden umgewandelt, damit er als Parameter in der Funktion SYSTEM$WAIT verwendet werden kann.

Die anderen Varianten der WAITFOR-Klausel werden in Snowflake nicht unterstützt und sind daher mit der entsprechenden Meldung gekennzeichnet.

SQL Server

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

Da CURSORS-Anweisungen von Snowflake nicht unterstützt werden, ordnet SnowConvert AI deren Funktion einer JavaScript-Hilfsfunktion zu, die das ursprüngliche Verhalten in der Zielplattform emuliert. Beispiel:

SQL Server

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

DECLARE myCursor1 CURSOR FOR SELECT COL1 FROM TABLE1
Copy

Snowflake

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

OPEN

SQL Server

OPEN myCursor1
OPEN GLOBAL myCursor2
Copy

Snowflake

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

FETCH

SQL Server

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

Snowflake

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

CLOSE

SQL Server

CLOSE myCursor1
CLOSE GLOBAL myCursor2
Copy

Snowflake

myCursor1.CLOSE()
myCursor2.CLOSE()
Copy

DEALLOCATE

SQL Server

DEALLOCATE myCursor1
DEALLOCATE GLOBAL myCursor2
Copy

Snowflake

myCursor1.DEALLOCATE()
myCursor2.DEALLOCATE()
Copy

@@FETCH_STATUS

SQL Server

 @@FETCH_STATUS
Copy

Snowflake

myCursor1.FETCH_STATUS()
Copy

@@CURSOR_ROWS

SQL Server

 @@CURSOR_ROWS
Copy

Snowflake

myCursor1.FETCH_STATUS()
Copy

4. Expressions

Binäre Operationen

SQL Server

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

Bedingungen

SQL Server

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

Snowflake

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

NULL-Prädikat

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

5. Labels and Goto

Labels verhalten sich in JavaScript nicht so wie in SQL Server. Um die Verhaltensweise zu simulieren, werden sie in functions umgewandelt. Ihre Verwendung wird durch einen Aufruf der generierten Funktion ersetzt, die die gesamte Logik des Labels enthält. Beispiel:

Quellcode

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

Wie Sie im obigen Beispiel sehen, werden die Funktionsdeklarationen, die im Quellcode die Bezeichnungen waren, an das Ende des Codes gesetzt, um ihn übersichtlicher zu gestalten.

GOTO ist ein weiterer Befehl, der in JavaScript nicht existiert. Um die Verhaltensweise zu simulieren, werden die Verwendungen in Aufrufe der referenzierten Funktion (Label) umgewandelt, denen eine RETURN-Anweisung vorangestellt wird. Beispiel:

SQL Server

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

Wie Sie im obigen Beispiel sehen, wird return dem Funktionsaufruf hinzugefügt, um den Codefluss zu stoppen, wie es SQL Server mit GOTO tut.