Snowflake Scriptingの一般的な使用例¶
一般的なユースケースに対応するソリューションとして、Snowflakeスクリプト言語の要素、データ型、変数を使用する匿名ブロックとストアドプロシージャを作成できます。このトピックには、いくつかの一般的なユースケースにおけるSnowflakeスクリプトコードの例が含まれています。
ユーザー入力でテーブルデータを更新する¶
次の例では、ユーザー入力でテーブルデータを更新するストアドプロシージャを作成します。 FOR ループ を使用して、テーブルの RESULTSET 内の行を反復処理します。FOR ループには 条件ロジック が含まれています。ユーザー入力に基づく バインド変数 によって、ストアドプロシージャが実行する正確な更新が決定されます。
この例では次のデータを使用します。
CREATE OR REPLACE TABLE bonuses (
emp_id INT,
performance_rating INT,
salary NUMBER(12, 2),
bonus NUMBER(12, 2)
);
INSERT INTO bonuses (emp_id, performance_rating, salary, bonus) VALUES
(1001, 3, 100000, NULL),
(1002, 1, 50000, NULL),
(1003, 4, 75000, NULL),
(1004, 4, 80000, NULL),
(1005, 5, 120000, NULL),
(1006, 2, 60000, NULL),
(1007, 5, 40000, NULL),
(1008, 3, 140000, NULL),
(1009, 1, 95000, NULL);
SELECT * FROM bonuses;
+--------+--------------------+-----------+-------+
| EMP_ID | PERFORMANCE_RATING | SALARY | BONUS |
|--------+--------------------+-----------+-------|
| 1001 | 3 | 100000.00 | NULL |
| 1002 | 1 | 50000.00 | NULL |
| 1003 | 4 | 75000.00 | NULL |
| 1004 | 4 | 80000.00 | NULL |
| 1005 | 5 | 120000.00 | NULL |
| 1006 | 2 | 60000.00 | NULL |
| 1007 | 5 | 40000.00 | NULL |
| 1008 | 3 | 140000.00 | NULL |
| 1009 | 1 | 95000.00 | NULL |
+--------+--------------------+-----------+-------+
以下のストアドプロシージャは FOR ループを使用して、 bonuses
テーブルの RESULTSET 内の行を反復処理します。指定された業績評価を受けた各従業員の給与の指定された割合としてボーナスを適用します。ストアドプロシージャは、条件付きロジックを使用して、指定されたパフォーマンス評価を持つ従業員にのみボーナスを適用します。また、入力(bonus_percentage
および performance_value
)をバインド変数として使用します。
CREATE OR REPLACE PROCEDURE apply_bonus(bonus_percentage INT, performance_value INT)
RETURNS TEXT
LANGUAGE SQL
AS
DECLARE
-- Use input to calculate the bonus percentage
updated_bonus_percentage NUMBER(2,2) DEFAULT (:bonus_percentage/100);
-- Declare a result set
rs RESULTSET;
BEGIN
-- Assign a query to the result set and execute the query
rs := (SELECT * FROM bonuses);
-- Use a FOR loop to iterate over the records in the result set
FOR record IN rs DO
-- Assign variable values using values in the current record
LET emp_id_value INT := record.emp_id;
LET performance_rating_value INT := record.performance_rating;
LET salary_value NUMBER(12, 2) := record.salary;
-- Determine whether the performance rating in the record matches the user input
IF (performance_rating_value = :performance_value) THEN
-- If the condition is met, update the bonuses table using the calculated bonus percentage
UPDATE bonuses SET bonus = ( :salary_value * :updated_bonus_percentage )
WHERE emp_id = :emp_id_value;
END IF;
END FOR;
-- Return text when the stored procedure completes
RETURN 'Update applied';
END;
注: SnowSQL、 Classic Console、 execute_stream
または execute_string
メソッドを Python Connector コードで使用している場合は、代わりにこの例を使用してください(SnowSQL、 Classic Console、Python ConnectorでSnowflakeスクリプトを使用する を参照)。
CREATE OR REPLACE PROCEDURE apply_bonus(bonus_percentage INT, performance_value INT)
RETURNS TEXT
LANGUAGE SQL
AS
$$
DECLARE
-- Use input to calculate the bonus percentage
updated_bonus_percentage NUMBER(2,2) DEFAULT (:bonus_percentage/100);
-- Declare a result set
rs RESULTSET;
BEGIN
-- Assign a query to the result set and execute the query
rs := (SELECT * FROM bonuses);
-- Use a FOR loop to iterate over the records in the result set
FOR record IN rs DO
-- Assign variable values using values in the current record
LET emp_id_value INT := record.emp_id;
LET performance_rating_value INT := record.performance_rating;
LET salary_value NUMBER(12, 2) := record.salary;
-- Determine whether the performance rating in the record matches the user input
IF (performance_rating_value = :performance_value) THEN
-- If the condition is met, update the bonuses table using the calculated bonus percentage
UPDATE bonuses SET bonus = ( :salary_value * :updated_bonus_percentage )
WHERE emp_id = :emp_id_value;
END IF;
END FOR;
-- Return text when the stored procedure completes
RETURN 'Update applied';
END;
$$
;
ストアドプロシージャを実行するには、ボーナスパーセンテージとパフォーマンス評価を指定します。たとえば、ストアドプロシージャを呼び出して、パフォーマンス評価が5の従業員に3%のボーナスを適用します。
CALL apply_bonus(3, 5);
クエリを実行して結果を表示します。
SELECT * FROM bonuses;
+--------+--------------------+-----------+---------+
| EMP_ID | PERFORMANCE_RATING | SALARY | BONUS |
|--------+--------------------+-----------+---------|
| 1001 | 3 | 100000.00 | NULL |
| 1002 | 1 | 50000.00 | NULL |
| 1003 | 4 | 75000.00 | NULL |
| 1004 | 4 | 80000.00 | NULL |
| 1005 | 5 | 120000.00 | 3600.00 |
| 1006 | 2 | 60000.00 | NULL |
| 1007 | 5 | 40000.00 | 1200.00 |
| 1008 | 3 | 140000.00 | NULL |
| 1009 | 1 | 95000.00 | NULL |
+--------+--------------------+-----------+---------+
データのフィルタリングと収集¶
次の例では、テーブル内のデータをフィルター処理して収集するストアドプロシージャを作成します。このプロシージャでは、収集されたデータを使用して別のテーブルに行を挿入し、履歴の傾向を追跡します。
この例では、仮想マシンの所有権と設定を追跡する次のデータを使用します(VMs)。
CREATE OR REPLACE TABLE vm_ownership (
emp_id INT,
vm_id VARCHAR
);
INSERT INTO vm_ownership (emp_id, vm_id) VALUES
(1001, 1),
(1001, 5),
(1002, 3),
(1003, 4),
(1003, 6),
(1003, 2);
CREATE OR REPLACE TABLE vm_settings (
vm_id INT,
vm_setting VARCHAR,
value NUMBER
);
INSERT INTO vm_settings (vm_id, vm_setting, value) VALUES
(1, 's1', 5),
(1, 's2', 500),
(2, 's1', 10),
(2, 's2', 600),
(3, 's1', 3),
(3, 's2', 400),
(4, 's1', 8),
(4, 's2', 700),
(5, 's1', 1),
(5, 's2', 300),
(6, 's1', 7),
(6, 's2', 800);
CREATE OR REPLACE TABLE vm_settings_history (
vm_id INT,
vm_setting VARCHAR,
value NUMBER,
owner INT,
date DATE
);
ある企業が、設定値が特定のしきい値を超えたときに、この表のデータを時間の経過とともに追跡したいとします。次のストアドプロシージャは、 vm_settings
テーブルのデータを収集およびフィルタリングし、次の条件が満たされたときに、 vm_settings_history
テーブルに行を挿入します。
s1
の値を持つvm_setting
は、5
よりも低く設定されます。s2
の値を持つvm_setting
は、500
よりも高く設定されます。
vm_settings_history
テーブルに挿入された行には、 vm_settings
テーブルのすべての列の値と、 VM を所有する従業員の emp_id
および現在の日付が含まれます。
CREATE OR REPLACE PROCEDURE vm_user_settings()
RETURNS VARCHAR
LANGUAGE SQL
AS
DECLARE
-- Declare a cursor and a variable
c1 CURSOR FOR SELECT * FROM vm_settings;
current_owner NUMBER;
BEGIN
-- Open the cursor to execute the query and retrieve the rows into the cursor
OPEN c1;
-- Use a FOR loop to iterate over the records in the result set
FOR record IN c1 DO
-- Assign variable values using values in the current record
LET current_vm_id NUMBER := record.vm_id;
LET current_vm_setting VARCHAR := record.vm_setting;
LET current_value NUMBER := record.value;
-- Assign a value to the current_owner variable by querying the vm_ownership table
SELECT emp_id INTO :current_owner
FROM vm_ownership
WHERE vm_id = :current_vm_id;
-- If the record has a vm_setting equal to 's1', determine whether its value is less than 5
IF (current_vm_setting = 's1' AND current_value < 5) THEN
-- If the condition is met, insert a row into the vm_settings_history table
INSERT INTO vm_settings_history VALUES (
:current_vm_id,
:current_vm_setting,
:current_value,
:current_owner,
SYSDATE());
-- If the record has a vm_setting equal to 's2', determine whether its value is greater than 500
ELSEIF (current_vm_setting = 's2' AND current_value > 500) THEN
-- If the condition is met, insert a row into the vm_settings_history table
INSERT INTO vm_settings_history VALUES (
:current_vm_id,
:current_vm_setting,
:current_value,
:current_owner,
SYSDATE());
END IF;
END FOR;
-- Close the cursor
CLOSE c1;
-- Return text when the stored procedure completes
RETURN 'Success';
END;
注: SnowSQL、 Classic Console、 execute_stream
または execute_string
メソッドを Python Connector コードで使用している場合は、代わりにこの例を使用してください(SnowSQL、 Classic Console、Python ConnectorでSnowflakeスクリプトを使用する を参照)。
CREATE OR REPLACE PROCEDURE vm_user_settings()
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
DECLARE
-- Declare a cursor and a variable
c1 CURSOR FOR SELECT * FROM vm_settings;
current_owner NUMBER;
BEGIN
-- Open the cursor to execute the query and retrieve the rows into the cursor
OPEN c1;
-- Use a FOR loop to iterate over the records in the result set
FOR record IN c1 DO
-- Assign variable values using values in the current record
LET current_vm_id NUMBER := record.vm_id;
LET current_vm_setting VARCHAR := record.vm_setting;
LET current_value NUMBER := record.value;
-- Assign a value to the current_owner variable by querying the vm_ownership table
SELECT emp_id INTO :current_owner
FROM vm_ownership
WHERE vm_id = :current_vm_id;
-- If the record has a vm_setting equal to 's1', determine whether its value is less than 5
IF (current_vm_setting = 's1' AND current_value < 5) THEN
-- If the condition is met, insert a row into the vm_settings_history table
INSERT INTO vm_settings_history VALUES (
:current_vm_id,
:current_vm_setting,
:current_value,
:current_owner,
SYSDATE());
-- If the record has a vm_setting equal to 's2', determine whether its value is greater than 500
ELSEIF (current_vm_setting = 's2' AND current_value > 500) THEN
-- If the condition is met, insert a row into the vm_settings_history table
INSERT INTO vm_settings_history VALUES (
:current_vm_id,
:current_vm_setting,
:current_value,
:current_owner,
SYSDATE());
END IF;
END FOR;
-- Close the cursor
CLOSE c1;
-- Return text when the stored procedure completes
RETURN 'Success';
END;
$$;
ストアドプロシージャを実行します。
CALL vm_user_settings();
次のクエリを実行すると、プロシージャによって vm_settings_history
テーブルに挿入されたデータを確認できます。
SELECT * FROM vm_settings_history ORDER BY vm_id;
+-------+------------+-------+-------+------------+
| VM_ID | VM_SETTING | VALUE | OWNER | DATE |
|-------+------------+-------+-------+------------|
| 2 | s2 | 600 | 1003 | 2024-04-01 |
| 3 | s1 | 3 | 1002 | 2024-04-01 |
| 4 | s2 | 700 | 1003 | 2024-04-01 |
| 5 | s1 | 1 | 1001 | 2024-04-01 |
| 6 | s2 | 800 | 1003 | 2024-04-01 |
+-------+------------+-------+-------+------------+