카테고리:

테이블, 뷰 및 시퀀스 DDL

CREATE VIEW

하나 이상의 기존 테이블의 쿼리(또는 다른 유효한 쿼리 식)를 기반으로 현재/지정된 스키마에 새 뷰를 만듭니다.

참고 항목:

ALTER VIEW , DROP VIEW , SHOW VIEWS , DESCRIBE VIEW

이 항목의 내용:

구문

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

뷰를 만드는 데 사용되는 쿼리를 지정합니다. 하나 이상의 원본 테이블 또는 다른 유효한 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 <오브젝트> 문은 원자성입니다. 즉, 오브젝트가 바뀔 때 이전 오브젝트 삭제와 새 오브젝트 생성이 단일 트랜잭션으로 처리됩니다.

    이는 CREATE OR REPLACE VIEW 작업과 동시에 수행되는 모든 쿼리가 이전 또는 새 뷰 버전을 사용함을 의미합니다.

    뷰를 다시 만들거나 바꾸면 그 변경 데이터가 삭제되어 뷰의 모든 스트림을 부실하게 만듭니다. 부실 상태의 스트림은 읽을 수 없습니다.

  • COPY GRANTS 사용하기:

    • 데이터 공유:

      • 기존 보안 뷰를 다른 계정과 공유한 경우 대체 뷰도 공유됩니다.

      • 기존 보안 뷰를 데이터 컨슈머로서 자신의 계정과 공유하고 (부모 데이터베이스에서 GRANT IMPORTED PRIVILEGES를 사용하여) 계정의 다른 역할에 추가로 액세스 권한을 부여한 경우 대체 뷰에도 액세스 권한이 부여됩니다.

    • 대체 뷰에 대한 SHOW GRANTS 출력에는 CREATE VIEW 문이 실행될 때 현재 타임스탬프를 포함한 이 문을 실행한 역할로서 복사된 권한의 피부여자가 나열됩니다.

  • 뷰를 만든 다음 해당 뷰에 대한 권한을 역할에 부여하면 해당 역할은 뷰가 액세스하는 기본 테이블에 대한 권한이 없더라도 뷰를 사용할 수 있습니다. 이는 테이블의 서브세트에만 역할 액세스 권한을 부여하는 뷰를 만들 수 있다는 뜻입니다. 예를 들어, 같은 테이블에서 의료 진단 정보가 아니라 의료 청구 정보에 액세스하는 뷰를 만들 수 있습니다. 그런 다음, 해당 뷰에서 회계사가 환자의 진단 정보는 보지 않고 청구 정보를 볼 수 있도록 하는 권한을 《회계사》 역할에 부여할 수 있습니다.

  • SHOW VIEWS 명령은 보안 뷰에 대한 정보를 제공하지 않도록 되어 있습니다. 보안 뷰에 대한 정보를 보려면 Information Schema에서 VIEWS 뷰와 뷰를 소유한 역할을 사용해야 합니다.

  • 재귀 뷰는 열 이름 목록을 제공해야 합니다.

  • 재귀 뷰를 정의할 때 무한 재귀를 방지하십시오. 재귀 뷰 정의에서 WHERE 절을 사용하면 일반적으로 데이터 계층 구조의 마지막 수준을 처리한 후 데이터가 부족해져 결국에는 재귀를 중지할 수 있습니다.

  • 메타데이터 관련:

    주의

    고객은 Snowflake 서비스를 사용할 때 개인 데이터(사용자 오브젝트 제외), 민감한 데이터, 수출 통제 대상 데이터 또는 기타 규제 데이터가 메타데이터로 입력되지 않도록 해야 합니다. 자세한 내용은 Snowflake의 메타데이터 필드 섹션을 참조하십시오.

  • 하나 이상의 뷰 열에 마스킹 정책을 사용하여 뷰를 생성하거나, 뷰에 추가된 행 액세스 정책을 생성할 때, POLICY_CONTEXT 함수를 사용하여, 마스킹 정책에 의해 보호되는 열 및 행 액세스 정책에 의해 보호되는 뷰에 대한 쿼리를 시뮬레이션합니다.

  • 동일한 역할이 뷰와 원본 스트림을 모두 소유하지 않는 한 스트림을 원본 오브젝트로 사용하여 뷰를 만들지 마십시오(즉, 동일한 역할 또는 역할 계층 구조에서 더 낮은 역할이 뷰 및 원본 스트림에 대한 OWNERSHIP 권한을 가짐). 대신 원본 오브젝트로 추적할 오브젝트가 있는 뷰를 만듭니다. 그런 다음 해당 뷰에서 스트림을 만듭니다. 자세한 내용은 뷰의 스트림 섹션을 참조하십시오.

포팅 참고 사항

  • 일부 벤더는 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';

아래에서는 재귀 뷰를 만드는 두 가지 방법을 보여줍니다.

먼저 테이블을 만들어 로딩합니다.

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          |
+----------------------------+-------------+------------+-----------------------------+----------------------------+
맨 위로 이동