【问题标题】:How can I drop a table if there is a foreign key constraint in SQL Server?如果 SQL Server 中存在外键约束,如何删除表?
【发布时间】:2013-02-27 08:23:31
【问题描述】:

我有以下几点:

DROP TABLE [dbo].[ExtraUserInformation];
DROP TABLE [dbo].[UserProfile];
DROP TABLE [dbo].[webpages_Membership];
DROP TABLE [dbo].[webpages_OAuthMembership];
DROP TABLE [dbo].[webpages_Roles];
DROP TABLE [dbo].[webpages_UsersInRoles];

CREATE TABLE [dbo].[ExtraUserInformation] (
    [Id]       INT            IDENTITY (1, 1) NOT NULL,
    [UserId]   INT            NOT NULL,
    [FullName] NVARCHAR (MAX) NULL,
    [Link]     NVARCHAR (MAX) NULL,
    [Verified] BIT            NULL,
    CONSTRAINT [PK_dbo.ExtraUserInformation] PRIMARY KEY CLUSTERED ([Id] ASC)
);

CREATE TABLE [dbo].[webpages_UsersInRoles] (
    [UserId] INT NOT NULL,
    [RoleId] INT NOT NULL,
    PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
    CONSTRAINT [fk_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserProfile] ([UserId]),
    CONSTRAINT [fk_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[webpages_Roles] ([RoleId])
);

但是这失败了,并显示一条消息:

Msg 3726, Level 16, State 1, Line 6
Could not drop object 'dbo.UserProfile' because it is referenced by a FOREIGN KEY constraint.
Msg 3726, Level 16, State 1, Line 9
Could not drop object 'dbo.webpages_Roles' because it is referenced by a FOREIGN KEY constraint.
Msg 2714, Level 16, State 6, Line 27
There is already an object named 'UserProfile' in the database.
Checking identity information: current identity value 'NULL', current column value 'NULL'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.

在这些情况下如何删除表?

【问题讨论】:

标签: sql-server


【解决方案1】:

您必须先删除约束,然后才能删除表。否则它的规则违规可能会破坏数据库的引用完整性。

如何获得外键关系请参阅这个老问题。 SQL DROP TABLE foreign key constraint

【讨论】:

    【解决方案2】:

    1-首先,在删除表之后删除外键约束。

    2-您可以通过执行以下查询来删除所有外键:

    DECLARE @SQL varchar(4000)=''
    SELECT @SQL = 
    @SQL + 'ALTER TABLE ' + s.name+'.'+t.name + ' DROP CONSTRAINT [' + RTRIM(f.name) +'];' + CHAR(13)
    FROM sys.Tables t
    INNER JOIN sys.foreign_keys f ON f.parent_object_id = t.object_id
    INNER JOIN sys.schemas     s ON s.schema_id = f.schema_id
    
    --EXEC (@SQL)
    
    PRINT @SQL
    

    如果你执行打印的结果@SQL,外键将被丢弃。

    【讨论】:

    • 这会生成 所有 DROP CONSTRAINT 语句,而不仅仅是“我们”关心的语句。
    【解决方案3】:

    删除包含外部约束的表的最佳答案是:

    • 步骤 1:删除表的主键。
    • 第二步:现在会提示是否删除所有的外引用。
    • 第 3 步:删除表。

    【讨论】:

    • 谢谢,这对我有用。我想要的只是运行脚本来更新数据库中的用户表,并且为了测试,我只想将用户表从实时复制到开发副本......不必复制整个 5gb 数据库。
    【解决方案4】:

    您必须在删除表之前删除约束。

    您可以使用这些查询来查找表中的所有 FK,并在使用您的表的表中查找 FK。

    Declare @SchemaName VarChar(200) = 'Your Schema name'
    Declare @TableName VarChar(200) = 'Your Table Name'
    
    -- Find FK in This table.
    SELECT 
        ' IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = 
    OBJECT_ID(N''' + 
          '[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + FK.name + ']'
    + ''') AND parent_object_id = OBJECT_ID(N''' + 
          '[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + 
    OBJECT_NAME(FK.parent_object_id) + ']' + ''')) ' +
    
        'ALTER TABLE ' +  OBJECT_SCHEMA_NAME(FK.parent_object_id) +
        '.[' + OBJECT_NAME(FK.parent_object_id) + 
        '] DROP CONSTRAINT ' + FK.name
        , S.name , O.name, OBJECT_NAME(FK.parent_object_id)
    FROM sys.foreign_keys AS FK
    INNER JOIN Sys.objects As O 
      ON (O.object_id = FK.parent_object_id )
    INNER JOIN SYS.schemas AS S 
      ON (O.schema_id = S.schema_id)  
    WHERE 
          O.name = @TableName
          And S.name = @SchemaName
    
    
    -- Find the FKs in the tables in which this table is used
      SELECT 
        ' IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id =   
          OBJECT_ID(N''' + 
          '[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + FK.name + ']'
      + ''') AND parent_object_id = OBJECT_ID(N''' + 
          '[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + 
     OBJECT_NAME(FK.parent_object_id) + ']' + ''')) ' +
    
        ' ALTER TABLE ' +  OBJECT_SCHEMA_NAME(FK.parent_object_id) +
        '.[' + OBJECT_NAME(FK.parent_object_id) + 
        '] DROP CONSTRAINT ' + FK.name
        , S.name , O.name, OBJECT_NAME(FK.parent_object_id)
    FROM sys.foreign_keys AS FK
    INNER JOIN Sys.objects As O 
      ON (O.object_id = FK.referenced_object_id )
    INNER JOIN SYS.schemas AS S 
      ON (O.schema_id = S.schema_id)  
    WHERE 
          O.name = @TableName
          And S.name = @SchemaName 
    

    【讨论】:

    • 程序很好!!
    • 这太疯狂了。我有一个表,它本身有一个外键约束(它自己的列引用另一个表)。当我发出删除表的命令时,SQL Server 真的应该在删除表之前删除该约束。深不可测,它无法处理。
    【解决方案5】:
        --Find and drop the constraints
    
        DECLARE @dynamicSQL VARCHAR(MAX)
        DECLARE MY_CURSOR CURSOR 
    
        LOCAL STATIC READ_ONLY FORWARD_ONLY 
        FOR
            SELECT dynamicSQL = 'ALTER TABLE [' +  OBJECT_SCHEMA_NAME(parent_object_id) + '].[' + OBJECT_NAME(parent_object_id) + '] DROP CONSTRAINT [' + name + ']'
            FROM sys.foreign_keys
            WHERE object_name(referenced_object_id)  in ('table1', 'table2', 'table3')
        OPEN MY_CURSOR
        FETCH NEXT FROM MY_CURSOR INTO @dynamicSQL
        WHILE @@FETCH_STATUS = 0
        BEGIN
    
            PRINT @dynamicSQL
            EXEC (@dynamicSQL)
    
            FETCH NEXT FROM MY_CURSOR INTO @dynamicSQL
        END
        CLOSE MY_CURSOR
        DEALLOCATE MY_CURSOR
    
    
        -- Drop tables
        DROP 'table1'
        DROP 'table2'
        DROP 'table3'
    

    【讨论】:

      【解决方案6】:

      BhupeshC and murat ,这就是我要找的。但是 @SQL varchar(4000) 还不够大。所以,小改变

      DECLARE @cmd varchar(4000)
      
      DECLARE MY_CURSOR CURSOR 
        LOCAL STATIC READ_ONLY FORWARD_ONLY
      FOR 
      
      select 'ALTER TABLE ['+s.name+'].['+t.name+'] DROP CONSTRAINT [' + RTRIM(f.name) +'];' FROM sys.Tables t INNER JOIN sys.foreign_keys f ON f.parent_object_id = t.object_id INNER JOIN sys.schemas s ON s.schema_id = f.schema_id
      
      OPEN MY_CURSOR
      FETCH NEXT FROM MY_CURSOR INTO @cmd
      WHILE @@FETCH_STATUS = 0
      BEGIN
          -- EXEC (@cmd)
          PRINT @cmd
          FETCH NEXT FROM MY_CURSOR INTO @cmd
      END
      CLOSE MY_CURSOR
      DEALLOCATE MY_CURSOR
      
      GO
      

      【讨论】:

        【解决方案7】:

        如果 MySQL 服务器中存在外键约束,则删除表?

        运行sql查询:

        SET FOREIGN_KEY_CHECKS = 0; DROP TABLE 表名

        希望对你有帮助!

        【讨论】:

        • 问题是关于 Microsoft SQL Server 而不是 MySQL
        • 虽然这个问题是关于 SQL Server 的,但我想在 MySQL 中做同样的事情,这个答案对我有帮助。
        【解决方案8】:

        重新删除约束并删除表,此脚本可以获取选定表列表的所有约束,然后删除约束,然后删除表。

        DECLARE @id INT
        DECLARE @strSQL NVARCHAR(max)
        DECLARE @deleteCurser CURSOR
        DECLARE @deleteTableCurser CURSOR
        
        
        
        declare @SelectedTables table ([name] sysname, [object_id] int)
        Insert into @SelectedTables ([name], [object_id])
        SELECT t.name, t.object_id 
        FROM sys.Tables t
        where t.name in
        -- Change Name of tables here
        ('table1','table2','table100')
        
        
        
        SET @deleteTableCurser = CURSOR FOR
        SELECT strSQL = 
        'ALTER TABLE ' + s.name+'.'+t.name + ' DROP CONSTRAINT [' + RTRIM(f.name) +'];'
        FROM @SelectedTables t
        INNER JOIN sys.foreign_keys f ON f.parent_object_id = t.object_id
        INNER JOIN sys.schemas     s ON s.schema_id = f.schema_id
        
        
        OPEN @deleteTableCurser
        FETCH Next 
        FROM @deleteTableCurser INTO @strSQL
        WHILE @@FETCH_STATUS = 0
        BEGIN
            print(@strSQL)
            EXEC (@strSQL)
            FETCH NEXT
            FROM @deleteTableCurser INTO @strSQL
        END
        
        CLOSE @deleteTableCurser
        DEALLOCATE @deleteTableCurser
        
        
        SET @deleteCurser = CURSOR FOR
        SELECT strSQL = 'DROP TABLE ['+ t.name+ '];'
        FROM @SelectedTables t
        
        OPEN @deleteCurser
        FETCH Next 
        FROM @deleteCurser INTO @strSQL
        WHILE @@FETCH_STATUS = 0
        BEGIN
            print(@strSQL)
            EXEC (@strSQL)
            FETCH NEXT
            FROM @deleteCurser INTO @strSQL
        END
        
        
        CLOSE @deleteCurser
        DEALLOCATE @deleteCurser
        

        【讨论】:

          【解决方案9】:

          输入这个....SET foreign_key_checks = 0;
          删除你的表然后输入SET foreign_key_checks = 1;

          MySQL – Temporarily disable Foreign Key Checks or Constraints

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-10-03
            • 1970-01-01
            • 1970-01-01
            • 2011-01-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多