UDFsの概要

このトピックでは、すべての型の UDFs (ユーザー定義関数)に適用される概念と使用法の詳細について説明します。

このトピックの内容:

ユーザー定義関数の型

SQL

SQL UDF は、任意の SQL 式を評価し、式の結果を返します。関数定義は、スカラー(単一)値、またはテーブル関数として定義されている場合は行のセットを返す SQL 式です。

式はクエリ式にできますが、非表形式関数の場合、クエリ式は1列を含む最大1行を返すことが保証されている必要があります。

UDF を定義する式は、関数の入力引数、およびテーブル、ビュー、シーケンスなどのデータベースオブジェクトを参照できます。UDF 所有者には、 UDF がアクセスするデータベースオブジェクトに対する適切な権限が必要です。SQL UDF の定義式は他のユーザー定義関数を参照できますが、直接または別の関数を呼び出してそれ自体を再帰的に参照することはできません。

JavaScript

JavaScript UDFs は、 JavaScript プログラミング言語とランタイム環境を使用してデータを操作できます。JavaScript UDFs は、SQL UDFsと同じ方法で作成されますが、 LANGUAGE パラメーターを JAVASCRIPT に設定します。

SQL UDFs と同様に、 JavaScript UDFs は UDF の定義方法に応じて、スカラーまたは表形式の結果を返すことができます。

JavaScript UDF の定義式はそれ自体を再帰的に参照できますが、他のユーザー定義関数を参照することはできません。

注釈

JavaScript UDFs は、 SQL UDFsには適用されない要件、使用方法の詳細、制限があります。例などの詳細については、 JavaScript UDFs をご参照ください。

スカラーとテーブル UDFs

デフォルトでは、 UDF はスカラーであり、単一の列/値で構成される最大1行を返します。

ただし、1つ以上の列を持つ行のセットを返すように UDF を定義することもでき、クエリの FROM 句でアクセスできます。ユーザー定義のテーブル関数(UDTF)は、 TABLE キーワードを含み、表結果の列の名前と型を指定する戻り型を指定することにより定義されます。

例を含む、 UDTFs の作成および使用の詳細については、 SQL UDTFs (ユーザー定義のテーブル関数) および JavaScript UDTFs (ユーザー定義のテーブル関数) をご参照ください。Snowflakeで提供されるシステム定義のテーブル関数の一般的な情報については、 テーブル関数 をご参照ください。

UDFs の命名規則

UDFs はデータベースオブジェクトであり、指定されたデータベースとスキーマで作成されます。そのため、 データベース.スキーマ.関数名 の形式で、名前空間で定義された完全修飾名を持っています。例:

SELECT temporary_db_qualified_names_test.temporary_schema_1.udf_pi();

完全修飾名なしで呼び出された場合、 UDFs はセッションで使用されているデータベースとスキーマに従って解決されます。

これは、Snowflakeが提供する組み込みのシステム定義関数とは対照的です。Snowflakeは名前空間を持たないため、どこからでも呼び出すことができます。

システム定義関数との競合

関数を呼び出すときの競合を避けるために、Snowflakeでは、システム定義の関数と同じ名前の UDFs を作成できません。

UDF 名のオーバーロード

Snowflakeは、 UDF 名のオーバーロードをサポートしています。同じスキーマ内の複数の UDFs は、引数の署名が引数の数または引数の種類によって異なる限り、同じ名前を持つことができます。オーバーロードされた UDF が呼び出されると、Snowflakeは引数をチェックし、正しい関数を呼び出します。

add5 という名前の2つの SQL UDFs を作成する次の例を検討してください。

CREATE OR REPLACE FUNCTION add5 (n number)
  RETURNS number
  AS 'n + 5';

CREATE OR REPLACE FUNCTION add5 (s string)
  RETURNS string
  AS 's || ''5''';

重要

2番目の ADD5 関数では、文字列リテラル '5' をエスケープするために一重引用符が使用されます。UDF 定義で使用される一重引用符は、 必ず 一重引用符でエスケープする必要があります。

add5 が数値引数で呼び出された場合、最初の実装が選択され、文字列型の引数は2番目の実装を使用します。引数が数値でも文字列でもない場合、実装はSnowflakeの暗黙的な型変換規則に依存します。例えば、日付型の引数は文字列に変換され、 DATE から NUMBER への変換はサポートされていないため、文字列実装が選択されます。

例:

select add5(1);

+---------+
| ADD5(1) |
|---------|
|       6 |
+---------+

select add5('1');

+-----------+
| ADD5('1') |
|-----------|
| 15        |
+-----------+

select add5('hello');

+---------------+
| ADD5('HELLO') |
|---------------|
| hello5        |
+---------------+

select add5(to_date('2014-01-01'));

+-----------------------------+
| ADD5(TO_DATE('2014-01-01')) |
|-----------------------------|
| 2014-01-015                 |
+-----------------------------+

オーバーロードを使用する場合は注意してください。自動型変換とオーバーロードの組み合わせにより、軽微なユーザーエラーが予期しない結果を引き起こしやすくなります。例については、 関数名のオーバーロード をご参照ください。

UDFsのセキュリティ/権限要件

関数定義が非修飾テーブルを参照する場合、そのテーブルは関数を含むスキーマで解決されます。別のスキーマオブジェクト(テーブル、ビュー、または他の関数など)への参照には、その関数の所有者がそのスキーマオブジェクトにアクセスする権限を持っている必要があります。関数の呼び出し側は、関数定義で参照されるオブジェクトにアクセスする必要はありませんが、関数を使用するための権限のみが必要です。

例えば、管理者は通常アクセスできない機密データを含む users という名前のテーブルを所有していますが、管理者は他のユーザーがアクセス権限を持っている関数を通じて合計ユーザー数を公開できます。

use role dataadmin;

desc table users;

+-----------+--------------+--------+-------+---------+-------------+------------+--------+------------+---------+
| name      | type         | kind   | null? | default | primary key | unique key | check  | expression | comment |
|-----------+--------------+--------+-------+---------+-------------+------------+--------+------------+---------|
| USER_ID   | NUMBER(38,0) | COLUMN | Y     | [NULL]  | N           | N          | [NULL] | [NULL]     | [NULL]  |
| USER_NAME | VARCHAR(100) | COLUMN | Y     | [NULL]  | N           | N          | [NULL] | [NULL]     | [NULL]  |
  ...
  ...
  ...
+-----------+--------------+--------+-------+---------+-------------+------------+--------+------------+---------+

create function total_user_count() returns number as 'select count(*) from users';

grant usage on function total_user_count() to role analyst;

use role analyst;

-- This will fail because the role named "analyst" does not have the
-- privileges required in order to access the table named "users".
select * from users;

FAILURE: SQL compilation error:
Object 'USERS' does not exist.

-- However, this will succeed.
select total_user_count();

+--------------------+
| TOTAL_USER_COUNT() |
|--------------------+
| 123                |
+--------------------+

ロールと権限を使用してアクセス制御を管理する方法の詳細については、 Snowflakeのアクセス制御 をご参照ください。

関数名のオーバーロード

このトピック内の UDF 名のオーバーロード で説明されているように、関数名をオーバーロードできます。

次のオーバーロードの例は、オーバーロードと自動型変換を組み合わせて、予期しない結果を簡単に得る方法を示しています。

FLOAT パラメーターを受け取る関数を作成します。

CREATE FUNCTION add_pi(PARAM_1 FLOAT)
    RETURNS FLOAT
    LANGUAGE SQL
    AS $$
        PARAM_1 + 3.1415926::FLOAT
    $$;

関数を2回呼び出します。1回目は、 FLOATを渡します。2回目は、 VARCHARを渡します。 VARCHAR は FLOATに変換され、各呼び出しからの出力は同じです。

SELECT add_pi(1.0), add_pi('1.0');
+-------------+---------------+
| ADD_PI(1.0) | ADD_PI('1.0') |
|-------------+---------------|
|   4.1415926 |     4.1415926 |
+-------------+---------------+

次に、 VARCHAR パラメーターを受け取るオーバーロード関数を作成します。

CREATE FUNCTION add_pi(PARAM_1 VARCHAR)
    RETURNS VARCHAR
    LANGUAGE SQL
    AS $$
        PARAM_1 || ' + 3.1415926'
    $$;

前とまったく同じ CALLs を使用します。これら2つの CALLs と前の2つの CALLsの出力の違いに注意してください。

SELECT add_pi(1.0), add_pi('1.0');
+-------------+-----------------+
| ADD_PI(1.0) | ADD_PI('1.0')   |
|-------------+-----------------|
|   4.1415926 | 1.0 + 3.1415926 |
+-------------+-----------------+