2017-10-18 37 views
0

所以我需要重新创建一堆外键。原因是我想添加级联到密钥,并且为此我需要删除并重新创建密钥。当然,我可以通过右键单击密钥 - >修改 - >并添加级联来实现。 但我有索姆100键,我想在脚本中做到这一点。tsql得到fk_key规范

我有一个想法,我应该能够调用ssms中的方法,将该脚本的脚本脚本编写到新的查询编辑器中,而是将生成的脚本推送到变量中。放下现有的密钥。更新密钥的字符串表示形式,然后执行动态sql来创建它。

虽然我无法编写密钥脚本。 有谁知道如何做到这一点或有其他的方法吗?

回答

0

Aaron Bertrand的article描述了这一点,它将为您完成这项工作。

它动态创建@create@drop sql查询。您只需要更改创建脚本,让你在@create查询的这部分添加'on delete cascade'

FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') + ') 
ON DELETE CASCADE;' 

它会删除并重新创建你的数据库的每个表的每个外键。

确保在执行它们之前检查生成的查询。

你可以尝试一个工作版本here,Rextester已经有一个模式和一些表已经可以看到结果。

0

我已经脚本外键,并使用sys表来获取我需要重建该脚本的所有细节:

SELECT FK.[name] 
     -- 
     ,FK.[delete_referential_action_desc] 
     ,FK.[update_referential_action_desc] 
     -- 
     ,KC.[constraint_column_id] 
     ,PS.[name] 
     ,P.[name] 
     ,PTC.[name] 
     -- 
     ,RTS.[name] 
     ,RT.[name] 
     ,RTC.[name] 
FROM [sys].[foreign_keys] FK 
INNER JOIN [sys].[objects] P 
    ON FK.[parent_object_id] = P.[object_id] 
INNER JOIN [sys].[schemas] PS 
    ON P.[schema_id] = PS.[schema_id] 
INNER JOIN [sys].[foreign_key_columns] KC 
    ON FK.[object_id] = KC.[constraint_object_id] 
-- parent columns 
INNER JOIN [sys].[columns] PTC 
    ON P.[object_id] = PTC.[object_id] 
    AND KC.[parent_column_id] = PTC.[column_id] 
-- referenced table schema, name and columns 
INNER JOIN [sys].[objects] RT 
    ON KC.[referenced_object_id] = RT.[object_id] 
INNER JOIN [sys].[schemas] RTS 
    ON RT.[schema_id] = RTS.[schema_id] 
INNER JOIN [sys].[columns] RTC 
    ON RT.[object_id] = RTC.[object_id] 
    AND KC.[referenced_column_id] = RTC.[column_id]; 

这会给我甚至每个表的架构细节。现在,你可以使用这个T-SQL语句来做你想做的事情。请注意,我正在使用CTE来包装它,只是为了让这些东西更具可读性。此外,我们还有第二个CTE以处理外键由多列组成的情况。

WITH DataSource AS 
(
    SELECT FK.[name] AS [FK_Name] 
      -- 
      ,FK.[delete_referential_action_desc] 
      ,FK.[update_referential_action_desc] 
      -- 
      ,KC.[constraint_column_id] AS [FK_ColumnPos] 
      ,PS.[name] AS [PT_SCHEMA_NAME] 
      ,P.[name] AS [PT_NAME] 
      ,PTC.[name] AS [PT_COLUMN_NAME] 
      -- 
      ,RTS.[name] AS [RF_SCHEMA_NAME] 
      ,RT.[name] AS [RF_NAME] 
      ,RTC.[name] AS [RF_COLUMN_NAME] 
    FROM [sys].[foreign_keys] FK 
    INNER JOIN [sys].[objects] P 
     ON FK.[parent_object_id] = P.[object_id] 
    INNER JOIN [sys].[schemas] PS 
     ON P.[schema_id] = PS.[schema_id] 
    INNER JOIN [sys].[foreign_key_columns] KC 
     ON FK.[object_id] = KC.[constraint_object_id] 
    -- parent columns 
    INNER JOIN [sys].[columns] PTC 
     ON P.[object_id] = PTC.[object_id] 
     AND KC.[parent_column_id] = PTC.[column_id] 
    -- referenced table schema, name and columns 
    INNER JOIN [sys].[objects] RT 
     ON KC.[referenced_object_id] = RT.[object_id] 
    INNER JOIN [sys].[schemas] RTS 
     ON RT.[schema_id] = RTS.[schema_id] 
    INNER JOIN [sys].[columns] RTC 
     ON RT.[object_id] = RTC.[object_id] 
     AND KC.[referenced_column_id] = RTC.[column_id] 
), DataSourcePrecalc AS 
(
    SELECT DISTINCT 
      [FK_Name] 
      ,[delete_referential_action_desc] 
      ,[update_referential_action_desc] 
      ,[PT_SCHEMA_NAME] 
      ,[PT_NAME] 
      ,STUFF 
      (
       (
        SELECT ', [' + DS1.[PT_COLUMN_NAME] + ']' 
        FROM DataSource DS1 
        WHERE DS1.[FK_Name] = DS.[FK_Name] 
         AND DS1.[PT_NAME] = DS.[PT_NAME] 
        ORDER BY DS1.[FK_ColumnPos] 
        FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)') 
       ,1 
       ,2 
       ,'' 
     ) AS [PT_COLUMNS] 
      ,[RF_SCHEMA_NAME] 
      ,[RF_NAME] 
      ,STUFF 
      (
       (
        SELECT ', [' + DS2.[RF_COLUMN_NAME] + ']' 
        FROM DataSource DS2 
        WHERE DS2.[FK_Name] = DS.[FK_Name] 
         AND DS2.[RF_NAME] = DS.[RF_NAME] 
        ORDER BY DS2.[FK_ColumnPos] 
        FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)') 
       ,1 
       ,2 
       ,'' 
     ) AS [RT_COLUMNS] 
    FROM DataSource DS 
) 
SELECT 
' 
ALTER TABLE [' + [PT_SCHEMA_NAME] + '].[' + [PT_NAME] + '] DROP CONSTRAINT [' + [FK_Name] + ']; 

ALTER TABLE [' + [PT_SCHEMA_NAME] + '].[' + [PT_NAME] + '] WITH CHECK ADD CONSTRAINT [' + [FK_Name] + '] FOREIGN KEY(' + [PT_COLUMNS] + ') 
REFERENCES [' + [RF_SCHEMA_NAME] + '].[' + [RF_NAME] + '] (' + [RT_COLUMNS] + ') 
ON UPDATE CASCADE 
ON DELETE CASCADE; 

ALTER TABLE [' + [PT_SCHEMA_NAME] + '].[' + [PT_NAME] + '] CHECK CONSTRAINT [' + [FK_Name] + ']; 
' 
FROM DataSourcePrecalc; 

注意,这里的CASCADE值硬codded。你可以添加一些其他的逻辑,如果你想使用原来的。这里最重要的是最初的查询,它为我们带来了所有需要的细节。拥有它,你可以做任何你想做的事情。