【问题标题】:Delete or change the primary key constraint to UNIQUE constraint using SQL Server 2008使用 SQL Server 2008 删除主键约束或将主键约束更改为 UNIQUE 约束
【发布时间】:2012-09-04 22:08:53
【问题描述】:

我真的需要知道是否有任何方法可以将表的主键约束更改或删除为 UNIQUE 约束

当我尝试从Entreprise 表中删除主要约束时:

ALTER TABLE Entreprise
DROP CONSTRAINT  PK__Entrepri__AABA1D8F1B0907CE

我得到这个错误:

消息 3725,第 16 级,状态 0,第 1 行
约束“PK_Entrepri_AABA1D8F1B0907CE”被表“Dossier”引用,外键约束“Cle_FDOs”。
消息 3727,第 16 级,状态 0,第 1 行
无法删除约束。查看以前的错误。

所以问题是我不想删除dossier 表中的行

这是Entreprise 表:

create table Entreprise
(
    ID_Entreprise integer ,
    Raison_Social varchar(100),/*Nom Entreprise*/
    Num_Raison_Sociale varchar(20) unique ,
    Adress varchar(100),
    Abreviation varchar(10),
    CNSS_Entreprise integer unique,
    Eligible varchar(20),/*AUTOMATIQUE par raport aux CNSS_Entreprise*/
    Effectif integer,/*NB SALARIE*/
    Ville varchar(20),
    Responsable varchar(20),
    EMAIL_Responsable varchar(20),
    Tel_Responsable varchar(20),
    Fax_Responsable varchar(20),    
    Directeur varchar(20),
    EMAIL_Directeur varchar(20),
    Tel_Directeur varchar(20),
    Fax_Directeur varchar(20),
    RIB varchar(60),/*ici non sur le dossier lo*/
    Nom_Giac varchar(50) foreign key references GIAC(Nom_Giac),
    primary key(Nom_Giac,ID_Entreprise)
)
GO

这是Dossier 表:

create table Dossier
(
    ID_Dossier integer primary key,
    ID_Entreprise int,/*AUTOMATIQE par rapotrt aux la cnss de l'entreprise qui l'a donne*/
    Date_Depot datetime ,
    Type_Etude varchar(2),/*DS IF combobox*/
    Dernier_Type varchar(2),/* AUTOMATIQUE */
    Eligibile varchar(3),/*  par raport aux Dernier Type et CNSS et COTISTAION EXERCICES */
    Fiche_Information varchar(3),/*checkbox o/n */
    Buletin_Adhesion varchar(3),
    Fiche_Renseignment varchar(3),
    Attestation varchar(3),
    Date_Debut datetime,
    Date_Fin datetime,
    --Etat_Dossier varchar(3), /* hado m7aydine mn war9a*/
    --Motif text,/*en cas de rejet, peu prendre null apart le cnss et cotisation ex et dernier formation *//* hado m7aydine mn war9a*/
    ID_Cabinet integer foreign key references Cabinet(ID_Cabinet),
    Montant_Demander decimal(6,2),
    Duree integer,
    Porcentage_Taux varchar(3), /* combobox 70% 80% */
    Nom_Giac varchar(50),
    constraint Cle_FDOs foreign key(Nom_Giac,ID_Entreprise) references Entreprise(Nom_Giac,ID_Entreprise),
)
GO

【问题讨论】:

    标签: sql sql-server database sql-server-2008 constraints


    【解决方案1】:

    您无法通过一条 SQL 指令自动执行“更改”,但如果您愿意,您可以实现。

    首先,在具体情况下,您需要删除那些包含对被引用表 Enterprise 的引用的表的外键。

    您需要从Dossier 中删除外键,然后从Enterprise 中删除主键,并创建UNIQUE 约束。

    另一个问题是,你为什么有兴趣这样做?

    也许您可以阅读此other SO thread 讨论此事。

    【讨论】:

      【解决方案2】:

      正如错误提示,您需要先删除外键引用。这不会删除 Dossier 中的记录(请参阅我的 SQL Fiddle example。):

      ALTER TABLE Dossier DROP CONSTRAINT Cle_FDOs;
      

      【讨论】:

        【解决方案3】:

        我多次遇到这个问题,最终制作了一个可以接受任何主键约束并变成唯一索引的存储过程。它删除并重新创建任何引用相关表的内容(这是高度引用表的棘手部分)。

        它可以处理多部分主键。

        CREATE PROCEDURE spPrimaryKeyToUniqueKey
            @schema VARCHAR(255),
            @tableName VARCHAR(255)
        AS
        BEGIN
            SET NOCOUNT ON;
        
            DECLARE @constraintsToDrop NVARCHAR(MAX) = '';
            DECLARE @constraintsToCreate NVARCHAR(MAX) = '';
            DECLARE @indexesToDrop NVARCHAR(MAX) = '';
            DECLARE @indexesToCreate NVARCHAR(MAX) = '';
        
            ;WITH _fks AS (
                SELECT  
                  FkName               = fk.[name]
                , SchemaName           = sch.[name] 
                , TableName            = tab1.[name]
                , ColumnName           = col1.[name]
                , ReferencedSchema     = sch2.[name]
                , ReferencedTableName  = tab2.[name]
                , ReferencedColumnName = col2.[name]
                , ReferencedColOrder   = ic.key_ordinal
                FROM sys.foreign_key_columns fkc
                JOIN sys.foreign_keys fk ON fk.object_id = fkc.constraint_object_id
                JOIN sys.tables tab1 ON tab1.object_id = fkc.parent_object_id
                JOIN sys.schemas sch ON tab1.schema_id = sch.schema_id
                JOIN sys.columns col1 ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
                JOIN sys.tables tab2 ON tab2.object_id = fkc.referenced_object_id
                JOIN sys.schemas sch2 ON sch2.schema_id = tab2.schema_id
                JOIN sys.columns col2 ON col2.column_id = fkc.referenced_column_id AND col2.object_id = tab2.object_id
                JOIN sys.indexes i ON fk.key_index_id = i.index_id AND i.object_id = tab2.object_id
                JOIN sys.index_columns ic ON col2.column_id = ic.column_id AND ic.object_id = tab2.object_id AND i.index_id = ic.index_id
            ) 
            , _fksWithColList AS (
                SELECT
                  f.FkName    
                , f.SchemaName
                , f.TableName 
                , f.ReferencedSchema
                , f.ReferencedTableName
                , TableColNameList = STUFF(
                   (SELECT  ',[' + ff.ColumnName + ']'
                    FROM _fks ff
                    WHERE f.FkName = ff.FkName AND f.SchemaName = ff.SchemaName AND f.TableName = ff.TableName AND f.ReferencedSchema = ff.ReferencedSchema AND f.ReferencedTableName = ff.ReferencedTableName
                    ORDER BY ff.ReferencedColOrder
                    FOR XML PATH('')), 1, 1, '')
                , ReferencedTableColNameList = STUFF(
                   (SELECT  ',[' + ff.ReferencedColumnName + ']'
                    FROM _fks ff
                    WHERE f.FkName = ff.FkName AND f.SchemaName = ff.SchemaName AND f.TableName = ff.TableName AND f.ReferencedSchema = ff.ReferencedSchema AND f.ReferencedTableName = ff.ReferencedTableName
                    ORDER BY ff.ReferencedColOrder
                    FOR XML PATH('')), 1, 1, '')
                FROM _fks f
                GROUP BY f.FkName, f.SchemaName, f.TableName, f.ReferencedSchema, f.ReferencedTableName
            ) 
            , _commands AS (
                SELECT *, 
                  DropStatement   = REPLACE(REPLACE(REPLACE('ALTER TABLE [{0}].[{1}] DROP CONSTRAINT IF EXISTS [{2}];', 
                    '{0}', SchemaName), 
                    '{1}', TableName),
                    '{2}', FkName),
                  CreateStatement = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE('ALTER TABLE [{0}].[{1}] DROP CONSTRAINT IF EXISTS [{2}]; ALTER TABLE [{0}].[{1}] ADD CONSTRAINT [{2}] FOREIGN KEY ({3}) REFERENCES [{4}].[{5}]({6});',
                    '{0}', SchemaName), 
                    '{1}', TableName),
                    '{2}', FkName),
                    '{3}', TableColNameList),
                    '{4}', ReferencedSchema),
                    '{5}', ReferencedTableName),
                    '{6}', ReferencedTableColNameList)
                FROM _fksWithColList
                WHERE ReferencedSchema = @schema AND ReferencedTableName = @tableName
            )
            SELECT @constraintsToDrop = @constraintsToDrop + DropStatement + CHAR(13)+CHAR(10), @constraintsToCreate = @constraintsToCreate + c.CreateStatement + CHAR(13)+CHAR(10)
            FROM _commands c
        
            ;WITH _indexes AS (
                SELECT 
                  TableName  = t.[name]
                , SchemaName = s.[name]
                , IndexName  = i.[name]
                , ColumnName = c.[name]
                , ColOrder   = ic.key_ordinal
                , ColDesc    = ic.is_descending_key
                FROM sys.tables t
                JOIN sys.schemas s ON t.schema_id = s.schema_id
                JOIN sys.indexes i ON t.object_id = i.object_id        
                JOIN sys.columns c ON t.object_id = c.object_id
                JOIN sys.index_columns ic ON t.object_id = ic.object_id AND c.column_id = ic.column_id AND i.index_id = ic.index_id
                WHERE s.[name] = @schema AND t.[name] = @tableName AND i.is_primary_key = 1
            )
            , indexesWithColList AS (
                SELECT 
                  TableName 
                , SchemaName
                , IndexName 
                , IndexColList = STUFF(
                   (SELECT  ',[' + ii.ColumnName + ']' + IIF(ii.ColDesc = 1, ' DESC', '')
                    FROM _indexes ii
                    WHERE i.TableName = ii.TableName AND i.SchemaName = ii.SchemaName AND i.IndexName = ii.IndexName  AND ii.ColOrder > 0
                    ORDER BY ii.ColOrder
                    FOR XML PATH('')), 1, 1, '')
                , IndexColNameList = STUFF(
                   (SELECT  '_' + ii.ColumnName
                    FROM _indexes ii
                    WHERE i.TableName = ii.TableName AND i.SchemaName = ii.SchemaName AND i.IndexName = ii.IndexName  AND ii.ColOrder > 0
                    ORDER BY ii.ColOrder
                    FOR XML PATH('')), 1, 1, '')
                FROM _indexes i
                GROUP BY i.TableName, i.SchemaName, i.IndexName
            ) 
            , _commands AS (
                SELECT *,
                  DropStatement   = REPLACE(REPLACE(REPLACE('ALTER TABLE [{0}].[{1}] DROP CONSTRAINT {2};', 
                    '{0}', i.SchemaName),
                    '{1}', i.TableName),
                    '{2}', i.IndexName),
                  CreateStatement = REPLACE(REPLACE(REPLACE(REPLACE('CREATE UNIQUE NONCLUSTERED INDEX [{0}] ON [{1}].[{2}] ({3});',
                    '{0}', 'UX_' + i.SchemaName + '_' + i.TableName + '_' + i.IndexColNameList),
                    '{1}', i.SchemaName),
                    '{2}', i.TableName),
                    '{3}', i.IndexColList)
                FROM indexesWithColList i
            ) 
            SELECT @indexesToDrop = @indexesToDrop + c.DropStatement + CHAR(13)+CHAR(10), @indexesToCreate = @indexesToCreate + c.CreateStatement + CHAR(13)+CHAR(10)
            FROM _commands c
        
        
            DECLARE @sql NVARCHAR(MAX);
            SET @sql = REPLACE(REPLACE(REPLACE(REPLACE('
        SET XACT_ABORT ON;
        
        BEGIN TRAN t1
        
        --Drop foreign keys
        {0}
        
        --Drop indexes
        {1}
        
        --Create indexes
        {2}
        
        --Recreate foreign keys
        {3}
        
        COMMIT TRAN t1
        ',
            '{0}', @constraintsToDrop),
            '{1}', @indexesToDrop),
            '{2}', @indexesToCreate),
            '{3}', @constraintsToCreate);
        
            PRINT @sql;
        
            EXEC sp_executesql @sql
        END
        GO
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-11-20
          • 1970-01-01
          • 1970-01-01
          • 2021-04-11
          • 2015-11-29
          • 1970-01-01
          • 2013-06-13
          相关资源
          最近更新 更多