객체 이름 해석

객체 이름 해석 (Object name resolution)

이 문서는 Snowflake에서 스키마 객체(테이블, 뷰, 파일 포맷 등)의 이름이 어떻게 해석되는지 설명해요. 반정규화된 이름을 생략하는 규칙, 검색 경로(SEARCH_PATH), 그리고 컬럼 이름과 별칭이 겹칠 때의 우선순위를 다루어요.

출처: Snowflake SQL Reference

본문

완전히 한정된(fully-qualified) 스키마 객체(테이블, 뷰, 파일 포맷 등)는 다음과 같은 형태를 가져요:

<database_name>.<schema_name>.<object_name>

하지만 이렇게 쓰면 번거로울 수 있기 때문에, 사용자는 왼쪽부터 한정자(qualifier)를 생략할 수 있어요. 이 문서는 스키마 객체 이름이 어떻게 해석되는지 설명해요.

데이터베이스가 생략된 경우의 해석

(''<schema_name>.<object_name>'')

객체 이름에 현재 데이터베이스가 추가돼요. 세션이 시작될 때 현재 데이터베이스는 계정 설정에 따라 기본값으로 설정돼요. 이후에는 USE DATABASE 명령으로 변경할 수 있어요. CREATE DATABASE 명령도 현재 데이터베이스를 새로 생성한 데이터베이스로 묵시적으로 변경해요. 현재 데이터베이스의 이름은 CURRENT_DATABASE 함수가 반환해요.

예를 들어:

SELECT CURRENT_DATABASE();

+--------------------+
| CURRENT_DATABASE() |
+--------------------+
| TESTDB             |
+--------------------+

CREATE DATABASE db1;

+------------------------------------+
|               status               |
+------------------------------------+
| Database DB1 successfully created. |
+------------------------------------+

SELECT CURRENT_DATABASE();

+--------------------+
| CURRENT_DATABASE() |
+--------------------+
| DB1                |
+--------------------+

USE DATABASE testdb;

+----------------------------------+
|              status              |
+----------------------------------+
| Statement executed successfully. |
+----------------------------------+

SELECT CURRENT_DATABASE();

+--------------------+
| CURRENT_DATABASE() |
+--------------------+
| TESTDB             |
+--------------------+

스키마가 생략된 경우의 해석 (이중 점 표기법)

(''<database_name>..<object_name>'')

두 개의 점은 스키마 이름이 지정되지 않았음을 나타내요. 항상 PUBLIC 기본 스키마가 참조돼요.

이 표기 형식은 주로 Microsoft SQL Server, IBM Netezza 같은 다른 시스템과의 호환성을 위해 제공되는 점에 유의하세요. 새 쿼리에서는 이 표기법 사용을 권장하지 않아요.

정규화되지 않은 객체 (Unqualified objects)

정규화되지 않은 객체(단일 식별자)는 DDL/DML 문에 나타나는지 쿼리에 나타나는지에 따라 두 가지 방식으로 해석돼요.

DDL 및 DML 문

DDL과 DML 문에서 정규화되지 않은 객체에는 현재 데이터베이스와 스키마가 추가돼요. 현재 스키마는 현재 데이터베이스와 비슷하게 유지돼요. 현재 스키마는 항상 현재 데이터베이스에 속해요.

세션이 시작되면 현재 스키마는 연결 설정에 따라 초기화돼요. 현재 데이터베이스가 변경되면 현재 스키마는 내부 속성(보통 PUBLIC으로 설정)의 값으로 기본 설정돼요. 현재 스키마는 USE SCHEMA 명령으로 변경할 수 있어요 (항상 현재 데이터베이스 내에서). CREATE SCHEMA 명령으로도 묵시적으로 변경돼요. 현재 스키마의 이름은 CURRENT_SCHEMA 함수가 반환해요.

예를 들어:

SELECT CURRENT_SCHEMA();

+------------------+
| CURRENT_SCHEMA() |
+------------------+
| TESTSCHEMA       |
+------------------+

CREATE DATABASE db1;

+------------------------------------+
|               status               |
+------------------------------------+
| Database DB1 successfully created. |
+------------------------------------+

SELECT CURRENT_SCHEMA();

+------------------+
| CURRENT_SCHEMA() |
+------------------+
| PUBLIC           |
+------------------+

CREATE SCHEMA sch1;

+-----------------------------------+
|              status               |
+-----------------------------------+
| Schema SCH1 successfully created. |
+-----------------------------------+

SELECT current_schema();

+------------------+
| CURRENT_SCHEMA() |
|------------------|
| SCH1             |
|------------------+

쿼리에서의 이름 해석

쿼리에서 정규화되지 않은 객체 이름은 검색 경로(search path)를 통해 해석돼요.

검색 경로는 보통 현재 스키마를 포함하지만, 다른 스키마도 포함할 수 있어요.

검색 경로는 세션 수준 매개변수인 SEARCH_PATH에 저장돼요. 다른 매개변수와 마찬가지로 ALTER SESSION 명령으로 변경할 수 있어요.

검색 경로의 값은 식별자의 쉼표로 구분된 목록이에요. 목록에는 완전히 또는 부분적으로 한정된 스키마 이름이 들어갈 수 있어요. 각 스키마 이름은 큰따옴표로 감싼 식별자일 수 있어요.

검색 경로에는 다음 의사 변수(pseudo-variables)도 포함될 수 있어요:

  • $current — 현재 스키마를 지정해요 (위 참조).
  • $public — 현재 데이터베이스의 public 스키마를 지정해요. public 스키마의 이름은 Snowflake가 유지 관리하는 내부 속성으로 결정되며, 보통 PUBLIC으로 설정돼요 (각 데이터베이스에 자동으로 생성되는 PUBLIC 스키마용).

이 의사 변수 이름은 대소문자를 구분하지 않아요.

검색 경로의 기본값은 $current, $public이에요.

사용자가 검색 경로에 새 값을 지정하면 그 값이 검증돼요. 새 값에 지정된 모든 스키마 식별자는 기존 스키마와 일치해야 해요. 특히, 정규화되지 않은 모든 스키마는 현재 데이터베이스의 기존 스키마와 일치해야 해요. 그렇지 않으면 오류가 발생하고 search_path는 이전 값을 유지해요. 하지만 의사 변수는 자유롭게 사용할 수 있어요. 예를 들어 현재 데이터베이스에 public 스키마가 없어도 $public을 사용할 수 있어요.

SEARCH_PATH 매개변수의 값은 사용될 때마다 다시 해석돼요. 따라서 현재 스키마를 변경하면 $current의 의미가 바뀌고, 현재 데이터베이스를 변경하면 $public과 검색 경로의 정규화되지 않은 스키마의 의미도 바뀌어요.

검색 경로의 스키마가 삭제되거나, 현재 데이터베이스가 변경되어 검색 경로의 일부 정규화되지 않은 스키마가 새 데이터베이스에 없어도 오류는 발생하지 않아요.

SEARCH_PATH는 뷰나 UDF 안에서는 사용되지 않아요. 뷰나 UDF 정의의 모든 정규화되지 않은 객체는 뷰 또는 UDF의 스키마에서만 해석돼요.

검색 경로의 리터럴 값은 SHOW PARAMETERS 명령으로 확인할 수 있어요.

쿼리에서 정규화되지 않은 객체에 대해 검색될 스키마를 보려면 CURRENT_SCHEMAS 함수를 사용하세요. 함수의 반환 값은 검색 경로의 완전히 한정된 스키마들을 쉼표로 구분해 담고 있어요.

예를 들어:

SELECT CURRENT_SCHEMAS();

+-------------------+
| CURRENT_SCHEMAS() |
+-------------------+
| []                |
+-------------------+

USE DATABASE mytestdb;

SELECT current_schemas();

+---------------------+
| CURRENT_SCHEMAS()   |
+---------------------+
| ["MYTESTDB.PUBLIC"] |
+---------------------+

CREATE SCHEMA private;

SELECT current_schemas();

+-----------------------------------------+
| CURRENT_SCHEMAS()                       |
+-----------------------------------------+
| ["MYTESTDB.PRIVATE", "MYTESTDB.PUBLIC"] |
+-----------------------------------------+

의사 변수는 현재 값으로 확장되고, 정규화되지 않은 스키마는 완전히 한정되며, 존재하지 않거나 보이지 않는 스키마는 생략돼요.

SHOW PARAMETERS LIKE 'search_path';

+-------------+--------------------+--------------------+------------------------------------------------+
| key         | value              | default            | description                                    |
+-------------+--------------------+--------------------+------------------------------------------------+
| SEARCH_PATH | $current, $public, | $current, $public, | Search path for unqualified object references. |
+-------------+--------------------+--------------------+------------------------------------------------+

SELECT current_schemas();

+---------------------------------------------------------------------------+
|                       CURRENT_SCHEMAS()                                   |
+---------------------------------------------------------------------------+
| [XY12345.TESTDB.TESTSCHEMA, XY12345.TESTDB.PUBLIC, SAMPLES.COMMON.PUBLIC] |
+---------------------------------------------------------------------------+

컬럼 이름과 별칭이 일치할 때의 우선순위

컬럼 이름과 일치하는 별칭을 포함하는 쿼리를 만드는 것이 가능하지만(보통 권장되지는 않음), 다음과 같이 만들 수 있어요:

SELECT x, some_expression AS x
  FROM ...

어떤 절에 컬럼 이름과 별칭 모두와 일치하는 이름이 있으면, 그 절은 컬럼 이름을 사용해요. 다음 예제는 GROUP BY 절에서 이 동작을 보여줘요.

테이블을 만들고 행을 삽입해 봐요:

CREATE TABLE employees (salary FLOAT, state VARCHAR, employment_state VARCHAR);
INSERT INTO employees (salary, state, employment_state) VALUES
  (60000, 'California', 'Active'),
  (70000, 'California', 'On leave'),
  (80000, 'Oregon', 'Active');

다음 쿼리는 active인 직원 급여의 합과 on leave인 직원 급여의 합을 반환해요:

SELECT SUM(salary), ANY_VALUE(employment_state)
  FROM employees
  GROUP BY employment_state;

+-------------+-----------------------------+
| SUM(SALARY) | ANY_VALUE(EMPLOYMENT_STATE) |
|-------------+-----------------------------|
|      140000 | Active                      |
|       70000 | On leave                    |
+-------------+-----------------------------+

다음 쿼리는 쿼리의 테이블에 있는 컬럼 이름과 일치하는 별칭 state를 사용해요. GROUP BY 절에서 state를 사용하면 Snowflake는 이를 별칭이 아니라 컬럼 이름을 참조하는 것으로 해석해요. 따라서 이 쿼리는 California 주 직원 급여의 합과 Oregon 주 직원 급여의 합을 반환하지만, 주 이름 대신 Active 같은 employment_state 정보를 표시해요:

SELECT SUM(salary), ANY_VALUE(employment_state) AS state
  FROM employees
  GROUP BY state;

+-------------+--------+
| SUM(SALARY) | STATE  |
|-------------+--------|
|      130000 | Active |
|       80000 | Active |
+-------------+--------+

더 알아보기 (Learn more)