【问题标题】:Removing All Primary Keys删除所有主键
【发布时间】:2011-01-21 05:12:45
【问题描述】:

这听起来像是一个疯狂的请求。我报告的数据库没有任何外键,每个主键都是一个身份列。这使得使用 TOAD 等工具变得困难,因为 Intellisense 通过读取 PK 和 FK 关系来工作。

任何人都有一个脚本可以从数据库中的每个表中删除主键,以便我可以用“正确”的 PK 替换它们并添加 FK 以帮助报告?

为了阻止“不要这样做!!!”的雪崩回复,让我明确表示我不会对我的生产数据库执行此操作,而是将其复制到另一台服务器上。

任何建议将不胜感激。

------- 编辑这是用正确的信息更新的。 ----------------

谢谢大家,但我意识到我犯了一个错误。几乎每个表都有一个具有标识属性的“identity_column”。该标识是一个聚集索引。但是,它没有被指定为主键。

首先,主键和聚集索引有什么区别?

其次,如何编写出所有聚集索引的脚本? 这行得通吗?

SELECT 
  'ALTER TABLE ' + OBJECT_NAME(OBJECT_ID) + ' DROP CONSTRAINT ' + name 
FROM sys.indexes WHERE type_desc = 'CLUSTERED'

感谢您的耐心等待

【问题讨论】:

  • 为什么要删除聚集索引?这将导致对每一行进行完全重写!
  • 我的问题是这个。我的数据库没有主键,只有聚集索引。我正在编写一个脚本来获取数据库的报告副本,并将适当的 PK 和 FK 关系放入其中,以促进 TOAD 和 SSRS 的报告。由于这会在停机期间发生,并且我将在总表的一小部分上执行它,因此我认为性能损失并不重要。

标签: tsql sql-server-2000 constraints information-schema


【解决方案1】:

另一种选择是两步过程:

  1. 首先,从系统目录视图中选择必要的信息,并使用这些信息来构建您需要实际删除索引和约束的 T-SQL 语句:

    SELECT
      'ALTER TABLE ' + OBJECT_NAME(OBJECT_ID) + ' DROP CONSTRAINT ' + name
    FROM sys.indexes WHERE is_primary_key = 1
    
  2. 使用该结果集,将其复制并粘贴到新的查询窗口中,然后运行它 - 它会从您在其中运行它的数据库中的所有表中删除所有主键约束

    李>

这样您就可以避开光标,并获得一个要执行的语句列表,如果您不需要它,您仍然可以“按原样”使用、调整甚至完全丢弃它。

【讨论】:

  • 这行得通,但我意识到我犯了一个错误。我会在上面解释。
  • 这行得通吗? SELECT 'ALTER TABLE ' + OBJECT_NAME(OBJECT_ID) + ' DROP CONSTRAINT ' + name FROM sys.indexes WHERE type_desc = 'CLUSTERED'
  • 是的,但这会为您提供 聚集 索引 - 这些索引不一定与表上的 主键 相同。但是,如果这就是您所追求的,删除所有聚集索引,那么是的,这将创建 ALTER TABLE 语句列表
【解决方案2】:

this 之类的怎么样?

-- Helper Procedure 
CREATE PROC #DropConstraints 
  @tableSchema nvarchar(max), 
  @tableName nvarchar(max), 
  @constraintType nvarchar(20) 
AS 
BEGIN 
  DECLARE @cName nvarchar(max); 

  DECLARE constraint_cursor CURSOR FOR 
    SELECT CONSTRAINT_NAME  
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
    WHERE  
      CONSTRAINT_TYPE = @constraintType 
      AND TABLE_NAME = @tableName 
      AND TABLE_SCHEMA = @tableSchema 

  OPEN constraint_cursor 

  FETCH NEXT FROM constraint_cursor INTO @cName 
  WHILE @@FETCH_STATUS = 0 
  BEGIN 
    EXEC ('ALTER TABLE ' + @tableSchema + '.' + @tableName + ' DROP CONSTRAINT ' + @cName); 
    FETCH NEXT FROM constraint_cursor INTO @cName 
  END 

  CLOSE constraint_cursor 
  DEALLOCATE constraint_cursor 
END 
GO

BEGIN TRANSACTION

  -- Setup Cursor for looping 
  DECLARE table_cursor SCROLL CURSOR FOR 
    SELECT TABLE_SCHEMA, TABLE_NAME  
    FROM INFORMATION_SCHEMA.TABLES 

  OPEN table_cursor

  -- Declare Variables

  DECLARE 
    @tableSchema nvarchar(max), 
    @tableName nvarchar(max) 

 -- Drop Primary Keys 

  FETCH FIRST FROM table_cursor INTO @tableSchema, @tableName 
  WHILE @@FETCH_STATUS = 0 
  BEGIN 
    EXEC #DropConstraints @tableSchema, @tableName, 'PRIMARY KEY'; 

    FETCH NEXT FROM table_cursor INTO @tableSchema, @tableName 
  END 

  -- Cleanup 
  CLOSE table_cursor 
  DEALLOCATE table_cursor

COMMIT TRANSACTION 
GO

DROP PROCEDURE #DropConstraints;
GO

【讨论】:

    【解决方案3】:

    要回答关于 PK 和聚集索引之间差异的问题:

    主键是保证记录可以唯一标识的键值。除了创建主键的默认设置是使其成为聚集索引之外,它们与聚集索引(指示记录物理存储的顺序)无关。但是,您不必将其设为聚集索引。

    请注意,如果您过去没有主键和外键,您的数据可能会被彻底清除,在清理之前您不应创建外键。

    【讨论】:

      【解决方案4】:

      要删除所有聚集索引,您必须区分约束(主或唯一)是聚集索引或非约束索引是否是聚集索引的情况。不能使用 DROP INDEX 删除约束索引,也不能使用 DROP CONSTRAINT 删除索引。因此,您需要执行以下操作:

      Select 'ALTER TABLE ' + QUOTENAME(OBJECT_NAME([object_id])) + ' DROP CONSTRAINT ' + QUOTENAME([name])
      From sys.indexes
      Where is_primary_key = 1 Or is_unique_constraint = 1
       And type_desc = 'CLUSTERED'
      Union All
      Select 'DROP INDEX ' + QUOTENAME([name]) + ' ON ' + QUOTENAME(OBJECT_NAME([object_id])) 
      from sys.indexes
      Where is_primary_key = 0 And is_unique_constraint = 0
       And type_desc = 'CLUSTERED'
      

      坦率地说,即使这样也可能行不通,因为必须先删除任何主键的所有外键,然后才能删除主键。要做到这一点,您需要编写所有外键的脚本,将它们全部删除,然后删除所有集群约束,然后重新创建所有外键。

      我不得不问这是否真的是你想要做的。通过删除所有聚集索引,您将强制重建所有受影响表中的所有索引。

      【讨论】:

        【解决方案5】:

        在我之前提供的代码示例都有效,无论是仅主键版本,还是同时处理其他类型的聚集索引的版本。

        然而,没有人关心对象可能不存在于默认方案中的事实,也没有人控制索引和约束不是 SQL Server 需要的系统对象。

        这是简单的版本,只删除了主键:

        select  'ALTER TABLE ' + quotename(object_schema_name(object_id)) + '.'
                + quotename(object_name(object_id)) + ' DROP CONSTRAINT ' + name
        from    sys.indexes
        where   is_primary_key = 1
        

        这是第二个版本,它还编写了删除非主键聚集索引的脚本:

        select  'ALTER TABLE ' + quotename(object_schema_name(object_id)) + '.'
                + quotename(object_name([object_id])) + ' DROP CONSTRAINT '
                + quotename([name])
        from    sys.indexes
        where   is_primary_key = 1
                or is_unique_constraint = 1
                and type_desc = 'CLUSTERED'
        union all
        select  'DROP INDEX ' + quotename(i.[name]) + ' ON '
                + quotename(object_schema_name(i.[object_id])) + '.'
                + +quotename(object_name(i.[object_id]))
        from    sys.indexes as i
                inner join sys.objects as o on o.object_id = i.object_id
        where   is_primary_key = 0
                and is_unique_constraint = 0
                and i.type_desc = 'CLUSTERED'
                and o.[type] not in ( 'S' )
                and o.is_ms_shipped = 0
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-10-21
          • 2017-12-08
          • 1970-01-01
          • 1970-01-01
          • 2019-02-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多