在SQL Server中更改主键列

64

更新

以下是查询结果导致的约束条件

SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = 'history'

CONSTRAINT_NAME   COLUMN_NAME  ORDINAL_POSITION
PK_history        userKey       1
PK_history        name          2

以下是查询的结果

SELECT * 
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
WHERE TABLE_NAME = 'history'

CONSTRAINT_NAME   CONSTRAINT_TYPE  IS_DEFERRABLE  INITIALLY_DEFERRED
PK_history        PRIMARY KEY      NO             NO

更新结束

我的主机通过ASP.NET Enterprise Manager提供了与我的SQL Server DB的接口。

我的history表中有3个列:

  • userId(键,整数,不允许为空)
  • name(键,字符串,不允许为空)
  • id(非键,整数,允许为空)

我想将id列设置为唯一键。

为此,我认为需要执行以下操作:

  1. 确保该列中没有任何行的值为NULL
  2. 将该列设置为不允许为空
  3. 将该列添加为主键
  4. 将其他2个列作为键删除

然而,当我使用提供的UI时,它从未起作用。有时它只是看起来试图做些什么,但当我刷新列的视图时它从未发生变化。它偶尔会创建一个临时表,看起来它尝试执行部分操作,但它从未复制/覆盖我正在尝试更改的原始表。

当我尝试使用查询时,更改也不会显示出来。以下是我认为需要使用的查询:

    SELECT * from history WHERE id is NULL     <---- This shows 0 results

    ALTER TABLE history
    ALTER COLUMN id int NOT NULL

    ALTER TABLE history ADD PRIMARY KEY (id)

    ALTER TABLE history
    DROP CONSTRAINT userId
    DROP CONSTRAINT name
    GO

我只尝试了禁止 NULL 值和为 id 列添加主键的操作,但好像不起作用。有人能指点一下我吗?谢谢!


你应该先删除约束。 - Hector Sanchez
没有问题,我在查询中没有收到任何错误消息。但是在使用UI时,当将id列设置为键而允许为空时,出现了相关错误,但是在试图禁止为空时没有错误。 - ckbhodge
先生:我尝试先删除约束,但它没有起作用 :( - ckbhodge
2个回答

95
假设当前的主键约束为pk_history,您可以替换以下行:
ALTER TABLE history ADD PRIMARY KEY (id)

ALTER TABLE history
DROP CONSTRAINT userId
DROP CONSTRAINT name

使用这些:

ALTER TABLE history DROP CONSTRAINT pk_history

ALTER TABLE history ADD CONSTRAINT pk_history PRIMARY KEY (id)

如果您不知道主键的名称,可以使用以下查询语句找到它:

SELECT * 
  FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
 WHERE TABLE_NAME = 'history'

谢谢。我尝试了这些方法(在使用您的查询查找主键名称“PK_history”后),但是UI仍然显示原始的两列作为键,而ID列则没有。我没有收到错误消息。也许这是因为ID列仍允许为空值的缘故? - ckbhodge
1
你在UI界面上进行了刷新吗?我强烈怀疑它们可能是外键而不是主键。你可以使用SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = 'history'来确定表中每个列与哪个约束关联。 - competent_tech
再试一次。我现在注意到将id列设置为不允许为空的查询实际上每隔几秒钟就会在右下角以非常微妙的方式显示正在运行。也许我上次在UI上点击其他地方之前没有等待足够长的时间? - ckbhodge
如果这是一张大表,可能需要一段时间。你应该从其中一项操作中的某个点得到某种积极的确认。 - competent_tech
设置ID列禁止为空的查询似乎仍在运行(不清晰的用户界面让人高兴!)。我正在考虑创建一个新列,已设置为不允许为空,然后将其复制到该列。 - ckbhodge
显示剩余6条评论

1
Necromancing。 看起来你和我一样有一个很好的架构来使用... 以下是正确的操作方法:
在这个例子中,表名为dbo.T_SYS_Language_Forms,列名为LANG_UID。
-- First, chech if the table exists...
IF 0 < (
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES 
    WHERE TABLE_TYPE = 'BASE TABLE'
    AND TABLE_SCHEMA = 'dbo'
    AND TABLE_NAME = 'T_SYS_Language_Forms'
)
BEGIN
    -- Check for NULL values in the primary-key column
    IF 0 = (SELECT COUNT(*) FROM T_SYS_Language_Forms WHERE LANG_UID IS NULL)
    BEGIN
        ALTER TABLE T_SYS_Language_Forms ALTER COLUMN LANG_UID uniqueidentifier NOT NULL 

        -- No, don't drop, FK references might already exist...
        -- Drop PK if exists 
        -- ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT pk_constraint_name 
        --DECLARE @pkDropCommand nvarchar(1000) 
        --SET @pkDropCommand = N'ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT ' + QUOTENAME((SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
        --WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
        --AND TABLE_SCHEMA = 'dbo' 
        --AND TABLE_NAME = 'T_SYS_Language_Forms' 
        ----AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms' 
        --))
        ---- PRINT @pkDropCommand 
        --EXECUTE(@pkDropCommand) 

        -- Instead do
        -- EXEC sp_rename 'dbo.T_SYS_Language_Forms.PK_T_SYS_Language_Forms1234565', 'PK_T_SYS_Language_Forms';


        -- Check if they keys are unique (it is very possible they might not be) 
        IF 1 >= (SELECT TOP 1 COUNT(*) AS cnt FROM T_SYS_Language_Forms GROUP BY LANG_UID ORDER BY cnt DESC)
        BEGIN

            -- If no Primary key for this table
            IF 0 =  
            (
                SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
                WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
                AND TABLE_SCHEMA = 'dbo' 
                AND TABLE_NAME = 'T_SYS_Language_Forms' 
                -- AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms' 
            )
                ALTER TABLE T_SYS_Language_Forms ADD CONSTRAINT PK_T_SYS_Language_Forms PRIMARY KEY CLUSTERED (LANG_UID ASC)
            ;

            -- Adding foreign key
            IF 0 = (SELECT COUNT(*) FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_T_ZO_SYS_Language_Forms_T_SYS_Language_Forms') 
                ALTER TABLE T_ZO_SYS_Language_Forms WITH NOCHECK ADD CONSTRAINT FK_T_ZO_SYS_Language_Forms_T_SYS_Language_Forms FOREIGN KEY(ZOLANG_LANG_UID) REFERENCES T_SYS_Language_Forms(LANG_UID); 
        END -- End uniqueness check
        ELSE
            PRINT 'FSCK, this column has duplicate keys, and can thus not be changed to primary key...' 
    END -- End NULL check
    ELSE
        PRINT 'FSCK, need to figure out how to update NULL value(s)...' 
END 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接