2009-05-15 8 views
34

Ich habe eine SQL 2005-Datenbank mit ca. 250 Tabellen.SQL-Skript zum Ändern aller Fremdschlüssel zum Hinzufügen von ON DELETE CASCADE

Ich möchte ON DELETE CASCADE für alle Fremdschlüssel vorübergehend aktivieren, damit ich eine Massenlöschung problemlos durchführen kann.

Ich möchte dann ON DELETE CASCADE auf allen fremden Schlüsseln ausschalten.

Der einzige Weg, ich weiß, dies zu tun, ist Management Studio zu verwenden, um eine vollständige Datenbank erstellen Skript zu generieren, eine Art von Suche und Ersetzen alles andere als Fremdschlüssel Streifen aus, um das Skript speichern, tun dann etwas mehr suchen und Ersetzen, um die ON DELETE CASCADE hinzuzufügen.

Dann führe ich das Skript, mache mein Löschen, und dann das andere Skript ausführen.

Gibt es eine einfachere Möglichkeit, dieses Skript zu erstellen? Diese Methode scheint viel zu fehleranfällig zu sein, und ich muss das Skript mit allen anderen Änderungen, die wir an der Datenbank vornehmen, auf dem neuesten Stand halten oder es jedes Mal neu erzeugen, wenn ich es möglicherweise brauche.

Ist eine alternative Option, eine Auswahl auf den Systemtabellen auszuführen, um das Skript für mich zu "generieren"? Könnte es sogar möglich sein, ein Update für eine Systemtabelle auszuführen, die ON DELETE CASCADE aktiviert und deaktiviert?

Antwort

65

Hier ist ein Skript, das ich für einen ähnlichen Zweck verwendet habe. Es unterstützt keine zusammengesetzten Fremdschlüssel (die mehr als ein Feld verwenden). Und es würde wahrscheinlich einige Feinabstimmungen erfordern, bevor es für Ihre Situation funktioniert. EDIT: Insbesondere behandelt es mehrspaltige Fremdschlüssel nicht korrekt.

select 
    DropStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema + 
     '].[' + ForeignKeys.ForeignTableName + 
     '] DROP CONSTRAINT [' + ForeignKeys.ForeignKeyName + ']; ' 
, CreateStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema + 
     '].[' + ForeignKeys.ForeignTableName + 
     '] WITH CHECK ADD CONSTRAINT [' + ForeignKeys.ForeignKeyName + 
     '] FOREIGN KEY([' + ForeignKeys.ForeignTableColumn + 
     ']) REFERENCES [' + schema_name(sys.objects.schema_id) + '].[' + 
    sys.objects.[name] + ']([' + 
    sys.columns.[name] + ']) ON DELETE CASCADE; ' 
from sys.objects 
    inner join sys.columns 
    on (sys.columns.[object_id] = sys.objects.[object_id]) 
    inner join (
    select sys.foreign_keys.[name] as ForeignKeyName 
    ,schema_name(sys.objects.schema_id) as ForeignTableSchema 
    ,sys.objects.[name] as ForeignTableName 
    ,sys.columns.[name] as ForeignTableColumn 
    ,sys.foreign_keys.referenced_object_id as referenced_object_id 
    ,sys.foreign_key_columns.referenced_column_id as referenced_column_id 
    from sys.foreign_keys 
     inner join sys.foreign_key_columns 
     on (sys.foreign_key_columns.constraint_object_id 
      = sys.foreign_keys.[object_id]) 
     inner join sys.objects 
     on (sys.objects.[object_id] 
      = sys.foreign_keys.parent_object_id) 
     inner join sys.columns 
      on (sys.columns.[object_id] 
      = sys.objects.[object_id]) 
      and (sys.columns.column_id 
      = sys.foreign_key_columns.parent_column_id) 
    ) ForeignKeys 
    on (ForeignKeys.referenced_object_id = sys.objects.[object_id]) 
    and (ForeignKeys.referenced_column_id = sys.columns.column_id) 
where (sys.objects.[type] = 'U') 
    and (sys.objects.[name] not in ('sysdiagrams')) 
+3

Das ist eine verdammt nützliche Select-Anweisung. –

+0

Danke, hat super funktioniert. – rball

+5

* Tear * das ist ... so ... schön –

3

Du musst die Tabelle ändern, lassen Sie sie FK Einschränkungen und neu erstellen:

Dies ist db2-Syntax. SQLServer sollte

ALTER TABLE emp DROP CONSTRAINT fk_dept; 

ALTER TABLE emp ADD CONSTRAINT fk_dept 
FOREIGN KEY(dept_no) 
REFERENCES dept(deptno) 
ON DELETE CASCADE; 

Sie ähnlich sein können eigene sp schreiben die Systemtabelle für alle Fremdschlüssel abzufragen, lassen Sie sie und sie neu erstellen. Sie müssen dynamic sql in Ihrem sp verwenden, um dies zu tun, wo Sie das fk defn durchlaufen können, setzen Sie sie in einen varchar und append/edit, um CASCADE einzuschließen und dann stmt auszuführen.

0

Erstellen Sie eine neue gespeicherte Prozedur, wobei der einzige Parameter der Name der zu verarbeitenden Tabelle ist. In diesem Verfahren müssen Sie sys.foreign_keys und sys.foreign_key_columns überschleifen, um die richtige Drop- und Create-Syntax zu erstellen. Verwenden Sie dazu einfach einen Cursor und einige Ausdrucke (KISS).

Aufruf dieses Verfahren mit der Syntax:

EXEC sp_msforeachtable 'YourProcedureName ''?''' 

und es wird für jede Tabelle laufen. Nehmen Sie die Ausgabe und führen Sie sie aus, und Sie sind fertig.

+0

Zum Glück alle anderen nahm dann die Zeit vorschlagen _how_ dies könnte gebaut werden. –

11

Andomar Antwort oben ist gut, aber funktioniert für einspaltig Fremd nur Schlüssel-Constraints. Ich passte es ein wenig für mehrspaltige Einschränkungen:

create function dbo.fk_columns (@constraint_object_id int) 
returns varchar(255) 
as begin 
declare @r varchar(255) 
select @r = coalesce(@r + ',', '') + c.name 
from sys.foreign_key_columns fkc 
join sys.columns c 
    on fkc.parent_object_id = c.object_id 
    and fkc.parent_column_id = c.column_id 
where fkc.constraint_object_id = @constraint_object_id 
return @r 
end 

select distinct 
    DropStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema + 
     '].[' + ForeignKeys.ForeignTableName + 
     '] DROP CONSTRAINT [' + ForeignKeys.ForeignKeyName + '] ' 
, CreateStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema + 
    '].[' + ForeignKeys.ForeignTableName + 
    '] WITH CHECK ADD CONSTRAINT [' + ForeignKeys.ForeignKeyName + 
    '] FOREIGN KEY(' + dbo.fk_columns(constraint_object_id) + ')' + 
    'REFERENCES [' + schema_name(sys.objects.schema_id) + '].[' + 
    sys.objects.[name] + '] ' 
    + ' ON DELETE CASCADE' 
from sys.objects 
    inner join sys.columns 
    on (sys.columns.[object_id] = sys.objects.[object_id]) 
    inner join (
select sys.foreign_keys.[name] as ForeignKeyName 
,schema_name(sys.objects.schema_id) as ForeignTableSchema 
,sys.objects.[name] as ForeignTableName 
,sys.columns.[name] as ForeignTableColumn 
,sys.foreign_keys.referenced_object_id as referenced_object_id 
,sys.foreign_key_columns.referenced_column_id as referenced_column_id 
,sys.foreign_keys.object_id as constraint_object_id 
from sys.foreign_keys 
    inner join sys.foreign_key_columns 
    on (sys.foreign_key_columns.constraint_object_id 
     = sys.foreign_keys.[object_id]) 
    inner join sys.objects 
    on (sys.objects.[object_id] 
     = sys.foreign_keys.parent_object_id) 
    inner join sys.columns 
     on (sys.columns.[object_id] 
     = sys.objects.[object_id]) 
     and (sys.columns.column_id 
     = sys.foreign_key_columns.parent_column_id) 
-- Uncomment this if you want to include only FKs that already 
-- have a cascade constraint. 
--  where (delete_referential_action_desc = 'CASCADE' or update_referential_action_desc = 'CASCADE') 
) ForeignKeys 
on (ForeignKeys.referenced_object_id = sys.objects.[object_id]) 
and (ForeignKeys.referenced_column_id = sys.columns.column_id) 
where (sys.objects.[type] = 'U') 
    and (sys.objects.[name] not in ('sysdiagrams')) 

Sie auch die Abfrage verwenden können entfernenON DELETE CASCADE von FKs zu helfen, die derzeit es haben.

Dies behandelt immer noch nicht den Fall, wo die Spalten unterschiedliche Dinge in den beiden Tabellen benannt werden - eine andere benutzerdefinierte Funktion müsste dafür definiert werden.

+0

Genie, reines Genie. –

1

Die Antwort von @Andomar funktionierte für mich, aber es war ein bisschen manuell - Sie müssen es ausführen, dann kopieren Sie die Ergebnisse und führen Sie sie aus. Ich musste dies als Teil meines automatisierten Test-Setups verwenden und benötigte es daher, um in einer Abfrage automatisch zu laufen.

Ich habe mit dem folgenden kommen, die alle SQL bekommt zu laufen, um die Fremdschlüssel-Constraints zu ändern, dann läuft es eigentlich alles in einem Rutsch:

IF Object_id('tempdb..#queriesForContraints') IS NOT NULL 
     BEGIN 
      DROP TABLE #queriesForContraints 
     END 

    DECLARE @ignoreTablesCommaSeparated VARCHAR(1000) 

    SELECT 'ALTER TABLE [' 
      + ForeignKeys.foreigntableschema + '].[' 
      + ForeignKeys.foreigntablename 
      + '] DROP CONSTRAINT [' 
      + ForeignKeys.foreignkeyname + ']; ' 
      + 'ALTER TABLE [' 
      + ForeignKeys.foreigntableschema + '].[' 
      + ForeignKeys.foreigntablename 
      + '] WITH CHECK ADD CONSTRAINT [' 
      + ForeignKeys.foreignkeyname 
      + '] FOREIGN KEY([' 
      + ForeignKeys.foreigntablecolumn 
      + ']) REFERENCES [' 
      + Schema_name(sys.objects.schema_id) + '].[' 
      + sys.objects.[name] + ']([' 
      + sys.columns.[name] 
      + ']) ON DELETE CASCADE; ' AS query 
    INTO #queriesForContraints 
    FROM sys.objects 
      INNER JOIN sys.columns 
        ON (sys.columns.[object_id] = sys.objects.[object_id]) 
      INNER JOIN (SELECT sys.foreign_keys.[name]      AS 
           ForeignKeyName, 
           Schema_name(sys.objects.schema_id)   AS 
        ForeignTableSchema, 
           sys.objects.[name]       AS 
        ForeignTableName, 
           sys.columns.[name]       AS 
        ForeignTableColumn, 
           sys.foreign_keys.referenced_object_id  AS 
        referenced_object_id, 
           sys.foreign_key_columns.referenced_column_id AS 
        referenced_column_id 
         FROM sys.foreign_keys 
           INNER JOIN sys.foreign_key_columns 
             ON ( 
           sys.foreign_key_columns.constraint_object_id = 
           sys.foreign_keys.[object_id]) 
           INNER JOIN sys.objects 
             ON (sys.objects.[object_id] = 
             sys.foreign_keys.parent_object_id) 
           INNER JOIN sys.columns 
             ON (sys.columns.[object_id] = 
              sys.objects.[object_id]) 
             AND (sys.columns.column_id = 
    sys.foreign_key_columns.parent_column_id)) 
    ForeignKeys 
    ON (ForeignKeys.referenced_object_id = sys.objects.[object_id]) 
    AND (ForeignKeys.referenced_column_id = sys.columns.column_id) 
    WHERE (sys.objects.[type] = 'U') 
      AND (sys.objects.[name] NOT IN ( 
       'sysdiagrams' --add more comma separated table names here if required 
      )) 

    DECLARE @queryToRun NVARCHAR(MAX) 

    SELECT @queryToRun = STUFF(
      (SELECT query + '' 
      FROM #queriesForContraints 
      FOR XML PATH ('')) 
     , 1, 0, '') 

    EXEC sp_executesql @statement = @queryToRun 

    IF Object_id('tempdb..#queriesForContraints') IS NOT NULL 
     BEGIN 
      DROP TABLE #queriesForContraints 
     END 
4

Weitere Standards konforme Lösung:

;WITH CTE AS 
(
    SELECT 
     KCU1.CONSTRAINT_NAME AS FK_CONSTRAINT_NAME 
     ,KCU1.TABLE_SCHEMA AS FK_SCHEMA_NAME 
     ,KCU1.TABLE_NAME AS FK_TABLE_NAME 
     ,KCU1.COLUMN_NAME AS FK_COLUMN_NAME 
     ,KCU1.ORDINAL_POSITION AS FK_ORDINAL_POSITION 
     ,KCU2.CONSTRAINT_NAME AS REFERENCED_CONSTRAINT_NAME 
     ,KCU2.TABLE_SCHEMA AS REFERENCED_SCHEMA_NAME 
     ,KCU2.TABLE_NAME AS REFERENCED_TABLE_NAME 
     ,KCU2.COLUMN_NAME AS REFERENCED_COLUMN_NAME 
     ,KCU2.ORDINAL_POSITION AS REFERENCED_ORDINAL_POSITION 
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC 

    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU1 
     ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG 
     AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA 
     AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME 

    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2 
     ON KCU2.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG 
     AND KCU2.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA 
     AND KCU2.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME 
     AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION 
) 


SELECT 
    FK_CONSTRAINT_NAME 
    --,FK_SCHEMA_NAME 
    --,FK_TABLE_NAME 
    --,FK_COLUMN_NAME 
    --,FK_ORDINAL_POSITION 
    --,REFERENCED_CONSTRAINT_NAME 
    --,REFERENCED_SCHEMA_NAME 
    --,REFERENCED_TABLE_NAME 
    --,REFERENCED_COLUMN_NAME 
    --,REFERENCED_ORDINAL_POSITION 

    , 
     'ALTER TABLE [' + FK_SCHEMA_NAME + ']' 
     + '.[' + FK_TABLE_NAME + '] ' 
     + 'DROP CONSTRAINT [' + FK_CONSTRAINT_NAME + ']; ' 
    AS DropStmt 

    , 
    'ALTER TABLE [' + FK_SCHEMA_NAME + ']' 
     + '.[' + FK_TABLE_NAME + '] ' + 
     + 'WITH CHECK ADD CONSTRAINT [' + FK_CONSTRAINT_NAME + '] ' 
     + 'FOREIGN KEY([' + FK_COLUMN_NAME + ']) ' 
     + 'REFERENCES [' + REFERENCED_SCHEMA_NAME + '].[' + REFERENCED_TABLE_NAME + ']([' + REFERENCED_COLUMN_NAME + ']) ON DELETE CASCADE; ' 
    AS CreateStmt 

FROM CTE 

WHERE (1=1) 
/* 
AND FK_TABLE_NAME IN 
(
    'T_SYS_Geschossrechte' 
    ,'T_SYS_Gebaeuderechte' 
    ,'T_SYS_Standortrechte' 
) 

AND REFERENCED_TABLE_NAME NOT LIKE 'T_AP_Ref_Mandant' 
*/ 

ORDER BY 
    FK_TABLE_NAME 
    ,FK_CONSTRAINT_NAME 
    ,FK_COLUMN_NAME 
    ,FK_ORDINAL_POSITION 
    ,REFERENCED_CONSTRAINT_NAME 
    ,REFERENCED_TABLE_NAME 
    ,REFERENCED_COLUMN_NAME 
    ,REFERENCED_ORDINAL_POSITION 

Edit:
Erweiterte für mehrspaltigen Fremdschlüssel:

;WITH CTE AS 
( 
    SELECT 
     KCU1.CONSTRAINT_NAME AS FK_CONSTRAINT_NAME 
     ,KCU1.TABLE_SCHEMA AS FK_SCHEMA_NAME 
     ,KCU1.TABLE_NAME AS FK_TABLE_NAME 
     ,KCU1.COLUMN_NAME AS FK_COLUMN_NAME 
     ,KCU1.ORDINAL_POSITION AS FK_ORDINAL_POSITION 
     ,KCU2.CONSTRAINT_NAME AS REFERENCED_CONSTRAINT_NAME 
     ,KCU2.TABLE_SCHEMA AS REFERENCED_SCHEMA_NAME 
     ,KCU2.TABLE_NAME AS REFERENCED_TABLE_NAME 
     ,KCU2.COLUMN_NAME AS REFERENCED_COLUMN_NAME 
     ,KCU2.ORDINAL_POSITION AS REFERENCED_ORDINAL_POSITION 
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC 

    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU1 
     ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG 
     AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA 
     AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME 

    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2 
     ON KCU2.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG 
     AND KCU2.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA 
     AND KCU2.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME 
     AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION 
) 
SELECT 
    FK_SCHEMA_NAME 
    ,FK_TABLE_NAME 
    ,FK_CONSTRAINT_NAME 
    --,FK_COLUMN_NAME 
    --,REFERENCED_COLUMN_NAME 



    , 
    'ALTER TABLE ' + QUOTENAME(FK_SCHEMA_NAME) + '.' + QUOTENAME(FK_TABLE_NAME) + ' ' 
     + 'DROP CONSTRAINT ' + QUOTENAME(FK_CONSTRAINT_NAME) + '; ' 
    AS DropStmt 

    , 
    'ALTER TABLE ' + QUOTENAME(FK_SCHEMA_NAME) + '.' + QUOTENAME(FK_TABLE_NAME) + ' 
    ADD CONSTRAINT ' + QUOTENAME(FK_CONSTRAINT_NAME) + ' 
    FOREIGN KEY(' 
    + 
     SUBSTRING 
     ( 
      (
       SELECT ', ' + QUOTENAME(FK.FK_COLUMN_NAME) AS [text()] 
       FROM CTE AS FK 
       WHERE FK.FK_CONSTRAINT_NAME = CTE.FK_CONSTRAINT_NAME 
       AND FK.FK_SCHEMA_NAME = CTE.FK_SCHEMA_NAME 
       AND FK.FK_TABLE_NAME = CTE.FK_TABLE_NAME 
       FOR XML PATH, TYPE 
      ).value('.[1]', 'nvarchar(MAX)') 
      ,3, 4000 
     ) 
    + ') 
' 
    + ' REFERENCES ' + QUOTENAME(REFERENCED_SCHEMA_NAME) + '.' + QUOTENAME(REFERENCED_TABLE_NAME) + '(' 
    + SUBSTRING 
     ( 
      (
       SELECT ', ' + QUOTENAME(Referenced.REFERENCED_COLUMN_NAME) AS [text()] 
       FROM CTE AS Referenced 
       WHERE Referenced.FK_CONSTRAINT_NAME = CTE.FK_CONSTRAINT_NAME 
       AND Referenced.REFERENCED_SCHEMA_NAME = CTE.REFERENCED_SCHEMA_NAME 
       AND Referenced.REFERENCED_TABLE_NAME = CTE.REFERENCED_TABLE_NAME 
       FOR XML PATH, TYPE 
     ).value('.[1]', 'nvarchar(MAX)') 
      , 3, 4000 
    ) 
    + ') 
    ON DELETE CASCADE 
; ' AS CreateStmt 

FROM CTE 

GROUP BY 
    FK_SCHEMA_NAME 
    ,FK_TABLE_NAME 
    ,FK_CONSTRAINT_NAME 

    ,REFERENCED_SCHEMA_NAME 
    ,REFERENCED_TABLE_NAME 

Und die weit einfachere Version für PostGreSQL:

;WITH CTE AS 
( 
    SELECT 
     KCU1.CONSTRAINT_NAME AS FK_CONSTRAINT_NAME 
     ,KCU1.TABLE_SCHEMA AS FK_SCHEMA_NAME 
     ,KCU1.TABLE_NAME AS FK_TABLE_NAME 
     ,KCU1.COLUMN_NAME AS FK_COLUMN_NAME 
     ,KCU1.ORDINAL_POSITION AS FK_ORDINAL_POSITION 
     ,KCU2.CONSTRAINT_NAME AS REFERENCED_CONSTRAINT_NAME 
     ,KCU2.TABLE_SCHEMA AS REFERENCED_SCHEMA_NAME 
     ,KCU2.TABLE_NAME AS REFERENCED_TABLE_NAME 
     ,KCU2.COLUMN_NAME AS REFERENCED_COLUMN_NAME 
     ,KCU2.ORDINAL_POSITION AS REFERENCED_ORDINAL_POSITION 
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC 

    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU1 
     ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG 
     AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA 
     AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME 

    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2 
     ON KCU2.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG 
     AND KCU2.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA 
     AND KCU2.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME 
     AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION 
) 
SELECT 
    FK_SCHEMA_NAME 
    ,FK_TABLE_NAME 
    ,FK_CONSTRAINT_NAME 
    --,FK_COLUMN_NAME 
    --,REFERENCED_COLUMN_NAME 



    , 
    'ALTER TABLE ' || QUOTE_IDENT(FK_SCHEMA_NAME) || '.' || QUOTE_IDENT(FK_TABLE_NAME) || ' ' 
     || 'DROP CONSTRAINT ' || QUOTE_IDENT(FK_CONSTRAINT_NAME) || '; ' 
    AS DropStmt 

    , 
    'ALTER TABLE ' || QUOTE_IDENT(FK_SCHEMA_NAME) || '.' || QUOTE_IDENT(FK_TABLE_NAME) || ' 
    ADD CONSTRAINT ' || QUOTE_IDENT(FK_CONSTRAINT_NAME) || ' 
    FOREIGN KEY(' || string_agg(FK_COLUMN_NAME, ', ') || ') 
' 
    || ' REFERENCES ' || QUOTE_IDENT(REFERENCED_SCHEMA_NAME) || '.' || QUOTE_IDENT(REFERENCED_TABLE_NAME) || '(' || string_agg(REFERENCED_COLUMN_NAME, ', ') || ') 
    ON DELETE CASCADE 
; ' AS CreateStmt 

FROM CTE 

GROUP BY 
    FK_SCHEMA_NAME 
    ,FK_TABLE_NAME 
    ,FK_CONSTRAINT_NAME 

    ,REFERENCED_SCHEMA_NAME 
    ,REFERENCED_TABLE_NAME 
+0

upvoted für _wayyy_ nicer (d. H. Tatsächlich lesbare) Syntax als die verblüffende "select", Nicht-ANSI-Monstrositäten oben. _Wie auch immer _... das geht auch nicht mit zusammengesetzten Schlüsseln um: es gibt uns _n_ separate 'add constraint' Anweisungen für jede Mitgliedsspalte, anstatt den richtigen' tableName (Liste, von, Spalten) '. Ich benutze zusammengesetzte Schlüssel. Also, meine nächste Mission ist es, Ihr Skript zu nehmen und es zu beheben, um dies zu berücksichtigen. Wenn ich das tue, lasse ich es Sie wissen! –

+0

@underscore_d: In PostGre können Sie eine Gruppe nach FK_SCHEMA_Name, FK_TABLE_NAME, FK_COLUMN_NAME und dann string_agg (FK_COLUMN_NAME, ','); Auf SQL-Server müssen Sie String-Aggregation als CLR-Funktion hinzufügen, oder es wird mit XML-Pfad viel hässlicher ... –

+0

@underscore_d: Multi-Column wird jetzt unterstützt. Ich verstehe immer noch nicht, warum jemand mehrspaltige Fremdschlüssel benötigt (da sie nur auf eine Tabelle verweisen können, nicht auf mehrere Tabellen, sonst wäre es sinnvoll). –

Verwandte Themen