Verwenden von Schleifen

Snowflake Scripting unterstützt die folgenden Typen von Schleifen:

Unter diesem Thema wird erläutert, wie die einzelnen Schleifentypen verwendet werden.

FOR-Schleife

Eine FOR-Schleife wiederholt eine Sequenz von Schritten mit der angegebenen Häufigkeit oder für jede Zeile eines Resultsets. Snowflake Scripting unterstützt die folgenden Typen von FOR-Schleifen:

In den nächsten Abschnitten wird erläutert, wie diese Typen von FOR-Schleifen verwendet werden:

Zählerbasierte FOR-Schleifen

Eine zählerbasierte FOR-Schleife wird eine bestimmte Anzahl von Malen ausgeführt.

Verwenden Sie die folgende Syntax für eine zählerbasierte FOR-Schleife:

FOR <counter_variable> IN [ REVERSE ] <start> TO <end> { DO | LOOP }
  <statement>;
  [ <statement>; ... ]
END { FOR | LOOP } [ <label> ] ;

Die folgende FOR-Schleife wird zum Beispiel fünfmal ausgeführt:

DECLARE
  counter INTEGER DEFAULT 0;
  maximum_count INTEGER default 5;
BEGIN
  FOR i IN 1 TO maximum_count DO
    counter := counter + 1;
  END FOR;
  RETURN counter;
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
DECLARE
  counter INTEGER DEFAULT 0;
  maximum_count INTEGER default 5;
BEGIN
  FOR i IN 1 TO maximum_count DO
    counter := counter + 1;
  END FOR;
  RETURN counter;
END;
$$
;
+-----------------+
| anonymous block |
|-----------------|
|               5 |
+-----------------+

Sie können SQL-Anweisungen in Snowflake Scripting-Schleifen einfügen. Die folgende FOR-Schleife führt beispielsweise eine INSERT-Anweisung fünfmal aus, um den Wert des Zählers in eine Tabelle einzufügen:

DECLARE
  counter INTEGER DEFAULT 0;
  maximum_count INTEGER default 5;
BEGIN
  CREATE OR REPLACE TABLE test_for_loop_insert(i INTEGER);
  FOR i IN 1 TO maximum_count DO
    INSERT INTO test_for_loop_insert VALUES (:i);
    counter := counter + 1;
  END FOR;
  RETURN counter || ' rows inserted';
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
DECLARE
  counter INTEGER DEFAULT 0;
  maximum_count INTEGER default 5;
BEGIN
  CREATE OR REPLACE TABLE test_for_loop_insert(i INTEGER);
  FOR i IN 1 TO maximum_count DO
    INSERT INTO test_for_loop_insert VALUES (:i);
    counter := counter + 1;
  END FOR;
  RETURN counter || ' rows inserted';
END;
$$
;
+-----------------+
| anonymous block |
|-----------------|
| 5 rows inserted |
+-----------------+

Fragen Sie die Tabelle ab, um die eingefügten Zeilen anzuzeigen:

SELECT * FROM test_for_loop_insert;
+---+
| I |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+---+

Im folgenden Beispiel wird eine zählerbasierte FOR-Schleife verwendet, um eine Datumsdimensionstabelle zu füllen, was eine häufige Aufgabe beim Einrichten eines Data Warehouses ist. Die Schleife iteriert über einen Bereich von Tagen und fügt für jedes Datum eine Zeile mit berechneten Attributen ein:

DECLARE
  start_date DATE DEFAULT '2025-01-01';
  current_date_val DATE;
BEGIN
  CREATE OR REPLACE TABLE date_dimension (
    date_key INTEGER,
    full_date DATE,
    day_of_week VARCHAR,
    month_name VARCHAR,
    quarter INTEGER,
    year INTEGER
  );
  FOR i IN 1 TO 7 DO
    current_date_val := DATEADD('day', :i - 1, :start_date);
    INSERT INTO date_dimension
      SELECT :i, :current_date_val, DAYNAME(:current_date_val),
        MONTHNAME(:current_date_val), QUARTER(:current_date_val),
        YEAR(:current_date_val);
  END FOR;
  RETURN 'Populated date dimension with 7 rows';
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
DECLARE
  start_date DATE DEFAULT '2025-01-01';
  current_date_val DATE;
BEGIN
  CREATE OR REPLACE TABLE date_dimension (
    date_key INTEGER,
    full_date DATE,
    day_of_week VARCHAR,
    month_name VARCHAR,
    quarter INTEGER,
    year INTEGER
  );
  FOR i IN 1 TO 7 DO
    current_date_val := DATEADD('day', :i - 1, :start_date);
    INSERT INTO date_dimension
      SELECT :i, :current_date_val, DAYNAME(:current_date_val),
        MONTHNAME(:current_date_val), QUARTER(:current_date_val),
        YEAR(:current_date_val);
  END FOR;
  RETURN 'Populated date dimension with 7 rows';
END;
$$
;
+----------------------------------------+
| anonymous block                        |
|----------------------------------------|
| Populated date dimension with 7 rows   |
+----------------------------------------+

Um die Ergebnisse zu überprüfen, fragen Sie die Tabelle ab:

SELECT * FROM date_dimension ORDER BY date_key;
+----------+------------+-------------+------------+---------+------+
| DATE_KEY | FULL_DATE  | DAY_OF_WEEK | MONTH_NAME | QUARTER | YEAR |
|----------+------------+-------------+------------+---------+------|
|        1 | 2025-01-01 | Wed         | Jan        |       1 | 2025 |
|        2 | 2025-01-02 | Thu         | Jan        |       1 | 2025 |
|        3 | 2025-01-03 | Fri         | Jan        |       1 | 2025 |
|        4 | 2025-01-04 | Sat         | Jan        |       1 | 2025 |
|        5 | 2025-01-05 | Sun         | Jan        |       1 | 2025 |
|        6 | 2025-01-06 | Mon         | Jan        |       1 | 2025 |
|        7 | 2025-01-07 | Tue         | Jan        |       1 | 2025 |
+----------+------------+-------------+------------+---------+------+

Die vollständige Syntax und weitere Einzelheiten zu FOR-Schleifen finden Sie unter FOR (Snowflake Scripting).

Cursorbasierte FOR-Schleifen

Eine cursorbasierte FOR-Schleife iteriert über einem Resultset. Die Anzahl der Iterationen wird durch die Anzahl der Zeilen im Cursor bestimmt.

Die Syntax für eine cursorbasierte FOR-Schleife lautet:

FOR <row_variable> IN <cursor_name> DO
  <statement>;
  [ <statement>; ... ]
END FOR [ <label> ] ;

Für das erste Beispiel in diesem Abschnitt werden die Daten der folgenden Tabelle invoices verwendet:

CREATE OR REPLACE TABLE invoices (price NUMBER(12, 2));

INSERT INTO invoices (price) VALUES
  (11.11),
  (22.22);

Das folgende Beispiel verwendet eine FOR-Schleife, um über die Zeilen in einem Cursor der Tabelle invoices zu iterieren:

DECLARE
  total_price FLOAT;
  c1 CURSOR FOR SELECT price FROM invoices;
BEGIN
  total_price := 0.0;
  FOR record IN c1 DO
    total_price := total_price + record.price;
  END FOR;
  RETURN total_price;
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
DECLARE
  total_price FLOAT;
  c1 CURSOR FOR SELECT price FROM invoices;
BEGIN
  total_price := 0.0;
  FOR record IN c1 DO
    total_price := total_price + record.price;
  END FOR;
  RETURN total_price;
END;
$$
;
+-----------------+
| anonymous block |
|-----------------|
|           33.33 |
+-----------------+

Das folgende Beispiel verwendet eine cursorbasierte FOR-Schleife, um über eine Tabelle mit Mitarbeitenden zu iterieren, jedem Mitarbeiter eine Erhöhung auf der Grundlage seiner Abteilung zu gewähren und einen Überwachungsdatensatz für jede Aktualisierung einzufügen:

CREATE OR REPLACE TABLE loop_test_employees (
  emp_id INTEGER,
  name VARCHAR,
  department VARCHAR,
  salary NUMBER(12,2));

INSERT INTO loop_test_employees VALUES
  (1, 'Alice', 'Engineering', 90000),
  (2, 'Bob', 'Sales', 70000),
  (3, 'Carol', 'Engineering', 95000),
  (4, 'Dave', 'Sales', 72000);

CREATE OR REPLACE TABLE salary_audit (
  emp_id INTEGER,
  old_salary NUMBER(12,2),
  new_salary NUMBER(12,2),
  updated_on TIMESTAMP);
DECLARE
  rows_updated INTEGER DEFAULT 0;
  raise_pct INTEGER;
  new_salary NUMBER(12,2);
  cur_emp_id INTEGER;
  cur_salary NUMBER(12,2);
  c1 CURSOR FOR SELECT emp_id, department, salary FROM loop_test_employees;
BEGIN
  FOR record IN c1 DO
    cur_emp_id := record.emp_id;
    cur_salary := record.salary;
    IF (record.department = 'Engineering') THEN
      raise_pct := 10;
    ELSE
      raise_pct := 5;
    END IF;
    new_salary := :cur_salary * (1 + :raise_pct / 100);
    UPDATE loop_test_employees SET salary = :new_salary WHERE emp_id = :cur_emp_id;
    INSERT INTO salary_audit
      SELECT :cur_emp_id, :cur_salary, :new_salary, CURRENT_TIMESTAMP();
    rows_updated := rows_updated + 1;
  END FOR;
  RETURN rows_updated || ' employees updated';
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
DECLARE
  rows_updated INTEGER DEFAULT 0;
  raise_pct INTEGER;
  new_salary NUMBER(12,2);
  cur_emp_id INTEGER;
  cur_salary NUMBER(12,2);
  c1 CURSOR FOR SELECT emp_id, department, salary FROM loop_test_employees;
BEGIN
  FOR record IN c1 DO
    cur_emp_id := record.emp_id;
    cur_salary := record.salary;
    IF (record.department = 'Engineering') THEN
      raise_pct := 10;
    ELSE
      raise_pct := 5;
    END IF;
    new_salary := :cur_salary * (1 + :raise_pct / 100);
    UPDATE loop_test_employees SET salary = :new_salary WHERE emp_id = :cur_emp_id;
    INSERT INTO salary_audit
      SELECT :cur_emp_id, :cur_salary, :new_salary, CURRENT_TIMESTAMP();
    rows_updated := rows_updated + 1;
  END FOR;
  RETURN rows_updated || ' employees updated';
END;
$$
;
+----------------------+
| anonymous block      |
|----------------------|
| 4 employees updated  |
+----------------------+

Um die Aktualisierungen zu überprüfen, fragen Sie die Tabellen ab:

SELECT emp_id, name, department, salary FROM loop_test_employees ORDER BY emp_id;
+--------+-------+-------------+-----------+
| EMP_ID | NAME  | DEPARTMENT  |    SALARY |
|--------+-------+-------------+-----------|
|      1 | Alice | Engineering |  99000.00 |
|      2 | Bob   | Sales       |  73500.00 |
|      3 | Carol | Engineering | 104500.00 |
|      4 | Dave  | Sales       |  75600.00 |
+--------+-------+-------------+-----------+
SELECT emp_id, old_salary, new_salary FROM salary_audit ORDER BY emp_id;
+--------+------------+------------+
| EMP_ID | OLD_SALARY | NEW_SALARY |
|--------+------------+------------|
|      1 |   90000.00 |   99000.00 |
|      2 |   70000.00 |   73500.00 |
|      3 |   95000.00 |  104500.00 |
|      4 |   72000.00 |   75600.00 |
+--------+------------+------------+

Die vollständige Syntax und weitere Einzelheiten zu FOR-Schleifen finden Sie unter FOR (Snowflake Scripting).

RESULTSET-basierte FOR-Schleifen

Eine RESULTSET-basierte FOR-Schleife iteriert über einem Resultset. Die Anzahl der Iterationen wird durch die Anzahl der Zeilen bestimmt, die von der RESULTSET-Abfrage zurückgegeben werden.

Die Syntax für eine RESULTSET-basierte FOR-Schleife lautet:

FOR <row_variable> IN <RESULTSET_name> DO
  <statement>;
  [ <statement>; ... ]
END FOR [ <label> ] ;

Für das erste Beispiel in diesem Abschnitt werden die Daten der folgenden Tabelle invoices verwendet:

CREATE OR REPLACE TABLE invoices (price NUMBER(12, 2));
INSERT INTO invoices (price) VALUES
  (11.11),
  (22.22);

Das folgende Beispiel verwendet eine FOR-Schleife, um über die Zeilen in einem RESULTSET der Tabelle invoices zu iterieren:

DECLARE
  total_price FLOAT;
  rs RESULTSET;
BEGIN
  total_price := 0.0;
  rs := (SELECT price FROM invoices);
  FOR record IN rs DO
    total_price := total_price + record.price;
  END FOR;
  RETURN total_price;
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
DECLARE
  total_price FLOAT;
  rs RESULTSET;
BEGIN
  total_price := 0.0;
  rs := (SELECT price FROM invoices);
  FOR record IN rs DO
    total_price := total_price + record.price;
  END FOR;
  RETURN total_price;
END;
$$
;
+-----------------+
| anonymous block |
|-----------------|
|           33.33 |
+-----------------+

Im folgenden Beispiel wird eine RESULTSET-basierte FOR-Schleife zur Validierung von Kundendatensätzen verwendet. Es wird jeder Datensatz auf die erforderlichen Kontaktinformationen überprüft und die status-Spalte wird aktualisiert, um jeden Datensatz als verifiziert oder unvollständig zu markieren. Diese Art der Datenqualitätsprüfung ist ein häufiger Schritt beim Extrahieren, Transformieren und Laden von (ETL)-Pipelines:

CREATE OR REPLACE TABLE loop_test_customers (
  customer_id INTEGER,
  customer_name VARCHAR,
  customer_email VARCHAR,
  customer_phone VARCHAR,
  status VARCHAR DEFAULT 'pending_review');

INSERT INTO loop_test_customers (customer_id, customer_name, customer_email, customer_phone) VALUES
  (1, 'Alice Smith', 'alice@example.com', '800-555-0101'),
  (2, 'Bob Jones', NULL, '800-555-0102'),
  (3, 'Carol White', 'carol@example.com', NULL),
  (4, 'Dave Brown', NULL, NULL),
  (5, 'Eve Davis', 'eve@example.com', '800-555-0105');
DECLARE
  rs RESULTSET;
  valid_count INTEGER DEFAULT 0;
  invalid_count INTEGER DEFAULT 0;
  cur_customer_id INTEGER;
BEGIN
  rs := (SELECT customer_id, customer_email, customer_phone FROM loop_test_customers WHERE status = 'pending_review');
  FOR record IN rs DO
    cur_customer_id := record.customer_id;
    IF (record.customer_email IS NOT NULL AND record.customer_phone IS NOT NULL) THEN
      UPDATE loop_test_customers SET status = 'verified' WHERE customer_id = :cur_customer_id;
      valid_count := valid_count + 1;
    ELSE
      UPDATE loop_test_customers SET status = 'incomplete' WHERE customer_id = :cur_customer_id;
      invalid_count := invalid_count + 1;
    END IF;
  END FOR;
  RETURN 'Verified: ' || valid_count || ', Incomplete: ' || invalid_count;
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
DECLARE
  rs RESULTSET;
  valid_count INTEGER DEFAULT 0;
  invalid_count INTEGER DEFAULT 0;
  cur_customer_id INTEGER;
BEGIN
  rs := (SELECT customer_id, customer_email, customer_phone FROM loop_test_customers WHERE status = 'pending_review');
  FOR record IN rs DO
    cur_customer_id := record.customer_id;
    IF (record.customer_email IS NOT NULL AND record.customer_phone IS NOT NULL) THEN
      UPDATE loop_test_customers SET status = 'verified' WHERE customer_id = :cur_customer_id;
      valid_count := valid_count + 1;
    ELSE
      UPDATE loop_test_customers SET status = 'incomplete' WHERE customer_id = :cur_customer_id;
      invalid_count := invalid_count + 1;
    END IF;
  END FOR;
  RETURN 'Verified: ' || valid_count || ', Incomplete: ' || invalid_count;
END;
$$
;
+-------------------------------+
| anonymous block               |
|-------------------------------|
| Verified: 2, Incomplete: 3   |
+-------------------------------+

Um die Änderungen zu überprüfen, fragen Sie die Tabelle ab:

SELECT * FROM loop_test_customers ORDER BY customer_id;
+-------------+-----------------+-------------------+----------------+------------+
| CUSTOMER_ID | CUSTOMER_NAME   | CUSTOMER_EMAIL    | CUSTOMER_PHONE | STATUS     |
|-------------+-----------------+-------------------+----------------+------------|
|           1 | Alice Smith     | alice@example.com | 800-555-0101   | verified   |
|           2 | Bob Jones       | NULL              | 800-555-0102   | incomplete |
|           3 | Carol White     | carol@example.com | NULL           | incomplete |
|           4 | Dave Brown      | NULL              | NULL           | incomplete |
|           5 | Eve Davis       | eve@example.com   | 800-555-0105   | verified   |
+-------------+-----------------+-------------------+----------------+------------+

Die vollständige Syntax und weitere Einzelheiten zu FOR-Schleifen finden Sie unter FOR (Snowflake Scripting).

WHILE-Schleife

Eine WHILE-Schleife wird wiederholt, solange eine Bedingung erfüllt ist. Bei einer WHILE-Schleife wird die Bedingung unmittelbar vor Ausführung des Schleifeninhalts geprüft. Wenn die Bedingung vor der ersten Iteration nicht erfüllt ist, wird der Schleifeninhalt nicht ein einziges Mal ausgeführt.

Die Syntax für eine WHILE-Schleife lautet:

WHILE ( <condition> ) { DO | LOOP }
  <statement>;
  [ <statement>; ... ]
END { WHILE | LOOP } [ <label> ] ;

Beispiel:

BEGIN
  LET counter := 0;
  WHILE (counter < 5) DO
    counter := counter + 1;
  END WHILE;
  RETURN counter;
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
BEGIN
  LET counter := 0;
  WHILE (counter < 5) DO
    counter := counter + 1;
  END WHILE;
  RETURN counter;
END;
$$
;
+-----------------+
| anonymous block |
|-----------------|
|               5 |
+-----------------+

Im folgenden Beispiel wird eine WHILE-Schleife verwendet, um aus den Rohdaten der Transaktion eine tägliche Verkaufszusammenfassung zu erstellen. Sie verarbeitet immer ein Datum, fasst die Transaktionen für dieses Datum in einer Zusammenfassungszeile zusammen und markiert sie als geladen. Dieses Muster von Datum für Datum ist beim Extrahieren, Transformieren und Laden von (ETL)-Pipelines üblich:

CREATE OR REPLACE TABLE loop_test_raw_transactions (
  txn_id INTEGER,
  amount NUMBER(12,2),
  txn_date DATE,
  loaded BOOLEAN DEFAULT FALSE);

INSERT INTO loop_test_raw_transactions (txn_id, amount, txn_date) VALUES
  (1, 150.00, '2025-03-01'),
  (2, 230.50, '2025-03-01'),
  (3, 89.99, '2025-03-01'),
  (4, 412.00, '2025-03-02'),
  (5, 55.25, '2025-03-03'),
  (6, 178.75, '2025-03-03');

CREATE OR REPLACE TABLE loop_test_daily_sales_summary (
  summary_date DATE,
  total_sales NUMBER(12,2),
  txn_count INTEGER);
DECLARE
  next_date DATE;
BEGIN
  next_date := (SELECT MIN(txn_date) FROM loop_test_raw_transactions WHERE NOT loaded);
  WHILE (next_date IS NOT NULL) DO
    INSERT INTO loop_test_daily_sales_summary
      SELECT txn_date, SUM(amount), COUNT(*)
      FROM loop_test_raw_transactions
      WHERE txn_date = :next_date AND NOT loaded
      GROUP BY txn_date;
    UPDATE loop_test_raw_transactions SET loaded = TRUE WHERE txn_date = :next_date;
    next_date := (SELECT MIN(txn_date) FROM loop_test_raw_transactions WHERE NOT loaded);
  END WHILE;
  RETURN 'Daily summaries created for all transaction dates';
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
DECLARE
  next_date DATE;
BEGIN
  next_date := (SELECT MIN(txn_date) FROM loop_test_raw_transactions WHERE NOT loaded);
  WHILE (next_date IS NOT NULL) DO
    INSERT INTO loop_test_daily_sales_summary
      SELECT txn_date, SUM(amount), COUNT(*)
      FROM loop_test_raw_transactions
      WHERE txn_date = :next_date AND NOT loaded
      GROUP BY txn_date;
    UPDATE loop_test_raw_transactions SET loaded = TRUE WHERE txn_date = :next_date;
    next_date := (SELECT MIN(txn_date) FROM loop_test_raw_transactions WHERE NOT loaded);
  END WHILE;
  RETURN 'Daily summaries created for all transaction dates';
END;
$$
;
+----------------------------------------------------+
| anonymous block                                    |
|----------------------------------------------------|
| Daily summaries created for all transaction dates  |
+----------------------------------------------------+

Um die Ergebnisse zu überprüfen, fragen Sie die Zusammenfassungstabelle ab:

SELECT * FROM loop_test_daily_sales_summary ORDER BY summary_date;
+--------------+-------------+-----------+
| SUMMARY_DATE | TOTAL_SALES | TXN_COUNT |
|--------------+-------------+-----------|
| 2025-03-01   |      470.49 |         3 |
| 2025-03-02   |      412.00 |         1 |
| 2025-03-03   |      234.00 |         2 |
+--------------+-------------+-----------+

Die vollständige Syntax und weitere Einzelheiten zu WHILE-Schleifen finden Sie unter WHILE (Snowflake Scripting).

REPEAT-Schleife

Eine REPEAT-Schleife wird solange wiederholt, bis eine Bedingung erfüllt ist. In einer REPEAT-Schleife wird die Bedingung unmittelbar nach Ausführung des Schleifeninhalts geprüft. Das hat zur Folge, dass der Inhalt der Schleifen immer mindestens einmal ausgeführt wird.

Die Syntax für eine REPEAT-Schleife lautet:

REPEAT
  <statement>;
  [ <statement>; ... ]
UNTIL ( <condition> )
END REPEAT [ <label> ] ;

Beispiel:

BEGIN
  LET counter := 5;
  LET number_of_iterations := 0;
  REPEAT
    counter := counter - 1;
    number_of_iterations := number_of_iterations + 1;
  UNTIL (counter = 0)
  END REPEAT;
  RETURN number_of_iterations;
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
BEGIN
  LET counter := 5;
  LET number_of_iterations := 0;
  REPEAT
    counter := counter - 1;
    number_of_iterations := number_of_iterations + 1;
  UNTIL (counter = 0)
  END REPEAT;
  RETURN number_of_iterations;
END;
$$
;
+-----------------+
| anonymous block |
|-----------------|
|               5 |
+-----------------+

Im folgenden Beispiel werden eine Staging-Tabelle und eine Zieltabelle mit einer zusätzlichen batch_id-Spalte erstellt. Anschließend wird eine REPEAT-Schleife verwendet, um Zeilen in Batches aus der Staging-Tabelle in die Zieltabelle zu verschieben, wobei die Batch-ID nach jeder Iteration erhöht wird, bis keine Zeilen mehr in der Staging-Tabelle vorhanden sind:

CREATE OR REPLACE TABLE loop_test_orders_staging (
  order_id INTEGER,
  customer VARCHAR,
  amount NUMBER(12,2));

INSERT INTO loop_test_orders_staging VALUES
  (101, 'TestA Corp', 500.00),
  (102, 'TestB Corp', 1200.00),
  (103, 'TestA Corp', 300.00),
  (104, 'TestC Corp', 750.00),
  (105, 'TestB Corp', 425.00),
  (106, 'TestC Corp', 980.00);

CREATE OR REPLACE TABLE loop_test_orders_processed (
    order_id INTEGER,
    customer VARCHAR,
    amount NUMBER(12,2),
    batch_id INTEGER);
DECLARE
  batch_size INTEGER DEFAULT 2;
  batch_id INTEGER DEFAULT 1;
  remaining INTEGER;
BEGIN
  remaining := (SELECT COUNT(*) FROM loop_test_orders_staging);
  REPEAT
    INSERT INTO loop_test_orders_processed
      SELECT order_id, customer, amount, :batch_id
      FROM loop_test_orders_staging
      ORDER BY order_id
      LIMIT :batch_size;
    DELETE FROM loop_test_orders_staging WHERE order_id IN (
      SELECT order_id
        FROM loop_test_orders_processed
        WHERE batch_id = :batch_id
    );
    batch_id := batch_id + 1;
    remaining := (SELECT COUNT(*) FROM loop_test_orders_staging);
  UNTIL (remaining = 0)
  END REPEAT;
  RETURN 'Processed all orders in ' || (batch_id - 1) || ' batches';
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
DECLARE
  batch_size INTEGER DEFAULT 2;
  batch_id INTEGER DEFAULT 1;
  remaining INTEGER;
BEGIN
  remaining := (SELECT COUNT(*) FROM loop_test_orders_staging);
  REPEAT
    INSERT INTO loop_test_orders_processed
      SELECT order_id, customer, amount, :batch_id
      FROM loop_test_orders_staging
      ORDER BY order_id
      LIMIT :batch_size;
    DELETE FROM loop_test_orders_staging WHERE order_id IN (
      SELECT order_id
        FROM loop_test_orders_processed
        WHERE batch_id = :batch_id
    );
    batch_id := batch_id + 1;
    remaining := (SELECT COUNT(*) FROM loop_test_orders_staging);
  UNTIL (remaining = 0)
  END REPEAT;
  RETURN 'Processed all orders in ' || (batch_id - 1) || ' batches';
END;
$$
;
+------------------------------------+
| anonymous block                    |
|------------------------------------|
| Processed all orders in 3 batches  |
+------------------------------------+

Um die Ergebnisse zu überprüfen, fragen Sie die Zieltabelle ab:

SELECT * FROM loop_test_orders_processed ORDER BY batch_id, order_id;
+----------+------------+---------+----------+
| ORDER_ID | CUSTOMER   |  AMOUNT | BATCH_ID |
|----------+------------+---------+----------|
|      101 | TestA Corp |  500.00 |        1 |
|      102 | TestB Corp | 1200.00 |        1 |
|      103 | TestA Corp |  300.00 |        2 |
|      104 | TestC Corp |  750.00 |        2 |
|      105 | TestB Corp |  425.00 |        3 |
|      106 | TestC Corp |  980.00 |        3 |
+----------+------------+---------+----------+

Die vollständige Syntax und weitere Einzelheiten zu REPEAT-Schleifen finden Sie unter REPEAT (Snowflake Scripting).

LOOP-Schleife

Eine LOOP-Schleife wird solange ausgeführt, bis ein BREAK-Befehl ausgeführt wird. Ein solcher BREAK-Befehl ist normalerweise in eine Verzweigungslogik eingebettet (z. B. IF-Anweisungen oder CASE-Anweisungen).

Die Syntax für eine LOOP-Anweisung lautet:

LOOP
  <statement>;
  [ <statement>; ... ]
END LOOP [ <label> ] ;

Beispiel:

BEGIN
  LET counter := 5;
  LOOP
    IF (counter = 0) THEN
      BREAK;
    END IF;
    counter := counter - 1;
  END LOOP;
  RETURN counter;
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
BEGIN
  LET counter := 5;
  LOOP
    IF (counter = 0) THEN
      BREAK;
    END IF;
    counter := counter - 1;
  END LOOP;
  RETURN counter;
END;
$$
;
+-----------------+
| anonymous block |
|-----------------|
|               0 |
+-----------------+

Das folgende Beispiel erstellt eine Protokolltabelle mit Einträgen, die sich über mehrere Daten erstrecken. Es wird eine LOOP verwendet, um Zeilen, die älter als ein Stichtag sind, in einer Archivtabelle zu archivieren und sie aus der Quelle zu löschen, wobei ein Tag nach dem anderen verarbeitet wird, bis keine qualifizierten Zeilen mehr vorhanden sind:

CREATE OR REPLACE TABLE loop_test_event_log (
  event_id INTEGER,
  event_date DATE,
  event_description VARCHAR);

INSERT INTO loop_test_event_log VALUES
  (1, DATEADD('month', -3, CURRENT_DATE()), 'User login'),
  (2, DATEADD('month', -3, CURRENT_DATE()), 'File upload'),
  (3, DATEADD('month', -2, CURRENT_DATE()), 'Password change'),
  (4, DATEADD('month', -1, CURRENT_DATE()), 'User login'),
  (5, DATEADD('month', -1, CURRENT_DATE()), 'Data export');

CREATE OR REPLACE TABLE loop_test_event_log_archive (
  event_id INTEGER,
  event_date DATE,
  event_description VARCHAR,
  archived_on DATE);
DECLARE
  cutoff_date DATE DEFAULT DATEADD('month', -1, CURRENT_DATE());
  oldest_date DATE;
  archived_total INTEGER DEFAULT 0;
  batch_count INTEGER;
BEGIN
  LOOP
    oldest_date := (SELECT MIN(event_date)
                      FROM loop_test_event_log
                      WHERE event_date < :cutoff_date);
    IF (oldest_date IS NULL) THEN
      BREAK;
    END IF;
    batch_count := (SELECT COUNT(*)
                      FROM loop_test_event_log
                      WHERE event_date = :oldest_date);
    INSERT INTO loop_test_event_log_archive
      SELECT event_id, event_date, event_description, CURRENT_DATE()
        FROM loop_test_event_log
        WHERE event_date = :oldest_date;
    DELETE FROM loop_test_event_log WHERE event_date = :oldest_date;
    archived_total := archived_total + batch_count;
  END LOOP;
  RETURN 'Archived ' || archived_total || ' events';
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
DECLARE
  cutoff_date DATE DEFAULT DATEADD('month', -1, CURRENT_DATE());
  oldest_date DATE;
  archived_total INTEGER DEFAULT 0;
  batch_count INTEGER;
BEGIN
  LOOP
    oldest_date := (SELECT MIN(event_date)
                      FROM loop_test_event_log
                      WHERE event_date < :cutoff_date);
    IF (oldest_date IS NULL) THEN
      BREAK;
    END IF;
    batch_count := (SELECT COUNT(*)
                      FROM loop_test_event_log
                      WHERE event_date = :oldest_date);
    INSERT INTO loop_test_event_log_archive
      SELECT event_id, event_date, event_description, CURRENT_DATE()
        FROM loop_test_event_log
        WHERE event_date = :oldest_date;
    DELETE FROM loop_test_event_log WHERE event_date = :oldest_date;
    archived_total := archived_total + batch_count;
  END LOOP;
  RETURN 'Archived ' || archived_total || ' events';
END;
$$
;
+---------------------+
| anonymous block     |
|---------------------|
| Archived 3 events   |
+---------------------+

Um die Ergebnisse zu überprüfen, fragen Sie beide Tabellen ab:

SELECT * FROM loop_test_event_log ORDER BY event_id;
+----------+------------+-------------------+
| EVENT_ID | EVENT_DATE | EVENT_DESCRIPTION |
|----------+------------+-------------------|
|        4 | 2026-02-04 | User login        |
|        5 | 2026-02-04 | Data export       |
+----------+------------+-------------------+
SELECT event_id,
       event_date,
       event_description
  FROM loop_test_event_log_archive
  ORDER BY event_id;
+----------+------------+-------------------+
| EVENT_ID | EVENT_DATE | EVENT_DESCRIPTION |
|----------+------------+-------------------|
|        1 | 2025-12-04 | User login        |
|        2 | 2025-12-04 | File upload       |
|        3 | 2026-01-04 | Password change   |
+----------+------------+-------------------+

Die vollständige Syntax und weitere Einzelheiten zu LOOP-Schleifen finden Sie unter LOOP (Snowflake Scripting).

Beenden einer Schleife oder Iteration

In einem Schleifenkonstrukt können Sie angeben, wann die Schleife oder eine Iteration der Schleife vorzeitig abgebrochen werden soll. In den nächsten Abschnitten wird dies näher erläutert:

Beenden einer Schleife

Sie können eine Schleife explizit vorzeitig beenden, indem Sie den Befehl BREAK ausführen. BREAK (und sein Synonym EXIT) hält die aktuelle Iteration sofort an und überspringt alle weiteren Iterationen. Sie können sich BREAK als Sprung zur ersten ausführbaren Anweisung nach dem Ende der Schleife vorstellen.

BREAK ist in LOOP erforderlich, in WHILE, FOR und REPEAT aber nicht. Wenn Sie bestimmte Anweisungen überspringen möchten, können Sie in den meisten Fällen Standardkonstrukte zur Verzweigung (IF-Anweisungen und CASE-Anweisungen) verwenden, um zu steuern, welche Anweisungen innerhalb einer Schleife ausgeführt werden.

Ein BREAK-Befehl selbst befindet sich normalerweise innerhalb einer IF- oder CASE-Anweisung.

Beenden einer Iteration ohne Beendigung der Schleife

Sie können mit dem Befehl CONTINUE (oder ITERATE) an das Ende einer Schleifeniteration springen und so die restlichen Anweisungen in der Schleife überspringen. Die Schleife wird mit dem Anfang der nächsten Iteration fortgesetzt.

Solche Sprünge sind selten erforderlich. Wenn Sie bestimmte Anweisungen überspringen möchten, können Sie in den meisten Fällen Standardkonstrukte zur Verzweigung (IF-Anweisungen und CASE-Anweisungen) verwenden, um zu steuern, welche Anweisungen innerhalb einer Schleife ausgeführt werden.

Ein CONTINUE- oder ITERATE-Befehl wird normalerweise innerhalb einer IF- oder CASE-Anweisung verwendet.

Festlegen, wo die Ausführung nach Schleifenende fortgesetzt wird

Wenn Sie nach einem BREAK- oder CONTINUE-Befehl die Ausführung an einem bestimmten Punkt im Code fortsetzen müssen (z. B. die äußere Schleife bei einer verschachtelten Schleife), geben Sie im Befehl ein Label an, das den Punkt angibt, an dem die Ausführung fortgesetzt werden soll.

Im folgenden Beispiel wird dies für eine verschachtelte Schleife gezeigt:

BEGIN
  LET inner_counter := 0;
  LET outer_counter := 0;
  LOOP
    LOOP
      IF (inner_counter < 5) THEN
        inner_counter := inner_counter + 1;
        CONTINUE OUTER;
      ELSE
        BREAK OUTER;
      END IF;
    END LOOP INNER;
    outer_counter := outer_counter + 1;
    BREAK;
  END LOOP OUTER;
  RETURN ARRAY_CONSTRUCT(outer_counter, inner_counter);
END;

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die klassische Konsole, den execute_stream oder die Methode execute_string in Python-Konnektor-Code verwenden, benutzen Sie stattdessen das folgende Beispiel (siehe Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):

EXECUTE IMMEDIATE $$
BEGIN
  LET inner_counter := 0;
  LET outer_counter := 0;
  LOOP
    LOOP
      IF (inner_counter < 5) THEN
        inner_counter := inner_counter + 1;
        CONTINUE OUTER;
      ELSE
        BREAK OUTER;
      END IF;
    END LOOP INNER;
    outer_counter := outer_counter + 1;
    BREAK;
  END LOOP OUTER;
  RETURN ARRAY_CONSTRUCT(outer_counter, inner_counter);
END;
$$;

In diesem Beispiel:

  • In diesem Beispiel gibt es eine Schleife mit der Bezeichnung INNER, die in einer Schleife mit der Bezeichnung OUTER verschachtelt ist.

  • CONTINUE OUTER startet eine weitere Iteration der Schleife mit dem Label OUTER.

  • BREAK OUTER beendet die innere Schleife und übergibt die Kontrolle an das Ende der äußeren Schleife (gekennzeichnet mit OUTER).

Die Ausgabe dieses Befehls lautet:

+-----------------+
| anonymous block |
|-----------------|
| [               |
|   0,            |
|   5             |
| ]               |
+-----------------+

Die Ausgabe zeigt Folgendes:

  • inner_counter wird bis 5 inkrementiert. CONTINUE OUTER startet eine neue Iteration der äußeren Schleife, die eine neue Iteration der inneren Schleife startet, die diesen Zähler bis 5 hochzählt. Diese Iterationen werden fortgesetzt, bis der Wert von inner_counter gleich 5 ist und BREAK OUTER die innere Schleife beendet.

  • outer_counter wird nie inkrementiert. Die Anweisung, die diesen Zähler inkrementiert, wird nie erreicht, da BREAK OUTER die Kontrolle an das Ende der äußeren Schleife übergibt.