Data Type Mappings Between SQL and Handler Languages¶
A stored procedure or user-defined function you write is called from SQL, and so receives and returns values in SQL data types. However, its underlying handler will use data types from the handler’s language, such as Java, Python, or Scala. At runtime, Snowflake converts between the SQL types and handler types for arguments and return values.
Note that Snowflake makes these conversions the following cases as well:
When dynamically constructing a SQL statement that uses a value in a handler variable.
When binding a handler variable’s value to a prepared statement.
This topic describes valid mappings between SQL data and types and those from the supported handler languages. Use this content to choose data types when writing a handler.
For information about Snowflake SQL data types, see Summary of data types.
SQL-Java Data Type Mappings¶
The table below shows the type mappings between SQL and Java. These mappings generally apply to both the arguments passed to the procedure or function and the values returned from it. However, there are some exceptions, which are listed in footnotes.
Note that some SQL data types (e.g. NUMBER) are compatible with multiple Java data types (e.g. int
, long
, etc.). In these cases,
you can use any Java data type that has enough capacity to hold the actual values that will be passed. If you
pass a SQL value to an incompatible Java data type (or vice versa), Snowflake throws an error.
SQL Type |
Java Type |
Notes |
---|---|---|
ARRAY |
|
Formats the elements of the array as strings. |
ARRAY |
|
Formats the array as a JSON string (e.g. |
BINARY |
|
|
BINARY |
|
Encodes the binary string in hexadecimal. [4] |
BINARY |
|
Exposes the BINARY value as a sequence of bytes. |
BOOLEAN |
|
Cannot be null. |
BOOLEAN |
|
|
BOOLEAN |
|
|
DATE |
|
|
DATE |
|
Formats the date as |
FLOAT |
|
Cannot be null. |
FLOAT |
|
|
FLOAT |
|
Cannot be null. Might result in precision loss. |
FLOAT |
|
Might result in precision loss. |
FLOAT |
|
Might result in precision loss (float -> string conversion is lossy). |
GEOGRAPHY |
|
Formats the geography as GeoJSON (https://tools.ietf.org/html/rfc7946) . |
GEOGRAPHY |
||
MAP |
|
The output format is MAP(VARCHAR, VARCHAR). |
NUMBER |
|
Cannot be null. Must fit in the range of short (no fractional part, and integer part cannot exceed the max/min short values). |
NUMBER |
|
Must fit in the range of short (no fractional part, and integer part cannot exceed the max/min short values). |
NUMBER |
|
Cannot be null. Must fit in the range of int (no fractional part, and integer part cannot exceed the max/min int values). |
NUMBER |
|
Must fit in the range of int (no fractional part, and integer part cannot exceed the max/min int values). |
NUMBER |
|
Cannot be null. Must fit in the range of long (no fractional part, and integer part cannot exceed the max/min long values). |
NUMBER |
|
Must fit in the range of long (no fractional part, and integer part cannot exceed the max/min long values). |
NUMBER |
|
|
NUMBER |
|
Must fit into the range of BigInteger (no fractional part). |
NUMBER |
|
|
OBJECT |
|
The map’s keys are the object’s keys, and the values are formatted as strings. |
OBJECT |
|
Formats the object as a JSON string (e.g. |
TIME |
|
|
TIME |
|
Formats the time as |
TIMESTAMP_LTZ |
|
Must fit in the range of java.sql.Timestamp. [3] |
TIMESTAMP_LTZ |
|
The output format is |
TIMESTAMP_NTZ |
|
Must fit in the range of java.sql.Timestamp. Treats the wallclock time as an offset from the Unix epoch (imposing a UTC time zone, effectively). [3] |
TIMESTAMP_NTZ |
|
Treats the wallclock time as an offset from the Unix epoch (imposing a UTC time zone, effectively). The output format is |
TIMESTAMP_TZ |
|
Must fit in the range of java.sql.Timestamp. [3] |
TIMESTAMP_TZ |
|
The output format is |
VARCHAR |
|
|
VARIANT |
The Variant data type is a class in the Snowpark package. For more information, see Snowpark Package Types Supported for User-Defined Functions. For an example, see Passing a VARIANT value to an in-line Java UDF. |
Arrays¶
Java UDFs can receive arrays of any of the following Java data types:
Data Type |
Notes |
---|---|
|
|
|
The Snowflake ARRAY must contain only BOOLEAN elements and must not contain any NULL values. |
|
The Snowflake ARRAY must contain either of the following, and must not contain any NULL values.
|
|
The Snowflake ARRAY must contain only fixed-point elements with a scale of 0, and must not contain any NULL values. |
NULL Values¶
Snowflake supports two distinct NULL values: SQL NULL
and VARIANT’s JSON null
. (For information about Snowflake
VARIANT NULL, see NULL Values.)
Java supports one null
value, which is only for non-primitive data types.
A SQL NULL
argument to a Java handler translates to the Java null
value, but only for Java data types that
support null
.
A returned Java null
value translates back to SQL NULL
.
TIMESTAMP_LTZ Values and Time Zones¶
A Java UDF is largely isolated from the environment in which it is called. However, the timezone is inherited from the calling environment. If the caller’s session set a default time zone before calling the Java UDF, then the Java UDF has the same default time zone. Java UDF uses the same IANA Time Zone Database (https://www.iana.org/time-zones) data as the native TIMEZONE Snowflake SQL uses (i.e. data from release 2021a of the Time Zone Database).
Snowpark Package Types Supported for User-Defined Functions¶
In a user-defined function, you can use a specific subset of types that are included in the Snowflake Snowpark Java package. Although these types are designed for use in Snowpark code, a few are also supported for use in UDFs for the convenience they can provide. (For more about Snowpark, see the Snowpark documentation.)
Note
The Snowpark library is a requirement for stored procedures written in Java, Python, and Scala. As a result, you can use Snowpark types there without restriction.
Snowpark types in the following table are supported in UDF code. You should not use other Snowpark types in UDF code; they are not supported there.
Snowpark Type |
Snowpark Version Required |
Description |
---|---|---|
1.2.0 and later |
Represents the Snowflake GEOGRAPHY type. For an example that uses the |
|
1.4.0 and later |
Represents Snowflake VARIANT data. For an example that uses the |
Specifying the Snowpark Package as a Dependency¶
When developing UDF code that uses the Snowpark package, you’ll need to set up your development environment so that you can compile and run code with Snowpark dependencies. For more, see Setting Up Other Development Environments for Snowpark Java.
When deploying a UDF by executing the CREATE FUNCTION statement, you can specify the Snowpark
package as a dependency without uploading the JAR file to a stage (the library is already in Snowflake). To do this, specify the package
name and version in the PACKAGES
clause. For a syntax example, see Passing a GEOGRAPHY value to an in-line Java UDF.
SQL-JavaScript Data Type Mappings¶
The following table shows the Snowflake SQL data types and the corresponding JavaScript data types:
SQL Data Type |
JavaScript Data Type |
Notes |
---|---|---|
ARRAY |
|
|
BOOLEAN |
|
The values |
DATE |
|
|
GEOGRAPHY, GEOMETRY |
|
|
REAL, FLOAT, FLOAT8, FLOAT4, DOUBLE, DOUBLE PRECISION |
|
|
TIME |
|
|
TIMESTAMP, TIMESTAMP_LTZ, TIMESTAMP_NTZ, TIMESTAMP_TZ |
|
When a timestamp is passed as an argument to a stored procedure, the timestamp is converted to a JavaScript |
VARCHAR, CHAR, CHARACTER, STRING, TEXT |
|
|
VARIANT |
|
Notes¶
Not all Snowflake SQL data types have a corresponding JavaScript data type. For example, JavaScript does not
directly support the INTEGER or NUMBER data types. In these cases, you should convert the SQL data type to an
appropriate alternative data type. For example, you can convert a SQL INTEGER into a SQL FLOAT, which can then be
converted to a JavaScript value of data type number
.
The table below shows appropriate conversions for the incompatible SQL data types:
Incompatible SQL Data Type |
Compatible SQL Data Type |
---|---|
BINARY |
Uint8Array |
INTEGER |
FLOAT |
NUMBER, NUMERIC, DECIMAL |
FLOAT |
OBJECT |
Uint8Array |
When Returning Values¶
If the return
statement in the JavaScript returns a data type different from the stored procedure’s declared return type,
the JavaScript value is cast to the SQL data type if possible. For example, if a number is returned, but the
stored procedure is declared as returning a string, the number is converted to a string within JavaScript, and
then copied to the string returned in the SQL statement. (Keep in mind that some JavaScript programming errors, such as
returning the wrong data type, can be hidden by this behavior.)
If no valid cast for the conversion exists, then an error occurs.
When Binding Values¶
When you bind JavaScript variables to SQL statements, Snowflake converts from the JavaScript data types to the SQL data types. You can bind variables of the following JavaScript data types:
number
string
SfDate
For more details about the
SfDate
data type, which is not a standard JavaScript data type, see the JavaScript stored procedures API.
For more information about binding, including some examples, see Binding variables.
You might also find the following topics helpful:
SQL-Python Data Type Mappings¶
The table below shows the type mappings between SQL and Python. These mappings generally apply to both the arguments passed to the Python handler and the values returned from it.
SQL Type |
Python Type |
Notes |
---|---|---|
ARRAY |
|
When a Python data type is converted to ARRAY, if there is any embedded Python decimal data, the embedded Python decimal will be converted to a String in the ARRAY. |
BINARY |
|
|
BOOLEAN |
|
|
DATE |
|
|
FLOAT |
|
Floating point operations can have small rounding errors, which can accumulate, especially when aggregate functions process large numbers of rows. Rounding errors can vary each time a query is executed if the rows are processed in a different order. For more information, see Numeric Data Types: Float. |
GEOGRAPHY, GEOMETRY |
|
Formats the geography as GeoJSON (https://tools.ietf.org/html/rfc7946) and then converts it to a Python dict. |
MAP |
|
MAP is not supported as a return type. |
NUMBER |
|
If the scale of the NUMBER type is 0 then the int Python type is used. Otherwise decimal.Decimal type is used. |
OBJECT |
|
When a Python data type is converted to OBJECT, if there is any embedded Python decimal data, the embedded Python decimal will be converted to a String in the OBJECT. |
TIME |
|
Although Snowflake can store time values with nanosecond precision, the Python datetime.time type maintains only millisecond precision. Conversion between Snowflake and Python data types can reduce effective precision to milliseconds. |
TIMESTAMP_LTZ |
|
Use local timezone to convert internal UTC time to local “naive” datetime. Requires “naive” datetime as return type. |
TIMESTAMP_NTZ |
|
Directly convert to “naive” datetime. Requires “naive” datetime as return type. |
TIMESTAMP_TZ |
|
Convert to “aware” datetime with timezone information. Requires “aware” datetime as return type. |
VARCHAR |
|
|
VARIANT |
|
Each variant row is converted to a Python type dynamically for arguments and vice versa for return values. The following types are converted to strings rather than native Python types: decimal, binary, date, time, timestamp_ltz, timestamp_ntz, timestamp_tz. When a Python data type is converted to VARIANT, if there is any embedded Python decimal data, the embedded Python decimal will be converted to a String in the VARIANT. |
VECTOR |
|
SQL-Scala Data Type Mappings¶
Snowflake supports the following Scala data types in addition to the Java types listed in SQL-Java Data Type Mappings:
SQL Data Type |
Scala Type |
Notes |
---|---|---|
ARRAY |
|
|
BINARY |
|
|
BOOLEAN |
|
|
DOUBLE |
|
|
FLOAT |
|
|
MAP |
|
The output format is MAP(VARCHAR, VARCHAR). |
NUMBER |
The following types are supported:
|
|
OBJECT |
|
|
VARCHAR |
|
|
VARIANT |
|
Formats the value depending on the type that is represented. Variant null is formatted as the string “null”. |
For DATE and TIMESTAMP, use the Java types listed in SQL-Java Data Type Mappings.