FOR ループ
FOR ループは、指定された回数、または結果セットの各行に対して一連のステップを繰り返します。Snowflakeスクリプトは、次のタイプの FOR ループをサポートします。
次のセクションでは、こうしたタイプの FOR ループの使用方法について説明します。
カウンターベースの FOR ループ
カウンターベースの FOR ループは、指定された回数を実行します。
カウンターベースのFORループには次の構文を使用します。
FOR <counter_variable> IN [ REVERSE ] <start> TO <end> { DO | LOOP }
<statement>;
[ <statement>; ... ]
END { FOR | LOOP } [ <label> ] ;
例えば、次の FOR ループは5回実行されます。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+-----------------+
Snowflake Scriptingのループ内に SQL ステートメントを含めることができます。例えば、次の FOR ループは、 INSERT ステートメントを5回実行し、カウンターの値をテーブルに挿入します。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+-----------------+
テーブルをクエリして、挿入された行を表示します。
SELECT * FROM test_for_loop_insert;
+---+
| I |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+---+
次の例では、カウンターベースのFORループを使用して、日付ディメンションテーブルにデータを入力します。これは、データウェアハウスをセットアップする際の一般的なタスクです。ループは日数の範囲を反復処理し、計算された属性とともに各日付の行を挿入します。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+----------------------------------------+
結果を確認するには、テーブルをクエリします。
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 |
+----------+------------+-------------+------------+---------+------+
FOR ループの包括的な構文と詳細については、 FOR (Snowflakeスクリプト) をご参照ください。
カーソルベースの FOR ループ
カーソルベースのFORループは、結果セットを反復処理します。反復回数は、 カーソル の行数によって決まります。
カーソルベースの FOR ループの構文は次のとおりです。
FOR <row_variable> IN <cursor_name> DO
<statement>;
[ <statement>; ... ]
END FOR [ <label> ] ;
このセクションの最初の例では、次の``invoices``テーブルのデータを使用します。
CREATE OR REPLACE TABLE invoices (price NUMBER(12, 2));
INSERT INTO invoices (price) VALUES
(11.11),
(22.22);
次の例では、FORループを使用して、``invoices``テーブルのカーソル内の行を反復処理します。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+-----------------+
次の例では、カーソルベースのFORループを使用して従業員のテーブルを反復処理し、部門に基づいて各従業員を昇給させ、変更ごとに監査記録を挿入します。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+----------------------+
変更を確認するには、テーブルをクエリします。
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 |
+--------+------------+------------+
FOR ループの包括的な構文と詳細については、 FOR (Snowflakeスクリプト) をご参照ください。
RESULTSET ベースの FOR ループ
RESULTSETベースのFORループは、結果セットを反復処理します。反復回数は、:doc:`RESULTSET<resultsets>`クエリが返す行数によって決まります。
RESULTSET ベースの FOR ループの構文は次のとおりです。
FOR <row_variable> IN <RESULTSET_name> DO
<statement>;
[ <statement>; ... ]
END FOR [ <label> ] ;
このセクションの最初の例では、次の``invoices``テーブルのデータを使用します。
CREATE OR REPLACE TABLE invoices (price NUMBER(12, 2));
INSERT INTO invoices (price) VALUES
(11.11),
(22.22);
次の例では、FORループを使用して、``invoices``テーブルのRESULTSET内の行を反復処理します。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+-----------------+
次の例では、RESULTSETベースのFORループを使用して顧客記録を検証します。必要な連絡先情報について各記録をチェックし、``status``列を更新して各記録を確認済みまたは不完全としてマークします。このタイプのデータ品質チェックは、抽出、変換、ロード(ETL)パイプラインの一般的なステップです。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+-------------------------------+
変更を確認するには、テーブルをクエリします。
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 |
+-------------+-----------------+-------------------+----------------+------------+
FOR ループの包括的な構文と詳細については、 FOR (Snowflakeスクリプト) をご参照ください。
WHILE ループ
WHILE ループは、条件がtrueの 間、反復されます。WHILE ループでは、ループの本文を実行する直前に条件がテストされます。最初の反復の前に条件がfalseの場合、ループの本文は1回も実行されません。
WHILE ループの構文は次のとおりです。
WHILE ( <condition> ) { DO | LOOP }
<statement>;
[ <statement>; ... ]
END { WHILE | LOOP } [ <label> ] ;
例:
BEGIN
LET counter := 0;
WHILE (counter < 5) DO
counter := counter + 1;
END WHILE;
RETURN counter;
END;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
EXECUTE IMMEDIATE $$
BEGIN
LET counter := 0;
WHILE (counter < 5) DO
counter := counter + 1;
END WHILE;
RETURN counter;
END;
$$
;
+-----------------+
| anonymous block |
|-----------------|
| 5 |
+-----------------+
次の例では、WHILEループを使用して、未加工のトランザクションデータから日次売上の概要を構築します。一度に1つの日付を処理し、その日付のトランザクションを要約行に集計して、ロード済みとしてマークします。このような日付ごとの要約パターンは、抽出、変換、ロード(ETL)パイプラインで一般的に使用されます。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+----------------------------------------------------+
結果を確認するには、要約テーブルをクエリします。
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 |
+--------------+-------------+-----------+
WHILE ループの包括的な構文と詳細については、 WHILE (Snowflakeスクリプト) をご参照ください。
REPEAT ループ
REPEAT ループは、条件がtrueに なるまで 反復されます。REPEAT ループでは、ループの本文を実行した直後に条件がテストされます。その結果、ループの本文は常に少なくとも1回実行されます。
REPEAT ループの構文は次のとおりです。
REPEAT
<statement>;
[ <statement>; ... ]
UNTIL ( <condition> )
END REPEAT [ <label> ] ;
例:
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+-----------------+
次の例では、ステージングテーブルと、追加の``batch_id``列を持つターゲットテーブルを作成します。次に、REPEATループを使用して、ステージングテーブルからターゲットテーブルに行をバッチで移動し、各反復の後にバッチIDをインクリメントして、ステージングテーブルから行がなくなるまで続けます。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+------------------------------------+
結果を確認するには、ターゲットテーブルをクエリします。
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 |
+----------+------------+---------+----------+
REPEAT ループの包括的な構文と詳細については、 REPEAT (Snowflakeスクリプト) をご参照ください。
LOOP ループ
BREAK コマンドが実行されるまで、 LOOP ループは実行されます。BREAK コマンドは通常、分岐ロジック(例: IF ステートメント または CASE ステートメント)内に埋め込まれています。
LOOP ステートメントの構文は次のとおりです。
LOOP
<statement>;
[ <statement>; ... ]
END LOOP [ <label> ] ;
例:
BEGIN
LET counter := 5;
LOOP
IF (counter = 0) THEN
BREAK;
END IF;
counter := counter - 1;
END LOOP;
RETURN counter;
END;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+-----------------+
次の例では、複数の日付にまたがるエントリを持つログテーブルを作成します。LOOPを使用して、カットオフ日より古い行をアーカイブテーブルにアーカイブしてソースから削除し、対象となる行がなくなるまで1日ずつ処理します。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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 |
+---------------------+
結果を確認するには、両方のテーブルをクエリします。
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 |
+----------+------------+-------------------+
LOOP ループの包括的な構文と詳細については、 LOOP (Snowflakeスクリプト) をご参照ください。
ループまたは反復の終了
ループ構造では、ループまたはループの反復を早期に終了するときを指定できます。次のセクションでは、これについて詳しく説明します。
ループの終了
BREAK コマンドを実行すれば、ループを明示的に早期終了させることができます。BREAK (およびその同義語 EXIT)は、現在の反復を直ちに停止し、残りの反復をスキップします。BREAK は、ループ終了後にある最初の実行可能ステートメントにジャンプすると考えることができます。
BREAK は、 LOOP ループでは必要ですが、 WHILE、 FOR、および REPEAT ループでは必要ありません。ほとんどの場合、スキップするステートメントがあるときは、標準の分岐構造(IF ステートメント および CASE ステートメント)を使用して、ループ内のどのステートメントを実行するかを制御できます。
BREAK コマンド自体は通常、 IF または CASE ステートメント内にあります。
ループを終了せずに反復を終了
CONTINUE (または ITERATE)コマンドを使用して、ループの残りのステートメントをスキップして、ループの反復の最後にジャンプできます。ループは次の反復の開始時に続きます。
このようなジャンプが必要になることはめったにありません。ほとんどの場合、スキップするステートメントがあるときは、標準の分岐構造(IF ステートメント および CASE ステートメント)を使用して、ループ内のどのステートメントを実行するかを制御できます。
CONTINUE または ITERATE コマンド自体は、通常、 IF または CASE ステートメント内にあります。
終了後に実行を継続する場所の指定
BREAK または CONTINUE コマンドで、コード内の特定のポイント(例: ネストされたループの外側のループ)で実行を続行する必要がある場合は、実行を続行するポイントを識別するラベルを指定します。
次の例は、ネストされたループでこれを示しています。
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;
注意:Snowflake CLI、SnowSQL、クラシックコンソール、または:code:execute_stream`や:code:`execute_string`メソッドを:doc:`Pythonコネクタ</developer-guide/python-connector/python-connector>`コードで使用する場合は、代わりに次の例を使用してください(:doc:/developer-guide/snowflake-scripting/running-examples`を参照)。
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;
$$;
この例では:
OUTER というラベルの付いたループにネストされた、 INNER というラベルの付いたループがあります。
CONTINUE OUTER は、ラベル OUTER があるループで別の反復を開始します。
BREAK OUTER は、内側のループを終了し、制御を外側のループ(OUTER のラベル付き)の最後に移します。
このコマンドの出力は次のとおりです。
+-----------------+
| anonymous block |
|-----------------|
| [ |
| 0, |
| 5 |
| ] |
+-----------------+
出力に示されているように、
inner_counter は5まで増加します。CONTINUE OUTER は、外側のループの新しい反復を開始します。これにより、内側のループの新しい反復が開始され、このカウンターは5まで増加します。これらの反復は、 inner_counter の値が5になり、 BREAK OUTER が内部ループを終了するまで続きます。
outer_counter が増加することはありません。このカウンターを増加するステートメントは、 BREAK OUTER が制御を外側のループの最後に移すため、このカウンターに到達することはありません。