CREATE VIEW¶
1つ以上ある既存のテーブル(またはその他の有効なクエリ式)のクエリに基づいて、現在のスキーマまたは指定されたスキーマに新しいビューを作成します。
- こちらもご参照ください。
構文¶
CREATE [ OR REPLACE ] [ SECURE ] [ RECURSIVE ] VIEW [ IF NOT EXISTS ] <name>
[ ( <column_list> ) ]
[ <col1> [ WITH ] MASKING POLICY <policy_name> [ USING ( <col1> , <cond_col1> , ... ) ]
[ WITH ] TAG ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] ) ]
[ , <col2> [ ... ] ]
[ [ WITH ] ROW ACCESS POLICY <policy_name> ON ( <col_name> [ , <col_name> ... ] ) ]
[ [ WITH ] TAG ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] ) ]
[ COPY GRANTS ]
[ COMMENT = '<string_literal>' ]
AS <select_statement>
必須パラメーター¶
name
ビューの識別子を指定します。ビューが作成されるスキーマに対して一意である必要があります。
また、識別子はアルファベット文字で始まる必要があり、識別子文字列全体が二重引用符で囲まれていない限り、スペースや特殊文字を含めることはできません(例:
"My object"
)。二重引用符で囲まれた識別子も大文字と小文字が区別されます。詳細については、 識別子の要件 をご参照ください。
select_statement
ビューの作成に使用するクエリを指定します。1つ以上のソーステーブルまたはその他の有効な SELECT ステートメントに配置できます。このクエリは、ビューのテキスト/定義として機能し、 SHOW VIEWS 出力と VIEWS Information Schemaビューに表示されます。
オプションのパラメーター¶
SECURE
ビューがセキュアであることを指定します。セキュアビューの詳細については、 セキュアビューの使用 をご参照ください。
デフォルト: 値なし(ビューはセキュアではない)
RECURSIVE
ビューが必ずしも CTE (共通テーブル式)を使用することなく再帰構文を使用してそれ自体を参照できることを指定します。一般的な再帰ビュー、および特に RECURSIVE キーワードの詳細については、 再帰的ビュー(非マテリアライズドビューのみ) および以下の再帰ビューの例をご参照ください。
デフォルト: 値なし(ビューは再帰的ではない、または CTE を使用することによってのみ再帰的)
column_list
列の名前を変更したり、新しいビューの列にコメントを追加したりする場合は、列名と(必要に応じて)列に関するコメントを指定する列リストを含めます。(列のデータ型を指定する必要なし。)
ビューの列のいずれかが式(単純な列名だけでなく)に基づいている場合、ビューの各列に列名を指定する必要があります。たとえば、次の場合には列名が必要です。
CREATE VIEW v1 (pre_tax_profit, taxes, after_tax_profit) AS SELECT revenue - cost, (revenue - cost) * tax_rate, (revenue - cost) * (1.0 - tax_rate) FROM table1;
列ごとにオプションのコメントを指定できます。例:
CREATE VIEW v1 (pre_tax_profit COMMENT 'revenue minus cost', taxes COMMENT 'assumes taxes are a fixed percentage of profit', after_tax_profit) AS SELECT revenue - cost, (revenue - cost) * tax_rate, (revenue - cost) * (1.0 - tax_rate) FROM table1;
コメントは、列名がわかりにくい場合に特に役立ちます。
コメントを表示するには、 DESCRIBE VIEW を使用します。
MASKING POLICY = policy_name
列に設定する マスキングポリシー を指定します。
USING ( col_name , cond_col_1 ... )
条件付きマスキングポリシー SQL 式に渡す引数を指定します。
リストの最初の列は、データをマスクまたはトークン化するポリシー条件の列を指定し、マスキングポリシーが設定されている列と一致する 必要 があります。
追加の列は、最初の列でクエリが実行されたときに、クエリ結果の各行のデータをマスクするかトークン化するかを決定するために評価する列を指定します。
USING 句が省略されている場合、Snowflakeは条件付きマスキングポリシーを通常の マスキングポリシー として扱います。
ROW ACCESS POLICY policy_name ON ( col_name [ , col_name ... ] )
ビューに設定する 行アクセスポリシー を指定します。
TAG tag_name = 'tag_value' [ , tag_name = 'tag_value' , ... ]
タグ の名前とタグ文字列の値を指定します。
タグ値は常に文字列であり、タグ値の最大文字数は256です。
ステートメントにあるタグの指定の詳細については、 オブジェクトおよび列のタグクォータ をご参照ください。
COPY GRANTS
OR REPLACE
句を使用して新しいビューが作成されるときに、元のビューのアクセス許可を保持します。このパラメーターは、既存のビューから新しいビューに OWNERSHIP を 除く すべての権限をコピーします。新しいビューは、スキーマ内のオブジェクト型に定義された将来の付与を継承 しません。デフォルトでは、 CREATE VIEW ステートメントを実行するロールが新しいビューを所有します。
パラメーターが CREATE VIEW ステートメントに含まれていない場合、新しいビューは元のビューに付与された明示的なアクセス権限を継承 しません が、スキーマ内のオブジェクトタイプに定義された将来の権限は継承します。
許可をコピーする操作は、 CREATE VIEW ステートメントで(つまり、同じトランザクション内で)アトミックに発生することに注意してください。
デフォルト:値なし(付与はコピーされない)
COMMENT = 'string_literal'
ビューのコメントを指定します。
デフォルト: 値なし
アクセス制御の要件¶
この SQL コマンドの実行に使用される ロール には、少なくとも次の 権限 が必要です。
権限 |
オブジェクト |
メモ |
---|---|---|
CREATE VIEW |
スキーマ |
|
SELECT |
テーブル、外部テーブル、ビュー |
ビュー定義でクエリされるすべてのテーブルおよび/またはビューで必要です。 |
APPLY |
マスキングポリシー、行アクセスポリシー、タグ |
ビューの作成時に、マスキングポリシー、行アクセスポリシー、オブジェクトタグ、またはこうした ガバナンス 機能の任意の組み合わせを適用する場合にのみ必要です。 |
スキーマ内の任意のオブジェクトを操作するには、親データベースとスキーマに対する USAGE 権限も必要であることに注意してください。
指定された権限のセットを使用してカスタムロールを作成する手順については、 カスタムロールの作成 をご参照ください。
セキュリティ保護可能なオブジェクト に対して SQL アクションを実行するためのロールと権限付与に関する一般的な情報については、 Snowflakeのアクセス制御 をご参照ください。
使用上の注意¶
ビュー定義には、 ORDER BY 句(例:
create view v1 as select * from t1 ORDER BY column1
)を含めることができます。ただし、Snowflakeは、ほとんどのビュー定義からORDER BY
句を 除外 することをお勧めします。並べ替えの恩恵を受けないコンテキストでビューが使用される場合、ORDER BY
句は不要なコストを追加します。たとえば、ビューが結合で使用され、結合列がORDER BY
列と同じでない場合、ビューの結果を並べ替えるための追加コストは通常無駄になります。クエリ結果を並べ替える必要がある場合は、通常、ビュー自体ではなく、ビューを使用するクエリでORDER BY
を指定する方が効率的です。ビュー定義は動的ではありません。特に列がドロップされたときなど、基になるソースがビュー定義と一致しないように変更された場合、ビューは自動的に更新されません。例:
ソーステーブルの特定の列を参照するビューが作成され、その後その列はテーブルからドロップされます。
ビューはテーブルから
SELECT *
を使用して作成され、その後、列はテーブルからドロップされます。
これらのシナリオのいずれかで、ビューをクエリすると、列の不一致エラーが返されます。
ビューのソーステーブルがドロップされた場合、ビューのクエリは
object does not exist
エラーを返します。スキーマには、同じ名前のテーブルとビューを含めることはできません。同じ名前のテーブルがスキーマに既に存在する場合、 CREATE VIEW ステートメントはエラーを生成します。
ビューが作成されると、テーブルおよびその他のデータベースオブジェクトへの 非修飾 参照は、セッションの現在のスキーマではなく、 ビューのスキーマで 解決されます。同様に、部分的に修飾されたオブジェクト(つまり、schema.object)は、セッションの現在のデータベースではなく、ビューのデータベースで解決されます。
SEARCH_PATH
セッションパラメーター(存在する場合)は無視されます。OR REPLACE
の使用は、既存のビューで DROP VIEW を使用してから、同じ名前で新しいビューを作成することと同じです。CREATE OR REPLACE <オブジェクト> ステートメントはアトミックです。つまり、オブジェクトが置き換えられると、古いオブジェクトの削除と新しいオブジェクトの作成が1つのトランザクションで処理されます。
これは、 CREATE OR REPLACE VIEW 操作と同時に実行されるクエリが、古いビューバージョンまたは新しいビューバージョンのいずれかを使用することを意味します。
ビューを再作成または交換すると、変更データがドロップされ、ビュー上のストリームが古くなります。 古い ストリームは読み取れません。
COPY GRANTS
を使用して、データ共有:
既存のセキュアビューが別のアカウントと共有されていた場合は、置換ビューも共有されます。
既存のセキュアビューがデータコンシューマーとしてアカウントと共有され、アクセス権がアカウント内の他のロールにも付与された場合(親データベースの GRANT IMPORTED PRIVILEGES を使用)、置換ビューにもアクセス権が付与されます。
置換ビューの SHOW GRANTS 出力には、ステートメントが実行されたときの現在のタイムスタンプとともに、コピーされた権限の被付与者が CREATE VIEW ステートメントを実行したロールとしてリストされます。
When you create a view and then grant privileges on that view to a role, the role can use the view even if the role does not have privileges on the underlying table(s) that the view accesses. This means that you can create a view to give a role access to only a subset of a table. For example, you can create a view that accesses medical billing information but not medical diagnosis information in the same table. Then you can grant privileges on that view to the "accountant" role so that the accountants can look at the billing information without seeing the patient's diagnosis.
設計上、 SHOW VIEWS コマンドはセキュアビューに関する情報を提供しません。セキュアビューに関する情報を表示するには、Information Schemaの VIEWS ビューを使用し、ビューを所有するロールを使用する必要があります。
再帰ビューは列名リストを提供する必要があります。
再帰的ビューを定義するときは、無限再帰を防止してください。再帰ビュー定義の WHERE 句は、通常、データの階層の最終レベルを処理した後にデータを使い果たすことにより、再帰を最終的に停止できるようにする必要があります。
メタデータについて。
注意
Snowflakeサービスを使用する場合、お客様は、個人データ(ユーザーオブジェクト向け以外)、機密データ、輸出管理データ、またはその他の規制されたデータがメタデータとして入力されていないことを確認する必要があります。詳細については、 Snowflakeのメタデータフィールド をご参照ください。
1つ以上のビュー列にマスキングポリシーを使用してビューを作成する場合、またはビューに行アクセスポリシーを追加する場合は、 POLICY_CONTEXT 関数を使用して、マスキングポリシーによって保護されている列と行アクセスポリシーによって保護されているビューに対するクエリをシミュレートします。
同じロールがビューストリームとソースストリームの両方を所有している(つまり、同じロール、またはロール階層の下位ロールがビューストリームとソースストリームに対する OWNERSHIP 権限を持っている)場合を除き、ストリームをソースオブジェクトとして使用したビューを作成しないでください。代わりに、ソースオブジェクトとして追跡するオブジェクトを持つビューを作成します。次に、それらのビューにストリームを作成します。詳細については、 Streams on Views をご参照ください。
移植の注意¶
一部のベンダーは
FORCE
キーワードをサポートしています。CREATE OR REPLACE FORCE VIEW ...
Snowflakeは
FORCE
キーワードを受け入れますが、サポートはしていません。つまり、このキーワードを使用しても構文エラーは発生しませんが、基になるデータベースオブジェクト(テーブルまたはビュー)がまだ存在しない場合は、FORCE
を使用してもビューの作成は強制されません。存在しないテーブルまたはビューのビューを作成しようとすると、FORCE
キーワードが使用されていてもエラーメッセージが表示されます。ビューでテーブルを検索するとき、一部のベンダーはアクティブなスキーマで修飾されていないテーブル名を検索します。Snowflakeは、 ビューと同じスキーマ内 で、修飾されていないテーブル名を検索します。Snowflakeに移植するときは、完全修飾テーブル名を使用するようにビューを更新することを検討してください。
例¶
現在のスキーマに、テーブルからすべての行を選択するコメント付きのビューを作成します。
CREATE VIEW myview COMMENT='Test view' AS SELECT col1, col2 FROM mytable; SHOW VIEWS; +---------------------------------+-------------------+----------+---------------+-------------+----------+-----------+--------------------------------------------------------------------------+ | created_on | name | reserved | database_name | schema_name | owner | comment | text | |---------------------------------+-------------------+----------+---------------+-------------+----------+-----------+--------------------------------------------------------------------------| | Thu, 19 Jan 2017 15:00:37 -0800 | MYVIEW | | MYTEST1 | PUBLIC | SYSADMIN | Test view | CREATE VIEW myview COMMENT='Test view' AS SELECT col1, col2 FROM mytable | +---------------------------------+-------------------+----------+---------------+-------------+----------+-----------+--------------------------------------------------------------------------+
次の例は、ビューがセキュアであることを除いて、前の例と同じです。
CREATE OR REPLACE SECURE VIEW myview COMMENT='Test secure view' AS SELECT col1, col2 FROM mytable; SELECT is_secure FROM information_schema.views WHERE view_name = 'MYVIEW';
以下に、再帰ビューを作成する2つの方法を示します。
まず、テーブルを作成してロードします。
CREATE OR REPLACE TABLE employees (title VARCHAR, employee_ID INTEGER, manager_ID INTEGER);INSERT INTO employees (title, employee_ID, manager_ID) VALUES ('President', 1, NULL), -- The President has no manager. ('Vice President Engineering', 10, 1), ('Programmer', 100, 10), ('QA Engineer', 101, 10), ('Vice President HR', 20, 1), ('Health Insurance Analyst', 200, 20);再帰 CTE を使用してビューを作成し、ビューをクエリします。
CREATE VIEW employee_hierarchy (title, employee_ID, manager_ID, "MGR_EMP_ID (SHOULD BE SAME)", "MGR TITLE") AS ( WITH RECURSIVE employee_hierarchy_cte (title, employee_ID, manager_ID, "MGR_EMP_ID (SHOULD BE SAME)", "MGR TITLE") AS ( -- Start at the top of the hierarchy ... SELECT title, employee_ID, manager_ID, NULL AS "MGR_EMP_ID (SHOULD BE SAME)", 'President' AS "MGR TITLE" FROM employees WHERE title = 'President' UNION ALL -- ... and work our way down one level at a time. SELECT employees.title, employees.employee_ID, employees.manager_ID, employee_hierarchy_cte.employee_id AS "MGR_EMP_ID (SHOULD BE SAME)", employee_hierarchy_cte.title AS "MGR TITLE" FROM employees INNER JOIN employee_hierarchy_cte WHERE employee_hierarchy_cte.employee_ID = employees.manager_ID ) SELECT * FROM employee_hierarchy_cte );SELECT * FROM employee_hierarchy ORDER BY employee_ID; +----------------------------+-------------+------------+-----------------------------+----------------------------+ | TITLE | EMPLOYEE_ID | MANAGER_ID | MGR_EMP_ID (SHOULD BE SAME) | MGR TITLE | |----------------------------+-------------+------------+-----------------------------+----------------------------| | President | 1 | NULL | NULL | President | | Vice President Engineering | 10 | 1 | 1 | President | | Vice President HR | 20 | 1 | 1 | President | | Programmer | 100 | 10 | 10 | Vice President Engineering | | QA Engineer | 101 | 10 | 10 | Vice President Engineering | | Health Insurance Analyst | 200 | 20 | 20 | Vice President HR | +----------------------------+-------------+------------+-----------------------------+----------------------------+キーワード RECURSIVE を使用してビューを作成し、ビューをクエリします。
CREATE RECURSIVE VIEW employee_hierarchy_02 (title, employee_ID, manager_ID, "MGR_EMP_ID (SHOULD BE SAME)", "MGR TITLE") AS ( -- Start at the top of the hierarchy ... SELECT title, employee_ID, manager_ID, NULL AS "MGR_EMP_ID (SHOULD BE SAME)", 'President' AS "MGR TITLE" FROM employees WHERE title = 'President' UNION ALL -- ... and work our way down one level at a time. SELECT employees.title, employees.employee_ID, employees.manager_ID, employee_hierarchy_02.employee_id AS "MGR_EMP_ID (SHOULD BE SAME)", employee_hierarchy_02.title AS "MGR TITLE" FROM employees INNER JOIN employee_hierarchy_02 WHERE employee_hierarchy_02.employee_ID = employees.manager_ID );SELECT * FROM employee_hierarchy_02 ORDER BY employee_ID; +----------------------------+-------------+------------+-----------------------------+----------------------------+ | TITLE | EMPLOYEE_ID | MANAGER_ID | MGR_EMP_ID (SHOULD BE SAME) | MGR TITLE | |----------------------------+-------------+------------+-----------------------------+----------------------------| | President | 1 | NULL | NULL | President | | Vice President Engineering | 10 | 1 | 1 | President | | Vice President HR | 20 | 1 | 1 | President | | Programmer | 100 | 10 | 10 | Vice President Engineering | | QA Engineer | 101 | 10 | 10 | Vice President Engineering | | Health Insurance Analyst | 200 | 20 | 20 | Vice President HR | +----------------------------+-------------+------------+-----------------------------+----------------------------+