Flow-Operatoren

Flow-Operatoren verketten SQL-Anweisungen miteinander, wobei die Ergebnisse einer Anweisung als Eingabe für eine andere Anweisung dienen. Derzeit ist der Pipe-Operator (->>) der einzige von Snowflake unterstützte Flow-Operator.

Pipe

Pipe-Operatoren ähneln Unix-Pipes (|) auf der Befehlszeile, sind aber für SQL-Anweisungen anstelle von Unix-Befehlen vorgesehen. Um den Pipe-Operator zu verwenden, geben Sie eine Reihe von SQL-Anweisungen an, die durch den Operator getrennt sind. Sie können jede gültige SQL-Anweisung angeben, z. B. SHOW, SELECT, CREATE, INSERT und so weiter. Nach der ersten SQL-Anweisung kann jede nachfolgende Anweisung die Ergebnisse einer beliebigen vorherigen Anweisung als Eingabe verwenden. In der FROM-Klausel wird eine vorherige SQL-Anweisung durch einen Parameter mit dem Dollarzeichen ($) und der Pipe-Nummer referenziert, die die relative Position der Anweisung in der Kette rückwärts gezählt von der aktuellen Anweisung angibt.

Der Pipe-Operator kettet die folgende Reihe von SQL-Anweisungen aneinander, und die Kommentare zeigen die relativen Referenznummern für jede Anweisung:

first_st -- Referenced as $4 in last_st, $3 in fourth_st, $2 in third_st, and $1 in second_st
  ->> second_st -- Referenced as $3 in last_st, $2 in fourth_st, and $1 in third_st
  ->> third_st  -- Referenced as $2 in last_st and $1 in fourth_st
  ->> fourth_st -- Referenced as $1 in last_st
  ->> last_st;
Copy

Diese Reihe von SQL-Anweisungen hat zum Beispiel einen Verweis auf eine Pipe-Nummer in drei SELECT-Anweisungen, und jede dieser Anweisungen nimmt die Ergebnisse der ersten SELECT-Anweisung als Eingabe:

SELECT ...
  ->> SELECT ... FROM $1
  ->> SELECT ... FROM $2
  ->> SELECT ... FROM $3;
Copy

Wie gezeigt: Beenden Sie die Kette der SQL-Anweisungen, indem Sie nach der letzten Anweisung ein Semikolon setzen. Setzen Sie kein Semikolon nach den vorherigen Anweisungen in der Kette. Die Ausgabe der gesamten Kette ist das Endergebnis der letzten SQL-Anweisung. Client-Tools, wie z. B. SnowSQL, behandeln die Kette von Anweisungen als eine einzige Anweisung.

Der Pipe-Operator bietet folgende Vorteile:

  • Vereinfacht die Ausführung von abhängigen SQL-Anweisungen.

  • Verbessert die Lesbarkeit und Flexibilität von komplexen SQL-Operationen.

Syntax

<sql_statement_1> ->> <sql_statement_2> [ ->> <sql_statement_n> ... ]
Copy

Nutzungshinweise

  • Jede Anweisung erzeugt ein Ergebnis, das nur von einer nachfolgenden Anweisung in der Kette genutzt werden kann.

  • Die Anweisungen werden in der angegebenen Reihenfolge ausgeführt. Im Gegensatz zu RESULT_SCAN(LAST_QUERY_ID()) wird die Pipe-Nummer in das richtige Resultset in der Kette aufgelöst, unabhängig davon, ob andere Abfragen gleichzeitig außerhalb der Kette ausgeführt wurden oder nicht.

  • Wenn eine Anweisung die Ergebnisse einer vorherigen Anweisung nutzt, entspricht das genutzte Resultset dem Resultset, das von der Funktion RESULT_SCAN zurückgegeben wird, der die Abfrage-ID der vorherigen Anweisung übergeben wurde.

    Diese Anweisungen beschränken zum Beispiel die Ausgabe des Befehls SHOW WAREHOUSES auf bestimmte Spalten:

    SHOW WAREHOUSES;
    
    SELECT "name", "state", "type", "size"
      FROM TABLE(RESULT_SCAN(LAST_QUERY_ID(-1)));
    
    Copy

    Diese Anweisung verwendet den Pipe-Operator, um das gleiche Ergebnis zu erzielen:

    SHOW WAREHOUSES
      ->> SELECT "name", "state", "type", "size" FROM $1;
    
    Copy
  • Bei einer Abfrage, die den Pipe-Operator verwendet, ist nicht garantiert, dass die Zeilen in der gleichen Reihenfolge zurückgegeben werden wie das Resultset einer vorherigen Abfrage in der Kette. Sie können eine ORDER BY-Klausel in die Abfrage einfügen, um die Reihenfolge festzulegen.

  • Ein Fehler, der durch eine SQL-Anweisung ausgelöst wird, stoppt die Ausführung der Kette. Der Fehler wird dann an den Client zurückgegeben.

  • Das Ergebnis der letzten Anweisung wird an den Client zurückgegeben.

  • Die Anweisungen werden als anonymer Snowflake Scripting-Block ausgeführt.

Einschränkungen

  • Der Parameter $n ist nur in der FROM-Klausel einer SQL-Anweisung gültig.

  • Jede SQL-Anweisung erzeugt ein Ergebnis, das nur von einer nachfolgenden Anweisung in der Pipe-Kette genutzt werden kann. Die Ergebnisse können nicht außerhalb der Pipe-Kette genutzt werden, mit Ausnahme der Ergebnisse der letzten Anweisung.

  • Positionale Bindungsvariablen werden nicht unterstützt.

Beispiele

Die folgenden Beispiele verwenden den Pipe-Operator:

Liste von Spalten für die Ausgabe eines SHOW-Befehls auswählen

Führen Sie den Befehl SHOW TABLES aus und verwenden Sie den Pipe-Operator, um die Ausgabe auf die Spalten created_on, name und owner für Tabellen zu beschränken, die nach dem 15. April 2025 erstellt wurden.

SHOW TABLES
  ->> SELECT "created_on" AS creation_date,
             "name" AS table_name,
             "owner" AS table_owner
        FROM $1
        WHERE creation_date > '2025-04-15'::DATE;
Copy
+-------------------------------+-------------+--------------+
| CREATION_DATE                 | TABLE_NAME  | TABLE_OWNER  |
|-------------------------------+-------------+--------------|
| 2025-04-16 08:46:16.130 -0700 | TEST_TABLE1 | ACCOUNTADMIN |
| 2025-04-16 09:44:13.701 -0700 | MYTABLE1    | USER_ROLE    |
| 2025-04-16 08:46:32.092 -0700 | MYTABLE2    | USER_ROLE    |
+-------------------------------+-------------+--------------+

Abfragen ausführen, die Eingaben aus Abfragen mehrerer Tabellen enthalten

Erstellen Sie zunächst eine dept_pipe_demo-Tabelle und eine emp_pipe_demo-Tabelle und fügen Sie in beide Tabellen Daten ein:

CREATE OR REPLACE TABLE dept_pipe_demo (
  deptno NUMBER(2),
  dname VARCHAR(14),
  loc VARCHAR(13)
  ) AS SELECT * FROM VALUES
     (10, 'ACCOUNTING', 'NEW YORK'),
     (20, 'RESEARCH', 'DALLAS'),
     (30, 'SALES', 'CHICAGO'),
     (40, 'OPERATIONS', 'BOSTON');

CREATE OR REPLACE TABLE emp_pipe_demo (
  empno NUMBER(4),
  ename VARCHAR(10),
  sal NUMBER(7,2),
  deptno NUMBER(2)
  ) AS SELECT * FROM VALUES
    (7369, 'SMITH', 800, 20),
    (7499, 'ALLEN', 1600, 30),
    (7521, 'WARD', 1250, 30),
    (7698, 'BLAKE', 2850, 30),
    (7782, 'CLARK', 2450, 10);
Copy

Im folgenden Beispiel wird der Pipe-Operator für eine Kette von SQL-Anweisungen verwendet, die die folgenden Operationen ausführen:

  1. Fragen Sie die Tabelle dept_pipe_demo ab, um Zeilen zurückzugeben, in denen dname gleich SALES ist.

  2. Fragen Sie die Tabelle emp_pipe_demo nach Mitarbeitern mit einem Gehalt größer als 1500 in der Abteilung SALES ab und verwenden Sie dabei Ergebnisse der vorherigen Abfrage als Eingabe. Geben Sie dazu $1 in der WHERE-Bedingung einer FROM-Klausel an.

  3. Führen Sie eine Abfrage aus, die die Werte ename und sal zurückgibt und dabei die Ergebnisse der vorherigen Abfrage als Eingabe verwendet, indem Sie $1 in der FROM-Klausel angeben.

SELECT * FROM dept_pipe_demo WHERE dname = 'SALES'
  ->> SELECT * FROM emp_pipe_demo WHERE sal > 1500 AND deptno IN (SELECT deptno FROM $1)
  ->> SELECT ename, sal FROM $1 ORDER BY 2 DESC;
Copy
+-------+---------+
| ENAME |     SAL |
|-------+---------|
| BLAKE | 2850.00 |
| ALLEN | 1600.00 |
+-------+---------+

Bemerkung

In diesem Beispiel soll gezeigt werden, wie Sie eine Reihe von Abfragen mit dem Pipe-Operator kombinieren können. Das gleiche Ergebnis kann jedoch auch mit einer Join-Abfrage erzielt werden, und Join-Abfragen schneiden in der Regel besser ab als Abfragen in Kombination mit dem Pipe-Operator.

Zeilenzahlen für DML-Operationen in einer Transaktion zurückgeben

Erstellen Sie eine Tabelle und fügen Sie eine Zeile nach der anderen ein. Wenn Sie alle Anweisungen verketten, können Sie den Pipe-Operator verwenden, um das Ergebnis jeder INSERT-Anweisung zu untersuchen, das die Gesamtzahl der eingefügten Zeilen darstellt.

In jeder der SELECT-Anweisungen im Beispiel ist $1 in der SELECT-Liste eine Kurzreferenz auf die erste Spalte, nicht auf ein vorheriges Ergebnis in der Pipe. Der Parameter $n für eine Pipe-Nummer ist nur in der FROM-Klausel gültig.

CREATE OR REPLACE TABLE test_sql_pipe_dml (a INT, b INT)
  ->> INSERT INTO test_sql_pipe_dml VALUES (1, 2)
  ->> INSERT INTO test_sql_pipe_dml VALUES (3, 4)
  ->> INSERT INTO test_sql_pipe_dml VALUES (5, 6)
  ->> INSERT INTO test_sql_pipe_dml VALUES (7, 8)
  ->> SELECT (SELECT $1 FROM $4) +
             (SELECT $1 FROM $3) +
             (SELECT $1 FROM $2) +
             (SELECT $1 FROM $1)
        AS "Number of rows";
Copy
+----------------+
| Number of rows |
|----------------|
|              4 |
+----------------+

Im folgenden Beispiel wird der Pipe-Operator für eine Kette von SQL-Anweisungen verwendet, die die folgenden Operationen ausführen:

  1. Starten Sie eine Transaktion.

  2. Fügen Sie eine Zeile in die zuvor erstellte Tabelle ein.

  3. Löschen Sie Zeilen aus der Tabelle.

  4. Aktualisieren Sie Zeilen in der Tabelle.

  5. Bestätigen Sie die Transaktion.

  6. Fragen Sie die Anzahl der Zeilen ab, die von jeder DML-Operation betroffen waren.

EXECUTE IMMEDIATE $$
BEGIN TRANSACTION
  ->> INSERT INTO test_sql_pipe_dml VALUES (1, 2)
  ->> DELETE FROM test_sql_pipe_dml WHERE a = 1
  ->> UPDATE test_sql_pipe_dml SET b = 2
  ->> COMMIT
  ->> SELECT
        (SELECT $1 FROM $4) AS "Inserted rows",
        (SELECT $1 FROM $3) AS "Deleted rows",
        (SELECT $1 FROM $2) AS "Updated rows";
$$;
Copy
+---------------+--------------+--------------+
| Inserted rows | Deleted rows | Updated rows |
|---------------+--------------+--------------|
|             1 |            2 |            3 |
+---------------+--------------+--------------+

Geben Sie die Ergebnisse für Inserts in eine Tabelle zurück, die später gelöscht wird.

In diesem Beispiel wird der Pipe-Operator für eine Kette von SQL-Anweisungen verwendet, die die folgenden Operationen ausführen:

  1. Erstellen Sie eine Tabelle mit einer IDENTITY-Spalte.

  2. Fügen Sie Zeilen in die Tabelle ein.

  3. Fragen Sie die Tabelle ab.

  4. Tabelle löschen

  5. Fragen Sie die Ergebnisse der Pipe-Nummer $2 ab (die SELECT-Anweisung).

Das Resultset, das in der letzten SELECT-Anweisung genutzt wird, entspricht dem Resultset, das von der Funktion RESULT_SCAN für die Abfrage-ID der vorherigen SELECT-Anweisung zurückgegeben wird.

CREATE OR REPLACE TABLE test_sql_pipe_drop (
    id INT IDENTITY START 10 INCREMENT 1,
    data VARCHAR)
  ->> INSERT INTO test_sql_pipe_drop (data) VALUES ('row1'), ('row2'), ('row3')
  ->> SELECT * FROM test_sql_pipe_drop
  ->> DROP TABLE test_sql_pipe_drop
  ->> SELECT COUNT(*) "Number of rows", MAX(id) AS "Last ID" FROM $2;
Copy
+----------------+---------+
| Number of rows | Last ID |
|----------------+---------|
|              3 |      12 |
+----------------+---------+