Snowflake SQL translation guide

This document details the similarities and differences in SQL syntax between Snowflake and BigQuery to help accelerate the planning and execution of moving your EDW (Enterprise Data Warehouse) to BigQuery. Snowflake data warehousing is designed to work with Snowflake-specific SQL syntax. Scripts written for Snowflake might need to be altered before you can use them in BigQuery, because the SQL dialects vary between the services. Use batch SQL translation to migrate your SQL scripts in bulk, or interactive SQL translation to translate ad hoc queries. Snowflake SQL is supported by both tools in preview.

Data types

This section shows equivalents between data types in Snowflake and in BigQuery.



Snowflake BigQuery Notes
NUMBER/ DECIMAL/NUMERIC NUMERIC/BIGNUMERIC Can be mapped to NUMERIC or BIGNUMERIC, depending on precision and scale.

The NUMBER data type in Snowflake supports 38 digits of precision and 37 digits of scale. Precision and scale can be specified according to the user.

BigQuery supports NUMERIC and BIGNUMERIC with optionally specified precision and scale within certain bounds.
INT/INTEGER BIGNUMERIC INT/INTEGER and all other INT-like datatypes, such as BIGINT, TINYINT, SMALLINT, BYTEINT represent an alias for the NUMBER datatype where the precision and scale cannot be specified and is always NUMBER(38, 0)

BigQuery converts INTEGER to INT64 by default. To configure the SQL translation to convert it to other data types, you can use the REWRITE_ZERO_SCALE_NUMERIC_AS_INTEGER configuration option
BIGINT BIGNUMERIC
SMALLINT BIGNUMERIC
TINYINT BIGNUMERIC
BYTEINT BIGNUMERIC
FLOAT/
FLOAT4/
FLOAT8
FLOAT64 The FLOAT data type in Snowflake establishes 'NaN' as > X, where X is any FLOAT value (other than 'NaN' itself).

The FLOAT data type in BigQuery establishes 'NaN' as < X, where X is any FLOAT value (other than 'NaN' itself).
DOUBLE/
DOUBLE PRECISION/

REAL
FLOAT64 The DOUBLE data type in Snowflake is synonymous with the FLOAT data type in Snowflake, but is commonly incorrectly displayed as FLOAT. It is properly stored as DOUBLE.
VARCHAR STRING The VARCHAR data type in Snowflake has a maximum length of 128 MB (uncompressed). If length is not specified, the default is the maximum length.

The STRING data type in BigQuery is stored as variable length UTF-8 encoded Unicode. For more information about column and row limits, see Query jobs.
CHAR/CHARACTER STRING
STRING/TEXT STRING The STRING data type in Snowflake is synonymous with Snowflake's VARCHAR.
BINARY BYTES
VARBINARY BYTES
BOOLEAN BOOL The BOOL data type in BigQuery can only accept TRUE/FALSE, unlike the BOOL data type in Snowflake, which can accept TRUE/FALSE/NULL.
DATE DATE The DATE type in Snowflake accepts most common date formats, unlike the DATE type in BigQuery, which only accepts dates in the format, 'YYYY-[M]M-[D]D'.
TIME TIME The TIME type in Snowflake supports 0 to 9 nanoseconds of precision, whereas the TIME type in BigQuery supports 0 to 6 nanoseconds of precision.
TIMESTAMP DATETIME TIMESTAMP is a user-configurable alias which defaults to TIMESTAMP_NTZ which maps to DATETIME in BigQuery.
TIMESTAMP_LTZ TIMESTAMP
TIMESTAMP_NTZ/DATETIME
DATETIME
TIMESTAMP_TZ TIMESTAMP
OBJECT JSON
VARIANT JSON
ARRAY ARRAY<JSON> The SQL translation service preserves the data type for typed arrays. For untyped arrays, such as ARRAY<VARIANT>, BigQuery converts these to ARRAY<JSON>

BigQuery also has the following data types which do not have a direct Snowflake analogue:

CREATE FUNCTION syntax

The following table addresses differences in SQL UDF creation syntax between Snowflake and BigQuery.

Snowflake BigQuery

CREATE [ OR REPLACE ] FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

AS sql_function_definition

s

CREATE [OR REPLACE] FUNCTION function_name

([sql_arg_name sql_arg_data_type[,..]])

AS sql_function_definition


Note: In BigQuery SQL UDF, return data type is optional. BigQuery infers the result type of the function from the SQL function body when a query calls the function.

CREATE [OR REPLACE] FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS TABLE (col_name, col_data_type[,..])

AS sql_function_definition


CREATE [OR REPLACE] FUNCTION function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

AS sql_function_definition


Note:In BigQuery SQL UDF, returning table type is not supported but is on the product roadmap and will be available soon. However, BigQuery supports returning ARRAY of type STRUCT.

CREATE [SECURE] FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

AS sql_function_definition


Note: Snowflake provides secure option to restrict UDF definition and details only to authorized users (that is, users who are granted the role that owns the view).

CREATE FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

AS sql_function_definition


Note: Function security is not a configurable parameter in BigQuery. BigQuery supports creating IAM roles and permissions to restrict access to underlying data and function definition.

CREATE [OR REPLACE] FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

[ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]

AS sql_function_definition

CREATE [OR REPLACE] FUNCTION function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

AS sql_function_definition


Note: Function behaviour for null inputs is implicitly handled in BigQuery and need not be specified as a separate option.

CREATE [OR REPLACE] FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

[VOLATILE | IMMUTABLE]

AS sql_function_definition

CREATE [OR REPLACE] FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

AS sql_function_definition


Note:Function volatility is not a configurable parameter in BigQuery. All BigQuery UDF volatility is equivalent to Snowflake's IMMUTABLE volatility (that is, it does not do database lookups or otherwise use information not directly present in its argument list).

CREATE [OR REPLACE] FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

AS [' | $$]

sql_function_definition

[' | $$]

CREATE [OR REPLACE] FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

AS sql_function_definition


Note: Using single quotes or a character sequence like dollar quoting ($$) is not required or supported in BigQuery. BigQuery implicitly interprets the SQL expression.

CREATE [OR REPLACE] FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

[COMMENT = '<string_literal>']

AS sql_function_definition

CREATE [OR REPLACE] FUNCTION

function_name

([sql_arg_name sql_arg_data_type[,..]])

RETURNS data_type

AS sql_function_definition


Note: Adding comments or descriptions in UDFs is not supported in BigQuery.

CREATE [OR REPLACE] FUNCTION function_name

(x integer, y integer)

RETURNS integer

AS $$

SELECT x + y

$$


Note: Snowflake does not support ANY TYPE for SQL UDFs. However, it supports using VARIANT data types.

CREATE [OR REPLACE] FUNCTION function_name

(x ANY TYPE, y ANY TYPE)

AS

SELECT x + y



Note: BigQuery supports using ANY TYPE as argument type. The function will accept an input of any type for this argument. For more information, see templated parameter in BigQuery.

BigQuery also supports the CREATE FUNCTION IF NOT EXISTSstatement which treats the query as successful and takes no action if a function with the same name already exists.

BigQuery's CREATE FUNCTIONstatement also supports creating TEMPORARY or TEMP functions, which do not have a Snowflake equivalent. See calling UDFs for details on executing a BigQuery persistent UDF.

DROP FUNCTION syntax

The following table addresses differences in DROP FUNCTION syntax between Snowflake and BigQuery.

Snowflake BigQuery

DROP FUNCTION [IF EXISTS]

function_name

([arg_data_type, ... ])

DROP FUNCTION [IF EXISTS] dataset_name.function_name


Note: BigQuery does not require using the function's signature (argument data type) for deleting the function.

BigQuery requires that you specify the project_name if the function is not located in the current project.

Additional function commands

This section covers additional UDF commands supported by Snowflake that are not directly available in BigQuery.

ALTER FUNCTION syntax

Snowflake supports the following operations using ALTER FUNCTION syntax.

  • Renaming a UDF
  • Converting to (or reverting from) a secure UDF
  • Adding, overwriting, removing a comment for a UDF

As configuring function security and adding function comments is not available in BigQuery, ALTER FUNCTION syntax is not supported. However, the CREATE FUNCTION statement can be used to create a UDF with the same function definition but a different name.

DESCRIBE FUNCTION syntax

Snowflake supports describing a UDF using DESC[RIBE] FUNCTION syntax. This is not supported in BigQuery. However, querying UDF metadata via INFORMATION SCHEMA will be available soon as part of the product roadmap.

SHOW USER FUNCTIONS syntax

In Snowflake, SHOW USER FUNCTIONS syntax can be used to list all UDFs for which users have access privileges. This is not supported in BigQuery. However, querying UDF metadata via INFORMATION SCHEMA will be available soon as part of the product roadmap.

Stored procedures

Snowflake stored procedures are written in JavaScript, which can execute SQL statements by calling a JavaScript API. In BigQuery, stored procedures are defined using a block of SQL statements.

CREATE PROCEDURE syntax

In Snowflake, a stored procedure is executed with a CALL command while in BigQuery, stored procedures are executed like any other BigQuery function.

The following table addresses differences in stored procedure creation syntax between Snowflake and BigQuery.

Snowflake BigQuery

CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

RETURNS data_type

AS procedure_definition;


Note: Snowflake requires that stored procedures return a single value. Hence, return data type is a required option.
CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_mode arg_name arg_data_type[,..]])

BEGIN

procedure_definition

END;


arg_mode: IN | OUT | INOUT


Note: BigQuery doesn't support a return type for stored procedures. Also, it requires specifying argument mode for each argument passed.

CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

RETURNS data_type

AS

$$

javascript_code

$$;

CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

BEGIN

statement_list

END;

CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

RETURNS data_type

[{CALLED ON NULL INPUT | {RETURNS NULL ON NULL INPUT | STRICT}}]

AS procedure_definition;

CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

BEGIN

procedure_definition

END;


Note: Procedure behavior for null inputs is implicitly handled in BigQuery and need not be specified as a separate option.
CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

RETURNS data_type

[VOLATILE | IMMUTABLE]

AS procedure_definition;

CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

BEGIN

procedure_definition

END;


Note:Procedure volatility is not a configurable parameter in BigQuery. It's equivalent to Snowflake's IMMUTABLE volatility.
CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

RETURNS data_type

[COMMENT = '<string_literal>']

AS procedure_definition;

CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

BEGIN

procedure_definition

END;


Note: Adding comments or descriptions in procedure definitions is not supported in BigQuery.
CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

RETURNS data_type

[EXECUTE AS { CALLER | OWNER }]

AS procedure_definition;


Note: Snowflake supports specifying the caller or owner of the procedure for execution

CREATE [OR REPLACE] PROCEDURE

procedure_name

([arg_name arg_data_type[,..]])

BEGIN

procedure_definition

END;


Note: BigQuery stored procedures are always executed as the caller

BigQuery also supports the CREATE PROCEDURE IF NOT EXISTS statement which treats the query as successful and takes no action if a function with the same name already exists.

DROP PROCEDURE syntax

The following table addresses differences in DROP FUNCTION syntax between Snowflake and BigQuery.

Snowflake BigQuery

DROP PROCEDURE [IF EXISTS]

procedure_name

([arg_data_type, ... ])

DROP PROCEDURE [IF EXISTS] dataset_name.procedure_name


Note: BigQuery does not require using procedure's signature (argument data type) for deleting the procedure.

BigQuery requires that you specify the project_name if the procedure is not located in the current project.

Additional procedure commands

Snowflake provides additional commands like ALTER PROCEDURE, DESC[RIBE] PROCEDURE, and SHOW PROCEDURES to manage the stored procedures. These are not supported in BigQuery.

Metadata and transaction SQL statements

Snowflake BigQuery

BEGIN [ { WORK | TRANSACTION } ] [ NAME <name> ]; START_TRANSACTION [ name <name> ];

BigQuery always uses Snapshot Isolation. For details, see Consistency guarantees elsewhere in this document.

COMMIT;

Not used in BigQuery.

ROLLBACK;

Not used in BigQuery

SHOW LOCKS [ IN ACCOUNT ]; SHOW TRANSACTIONS [ IN ACCOUNT ]; Note: If the user has the ACCOUNTADMIN role, the user can see locks/transactions for all users in the account.

Not used in BigQuery.

Multi-statement and multi-line SQL statements

Both Snowflake and BigQuery support transactions (sessions) and therefore support statements separated by semicolons that are consistently executed together. For more information, see Multi-statement transactions.

Metadata columns for staged files

Snowflake automatically generates metadata for files in internal and external stages. This metadata can be queried and loaded into a table alongside regular data columns. The following metadata columns can be utilized:

Consistency guarantees and transaction isolation

Both Snowflake and BigQuery are atomic—that is, ACID-compliant on a per-mutation level across many rows.

Transactions

Each Snowflake transaction is assigned a unique start time (includes milliseconds) that is set as the transaction ID. Snowflake only supports the READ COMMITTED isolation level. However, a statement can see changes made by another statement if they are both in the same transaction - even though those changes are not committed yet. Snowflake transactions acquire locks on resources (tables) when that resource is being modified. Users can adjust the maximum time a blocked statement will wait until the statement times out. DML statements are autocommitted if the AUTOCOMMIT parameter is turned on.

BigQuery also supports transactions. BigQuery helps ensure optimistic concurrency control (first to commit wins) with snapshot isolation, in which a query reads the last committed data before the query starts. This approach guarantees the same level of consistency on a per-row, per-mutation basis and across rows within the same DML statement, yet avoids deadlocks. In the case of multiple DML updates against the same table, BigQuery switches to pessimistic concurrency control. Load jobs can run completely independently and append to tables. However, BigQuery does not provide an explicit transaction boundary or session.

Rollback

If a Snowflake transaction's session is unexpectedly terminated before the transaction is committed or rolled back, the transaction is left in a detached state. The user should run SYSTEM$ABORT_TRANSACTION to abort the detached transaction or Snowflake will roll back the detached transaction after four idle hours. If a deadlock occurs, Snowflake detects the deadlock and selects the more recent statement to roll back. If the DML statement in an explicitly opened transaction fails, the changes are rolled back, but the transaction is kept open until it is committed or rolled back. DDL statements in Snowflake cannot be rolled back as they are autocommitted.

BigQuery supports the ROLLBACK TRANSACTION statement. There is no ABORT statement in BigQuery.

Database limits

Always check the BigQuery public documentation for the latest quotas and limits. Many quotas for large-volume users can be raised by contacting the Cloud Support team.

All Snowflake accounts have soft-limits set by default. Soft-limits are set during account creation and can vary. Many Snowflake soft-limits can be raised through the Snowflake account team or a support ticket.

The following table shows a comparison of the Snowflake and BigQuery database limits.

Limit Snowflake BigQuery
Size of query text 1 MB 1 MB
Maximum number of concurrent queries XS Warehouse - 8
S Warehouse - 16
M Warehouse - 32
L Warehouse - 64
XL Warehouse - 128
100