Home  |  Articles  |  Scripts  |  Consultancy  |  FAQs  |  Links  |  SSIS

 
/*
Here we update all the FKs which don't currently have the NFR flag set.
This query returns the script to be run and it will only work for singleton PKs ie no composite keys
*/

IF Object_id('tempdb..#mysql') IS NOT NULL
  DROP TABLE #mysql

CREATE TABLE #mysql
  (
     id      INT,
     mainsql VARCHAR(8000)
  )

INSERT INTO #mysql
VALUES     (1,'Set XACT_ABORT ON')

INSERT INTO #mysql
VALUES     (5,'BEGIN TRAN')

INSERT INTO #mysql
SELECT 100,
       'ALTER TABLE ' + s.name + '.' + tabs1.name
       + ' DROP CONSTRAINT ' + fks.name
       + ';ALTER TABLE ' + s.name + '.' + tabs1.name
       + ' WITH CHECK ADD CONSTRAINT ' + fks.name
       + ' FOREIGN KEY('
       + Col_name(cols.parent_object_id, parent_column_id)
       + ') REFERENCES ' + s2.name + '.' + tabs2.name + '('
       + Col_name(cols.referenced_object_id, cols.referenced_column_id)
       + ') ' + CASE WHEN fks.delete_referential_action = 0 THEN
       ' ON DELETE NO ACTION ' WHEN fks.delete_referential_action = 1 THEN
       ' ON DELETE CASCADE ' WHEN fks.delete_referential_action = 2 THEN
       ' ON DELETE SET NULL ' WHEN fks.delete_referential_action = 3 THEN
       ' ON DELETE SET DEFAULT ' ELSE '' END + 
       CASE
 WHEN fks.update_referential_action = 0 THEN ' ON UPDATE NO ACTION ' 
            WHEN
 fks.update_referential_action = 1 THEN ' ON UPDATE CASCADE ' 
            WHEN
 fks.update_referential_action = 2 THEN ' ON UPDATE SET NULL ' 
            WHEN
 fks.update_referential_action = 3 THEN ' ON UPDATE SET DEFAULT ' 
            ELSE
 '' 
       END
 + ' NOT FOR REPLICATION'
FROM   sys.foreign_keys fks
       INNER JOIN sys.foreign_key_columns cols
               ON fks.object_id = cols.constraint_object_id
       INNER JOIN sys.tables tabs1
               ON fks.parent_object_id = tabs1.object_id
       INNER JOIN sys.schemas s
               ON tabs1.schema_id = s.schema_id
       INNER JOIN sys.tables tabs2
               ON cols.referenced_object_id = tabs2.object_id
       INNER JOIN sys.schemas s2
               ON tabs2.schema_id = s2.schema_id
WHERE  is_not_for_replication = 0
       AND tabs2.is_ms_shipped = 0
       AND cols.constraint_object_id NOT IN (SELECT constraint_object_id
                                             FROM   sys.foreign_key_columns
                                             GROUP  BY constraint_object_id
                                             HAVING
           Count(constraint_column_id) > 1)

INSERT INTO #mysql
VALUES     (1000,
            'COMMIT TRAN')

SELECT mainsql
FROM   #mysql
ORDER  BY id ASC 


/*
This is version 2 that deals with composite FKs
*/

DECLARE @schema_name SYSNAME ;
DECLARE
 @table_name SYSNAME ;
DECLARE
 @constraint_name SYSNAME ;
DECLARE @constraint_object_id INT ;
DECLARE @referenced_object_name SYSNAME ;
DECLARE
 @is_disabled BIT ;
DECLARE
 @is_not_for_replication BIT ;
DECLARE @is_not_trusted BIT ;
DECLARE @delete_referential_action TINYINT ;
DECLARE
 @update_referential_action TINYINT ;
DECLARE @tsql NVARCHAR(4000) ;
DECLARE
 @tsql2 NVARCHAR(4000) ;
DECLARE @fkCol SYSNAME ;
DECLARE @pkCol SYSNAME ;
DECLARE
 @col1 BIT ;
DECLARE
 @action CHAR(6) ;
DECLARE
 @referenced_schema_name SYSNAME ;

DECLARE FKcursor CURSOR
FOR
    SELECT  OBJECT_SCHEMA_NAME(parent_object_id) ,
            OBJECT_NAME(parent_object_id) ,
            name ,
            OBJECT_NAME(referenced_object_id) ,
            object_id ,
            is_disabled ,
            is_not_for_replication ,
            is_not_trusted ,
            delete_referential_action ,
            update_referential_action ,
            OBJECT_SCHEMA_NAME(referenced_object_id)
    FROM    sys.foreign_keys
    WHERE   is_not_for_replication = 0
    ORDER BY 1 ,2 ;OPEN FKcursor ;
    FETCH
 NEXT FROM FKcursor 
    INTO
 @schema_name, @table_name, @constraint_name,
    @referenced_object_name, @constraint_object_id, @is_disabled,
    @is_not_for_replication, @is_not_trusted, @delete_referential_action,
    @update_referential_action, @referenced_schema_name ;
 
WHILE @@FETCH_STATUS = 0
    BEGIN

        IF @action <> 'CREATE'
            SET @tsql = 'ALTER TABLE ' + QUOTENAME(@schema_name) + '.'
                + QUOTENAME(@table_name) + ' DROP CONSTRAINT '
                + QUOTENAME(@constraint_name) + ';' ;
         ELSE
            BEGIN
                SET @tsql = 'ALTER TABLE ' + QUOTENAME(@schema_name) + '.'
                    + QUOTENAME(@table_name) + ' DROP CONSTRAINT '
                    + QUOTENAME(@constraint_name) + ';' + 'ALTER TABLE '
                    + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name)
                    + CASE @is_not_trusted
                        WHEN 0 THEN ' WITH CHECK '
                        ELSE ' WITH NOCHECK '
                      END + ' ADD CONSTRAINT ' + QUOTENAME(@constraint_name)
                    + ' FOREIGN KEY (' ;
                 SET @tsql2 = '' ;
                 DECLARE ColumnCursor CURSOR FOR
                    SELECT  COL_NAME(fk.parent_object_id, fkc.parent_column_id) ,
                            COL_NAME(fk.referenced_object_id,
                                     fkc.referenced_column_id)
                    FROM    sys.foreign_keys fk
                            INNER JOIN sys.foreign_key_columns fkc 
                            ON
 fk.object_id = fkc.constraint_object_id
                    WHERE   fkc.constraint_object_id = @constraint_object_id
                    ORDER BY fkc.constraint_column_id ;
                 OPEN ColumnCursor ;
                SET @col1 = 1 ;
                 FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol ;
                 WHILE @@FETCH_STATUS = 0
                    BEGIN
                        IF ( @col1 = 1 ) ;
                            SET @col1 = 0 ;
                        ELSE
                            BEGIN
                               SET @tsql = @tsql + ','
                                SET @tsql2 = @tsql2 + ',' ;
                            END ;
                        SET @tsql = @tsql + QUOTENAME(@fkCol) ;
                        SET @tsql2 = @tsql2 + QUOTENAME(@pkCol) ;
                        FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol ;
                    END ;
                CLOSE ColumnCursor ;
 
                DEALLOCATE ColumnCursor ;
                 SET @tsql = @tsql + ' ) REFERENCES '
                    + QUOTENAME(@referenced_schema_name) + '.'
                    + QUOTENAME(@referenced_object_name) + ' (' + @tsql2 + ')' ;
                 SET @tsql = @tsql + ' ON UPDATE '
                    + CASE @update_referential_action
                        WHEN 0 THEN 'NO ACTION '
                        WHEN 1 THEN 'CASCADE '
                        WHEN 2 THEN 'SET NULL '
                        ELSE 'SET DEFAULT '
                      END + ' ON DELETE ' + CASE @delete_referential_action
                                              WHEN 0 THEN 'NO ACTION '
                                              WHEN 1 THEN 'CASCADE '
                                              WHEN 2 THEN 'SET NULL '
                                              ELSE 'SET DEFAULT '
                                            END
                    + CASE @is_not_for_replication
                        WHEN 1 THEN ' NOT FOR REPLICATION '
                        ELSE ' NOT FOR REPLICATION '
                      END + ';' ;
            END ;
        PRINT @tsql ;
 
        IF @action = 'CREATE'
            BEGIN
                SET @tsql = 'ALTER TABLE ' + QUOTENAME(@schema_name) + '.'
                    + QUOTENAME(@table_name) + CASE @is_disabled
                                                 WHEN 0 THEN ' CHECK '
                                                 ELSE ' NOCHECK '
                                               END + 'CONSTRAINT '
                    + QUOTENAME(@constraint_name) + ';' ;
                PRINT @tsql ;
            END ;

        FETCH NEXT FROM FKcursor INTO @schema_name, @table_name,
            @constraint_name, @referenced_object_name, @constraint_object_id,
            @is_disabled, @is_not_for_replication, @is_not_trusted,
            @delete_referential_action, @update_referential_action,
            @referenced_schema_name ;
    END ;
CLOSE FKcursor ;
DEALLOCATE FKcursor ;