【Snowflake】ストアド ~ 入門編 ~

■ はじめに

https://dk521123.hatenablog.com/entry/2022/12/09/152837

で、Snowflakeには、Timerみたいに疑似的な処理がなさそうで
その代替え案としてストアドプロシージャを軽く触ったのを
きっかけに調べてみた。

目次

【1】ストアドプロシージャ (Stored Procedure)
 1)UDFs (ユーザー定義関数)との違い
【2】サポート言語
 1)使用上の注意
【3】使い方
 1)作成 - CREATE PROCEDURE -
 2)実行(呼び出し) - CALL -
 3)削除 - DROP PROCEDURE -
【4】コマンド
 1)SHOW PROCEDURES
 2)DESCRIBE PROCEDURE
【5】変数の扱い
 1)変数の宣言
 2)変数への値の格納

【1】ストアドプロシージャ (Stored Procedure)

https://docs.snowflake.com/ja/sql-reference/stored-procedures.html

より抜粋
~~~~~~~~~
ストアドプロシージャでは、
プログラムによる構成を使用して、分岐とループを実行できます。
~~~~~~~~~
 => DBの PostgreSQL の ストアド に近い形で組むことができる

1)UDFs (ユーザー定義関数)との違い

https://docs.snowflake.com/ja/sql-reference/stored-procedures-overview.html#differences-between-stored-procedures-and-udfs

に記載されているが、代表的なものとして以下。
~~~~~
[1] ストアドプロシージャから値を返さなくていい(UDFは値を返す)
[2] ストアドプロシージャは独立して呼び出し可能
~~~~~

【2】サポート言語

https://docs.snowflake.com/ja/sql-reference/stored-procedures-overview.html

より抜粋
~~~~~~~
1)Java(Snowparkを使用)
2)JavaScript
3)Python(Snowparkを使用)
4)Scala(Snowparkを使用)
5)Snowflakeスクリプト
~~~~~~~
こんなにあるんだっと、びっくりした、、、

Snowflakeスクリプト
https://docs.snowflake.com/ja/sql-reference/stored-procedures-snowflake-scripting.html

1)使用上の注意

https://docs.snowflake.com/ja/sql-reference/stored-procedures-javascript.html#label-considerations-for-case-sensitivity-in-stored-procedures

より抜粋
~~~~~
引数名は、ストアドプロシージャコードの
SQL 部分では大文字と小文字を区別しませんが、
JavaScript部分では大文字と小文字を区別します。
~~~~~

【3】使い方

1)作成 - CREATE PROCEDURE -

https://docs.snowflake.com/ja/sql-reference/sql/create-procedure.html
構文

CREATE PROCEDURE <関数名>(<引数>)
RETURNS <戻り値 (テーブルも返せる)>
LANGUAGE <言語(e.g. SQL)
COMMENT = '<コメント文>'
AS
$$
    -- ブロック (以下の「ブロックの基本構造」を参照)
$$
;

ブロックの基本構造
https://docs.snowflake.com/ja/developer-guide/snowflake-scripting/blocks.html#understanding-the-structure-of-a-block

DECLARE -- https://docs.snowflake.com/ja/sql-reference/snowflake-scripting/declare.html  
  ... (variable declarations, cursor declarations, etc.) ...
BEGIN -- https://docs.snowflake.com/ja/sql-reference/snowflake-scripting/begin.html  
  ... (Snowflake Scripting and SQL statements) ...
EXCEPTION -- https://docs.snowflake.com/ja/sql-reference/snowflake-scripting/exception.html  
  ... (statements for handling exceptions) ...
END;

-- EXCEPTION ブロック に関する詳細はl
-- 以下の関連記事を参照のこと。

https://dk521123.hatenablog.com/entry/2022/12/23/223345

create or replace procedure say_hello(val1 varchar, val2 varchar)
returns varchar not null
language sql
as
$$
begin
  return :val1 || ' ' || :val2 || '!!';
end;
$$
;

2)実行(呼び出し) - CALL -

https://docs.snowflake.com/ja/sql-reference/sql/call.html

-- プロシージャを実行
CALL <ストアドプロシージャ名>(<引数>);

SET var1 = 'Hello';
SET var2 = 'World';
CALL say_hello($var1, $var2);

補足:即時実行について

* 以下の関連記事を参照のこと。

https://dk521123.hatenablog.com/entry/2022/12/17/000217

3)削除 - DROP PROCEDURE -

https://docs.snowflake.com/ja/sql-reference/sql/drop-procedure.html

drop procedure say_hello(varchar, varchar);

【4】コマンド

 基本的に、他のコマンドと同じで、いつも通りなのだが、
SHOW PROCEDURESには、INがあったり、
DESCRIBE PROCEDUREには、()が入ったり
ちょっこと異なる点もある。

1)SHOW PROCEDURES

https://docs.snowflake.com/ja/sql-reference/sql/show-procedures.html

-- アクセスする権限があるストアドプロシージャを一覧表示
SHOW PROCEDURES [ LIKE '<pattern>' ] [ IN ...];

2)DESCRIBE PROCEDURE

https://docs.snowflake.com/ja/sql-reference/sql/desc-procedure.html

-- ストアドプロシージャの署名(引数)、戻り値、言語、および本文(定義)などを表示
DESC[RIBE] PROCEDURE <procedure_name> ( [ <arg_data_type> [ , <arg_data_type_2> ... ] ] );

DESC PROCEDURE say_hello();

DESC PROCEDURE say_hello(varchar, varchar);

-- 「DESC PROCEDURE say_hello;」だと、()がないので、エラー
-- 引数が分からない場合は、まず「SHOW PROCEDURES;」
-- で調べるといいかも

【5】変数の扱い

* 以下の公式ドキュメントを一読するといい

https://docs.snowflake.com/ja/developer-guide/snowflake-scripting/variables.html

1)変数の宣言

* 以下の2通りで変わる
 a) DECLARE セクション内
 b) BEGIN ... END セクション内

https://docs.snowflake.com/ja/developer-guide/snowflake-scripting/variables.html#declaring-a-variable
a) DECLARE セクション内

-- <variable_name> <type>;
-- <variable_name> DEFAULT <expression> ;
-- <variable_name> <type> DEFAULT <expression> ;

declare
    profit number(38, 2) default 0.0;

b) BEGIN ... END セクション内

-- LET <variable_name> <type> { DEFAULT | := } <expression> ;
-- LET <variable_name> { DEFAULT | := } <expression> ;

begin
    let cost number(38, 2) := 100.0;
    let revenue number(38, 2) default 110.0;

2)変数への値の格納

a) 変数への値の割り当て
https://docs.snowflake.com/ja/developer-guide/snowflake-scripting/variables.html#assigning-a-value-to-a-declared-variable

-- <variable_name> := <expression> ; (「:=」で格納)
profit := revenue - cost;

b) SQL ステートメントでの変数の使用(バインド)
https://docs.snowflake.com/ja/developer-guide/snowflake-scripting/variables.html#using-a-variable-in-a-sql-statement-binding

-- 変数名の前にコロンを付ける
insert into my_table (x) values (:my_variable)

-- オブジェクトの名前として変数を使用している場合
-- (例: SELECT ステートメントの FROM 句にあるテーブルの名前)は、
--  IDENTIFIER キーワードを使用して、変数がオブジェクト識別子を表す
select count(*) from identifier(:table_name)

関連記事

Snowflake ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2021/11/02/130111
Snowflake ~ 入門編 / Hello world
https://dk521123.hatenablog.com/entry/2021/11/22/212520
Snowflake】ストアド ~ 基本編 / 条件分岐 ~
https://dk521123.hatenablog.com/entry/2022/12/26/211349
Snowflake】ストアド ~ 基本編 / ループ ~
https://dk521123.hatenablog.com/entry/2022/12/16/143349
Snowflake】ストアド ~ EXECUTE IMMEDIATE ~
https://dk521123.hatenablog.com/entry/2022/12/17/000217
Snowflake】ストアド ~ クエリ結果を受け取る ~
https://dk521123.hatenablog.com/entry/2022/12/24/212242
Snowflake】ストアド ~ 例外 / EXCEPTION ~
https://dk521123.hatenablog.com/entry/2022/12/23/223345
Snowflake】ストアド ~ デバッグログについて ~
https://dk521123.hatenablog.com/entry/2022/12/18/121334
Snowflake】ストアド ~ S3内にパーティション構成でUnloadする ~
https://dk521123.hatenablog.com/entry/2022/12/27/225629
Snowflake】ストアド ~ ステージ内でデータ0件の場合エラーにする ~
https://dk521123.hatenablog.com/entry/2022/12/29/175848
Snowflake ~ テストデータ作成 / generator ~
https://dk521123.hatenablog.com/entry/2022/06/20/095659
ストアド ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2010/08/06/112528
指定した日付分アンロードするSQLを生成するPythonコード
https://dk521123.hatenablog.com/entry/2023/08/09/000000