CALL
CALL (익명 프로시저 포함)
저장 프로시저(stored procedure)와 비슷하지만 나중에 사용하기 위해 저장되지 않는 익명 프로시저(anonymous procedure)를 만들고 호출하는 명령이에요.
출처: 문서
본문
이 명령으로 WITH 절의 파라미터로 정의된 익명 프로시저를 만들고 그 프로시저를 동시에 호출해요.
이 명령에는 CREATE PROCEDURE 스키마 권한이 있는 역할이 필요하지 않아요.
프로시저는 caller's rights로 실행돼요. 즉 프로시저는 호출자의 권한으로 실행되고, 현재 세션 컨텍스트를 사용하며, 호출자의 세션 변수와 파라미터에 접근할 수 있어요.
관련 명령: CREATE PROCEDURE, CALL.
구문 (Syntax)
Java
Java 핸들러와 함께 RETURNS TABLE(...)를 통해 테이블 형 저장 프로시저를 사용하는 것은 모든 계정에서 사용할 수 있는 프리뷰 기능이에요.
WITH <name> AS PROCEDURE ([ <arg_name> <arg_data_type> ]) [ , ... ] )
RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
LANGUAGE { JAVA }
RUNTIME_VERSION = '<scala_or_java_runtime_version>'
PACKAGES = ( 'com.snowflake:snowpark:<version>' [, '<package_name_and_version>' ...] )
[ IMPORTS = ( '<stage_path_and_directory_or_file_name_to_read>' [, '<stage_path_and_directory_or_file_name_to_read>' ...] ) ]
HANDLER = '<fully_qualified_method_name>'
[ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
[ AS '<procedure_definition>' ]
[ , <cte_nameN> [ ( <cte_column_list> ) ] AS ( SELECT ... ) ]
CALL <name> ( [ [ <arg_name> => ] <arg> , ... ] )
[ INTO :<snowflake_scripting_variable> ]
스테이징된 핸들러(staged handlers)가 있는 Java 프로시저에는 다음 구문을 사용해요:
WITH <name> AS PROCEDURE ([ <arg_name> <arg_data_type> ]) [ , ... ] )
RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
LANGUAGE { JAVA }
RUNTIME_VERSION = '<scala_or_java_runtime_version>'
PACKAGES = ( 'com.snowflake:snowpark:<version>' [, '<package_name_and_version>' ...] )
[ IMPORTS = ( '<stage_path_and_directory_or_file_name_to_read>' [, '<stage_path_and_directory_or_file_name_to_read>' ...] ) ]
HANDLER = '<fully_qualified_method_name>'
[ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
[ , <cte_nameN> [ ( <cte_column_list> ) ] AS ( SELECT ... ) ]
CALL <name> ( [ [ <arg_name> => ] <arg> , ... ] )
[ INTO :<snowflake_scripting_variable> ]
JavaScript
WITH <name> AS PROCEDURE ([ <arg_name> <arg_data_type> ]) [ , ... ] )
RETURNS <result_data_type> [ [ NOT ] NULL ]
LANGUAGE JAVASCRIPT
[ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
AS '<procedure_definition>'
[ , <cte_nameN> [ ( <cte_column_list> ) ] AS ( SELECT ... ) ]
CALL <name> ( [ [ <arg_name> => ] <arg> , ... ] )
[ INTO :<snowflake_scripting_variable> ]
Python
인라인 프로시저에는 다음 구문을 사용해요:
WITH <name> AS PROCEDURE ( [ <arg_name> <arg_data_type> ] [ , ... ] )
RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
LANGUAGE PYTHON
RUNTIME_VERSION = '<python_version>'
PACKAGES = ( 'snowflake-snowpark-python[==<version>]'[, '<package_name>[==<version>]' ... ])
[ IMPORTS = ( '<stage_path_and_directory_or_file_name_to_read>' [, '<stage_path_and_directory_or_file_name_to_read>' ...] ) ]
HANDLER = '<function_name>'
[ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
[ , <cte_nameN> [ ( <cte_column_list> ) ] AS ( SELECT ... ) ]
AS '<procedure_definition>'
CALL <name> ( [ [ <arg_name> => ] <arg> , ... ] )
[ INTO :<snowflake_scripting_variable> ]
코드가 스테이지의 파일에 있는 프로시저에는 다음 구문을 사용해요:
WITH <name> AS PROCEDURE ( [ <arg_name> <arg_data_type> ] [ , ... ] )
RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
LANGUAGE PYTHON
RUNTIME_VERSION = '<python_version>'
PACKAGES = ( 'snowflake-snowpark-python[==<version>]'[, '<package_name>[==<version>]' ... ])
[ IMPORTS = ( '<stage_path_and_directory_or_file_name_to_read>' [, '<stage_path_and_directory_or_file_name_to_read>' ...] ) ]
HANDLER = '<module_file_name>.<function_name>'
[ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
[ , <cte_nameN> [ ( <cte_column_list> ) ] AS ( SELECT ... ) ]
CALL <name> ( [ [ <arg_name> => ] <arg> , ... ] )
[ INTO :<snowflake_scripting_variable> ]
Scala
프리뷰 기능 — 공개
Scala 핸들러와 함께 RETURNS TABLE(...)를 통해 테이블 형 저장 프로시저를 사용하는 것은 모든 계정에서 사용할 수 있는 프리뷰 기능이에요.
WITH <name> AS PROCEDURE ([ <arg_name> <arg_data_type> ]) [ , ... ] )
RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
LANGUAGE { SCALA }
RUNTIME_VERSION = '<scala_runtime_version>'
PACKAGES = ( 'com.snowflake:snowpark_<scala_version>:<version>' [, '<package_name_and_version>' ...] )
[ IMPORTS = ( '<stage_path_and_directory_or_file_name_to_read>' [, '<stage_path_and_directory_or_file_name_to_read>' ...] ) ]
HANDLER = '<fully_qualified_method_name>'
[ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
[ AS '<procedure_definition>' ]
[ , <cte_nameN> [ ( <cte_column_list> ) ] AS ( SELECT ... ) ]
CALL <name> ( [ [ <arg_name> => ] <arg> , ... ] )
[ INTO :<snowflake_scripting_variable> ]
스테이징된 핸들러가 있는 Scala 프로시저에는 다음 구문을 사용해요:
WITH <name> AS PROCEDURE ([ <arg_name> <arg_data_type> ]) [ , ... ] )
RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
LANGUAGE { SCALA }
RUNTIME_VERSION = '<scala_or_java_runtime_version>'
PACKAGES = ( 'com.snowflake:snowpark_<scala_version>:<version>' [, '<package_name_and_version>' ...] )
[ IMPORTS = ( '<stage_path_and_directory_or_file_name_to_read>' [, '<stage_path_and_directory_or_file_name_to_read>' ...] ) ]
HANDLER = '<fully_qualified_method_name>'
[ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
[ , <cte_nameN> [ ( <cte_column_list> ) ] AS ( SELECT ... ) ]
CALL <name> ( [ [ <arg_name> => ] <arg> , ... ] )
[ INTO :<snowflake_scripting_variable> ]
Snowflake Scripting
WITH <name> AS PROCEDURE ([ <arg_name> <arg_data_type> ]) [ , ... ] )
RETURNS { <result_data_type> | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
LANGUAGE SQL
[ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
AS '<procedure_definition>'
[ , <cte_nameN> [ ( <cte_column_list> ) ] AS ( SELECT ... ) ]
CALL <name> ( [ [ <arg_name> => ] <arg> , ... ] )
[ INTO :<snowflake_scripting_variable> ]
필수 파라미터 (Required parameters)
모든 언어 공통
WITH *name* AS PROCEDURE ( [ *arg_name* *arg_data_type* ] [ , ... ] )
프로시저의 식별자(*name*)와 입력 인수를 지정해요.
-
식별자:
- 식별자는 영문자로 시작해야 하고, 전체 식별자 문자열을 큰따옴표로 감싸지 않는 한 공백이나 특수 문자를 포함할 수 없어요(예: "My object"). 큰따옴표로 감싼 식별자는 대소문자를 구분해요. Identifier requirements를 참고하세요.
-
입력 인수:
-
*arg_name*에는 입력 인수의 이름을 지정해요. -
*arg_data_type*에는 사용하는 핸들러 언어에 해당하는 Snowflake 데이터 유형을 사용해요.-
Java 프로시저는 SQL-Java Data Type Mappings을 참고하세요.
-
JavaScript 프로시저는 SQL and JavaScript data type mapping을 참고하세요.
-
Python 프로시저는 SQL-Python Data Type Mappings을 참고하세요.
-
Scala 프로시저는 SQL-Scala Data Type Mappings을 참고하세요.
-
Snowflake Scripting은 SQL 데이터 유형을 사용해요.
-
-
참고
Java, Python, Scala로 작성하는 프로시저(Snowpark API 사용)에서는 Snowpark Session 객체의 인수를 생략해요.
Session 인수는 지정하는 정식 파라미터가 아니에요. 이 명령을 실행하면 Snowflake가 자동으로 Session 객체를 만들어 프로시저의 핸들러 함수에 전달해요.
RETURNS *result_data_type* [ [ NOT ] NULL ]
프로시저가 반환하는 결과의 유형을 지정해요.
NOT NULL을 사용해 프로시저가 null이 아닌 값만 반환해야 함을 지정해요. 기본값은 NULL이며, 프로시저가 NULL을 반환할 수 있음을 의미해요.
-
*result_data_type*에는 사용하는 언어 유형에 해당하는 Snowflake 데이터 유형을 사용해요.-
Java 프로시저는 SQL-Java Data Type Mappings을 참고하세요.
-
JavaScript 프로시저는 SQL and JavaScript data type mapping을 참고하세요.
-
Python 프로시저는 SQL-Python Data Type Mappings을 참고하세요.
-
Scala 프로시저는 SQL-Scala Data Type Mappings을 참고하세요.
-
Snowflake Scripting은 SQL 데이터 유형을 사용해요.
-
참고
Java나 Scala로 작성한 프로시저는 반환 값이 있어야 해요. Python에서 프로시저가 값을 반환하지 않으면 None을 반환하는 것으로 간주돼요.
참고로 핸들러 언어와 무관하게 이 명령의 WITH 절에는 프로시저가 명시적으로 아무것도 반환하지 않더라도 반환 유형을 정의하는 RETURNS 절이 반드시 포함되어야 해요.
RETURNS TABLE ( [ *col_name* *col_data_type* [ , ... ] ] )의 경우 반환되는 테이블 열의 Snowflake 데이터 유형을 알고 있으면 열 이름과 유형을 지정해요:
WITH get_top_sales() AS PROCEDURE
RETURNS TABLE (sales_date DATE, quantity NUMBER)
...
CALL get_top_sales();
그렇지 않으면(예: 런타임에 열 유형을 결정하는 경우) 열 이름과 유형을 생략할 수 있어요:
WITH get_top_sales() AS PROCEDURE
...
RETURNS TABLE ()
CALL get_top_sales();
참고
현재 RETURNS TABLE(...) 절에서는 GEOGRAPHY를 열 유형으로 지정할 수 없어요. 저장 프로시저를 만들 때든 익명 프로시저를 만들 때든 동일하게 적용돼요.
CREATE OR REPLACE PROCEDURE test_return_geography_table_1()
RETURNS TABLE(g GEOGRAPHY)
...
WITH test_return_geography_table_1() AS PROCEDURE
RETURNS TABLE(g GEOGRAPHY)
...
CALL test_return_geography_table_1();
GEOGRAPHY를 열 유형으로 지정하려 하면 저장 프로시저 호출에서 다음 오류가 발생해요:
Stored procedure execution error: data type of returned table does not match expected returned table type
이 문제를 해결하려면 RETURNS TABLE()에서 열 인수와 유형을 생략할 수 있어요.
CREATE OR REPLACE PROCEDURE test_return_geography_table_1()
RETURNS TABLE()
...
WITH test_return_geography_table_1() AS PROCEDURE
RETURNS TABLE()
...
CALL test_return_geography_table_1();
RETURNS TABLE(...)는 핸들러가 다음 언어로 작성된 경우에만 지원돼요:
실질적으로 Snowflake Scripting 블록 밖에서는 호출이 표현식의 일부가 될 수 없으므로 반환 값을 사용할 수 없어요.
LANGUAGE *language*
프로시저 핸들러 코드의 언어를 지정해요.
현재 *language*에 지원되는 값은 다음과 같아요:
-
JAVA(Java용) -
JAVASCRIPT(JavaScript용) -
PYTHON(Python용) -
SCALA(Scala용) -
SQL(Snowflake Scripting용)
AS *procedure_definition*
프로시저가 실행하는 코드를 정의해요. 정의는 유효한 어떤 코드로도 구성될 수 있어요.
다음에 유의하세요:
-
코드가 인라인이 아닌 프로시저에서는 AS 절을 생략해요. 여기에는 핸들러가 스테이지에 있는 프로시저가 포함돼요.
대신 IMPORTS 절을 사용해 프로시저 코드가 포함된 파일의 위치를 지정해요. 자세한 내용은 다음을 참고하세요:
-
{procedure definition}주위에는 Snowflake Scripting에서도 문자열 리터럴 구분자('또는$$)를 사용해야 해요. -
JavaScript 프로시저의 경우 개행이 포함된 문자열을 작성할 때는 문자열 주위에 백쿼트(backquote, `)를 사용할 수 있어요.
프로시저 본문에 작은따옴표와 큰따옴표가 모두 포함되어 있기 때문에 다음 JavaScript 프로시저 예제는 $$와 백쿼트를 사용해요:
WITH proc3 AS PROCEDURE ()
RETURNS VARCHAR
LANGUAGE javascript
AS
$$
var rs = snowflake.execute( { sqlText:
`INSERT INTO table1 ("column 1")
SELECT 'value 1' AS "column 1" ;`
} );
return 'Done.';
$$
CALL proc3();
- Snowflake는 핸들러 코드를 검증하지 않아요. 그러나 잘못된 핸들러 코드는 명령을 실행할 때 오류를 일으켜요.
저장 프로시저에 대한 자세한 내용은 Working with stored procedures를 참고하세요.
CALL *name* ( [ [ *arg_name* => ] *arg* , ... ] )
호출할 프로시저의 식별자(*name*)와 입력 인수를 지정해요.
입력 인수를 이름(*arg_name* => *arg*)으로 지정하거나 위치(*arg*)로 지정할 수 있어요.
참고
-
모든 인수를 이름으로 또는 위치로 지정해야 해요. 일부 인수는 이름으로, 다른 인수는 위치로 지정할 수 없어요.
-
인수를 이름으로 지정할 때는 인수 이름 주위에 큰따옴표를 사용할 수 없어요.
-
같은 이름이지만 다른 인수 유형을 가진 두 프로시저가 있다면, 인수 이름이 다를 때 인수 이름을 사용해 실행할 프로시저를 지정할 수 있어요. 자세한 내용은 Overloading procedures and functions을 참고하세요.
Java, Python 또는 Scala
RUNTIME_VERSION = '*language_runtime_version*'
사용할 언어 런타임 버전이에요. 현재 지원되는 버전은 다음과 같아요:
-
Java: 11
-
Python:
일반 제공 버전:
-
3.9 (중단됨)
-
3.10
-
3.11
-
3.12
-
3.13
-
3.14
-
-
Scala: 2.12
PACKAGES = ( '*snowpark_package_name*' [, '*package_name*' ...] )
핸들러 코드의 실행 환경에 포함해야 하는 Snowflake에 배포된 패키지 이름의 쉼표로 구분된 목록이에요. 보안 프로시저에는 Snowpark 패키지가 필요하므로 PACKAGES 절에 항상 참조해야 해요. Snowpark에 대한 자세한 내용은 Snowpark API를 참고하세요.
기본적으로 Snowflake가 프로시저를 실행하는 환경에는 지원 언어에 대한 선택된 패키지 집합이 포함돼요. PACKAGES 절에서 이 패키지들을 참조할 때는 IMPORTS 절에서 패키지를 포함한 파일을 참조할 필요가 없어요. 패키지가 이미 Snowflake에서 사용 가능하기 때문이에요.
주어진 언어에 대해 지원되는 패키지와 버전 목록은 언어를 지정해 INFORMATION_SCHEMA.PACKAGES 뷰를 쿼리해요. 예:
SELECT * FROM information_schema.packages WHERE language = '<language>';
여기서 *language*는 java, python 또는 scala예요.
PACKAGES 절에서 패키지를 참조하는 구문은 아래 설명된 대로 패키지의 언어에 따라 달라져요.
-
Java
다음 형식을 사용해 패키지 이름과 버전 번호를 지정해요:
domain:package_name:version
최신 버전을 지정하려면 *version*에 latest를 지정해요.
예를 들어 최신 Snowpark lib의 패키지를 포함하려면 다음을 지정해요:
PACKAGES = ('com.snowflake:snowpark:latest')
-
Python
패키지 이름과 버전 번호를 다음 형식 중 하나로 지정해요:
package_name[==version]
또는
package_name>=version
최신 버전을 지정하려면 *version*을 생략해요. 예: 'snowflake-snowpark-python'.
예를 들어 특정 PyPI 저장소 패키지를 포함하려면:
Packages = ('snowflake-snowpark-python', 'pyjwt==2.8.0')
-
Scala
다음 형식을 사용해 패키지 이름과 버전 번호를 지정해요:
domain:package_name:version
최신 버전을 지정하려면 *version*에 latest를 지정해요.
예를 들어 최신 Snowpark lib의 패키지를 포함하려면:
PACKAGES = ('com.snowflake:snowpark_2.12:latest')
IMPORTS = ( '*stage_path_and_directory_or_file_name_to_read*' [, ... ] )
프로시저에서 사용하는 파일(핸들러 코드 또는 종속성)이 들어 있는 스테이지 위치와 경로를 지정해요. 스테이지 위치가 사용 중인 스키마 내부에 있으면, 필요한 경우 스키마를 생략할 수 있어요.
예:
IMPORTS = ('@my_stage/handler.py')
지정된 파일이 다른 파일에 의존하면 스테이지의 전체 디렉터리 경로를 포함해도 돼요.
.zip 파일은 기본적으로 스테이지에 업로드되지 않아요. 포함하려면 @stage/path/file.zip 형식으로 명시적으로 참조해야 해요.
HANDLER = '*function_name*' | '*fully_qualified_method_name*' | '*package_name*.*class_name*.*method_name*'
호출할 핸들러 코드의 언어별 진입점을 지정해요.
CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT }
null 입력이 있을 때 저장 프로시저를 호출할지 지정해요.
-
CALLED ON NULL INPUT: 항상 프로시저를 호출해요. 프로시저 코드는 null 값을 처리해야 해요. 이 옵션은 기본값이에요. -
STRICT:RETURNS NULL ON NULL INPUT의 동의어. 입력 인수 중 하나라도 null이면 프로시저를 호출하지 않고 대신 항상 null을 반환해요.
기본값: CALLED ON NULL INPUT
COMMENT = '*string_literal*'
프로시저에 대한 주석을 지정해요.
EXECUTE AS = { CALLER | OWNER }
프로시저가 caller's rights 또는 owner's rights로 실행되는지 지정해요.
-
CALLER: 프로시저 코드는 호출자의 권한으로 실행돼요. 이 프로시저에서 소유한 스키마 객체에 접근하려면 호출자에게 적절한 권한이 있어야 해요. -
OWNER: 프로시저 코드는 프로시저 소유자의 권한으로 실행돼요. 이 프로시저에서 소유·참조한 스키마 객체에 대한 권한은 절대적으로 필요해요.
기본값: OWNER