Schreiben von gespeicherten Prozeduren in JavaScript¶
Unter diesem Thema wird erklärt, wie Sie JavaScript-Code für eine gespeicherte Prozedur schreiben.
Bemerkung
Um eine anonyme Prozedur sowohl zu erstellen als auch aufzurufen, verwenden Sie CALL (mit anonymer Prozedur). Das Erstellen und Aufrufen einer anonymen Prozedur erfordert keine Rolle mit CREATE PROCEDURE-Schemaberechtigungen.
Sie können während der Ausführung Ihres Handler-Codes Protokoll- und Ablaufverfolgungsdaten erfassen. Weitere Informationen dazu finden Sie unter Protokollierung, Ablaufverfolgung und Metriken.
Erläuterungen zur JavaScript-API¶
Die JavaScript-API für gespeicherte Prozeduren ist ähnlich, aber nicht identisch mit den APIs in Snowflake-Konnektoren und -Treibern (Node.js, JDBC, Python usw.).
Mithilfe der API können Sie folgende Operationen ausführen:
Ausführen einer SQL-Anweisung
Abrufen der Ergebnisse einer Abfrage (d. h. eines Resultset)
Abrufen von Metadaten zum Resultset (Anzahl der Spalten, Datentypen der Spalten usw.)
Diese Operationen lassen sich ausführen, indem Methoden für folgende Objekte aufgerufen werden:
snowflake– Verfügt über Methoden zum Erstellen einesStatement-Objekts und zum Ausführen eines SQL-Befehls.Statement– Hilft dabei, vorbereitete Anweisungen auszuführen und Metadaten für die vorbereiteten Anweisungen aufzurufen. Außerdem kann ein ResultSet-Objekt zurückerhalten werden.ResultSet– Enthält die Ergebnisse einer Abfrage (z. B. die Datenzeilen, die für eine SELECT-Anweisung abgerufen wurden).SfDate– Ist eine Erweiterung von JavaScript-Date (mit zusätzlichen Methoden) und dient als Rückgabetyp für die Snowflake SQL-Datentypen TIMESTAMP_LTZ, TIMESTAMP_NTZ und TIMESTAMP_TZ.
Diese Objekte sind unter API für gespeicherte Prozeduren in JavaScript ausführlich beschrieben.
Eine typische gespeicherte Prozedur enthält Code, der dem folgenden Pseudocode ähnelt:
In diesem Code wird ein Objekt mit dem Namen snowflake verwendet. Dabei handelt es sich um ein spezielles Objekt, das ohne Deklaration vorhanden ist. Das Objekt wird im Kontext jeder gespeicherten Prozedur bereitgestellt und macht die API verfügbar, sodass Sie mit dem Server interagieren können.
Die anderen Variablen (z. B. statement1) werden mit JavaScript var-Anweisungen erstellt. Beispiel:
Wie im obigen Codebeispiel gezeigt, können Sie mit dem snowflake-Objekt ein Statement-Objekt erstellen, indem Sie über die API eine der Methoden aufrufen.
Im folgenden Beispiel wird ein ResultSet abgerufen und durchlaufen:
Der Abschnitt Beispiele (am Ende unter diesem Thema) enthält zusätzliche Beispiele, in denen die einzelnen Objekte und viele der Methoden der JavaScript-API für gespeicherte Prozedur ausgeführt werden.
Zuordnen von SQL- und JavaScript-Datentypen¶
Beim Aufrufen, Verwenden und Empfangen von Werten aus gespeicherten Prozeduren müssen Sie häufig Snowflake-SQL-Datentypen in JavaScript-Datentypen konvertieren und umgekehrt.
Eine Konvertierung von SQL in JavaScript kann in folgenden Fällen erfolgen:
Aufrufen einer gespeicherten Prozedur mit einem Argument. Das Argument ist ein SQL-Datentyp. Wenn das Argument innerhalb der gespeicherten Prozedur in einer JavaScript-Variablen gespeichert ist, muss es konvertiert werden.
Beim Abrufen eines Werts aus einem ResultSet-Objekt in eine JavaScript-Variable. Das ResultSet enthält den Wert als SQL-Datentyp, und die JavaScript-Variable muss den Wert als einen der JavaScript-Datentypen speichern.
Eine Konvertierung von JavaScript in SQL kann in folgenden Fällen erfolgen:
Zurückgeben eines Werts aus der gespeicherten Prozedur. Die
return-Anweisung enthält normalerweise eine JavaScript-Variable, die in einen SQL-Datentyp konvertiert werden muss.Beim dynamischen Erstellen einer SQL-Anweisung, die einen Wert in einer JavaScript-Variable verwendet.
Beim Binden des Werts einer JavaScript-Variablen an eine vorbereitet Anweisung.
Weitere Informationen zur Zuordnung von JavaScript-Datentypen zu SQL-Datentypen in Snowflake finden Sie unter Zuordnung von Datentypen zwischen SQL und JavaScript.
Allgemeine Hinweise¶
Zeilenfortsetzung¶
SQL-Anweisungen können sehr lang sein, und es ist nicht immer praktisch, sie in eine einzelne Zeile einzufügen. JavaScript behandelt einen Zeilenumbruch als das Ende einer Anweisung. Wenn Sie eine lange SQL-Anweisung auf mehrere Zeilen aufteilen möchten, können Sie die üblichen JavaScript-Verfahren für den Umgang mit langen Zeichenfolgen verwenden, darunter:
Setzen Sie unmittelbar vor dem Zeilenende ein Backslash (Zeilenfortsetzungszeichen). Beispiel:
Verwenden Sie um die Zeichenfolge herum Backticks (einfache Backquotes) anstelle von doppelten Anführungszeichen. Beispiel:
Akkumulieren Sie die Zeichenfolge. Beispiel:
Hinweise zu gespeicherten Prozeduren in JavaScript¶
JavaScript-Nummernbereich¶
Der Bereich für Zahlen mit intakter Genauigkeit reicht von
-(2^53 -1)
bis
(2^53 -1)
Der Bereich der gültigen Werte in den Snowflake-Datentypen NUMBER(p, s) und DOUBLE ist größer. Wenn Sie einen Wert aus Snowflake abrufen und in einer numerischen JavaScript-Variablen speichern, kann dies zu Genauigkeitsverlusten führen. Beispiel:
Die ersten beiden Spalten sollten übereinstimmen und die dritte sollte 0,0 enthalten.
Das Problem betrifft benutzerdefinierte JavaScript-Funktionen (UDFs) und gespeicherte Prozeduren.
Wenn das Problem in gespeicherten Prozeduren bei Verwendung von getColumnValue() auftritt, können Sie das Problem möglicherweise vermeiden, indem Sie einen Wert als Zeichenfolge abrufen, z. B. mit:
Sie können dann die Zeichenfolge aus der gespeicherten Prozedur zurückgeben und die Zeichenfolge in einen numerischen Datentyp in SQL umwandeln.
Fehlerbehandlung in JavaScript¶
Da eine gespeicherte Prozedur in JavaScript verfasst wird, kann sie die Try/Catch-Syntax von JavaScript verwenden.
Die gespeicherte Prozedur kann eine vordefinierte Ausnahme oder eine benutzerdefinierte Ausnahme auslösen. Ein einfaches Beispiel für das Auslösen einer benutzerdefinierten Ausnahme finden Sie hier.
Sie können Ihre SQL-Anweisungen innerhalb eines Try-Blocks ausführen. Wenn ein Fehler auftritt, kann Ihr Catch-Block alle Anweisungen zurücksetzen (wenn Sie die Anweisungen in eine Transaktion setzen). Der Abschnitt „Beispiele“ enthält ein Beispiel für das Rollback einer Transaktion in einer gespeicherten Prozedur.
Einschränkungen bei gespeicherten Prozeduren¶
Gespeicherte Prozeduren unterliegen den folgenden Einschränkungen:
Der JavaScript-Code kann die JavaScript-Funktion
eval()nicht aufrufen.Gespeicherte JavaScript-Prozeduren unterstützen den Zugriff auf die JavaScript-Standardbibliothek. Beachten Sie, dass dadurch viele Objekte und Methoden ausgeschlossen werden, die normalerweise von Browsern bereitgestellt werden. Es gibt keinen Mechanismus zum Importieren, Einschließen oder Aufrufen zusätzlicher Bibliotheken. Durch das Zulassen von Bibliotheken, die von Drittanbietern stammen, können Sicherheitslücken entstehen.
JavaScript-Code wird in einem eingeschränkten Modul ausgeführt, wodurch Systemaufrufe aus dem JavaScript-Kontext (z. B. kein Netzwerk- und Festplattenzugriff) verhindert werden und die für das Modul verfügbare Systemressourcen, insbesondere der Arbeitsspeicher, eingeschränkt werden.
Groß-/Kleinschreibung in JavaScript-Argumenten¶
Bei Argumentnamen wird im SQL-Abschnitt des Codes einer gespeicherten Prozedur nicht zwischen Groß-/Kleinschreibung unterschieden, im JavaScript-Abschnitt jedoch schon.
Bei gespeicherten Prozeduren (und UDFs), die JavaScript verwenden, werden Bezeichner (z. B. Argumentnamen) im SQL-Abschnitt der Anweisung automatisch in Großbuchstaben konvertiert (sofern Sie den Bezeichner nicht in doppelte Anführungszeichen setzen), während Argumentnamen im JavaScript-Abschnitt in der ursprünglichen Schreibweise verbleiben. Das kann dazu führen, dass Ihre gespeicherte Prozedur fehlschlägt, ohne eine explizite Fehlermeldung zurückzugeben, da die Argumente nicht einsehbar sind.
Hier ist ein Beispiel für eine gespeicherte Prozedur, bei der der Name eines Arguments im JavaScript-Code nicht mit dem Namen des Arguments im SQL-Code übereinstimmt, weil die Groß-/Kleinschreibung anders ist:
Im folgenden Beispiel ist die erste Zuweisungsanweisung falsch, da der Name argument1 in Kleinbuchstaben geschrieben ist.
Eine konsistente Verwendung von Bezeichnern in Großbuchstaben (insbesondere von Argumentnamen) in Ihren SQL-Anweisungen und im JavaScript-Code führt tendenziell zu weniger Fehlern im Hintergrund.
JavaScript-Trennzeichen¶
Der JavaScript-Teil des Codes der gespeicherten Prozedur muss in einfache Anführungszeichen ' oder doppelte Dollarzeichen $$ eingeschlossen werden.
Die Verwendung von $$ erleichtert die Verarbeitung von JavaScript-Code, der einfache Anführungszeichen enthält, die nicht mit Escape-Zeichen umschlossen sind.
Überladen der Namen gespeicherter Prozeduren¶
Informationen zum Überladen von Namen und zu Namenskonventionen finden Sie unter Benennen und Überladen von Prozeduren und UDFs.
Binden von Variablen¶
Durch das Binden einer Variablen an eine SQL-Anweisung können Sie den Wert der Variablen in der Anweisung verwenden.
Sie können sowohl NULL- als auch Nicht-NULL-Werte binden.
Der Datentyp der Variablen sollte für die Verwendung des Werts in der SQL-Anweisung geeignet sein. Derzeit können nur JavaScript-Variablen vom Typ Zahl (number), Zeichenfolge (string) und SfDate gebunden werden. (Weitere Details zur Zuordnung zwischen SQL-Datentypen und JavaScript-Datentypen finden Sie unter Zuordnen von SQL- und JavaScript-Datentypen.)
Dies ist ein kurzes Beispiel zum Binden:
Hier ist ein vollständigeres Beispiel. In diesem Beispiel werden TIMESTAMP-Informationen gebunden. Da die direkte Bindung von SQL-TIMESTAMP-Daten nicht unterstützt wird, übergibt dieses Beispiel den Zeitstempel als VARCHAR und bindet diesen dann an die Anweisung. Beachten Sie, dass die SQL-Anweisung selbst den VARCHAR-Wert durch Aufrufen der TO_TIMESTAMP()-Funktion in einen TIMESTAMP-Wert konvertiert:
Diese einfache Funktion gibt TRUE zurück, wenn der angegebene Zeitstempel vor dem jetzigen Zeitpunkt liegt, und FALSE, wenn dies nicht der Fall ist.
Hier sehen Sie, wie Sie VARCHAR, TIMESTAMP_LTZ und andere Datentypen an eine INSERT-Anweisung binden. TIMESTAMP_LTZ bindet eine SfDate-Variable, die in der gespeicherten Prozedur erstellt wird.
Erstellen Sie eine Tabelle.
Erstellen Sie eine gespeicherte Prozedur. Diese Prozedur akzeptiert einen
VARCHAR-Wert und konvertiert den VARCHAR-Wert mit SQL in einenTIMESTAMP_LTZ-Wert. Die Prozedur ruft dann den konvertierten Wert aus einem ResultSet ab. Der Wert wird in einer JavaScript-Variablen vom Typ SfDate gespeichert. Die gespeicherte Prozedur bindet dann sowohl den ursprünglichenVARCHAR-Wert als auch denTIMESTAMP_LTZ-Wert an eineINSERT-Anweisung. Dies demonstriert auch die Bindung von numerischen JavaScript-Daten.Rufen Sie die Prozedur auf.
Stellen Sie sicher, dass die Zeile eingefügt wurde.
Weitere Beispiele zum Binden von Daten in JavaScript finden Sie unter Binden von Anweisungsparametern.
Code-Anforderungen¶
Der JavaScript-Code muss ein einzelnes Literal-JavaScript-Objekt definieren, damit die gespeicherte Prozedur gültig ist.
Wenn der JavaScript-Code diese Anforderung nicht erfüllt, wird die gespeicherte Prozedur zwar erstellt; sie wird beim Aufrufen aber fehlschlagen.
Codelänge¶
Snowflake begrenzt die maximale Größe des JavaScript-Quellcodes im Textteil einer gespeicherten JavaScript-Prozedur. Snowflake empfiehlt eine Begrenzung auf 100 KB. (Da der Code in komprimierter Form gespeichert ist, hängt das genaue Limit von der Komprimierbarkeit des Codes ab.)
Laufzeitfehler¶
Die meisten Fehler in gespeicherten Prozeduren treten zur Laufzeit auf, da der JavaScript-Code zum Zeitpunkt der Ausführung der gespeicherten Prozedur interpretiert wird und nicht zum Zeitpunkt der Erstellung der gespeicherten Prozedur.
Unterstützung für dynamische SQL¶
Gespeicherte Prozeduren können zur dynamischen Erstellung von SQL-Anweisungen dienen. Sie können beispielsweise eine SQL-Befehlszeichenfolge erstellen, die eine Mischung aus vorkonfigurierten SQL- und Benutzereingaben enthält (z. B. Kontonummer eines Benutzers).
Beispiele finden Sie unter Dynamisches Erstellen einer SQL-Anweisung und im Abschnitt Beispiele.
Synchrone API¶
Die API für gespeicherte Snowflake-Prozeduren ist synchron. Innerhalb einer gespeicherten Prozedur können Sie immer nur jeweils einen Thread ausführen.
Beachten Sie, dass dies nicht mit der Regel zur Ausführung von JavaScript mit dem Konnektor Node.js übereinstimmt, bei dem Sie asynchrone Threads ausführen können.
Beispiele¶
Grundlegende Beispiele¶
Das folgende Beispiel veranschaulicht die grundlegende Syntax zum Erstellen und Aufrufen einer gespeicherten Prozedur. Es wird weder SQL noch prozeduraler Code ausgeführt. Es bietet jedoch später einen Ausgangspunkt für realistischere Beispiele:
Beachten Sie, dass das Trennzeichen
$$den Anfang und das Ende des JavaScript-Codes markiert.Rufen Sie nun die soeben erstellte Prozedur auf:
Das folgende Beispiel zeigt, wie eine SQL-Anweisung innerhalb einer gespeicherten Prozedur ausgeführt wird:
Erstellen Sie eine Tabelle:
Erstellen Sie eine gespeicherte Prozedur. Dadurch wird eine Zeile in eine vorhandene Tabelle mit dem Namen
stproc_test_table1eingefügt und der Wert „Erfolgreich abgeschlossen“ zurückgegeben. Der zurückgegebene Wert ist aus einer SQL-Perspektive nicht besonders nützlich, ermöglicht es Ihnen aber, Statusinformationen (z. B. „Erfolgreich abgeschlossen“ oder „Fehlgeschlagen“) an den Benutzer zurückzugeben.Rufen Sie die gespeicherte Prozedur auf:
Bestätigen Sie, dass die gespeicherte Prozedur die Zeile eingefügt hat:
Im folgenden Beispiel wird ein Ergebnis abgerufen:
Erstellen einer Prozedur zum Zählen der Zeilen einer Tabelle (entspricht
select count(*) from table):Fragen Sie die gespeicherte Prozedur, wie viele Zeilen sich in der Tabelle befinden:
Prüfen Sie selbstständig, ob Sie die richtige Zahl erhalten haben:
Beispiel für eine rekursive gespeicherte Prozedur¶
Das folgende Beispiel veranschaulicht eine einfache, aber nicht besonders realistische rekursive gespeicherte Prozedur:
Dynamisches Erstellen einer SQL-Anweisung¶
Das folgende Beispiel zeigt, wie eine SQL-Anweisung dynamisch erstellt wird:
Bemerkung
Wie in Einschleusung von SQL-Befehlen (unter diesem Thema) angegeben, sollten Sie bei Verwendung von dynamischer SQL Maßnahmen gegen Angriffe ergreifen.
Erstellen Sie die gespeicherte Prozedur. Mit dieser Prozedur können Sie den Namen einer Tabelle übergeben und die Anzahl der Zeilen in dieser Tabelle abrufen (entspricht
select count(*) from table_name):Rufen Sie die gespeicherte Prozedur auf:
Zeigen Sie die Ergebnisse von
select count(*)für dieselbe Tabelle an:
Abrufen von Metadaten zum Resultset¶
In diesem Beispiel wird gezeigt, wie eine kleine Menge von Metadaten aus einem Resultset abgerufen wird:
Abfangen eines Fehlers mit Try/Catch¶
In diesem Beispiel wird die Verwendung eines JavaScript Try/Catch-Blocks zum Abfangen eines Fehlers in einer gespeicherten Prozedur dargestellt:
Erstellen Sie die gespeicherte Prozedur:
Rufen Sie die gespeicherte Prozedur auf. Dadurch sollten ein Fehler mit der Fehlernummer und weitere Informationen zurückgegeben werden:
Das folgende Beispiel veranschaulicht das Auslösen einer benutzerdefinierten Ausnahme:
Erstellen Sie die gespeicherte Prozedur:
Rufen Sie die gespeicherte Prozedur mit gültigen und ungültigen Werten auf:
Verwenden von Transaktionen in gespeicherten Prozeduren¶
Im folgenden Beispiel werden mehrere zusammenhängende Anweisungen in eine Transaktion gepackt und try/catch für Commit oder Rollback verwendet. Der Parameter force_failure ermöglicht dem Aufrufer die Wahl zwischen erfolgreicher Ausführung und absichtlichem Fehler.
Protokollieren von Fehlern¶
Sie können Protokoll- und Ablaufverfolgungsdaten von JavaScript-Handler-Code erfassen, indem Sie das snowflake-Objekt der JavaScript-API verwenden. Damit werden Protokollmeldungen und Ablaufverfolgungsdaten in einer Ereignistabelle gespeichert, die Sie mit Abfragen analysieren können.
Weitere Informationen dazu finden Sie unter:
Verwenden von RESULT_SCAN zum Abrufen des Ergebnisses einer gespeicherten Prozedur¶
Im folgenden Beispiel wird die Verwendung der Funktion RESULT_SCAN zum Abrufen und Verarbeiten des Ergebnisses einer CALL-Anweisung gezeigt:
Erstellen und Laden der Tabelle:
Erstellen Sie die gespeicherte Prozedur. Diese Prozedur gibt eine gut formatierte Zeichenfolge zurück, die wie ein Resultset mit drei Zeilen aussieht, aber tatsächlich eine einzelne Zeichenfolge ist:
Rufen Sie die gespeicherte Prozedur auf, und rufen Sie mit RESULT_SCAN die Ergebnisse ab:
Sie können komplexere Operationen auf den von der Funktion RESULT_SCAN zurückgegebenen Wert ausführen. Da in diesem Fall der Rückgabewert eine einzelne Zeichenfolge ist, möchten Sie möglicherweise die einzelnen „Zeilen“ extrahieren, die in der Zeichenfolge enthalten zu sein scheinen, und diese Zeilen in einer anderen Tabelle speichern.
Tipp
Sie können auch den Pipe-Operator (->>) anstelle der Funktion RESULT_SCAN zum Ausführen einer CALL-Anweisung und Verarbeitung des Resultsets mit einem einzigen -Befehl verwenden.
Das folgende Beispiel, das eine Fortsetzung des vorherigen Beispiels darstellt, veranschaulicht eine Methode dafür:
Erstellen Sie eine Tabelle zur langfristigen Speicherung. Diese Tabelle enthält den Provinznamen und die Provinz-ID, nachdem Sie sie aus der vom Befehl CALL zurückgegebenen Zeichenfolge extrahiert haben:
Rufen Sie die gespeicherte Prozedur auf, rufen Sie das Ergebnis mit RESULT_SCAN ab, extrahieren Sie die drei Zeilen aus der Zeichenfolge, und fügen Sie sie in die Tabelle ein:
Stellen Sie sicher, dass dies funktioniert hat, indem Sie die Zeilen in der Tabelle anzeigen:
Hier ist ungefähr derselbe Code, aber in kleineren Schritten:
Erstellen Sie eine Tabelle namens
one_string. In dieser Tabelle wird das Ergebnis des Befehls CALL temporär gespeichert. Da das Ergebnis von CALL eine einzelne Zeichenfolge ist, speichert die Tabelle nur einen VARCHAR-Wert.Rufen Sie die gespeicherte Prozedur auf, rufen Sie mit RESULT_SCAN das Ergebnis (eine Zeichenfolge) ab, und speichern Sie das Ergebnis in der Zwischentabelle namens
one_string:Dies zeigt die neue Zeile in der Tabelle
one_string. Denken Sie daran, dass die Ausgabe zwar so formatiert ist, dass sie wie drei Zeilen aussieht, es sich in Wahrheit jedoch um eine einzige Zeichenfolge handelt:Die folgenden Befehle zeigen, wie Sie mehrere Zeilen aus der Zeichenfolge extrahieren können:
Erstellen Sie als nächstes eine Tabelle namens
three_strings. Diese Tabelle enthält das Ergebnis, nachdem Sie sie in einzelne Zeilen/Zeichenfolgen aufgeteilt haben:Konvertieren Sie nun diese eine Zeichenfolge der Tabelle
one_stringin drei separate Zeichenfolgen, und zeigen Sie, dass es sich nun tatsächlich um drei Zeichenfolgen handelt:Konvertieren Sie die drei Zeichenfolgen in unserer Langzeittabelle mit dem Namen
all_provincesnun in drei Zeilen:Zeigen Sie die drei Zeilen in der Langzeittabelle an:
Zurückgeben eines Arrays an Fehlermeldungen¶
Ihre gespeicherte Prozedur führt möglicherweise mehr als eine SQL-Anweisung aus, und Sie wollen ggf. eine Status-/Fehlermeldung für jede der SQL-Anweisungen zurückgeben. Eine gespeicherte Prozedur gibt jedoch eine einzelne Zeile zurück; sie dient nicht dazu, mehrere Zeilen zurückzugeben.
Wenn alle Ihre Meldungen in einen einzelnen Wert vom Typ ARRAY passen, können Sie mit einigem Zusatzaufwand alle Meldungen von einer gespeicherten Prozedur abrufen.
Das folgende Beispiel zeigt eine Möglichkeit dafür (die angezeigten Fehlermeldungen sind nicht real, aber Sie können diesen Code erweitern, um mit Ihren tatsächlichen SQL-Anweisungen zu funktionieren):
Beachten Sie, dass dies keine allgemeine Lösung ist. Die maximale Größe von ARRAY-Datentypen ist begrenzt, und Ihr gesamtes Resultset muss in ein einzelnes ARRAY passen.
Zurückgeben eines Resultset¶
In diesem Abschnitt wird das in Zurückgeben eines Arrays an Fehlermeldungen beschriebene vorherige Beispiel erweitert. Dieses Beispiel ist allgemeiner gehalten und erlaubt es Ihnen, ein Resultset aus einer Abfrage zurückzugeben.
Eine gespeicherte Prozedur gibt eine einzelne Zeile zurück, die eine einzelne Spalte enthält. Sie ist nicht dafür geeignet, ein Resultset zurückzugeben. Wenn Ihr Resultset jedoch klein genug ist, um in einen einzelnen Wert vom Typ VARIANT oder ARRAY zu passen, können Sie das Resultset von einer gespeicherten Prozedur mit zusätzlichem Code zurückgeben:
Hier sehen Sie, wie Sie die beiden vorherigen Zeilen zu einer einzigen Zeile kombinieren:
Der Einfachheit halber können Sie die vorhergehende Zeile in eine Ansicht einschließen. Diese Ansicht konvertiert außerdem die Zeichenfolge ‚null‘ in eine wahre NULL. Sie müssen die Ansicht nur einmal erstellen. Sie müssen jedoch die gespeicherte Prozedur jedes Mal aufrufen, bevor Sie aus dieser Ansicht auswählen. Denken Sie daran, dass der Aufruf von RESULT_SCAN in der Ansicht aus der letzten Anweisung stammt, die der folgende CALL sein muss:
Sie können sie auch als echte Ansicht verwenden (d. h. eine Teilmenge davon auswählen):
Beachten Sie, dass dies keine universelle Lösung ist. Die maximale Größe der Datentypen VARIANT und ARRAY ist begrenzt, und Ihr gesamtes Resultset muss in eine einzelne VARIANT oder ARRAY passen.
Schutz der Privatsphäre¶
Dieses Beispiel veranschaulicht eine gespeicherte Prozedur, die für einen Onlinehändler nützlich ist. Diese gespeicherte Prozedur respektiert die Privatsphäre der Kunden und schützt gleichzeitig die berechtigten Interessen sowohl des Einzelhändlers als auch der Kunden. Wenn ein Kunde den Einzelhändler aus Datenschutzgründen dazu auffordert, seine Daten zu löschen, löscht diese gespeicherte Prozedur die meisten Kundendaten, belässt jedoch das Kaufprotokoll des Kunden, wenn eine der folgenden Bedingungen erfüllt ist:
Bei jedem gekauften Artikel, für den eine Garantie gilt, die noch nicht abgelaufen ist.
Wenn der Kunde noch Geld schuldet (oder dem Kunden eine Rückerstattung geschuldet wird).
In einer realistischeren Version würden einzelne Zeilen gelöscht, für die eine Zahlung erfolgt ist und die Garantie abgelaufen ist.
Beginnen Sie, indem Sie die Tabellen erstellen und laden:
Erstellen Sie die gespeicherte Prozedur:
Zeigen Sie die Daten in den Tabellen an, bevor Sie irgendwelche dieser Daten löschen:
Kunde #1 hat eine noch gültige Garantie. Die gespeicherte Prozedur löscht die von ihm veröffentlichten Bewertungskommentare, behält jedoch aufgrund der Garantie seinen Kaufdatensatz bei:
Kunde #2 schuldet noch Geld. Die gespeicherte Prozedur löscht seine Bewertungskommentare, behält jedoch seinen Kaufdatensatz bei:
Kunde #3 schuldet kein Geld (und wird auch kein Geld geschuldet). Seine Garantie ist abgelaufen, sodass die gespeicherte Prozedur sowohl die Bewertungskommentare als auch die Kaufdatensätze löscht:
Verwenden von Sitzungsvariablen bei gespeicherten Prozeduren mit Aufrufer- und Eigentümerrechten¶
Diese Beispiele veranschaulichen einen der Hauptunterschiede zwischen gespeicherten Prozeduren mit Aufruferrechten und gespeicherten Prozeduren mit Eigentümerrechten. Sie versuchen, Sitzungsvariablen auf zwei Arten zu verwenden:
Legen Sie eine Sitzungsvariable fest, bevor Sie die gespeicherte Prozedur aufrufen, und verwenden Sie dann die Sitzungsvariable innerhalb der gespeicherten Prozedur.
Legen Sie eine Sitzungsvariable innerhalb der gespeicherten Prozedur fest, und verwenden Sie diese, nachdem Sie von den gespeicherten Prozeduren zurückgekehrt sind.
Sowohl die Verwendung der Sitzungsvariablen als auch das Festlegen der Sitzungsvariablen funktionieren in der gespeicherten Prozedur mit Aufruferrechten ordnungsgemäß. Beide schlagen fehl, wenn eine gespeicherte Prozedur mit Eigentümerrechten verwendet wird, selbst wenn der Aufrufer der Eigentümer ist.
Gespeicherte Prozedur mit Aufruferrechten¶
Das folgende Beispiel zeigt eine gespeicherte Prozedur mit Aufruferrechten.
Erstellen und laden Sie eine Tabelle:
Legen Sie eine Sitzungsvariable fest:
Erstellen Sie eine gespeicherte Prozedur mit Aufruferrechten, die eine Sitzungsvariable nutzt und eine andere definiert:
Rufen Sie die Prozedur auf:
Zeigen Sie den Wert der Sitzungsvariablen an, die in der gespeicherten Prozedur festgelegt wurde:
Bemerkung
Obwohl Sie eine Sitzungsvariable in einer gespeicherten Prozedur festlegen und nach dem Ende der Prozedur gesetzt lassen können, wird dies von Snowflake nicht empfohlen.
Gespeicherte Prozedur mit Eigentümerrechten¶
Das folgende Beispiel zeigt eine gespeicherte Prozedur mit Eigentümerrechten.
Erstellen Sie eine gespeicherte Prozedur mit Eigentümerrechten, die eine Sitzungsvariable verwendet:
Rufen Sie die Prozedur auf (sie sollte fehlschlagen):
Erstellen Sie eine gespeicherte Prozedur mit Eigentümerrechten, die versucht, eine Sitzungsvariable festzulegen:
Rufen Sie die Prozedur auf (sie sollte fehlschlagen):
Problembehandlung¶
Eine allgemeine Methode zur Problembehandlung besteht darin, einen JavaScript-Try/Catch-Block zu verwenden, um den Fehler abzufangen und Fehlerinformationen anzuzeigen. Das Fehlerobjekt enthält:
Fehlercode
Fehlermeldung.
Fehlerstatus.
Stacktrace zum Zeitpunkt des Fehlers.
Weitere Informationen, einschließlich eines Beispiels zur Verwendung dieser Informationen, finden Sie unter Abfangen eines Fehlers mit Try/Catch (unter diesem Thema).
In den folgenden Abschnitten finden Sie zusätzliche Empfehlungen zum Debuggen bestimmter Probleme.
Gespeicherte Prozedur oder UDF gibt unerwartet NULL zurück¶
- Ursache:
Ihre gespeicherte Prozedur/UDF verfügt über einen Parameter, und innerhalb der Prozedur/UDF wird auf den Parameter durch seinen Namen in Kleinbuchstaben verwiesen; Snowflake hat den Namen jedoch automatisch in Großbuchstaben konvertiert.
- Lösung:
Entweder:
Verwenden Sie Großbuchstaben für den Variablennamen im JavaScript-Code; oder
setzen Sie den Variablennamen im SQL-Code in doppelte Anführungszeichen.
Weitere Details dazu finden Sie unter JavaScript-Argumente und zurückgegebene Werte.
Ausführung der gespeicherten Prozedur wird nie beendet¶
- Ursache:
Möglicherweise enthält Ihr JavaScript-Code eine Endlosschleife.
- Lösung:
Suchen Sie nach Endlosschleifen, und beseitigen Sie diese.
Fehler: Failed: empty argument passed¶
- Ursache:
Ihre gespeicherte Prozedur enthält möglicherweise „sqltext“, obwohl „sqlText“ erforderlich wäre (im ersten Fall in Kleinbuchstaben geschrieben, im zweiten Fall mit gemischter Groß-/Kleinschreibung).
- Lösung:
Verwenden Sie „sqlText“.
Fehler: JavaScript out of memory error: UDF thread memory limit exceeded¶
- Ursache:
Möglicherweise enthält Ihr JavaScript-Code eine Endlosschleife.
- Lösung:
Suchen Sie nach Endlosschleifen, und beseitigen Sie diese. Stellen Sie insbesondere sicher, dass Sie den Aufruf der nächsten Zeile beenden, wenn das Resultset aufgebraucht ist (d. h. wenn
resultSet.next()falsezurückgibt).