【发布时间】:2017-01-09 13:50:50
【问题描述】:
我正在处理SQL Server 2012:
我有一个主键列为INT 的表。我需要将其更改为 GUID。
我是否要更改表格并将 int 列删除为primary key?
添加 GUID 列并将其设置为 Primary 并删除旧的 INT 列?
谢谢。
【问题讨论】:
标签: sql-server-2012 primary-key
我正在处理SQL Server 2012:
我有一个主键列为INT 的表。我需要将其更改为 GUID。
我是否要更改表格并将 int 列删除为primary key?
添加 GUID 列并将其设置为 Primary 并删除旧的 INT 列?
谢谢。
【问题讨论】:
标签: sql-server-2012 primary-key
您不能更改主键列,除非您删除它。任何更改其数据类型的操作都会导致以下错误..
对象“XXXX”依赖于列“XXXX”。
唯一的选择是
1.删除主键
2.更改数据类型
3.重新创建主键
ALTER TABLE t1
DROP CONSTRAINT PK__t1__3213E83F88CF144D;
GO
alter table t1
alter column id varchar(10) not null
alter table t1 add primary key (id)
从 2012 年开始,有一个名为 (DROP_EXISTING = ON) 的子句使事情变得简单,通过在最后阶段删除聚集索引并保持旧索引可用于所有操作。但在您的情况下,此子句将不起作用。 .
所以我推荐
1.使用不同的名称创建具有所需架构和索引的新表
2.从旧表插入数据到新表
3.最后在切换的时候,插入积累的数据
4.将表重命名为旧表名
这样您可能会减少停机时间
【讨论】:
您可以分三步更改主键的日期类型
第 1 步:- 删除与主键关联的约束
ALTER TABLE table_name
DROP CONSTRAINT constraint_name;
第 2 步:- 将主键列更改为有效的主键数据类型
ALTER TABLE table_name
ALTER COLUMN pk_column_name target_data_type(size) not null;
第 3 步 :- 再次创建更改后的列主键
ALTER TABLE table_name
ADD PRIMARY KEY (pk_column_name);
PS :-
当您尝试更改约束时,您可以从错误消息中获取约束名称 pk_column
如果 pk_column 中已有数据,请确保该列的源数据类型和目标数据类型都可用于现有数据。否则需要另外两个步骤将现有数据移动到临时列,然后执行这些步骤并在审查和删除该临时列后恢复该数据。
【讨论】:
下面是我编写的一个脚本,用于帮助我们部署对主键列数据类型的更改。
此脚本假定根据该列不存在任何非主键约束(例如外键)。
它有一些安全检查,因为它被设计为部署到不同的服务器(dev、uat、live)如果服务器上的表因某种原因不同而不会产生副作用。
我希望这对某人有所帮助。如果您在投票前发现任何问题,请告诉我。我非常乐意更新脚本。
IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS C WITH (NOLOCK) WHERE C.TABLE_CATALOG = '<<DB>>' AND C.TABLE_SCHEMA = 'dbo' AND C.TABLE_NAME = '<<Table>>'
AND C.COLUMN_NAME = '<<COLUMN>>' AND C.DATA_TYPE = 'int') -- <- Additional test to check the current datatype so this won't make unnecessary or wrong updates
BEGIN
DECLARE @pkName VARCHAR(200);
SELECT @pkName = pkRef.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pkRef WITH (NOLOCK)
WHERE pkRef.TABLE_CATALOG = '<<DB>>' AND pkRef.TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '<<Table>>'
IF(@pkName IS NOT NULL)
BEGIN
-- Make sure the primary key name is the one you are going to use in script beyond this point.
IF(@pkName != '<<PRIMARY KEY NAME>>')
BEGIN
RAISERROR ('Unexpected primary key name - The primary key found has a different name than expected. Please update the script.', 16, 1);
RETURN;
END
ALTER TABLE dbo.<<Table>>
DROP CONSTRAINT <<PRIMARY KEY NAME>>; -- Note: this is not a string or a variable (just type the PK name)
SELECT 'Dropped existing primary key';
END
ALTER TABLE dbo.<<Table>> ALTER COLUMN ID BIGINT
SELECT 'Updated column type to big int';
ALTER TABLE dbo.<<Table>>
ADD CONSTRAINT <<PRIMARY KEY NAME>> PRIMARY KEY CLUSTERED (<<COLUMN>>);
SELECT 'Created the primary key';
END
ELSE
BEGIN
SELECT 'No change required.';
END
【讨论】:
如果其他表使用索引 FK 引用您的 PK,这些是您必须遵循的步骤。
在本例中,主表名为Main,单引用表Reference。我将数据类型更改为NVARCHAR(7)。要使用它:
dbo 架构;ALTER TABLE dbo.Main ADD IdNew NVARCHAR(7);
UPDATE dbo.Main SET IdNew = Id;
-- For all tables with FK's to this Main:
ALTER TABLE dbo.Reference ADD MainIdNew NVARCHAR(7);
UPDATE dbo.Reference SET MainIdNew = MainId;
ALTER TABLE dbo.Reference DROP CONSTRAINT FK_Reference_MainId_Main_Id;
DROP INDEX IX_Reference_MainId ON dbo.Reference;
ALTER TABLE dbo.Reference DROP COLUMN MainId;
-- Until here
ALTER TABLE dbo.Main DROP CONSTRAINT PK_Main;
ALTER TABLE dbo.Main DROP COLUMN Id;
EXEC sp_rename 'dbo.Main.IdNew', 'Id', 'COLUMN';
ALTER TABLE dbo.Main ALTER COLUMN Id NVARCHAR(7) NOT NULL;
ALTER TABLE dbo.Main ADD CONSTRAINT PK_Main PRIMARY KEY (Id);
-- Again for all tables with FK's to this Main:
EXEC sp_rename 'dbo.Reference.MainIdNew', 'MainId', 'COLUMN';
ALTER TABLE dbo.Reference ADD CONSTRAINT FK_Reference_MainId_Main_Id FOREIGN KEY (MainId) REFERENCES dbo.Main(Id);
CREATE INDEX IX_Reference_MainId ON dbo.Reference(MainId);
【讨论】:
在表格右边你要改变PK类型>>修改。进入列,更改类型并保存。如果你想看到这样的改变的代码,在保存之前,你可以右击>>“生成改变脚本..”。
【讨论】: