sql >> Databasteknik >  >> RDS >> Sqlserver

NOCHECK inaktiverar inte referenser för främmande nyckel

Jag använde följande två skript för att inaktivera främmande nycklar. Jag har inte skapat dem, jag hittade dem på interwebs, men de fungerade perfekt för mig de senaste åren. Tyvärr kan jag inte hitta källan till dem längre.

references_sp.sql är en lagrad procedur som måste skapas innan det andra skriptet körs.

references_run.sql är ett skript som genererar ett skript för att inaktivera/aktivera främmande nycklar.

Observera att det är säkert att köra skriptet som tillhandahålls här - det ändrar inte databasen (förutom att skapa och sedan ta bort tillfälliga tabeller) det genererar bara ett annat skript som släpper och återskapar de främmande nycklarna.

Och nu skripten.

references_sp.sql:

USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

/*********************************************************************************************
Copyright SQLServerNation.com
*  Author:  Tim Chapman
***********************************************************************************************/
CREATE PROCEDURE [dbo].[sp_ShowForeignKeyObjects]
AS
    SELECT 
        OBJECT_NAME(constid) AS ConstraintName,
        OBJECT_SCHEMA_NAME(fkeyid) + '.' + OBJECT_NAME(fkeyid) + '.' + COL_NAME(fkeyid, fkey) AS ForeignKeyObject,
        OBJECT_SCHEMA_NAME(rkeyid) + '.' + OBJECT_NAME(rkeyid) + '.' + COL_NAME(rkeyid, rkey) AS ReferenceKeyObject, 
        COL_NAME(fkeyid, fkey) AS ForeignKeyColumn,
        COL_NAME(rkeyid, rkey) AS ReferenceKeyColumn, 
        constid AS ConstraintID, 
        OBJECT_SCHEMA_NAME(fkeyid) + '.' + OBJECT_NAME(fkeyid) AS ForeignKeyTable,         
        fkeyid AS ForeignKeyID, 
        OBJECT_SCHEMA_NAME(rkeyid) + '.' + OBJECT_NAME(rkeyid) AS ReferenceKeyTable,
        rkeyid AS ReferenceKeyID,
        keyno AS KeySequenceNumber
    FROM 
        sysforeignkeys
    ORDER BY 
        OBJECT_NAME(rkeyid) ASC, COL_NAME(rkeyid, rkey)

GO

references_run.sql:

IF OBJECT_ID('tempdb..#FK')>0
  DROP TABLE #FK

IF OBJECT_ID('tempdb..#Const')>0
  DROP TABLE #Const

CREATE TABLE #FK
(
  ConstraintName VARCHAR(255),
  ForeignKeyObject VARCHAR(255),
  ReferenceObject VARCHAR(255),
  ForeignKeyColumn VARCHAR(255),
  ReferenceKeyColumn VARCHAR(255),
  ConstraintID INT, 
  ForeignKeyTable VARCHAR(255),
  ForeignKeyID INT, 
  ReferenceKeyTable VARCHAR(255),
  ReferenceKeyID INT, 
  KeySequenceNumber SMALLINT
)

CREATE TABLE #Const
(
  ConstraintID INT, 
  FBuildField VARCHAR(2000) DEFAULT(''), 
  RBuildField VARCHAR(2000) DEFAULT(''), 
  CountField SMALLINT 
)

INSERT INTO #FK
EXEC sp_Showforeignkeyobjects

SET NOCOUNT ON
DECLARE  tempcursor
CURSOR
READ_ONLY
FOR 

  SELECT    
    f.ConstraintName ,
    f.ForeignKeyObject ,
    f.ReferenceObject ,
    f.ForeignKeyColumn ,
    f.ReferenceKeyColumn,
    f.ConstraintID , 
    f.ForeignKeyID , 
    f.ReferenceKeyID , 
    f.KeySequenceNumber, 
    f.ForeignKeyTable,
    f.ReferenceKeyTable 
  FROM #FK AS  f
    INNER JOIN 
    (
      SELECT ConstraintID, MAX(KeySequenceNumber) AS MaxSeq
      FROM #FK AS  k
      GROUP BY k.ConstraintID
    )b ON f.ConstraintID = b.ConstraintID AND f.KeySequenceNumber = b.MaxSeq

DECLARE 
  @ConstraintName VARCHAR(255),
  @ForeignKeyObject VARCHAR(255),
  @ReferenceObject VARCHAR(255),
  @ForeignKeyColumn VARCHAR(255),
  @ReferenceKeyColumn VARCHAR(255),
  @ConstraintID INT, 
  @ForeignKeyID INT, 
  @ReferenceKeyID INT, 
  @KeySequenceNumber SMALLINT, 
  @ForeignKeyTable VARCHAR(255),
  @ReferenceKeyTable VARCHAR(255)

OPEN tempcursor

  FETCH NEXT FROM tempCursor INTO 
  @ConstraintName ,
  @ForeignKeyObject ,
  @ReferenceObject ,
  @ForeignKeyColumn ,
  @ReferenceKeyColumn,
  @ConstraintID , 
  @ForeignKeyID , 
  @ReferenceKeyID, 
  @KeySequenceNumber,
  @ForeignKeyTable ,
  @ReferenceKeyTable 

WHILE (@@fetch_status <> -1)
BEGIN

  DECLARE  tempcursor2
  CURSOR
  READ_ONLY
  FOR 

    SELECT ConstraintID, ForeignKeyColumn, ReferenceKeyColumn, KeySequenceNumber 
    FROM #FK 
    WHERE ConstraintID = @ConstraintID

    ORDER BY ConstraintID, KeySequenceNumber ASC

  DECLARE @ConstraintID2 INT, @ForeignKeyColumn2 VARCHAR(255), @ReferenceKeyColumn2 VARCHAR(255), @KeySequenceNumber2 SMALLINT
  DECLARE @FKeyBuildField VARCHAR(1000), @RKeyBuildField VARCHAR(1000), @Cnt SMALLINT 

  OPEN tempcursor2

  SELECT @FKeyBuildField = '', @RKeyBuildField = '', @Cnt = 0

  FETCH NEXT FROM tempcursor2 INTO @ConstraintID2 , @ForeignKeyColumn2 , @ReferenceKeyColumn2 , @KeySequenceNumber2
  WHILE (@@fetch_status <> -1)
  BEGIN
    SET @Cnt = @Cnt + 1
    SELECT @FKeyBuildField = @FKeyBuildField  + ISNULL(@ForeignKeyColumn2,'')+ 
      CASE 
        WHEN @ForeignKeyColumn2 IS NULL THEN '' 
      ELSE  
        CASE WHEN @KeySequenceNumber = @KeySequenceNumber2 THEN '' ELSE ',' END
      END

    SELECT @RKeyBuildField = @RKeyBuildField  + ISNULL(@ReferenceKeyColumn2,'')+ 
      CASE 
        WHEN @ReferenceKeyColumn2 IS NULL THEN '' 
      ELSE  
        CASE WHEN @KeySequenceNumber = @KeySequenceNumber2 THEN '' ELSE ',' END
      END

    INSERT INTO #Const
    (   
      ConstraintID , 
      FBuildField , 
      RBuildField, 
      CountField  
    )
    VALUES
    (
      @ConstraintID, 
      @FKeyBuildField,
      @RKeyBuildField,
      @Cnt
    )

    FETCH NEXT FROM tempcursor2 INTO @ConstraintID2 , @ForeignKeyColumn2 , @ReferenceKeyColumn2 , @KeySequenceNumber2
  END
  CLOSE tempcursor2
  DEALLOCATE tempcursor2

  FETCH NEXT FROM tempCursor INTO 
  @ConstraintName ,
  @ForeignKeyObject ,
  @ReferenceObject ,
  @ForeignKeyColumn ,
  @ReferenceKeyColumn,
  @ConstraintID , 
  @ForeignKeyID , 
  @ReferenceKeyID , 
  @KeySequenceNumber ,
  @ForeignKeyTable ,
  @ReferenceKeyTable 
END

CLOSE tempcursor
DEALLOCATE tempcursor

SELECT 'ALTER TABLE ' + FKTable + ' DROP CONSTRAINT ' + OBJECT_NAME(a.ConstraintID) AS DropKeys,
'ALTER TABLE ' + FKTable + ' WITH NOCHECK ADD CONSTRAINT ' + OBJECT_NAME(a.ConstraintID) + ' FOREIGN KEY(' + FBuildField + ') REFERENCES ' + RKTable + '(' + RBuildField+')' AS BuildKeys
,*
FROM #Const a
JOIN
(
  SELECT ConstraintID, MAX(countfield) AS maxcount
  FROM #Const
  GROUP BY ConstraintID
) b ON a.ConstraintID = b.ConstraintID  AND a.countfield = b.maxcount
JOIN
(
SELECT DISTINCT constraintid, '[' + OBJECT_SCHEMA_NAME(foreignkeyid) + '].[' + OBJECT_NAME(foreignkeyid) + ']' AS FKTable, '[' + OBJECT_SCHEMA_NAME(referencekeyid) + '].[' + OBJECT_NAME(referencekeyid) + ']' AS RKTable FROM #fk
) c ON a.constraintid = c.constraintid

DROP TABLE #Const



  1. Finns det en MySQL-motsvarighet till PHPs preg_replace?

  2. rätt syntax att använda nära '?'

  3. hur man löser Allmänt fel:2014 Kan inte köra frågor medan andra obuffrade frågor är aktiva. använder PDO-anslutning

  4. MYSQL LEFT JOIN MED GROUP BY