Snowflake SQL
Generate Snowflake-compatible SQL from metadata-provided object and column names. Preserve Snowflake object resolution, type, and semi-structured data semantics.
Namespaces and identifiers
- Qualify schema objects as
database.schema.objectwhen the current database and schema are not guaranteed; otherwise use the shortest unambiguous name. - Treat warehouses, roles, and databases as account-level objects rather than schema objects.
- Remember that unquoted identifiers are stored and resolved in uppercase, while double-quoted identifiers preserve exact case and characters.
- Reuse metadata names exactly. Use double quotes for case-sensitive, reserved, spaced, or special-character identifiers; do not use backticks or square brackets.
Queries and expressions
- Use
LIMITor ANSIFETCHfor row limiting and add a deterministicORDER BYfor pagination. - Use
QUALIFYto filter window-function results without an extra subquery when it makes the query clearer. - Use Snowflake functions such as
DATEADD,DATEDIFF,DATE_TRUNC,IFF, andTRY_TO_*with their Snowflake argument order and return semantics. - Use
ILIKEfor case-insensitive pattern matching when intended. Do not import another dialect's date formatting or interval syntax without conversion. - Treat session settings such as timezone, week policy, and timestamp mapping as part of date/time semantics when interpreting results.
Types and semi-structured data
- Use Snowflake types such as
NUMBER(p,s),FLOAT,VARCHAR,BINARY,BOOLEAN,DATE,TIME,TIMESTAMP_NTZ,TIMESTAMP_LTZ, andTIMESTAMP_TZ. - Distinguish
TIMESTAMP_NTZfrom session-timezone-awareTIMESTAMP_LTZand offset-preservingTIMESTAMP_TZ; do not use genericTIMESTAMPwhen the distinction matters. - Use
VARIANT,OBJECT, andARRAYfor semi-structured data. Parse text with functions such asPARSE_JSONbefore storing it inVARIANT. - Access semi-structured paths with Snowflake path syntax and cast scalar results to the required SQL type.
- Use
LATERAL FLATTEN(INPUT => expression)to expandVARIANT,OBJECT, orARRAYvalues into rows.
DDL and writes
- Use
CREATE OR REPLACEonly when replacing the object and its dependent behavior is acceptable; otherwise useIF NOT EXISTSor inspect metadata. - Use
CLUSTER BYfor clustering where justified. Do not generate traditional indexes for ordinary Snowflake tables. - Treat primary-key, unique, and foreign-key constraints on standard tables primarily as metadata; do not rely on them to enforce integrity. Account for enforced
NOT NULLand supportedCHECKconstraints, and distinguish hybrid-table enforcement. - Account for DDL transaction boundaries; do not assume DDL participates in a surrounding DML transaction.
- Use
MERGEfor matched update/delete and unmatched insert logic. Preserve the possibility of multiple source rows matching one target row when reasoning about correctness.
Data loading and unloading
- Use
COPY INTO tableto load from named, user, or table stages andCOPY INTO locationto unload query or table data. - Use existing stages and file formats from metadata when available. Otherwise make the required stage, path, file format, pattern, column mapping, and copy options explicit.
- Use a
SELECTtransform insideCOPY INTO tablewhen files require column reordering, casting, or semi-structured extraction. - Treat
VALIDATION_MODE,ON_ERROR,MATCH_BY_COLUMN_NAME,PURGE, andFORCEas explicit capabilities with data-quality and idempotency consequences; do not enable them implicitly. - Never place secrets directly in generated SQL when a storage integration, external stage, or configured credential is available.
Avoid common dialect leaks
Before returning SQL, reject backticks, PostgreSQL/MySQL upsert syntax, Oracle FROM DUAL, SQL Server TOP, traditional index DDL, and unqualified objects whose database and schema cannot be inferred.