Some parts in the output code are omitted for clarity reasons.
SnowConvert AI translates ALTER TABLE ... DROP CONSTRAINT statements to Snowflake, with the following adjustments:
IF EXISTS at the constraint level is stripped because Snowflake does not support IF EXISTS on DROP CONSTRAINT. Instead, IF EXISTS is added at the table level (ALTER TABLE IF EXISTS).
WITH (index options) such as WITH ( ONLINE = OFF ) are removed because Snowflake does not support index options.
1. IF EXISTS on DROP CONSTRAINT is not supported in Snowflake
Snowflake does not support IF EXISTS directly on DROP CONSTRAINT. SnowConvert AI strips it and adds IF EXISTS at the table level. If the constraint does not exist, the statement will fail.
2. WITH (index options) are removed
SQL Server-specific index options like WITH ( ONLINE = OFF ) have no equivalent in Snowflake and are silently removed.
Some parts in the output code are omitted for clarity reasons.
SnowConvert AI comments out ALTER TABLE ... CHECK CONSTRAINT ... and ALTER TABLE ... NOCHECK CONSTRAINT ... statements because enabling or disabling constraints is not applicable in Snowflake.
This behavior applies to the CHECK CONSTRAINT action. It does not apply to unsupported ADD CHECK (...) constraint definitions, which continue to be flagged separately.
In SQL Server, the ADD clause permits multiple actions per ADD, whereas Snowflake only allows a sequence of ADD column actions. Consequently, SnowConvert AI divides the ALTER TABLE ADD clause into individual ALTER TABLE statements.
There is a subset of functionalities provided by the ADD keyword, allowing the addition of different elements to the target table. These include:
Translation for column constraints is relatively straightforward. There are several parts of the syntax that are not required or not supported in Snowflake.
:force:-- PRIMARY KEYALTERTABLE[Person]ADDCONSTRAINT[PK_EmailAddress_BusinessEntityID_EmailAddressID]PRIMARYKEY CLUSTERED ([BusinessEntityID]ASC,[EmailAddressID]ASC)ON[PRIMARY]
GO
-- FOREING KEY TO ANOTHER TABLEALTERTABLE[Person].[EmailAddress]WITHCHECKADDCONSTRAINT[FK_EmailAddress_Person_BusinessEntityID]FOREIGNKEY([BusinessEntityID])REFERENCES[Person].[Person]([BusinessEntityID])ONDELETECASCADE
GO
1. DEFAULT is only supported withinCREATE TABLE and ALTER TABLE ... ADD COLUMN
SQL Server supports defining a DEFAULT property within a constraint, while Snowflake only allows that when adding the column through CREATE TABLE or ALTER TABLE ... ADD COLUMN. DEFAULT properties within the ADD CONSTRAINT syntax are not supported and will be translated to ALTER TABLE ALTER COLUMN.
:force:
ALTERTABLE bought
ADD COL2 VARCHAR(32);!!!RESOLVE EWI!!!/*** SSC-EWI-0109 - ALTER TABLE SYNTAX NOT APPLICABLE IN SNOWFLAKE ***/!!!ALTERTABLE bought
ADDCONSTRAINT EC_BOUGHT1 CONNECTION(Customer TO Product, Supplier TO Product)ONDELETE NO ACTION;
:force:[FOREIGNKEY]REFERENCES<ref_table_name>[(<ref_col_name>)][MATCH{FULL|SIMPLE|PARTIAL}][ON[UPDATE{CASCADE|SETNULL|SETDEFAULT|RESTRICT| NO ACTION }][DELETE{CASCADE|SETNULL|SETDEFAULT|RESTRICT| NO ACTION }]][[NOT]ENFORCED][[NOT]DEFERRABLE][INITIALLY{DEFERRED|IMMEDIATE}][ENABLE|DISABLE][VALIDATE|NOVALIDATE][RELY|NORELY]
:force:
ALTERTABLE Tests.dbo.Employee
ADDCONSTRAINT FK_Department FOREIGNKEY(DepartmentID)REFERENCES Department (DepartmentID)ONUPDATECASCADEONDELETE NO ACTION;
Note
Constraints are not enforced in Snowflake, excepting NOT NULL.
Primary and Foreign Key are only used for documentation purposes more than design constraints.
Some parts in the output code are omitted for clarity reasons.
In Transact SQL Server, the on partition statement is used inside alter statements and is used to divide the data across the database. For more information, see the SQL Server partitioned tables and indexes documentation.
Notice that in this example the ON PARTITION has been removed. This is because Snowflake provides an integrated partitioning methodology. Thus, the syntax is not relevant.
Additionally, a couple other parts are partially supported, and require additional work to be implemented to properly emulate the original functionality. Specifically, we’re talking about the MASKED WITH property, which will be covered in the patterns section of this page.
:force:
ADD[COLUMN]<col_name><col_type>[{DEFAULT<expr>|{AUTOINCREMENT|IDENTITY}[{(<start_num>,<step_num>)|START<num>INCREMENT<num>}]}]/* AUTOINCREMENT (or IDENTITY) supported only for columns with numeric data types (NUMBER, INT, FLOAT, etc.). *//* Also, if the table is not empty (i.e. rows exist in the table), only DEFAULT can be altered. */[ inlineConstraint ][[WITH]MASKINGPOLICY<policy_name>[USING(<col1_name>, cond_col_1 ,...)]]
:force:
ALTERTABLEIFEXISTStable_nameADDCOLUMN new_column_name VARCHARCOLLATE'EN-CI-AS'/*** SSC-PRF-0002 - CASE INSENSITIVE COLUMNS CAN DECREASE THE PERFORMANCE OF QUERIES ***/;
This pattern showcases the translation for MASKED WITH property. CREATE OR REPLACE MASKING POLICY is inserted somewhere before the first usage, and then referenced by a SET MASKING POLICY clause.
The name of the new MASKING POLICY will be the concatenation of the name and arguments of the original MASKED WITH FUNCTION, as seen below:
:force:--** SSC-FDM-TS0022 - MASKING ROLE MUST BE DEFINED PREVIOUSLY BY THE USER **CREATEORREPLACEMASKINGPOLICY"random_1_999"AS(val SMALLINT)RETURNSSMALLINT->CASEWHENcurrent_role()IN('YOUR_DEFINED_ROLE_HERE')THEN val
ELSEUNIFORM(1,999,RANDOM()):: SMALLINTEND;ALTERTABLEIFEXISTStable_nameMODIFYCOLUMN column_name/*** SSC-FDM-TS0021 - A MASKING POLICY WAS CREATED AS SUBSTITUTE FOR MASKED WITH ***/SETMASKINGPOLICY"random_1_999";
In SQL Server, SPARSE is used to define columns that are optimized for NULL storage. However, when we’re using Snowflake, we are not required to use this clause.
Snowflake performs optimizations over tables automatically, which mitigates the need for manual user-made optimizations.
:force:-- ADD COLUMN DEFINITION formALTERTABLE table3
ADD column1 intNULL SPARSE;----------------------------------------/* It also applies to the other forms */------------------------------------------ CREATE TABLE formCREATETABLE table3
(
column1 INT SPARSE NULL);-- ALTER COLUMN formALTERTABLE table3
ALTERCOLUMN column1 INTNULL SPARSE;
:force:-- ADD COLUMN DEFINITION formALTERTABLEIFEXISTS table3
ALTERCOLUMN column1
!!!RESOLVE EWI!!!/*** SSC-EWI-TS0061 - ALTER COLUMN COMMENTED OUT BECAUSE SPARSE COLUMN IS NOT SUPPORTED IN SNOWFLAKE ***/!!!INTNULL SPARSE;----------------------------------------/* It also applies to the other forms */------------------------------------------ CREATE TABLE formCREATEORREPLACETABLE table3
(
column1 INT!!!RESOLVE EWI!!!/*** SSC-EWI-0040 - THE 'SPARSE COLUMN OPTION' CLAUSE IS NOT SUPPORTED IN SNOWFLAKE ***/!!!
SPARSE NULL)COMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}';-- ALTER COLUMN formALTERTABLEIFEXISTS table3
ALTERCOLUMN column1
!!!RESOLVE EWI!!!/*** SSC-EWI-TS0061 - ALTER COLUMN COMMENTED OUT BECAUSE SPARSE COLUMN IS NOT SUPPORTED IN SNOWFLAKE ***/!!!INTNULL SPARSE;
:force:
ALTERTABLEIFEXISTStable_nameADD column_name VARCHAR!!!RESOLVE EWI!!!/*** SSC-EWI-0040 - THE 'ROWGUIDCOL COLUMN OPTION' CLAUSE IS NOT SUPPORTED IN SNOWFLAKE ***/!!!
ROWGUIDCOL;
1. Roles and users have to be previously set up for masking policies
Snowflake’s Masking Policies can be applied to columns only after the policies were created. This requires the user to create the policies and assign them to roles, and these roles to users, to work properly. Masking Policies can behave differently depending on which user is querying.
Warning
SnowConvert AI does not perform this setup automatically.
2. Masking policies require a Snowflake Enterprise account or higher.
The Snowflake documentation states that masking policies are available on Enterprise or higher rank accounts.
SQL Server’s DEFAULT property is partially supported by Snowflake, as long as its associated value is a constant.
4.FILESTREAM clause is not supported in Snowflake.
The entire FILESTSTREAM clause is commented out, since it is not supported in Snowflake.
5.SPARSE clause is not supported in Snowflake.
The entire SPARSE clause is commented out, since it is not supported in Snowflake. When it is added within an ALTER COLUMN statement, and it’s the only modification being made to the column, the entire statement is removed since it’s no longer adding anything.
:force:
inlineFK:=[CONSTRAINT<constraint_name>][FOREIGNKEY]REFERENCES<ref_table_name>[(<ref_col_name>)][MATCH{FULL|SIMPLE|PARTIAL}][ON[UPDATE{CASCADE|SETNULL|SETDEFAULT|RESTRICT| NO ACTION }][DELETE{CASCADE|SETNULL|SETDEFAULT|RESTRICT| NO ACTION }]][[NOT]ENFORCED][[NOT]DEFERRABLE][INITIALLY{DEFERRED|IMMEDIATE}][ENABLE|DISABLE][VALIDATE|NOVALIDATE][RELY|NORELY]
:force:[FOREIGNKEY]REFERENCES<ref_table_name>[(<ref_col_name>)][MATCH{FULL|SIMPLE|PARTIAL}][ON[UPDATE{CASCADE|SETNULL|SETDEFAULT|RESTRICT| NO ACTION }][DELETE{CASCADE|SETNULL|SETDEFAULT|RESTRICT| NO ACTION }]][[NOT]ENFORCED][[NOT]DEFERRABLE][INITIALLY{DEFERRED|IMMEDIATE}][ENABLE|DISABLE][VALIDATE|NOVALIDATE][RELY|NORELY]
Notice that Snowflake logic does not support the CHECK clause in the creation of foreign keys. The WITH CHECK statement is marked as not supported. Besides, the WITH NO CHECK clause is removed because it is the default behavior in Snowflake and the equivalence is the same.
Please, review the following examples to have a better understanding of the translation.