将 INT 转换为无符号 INT
Converting INT to Unsigned INT
我在产品中有一个很大的 table 数据类型,它是主键和标识列 (1,1)。行数是 2147479257。
在日常作业 运行 期间,ETL 由于算术溢出错误而失败,因为它无法将更多行放入目标 table。
请问如何将列更改为 unsigned int。
将数据类型更改为 bigint。
bigint -2^63 (-9,223,372,036,854,775,808) to 2^63-1 (9,223,372,036,854,775,807)
您溢出了一个整数,这意味着您在 table 中有大约 2B 行。通过切换到 unsigned int,您希望获得另外 20 亿行可寻址 space。这种方法的问题是 SQL 服务器不支持 unsigned int 作为数据类型。
您的直觉反应可能是采用 Greg 更改为 bigint 数据类型的方法。这种方法的挑战在于,当您的处理陷入困境时,您采取快速修复并更改为 bigint,table 的任何其他消费者现在都会失败。顺便说一下,我在 2011 年经历过这个。我们 修复了 数据库只是为了让所有报告和 .NET 应用程序失败。在那份工作中,在我们表现正常的情况下排队处理 N 天比通过让每个面向外部的应用程序失败来消除所有疑虑更灾难性。
通过标识列的一般实现,您无需更改任何代码即可轻松获得另一个 2B - 只需将标识值设置为下限,您就已经为自己赢得了足够的时间 plan 迁移到 bigint。这个命令是 dbcc checkident
您可能还希望确保将标识列指定为唯一值。人们通常将标识列设置为主键,但除此之外,您会 运行 编写类似于以下内容的代码。
SET NOCOUNT ON;
IF EXISTS
(
SELECT * FROM sys.tables AS T INNER JOIN sys.schemas AS S ON S.schema_id = T.schema_id WHERE S.name = 'dbo' AND T.name = 'IntOverfloweth'
)
BEGIN
DROP TABLE
dbo.IntOverfloweth;
END
CREATE TABLE
dbo.IntOverfloweth
(
IntOverflowethID int IDENTITY(2147483647,1) NOT NULL
, SomeValue varchar(30)
);
INSERT INTO
dbo.IntOverfloweth
(SomeValue)
OUTPUT
Inserted.*
VALUES
('Before');
BEGIN TRY
INSERT INTO
dbo.IntOverfloweth
(SomeValue)
OUTPUT
Inserted.*
VALUES
('Overflow');
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH
-- Push the pointer back around to the begining
DBCC CHECKIDENT('dbo.IntOverfloweth', RESEED, -2147483648);
-- Ensure uniqueness
CREATE UNIQUE INDEX UQ_IntOverfloweth
ON dbo.IntOverfloweth
(
IntOverflowethID
);
INSERT INTO
dbo.IntOverfloweth
(SomeValue)
OUTPUT
Inserted.*
VALUES
('Does not Overflow');
我在产品中有一个很大的 table 数据类型,它是主键和标识列 (1,1)。行数是 2147479257。 在日常作业 运行 期间,ETL 由于算术溢出错误而失败,因为它无法将更多行放入目标 table。
请问如何将列更改为 unsigned int。
将数据类型更改为 bigint。
bigint -2^63 (-9,223,372,036,854,775,808) to 2^63-1 (9,223,372,036,854,775,807)
您溢出了一个整数,这意味着您在 table 中有大约 2B 行。通过切换到 unsigned int,您希望获得另外 20 亿行可寻址 space。这种方法的问题是 SQL 服务器不支持 unsigned int 作为数据类型。
您的直觉反应可能是采用 Greg 更改为 bigint 数据类型的方法。这种方法的挑战在于,当您的处理陷入困境时,您采取快速修复并更改为 bigint,table 的任何其他消费者现在都会失败。顺便说一下,我在 2011 年经历过这个。我们 修复了 数据库只是为了让所有报告和 .NET 应用程序失败。在那份工作中,在我们表现正常的情况下排队处理 N 天比通过让每个面向外部的应用程序失败来消除所有疑虑更灾难性。
通过标识列的一般实现,您无需更改任何代码即可轻松获得另一个 2B - 只需将标识值设置为下限,您就已经为自己赢得了足够的时间 plan 迁移到 bigint。这个命令是 dbcc checkident
您可能还希望确保将标识列指定为唯一值。人们通常将标识列设置为主键,但除此之外,您会 运行 编写类似于以下内容的代码。
SET NOCOUNT ON;
IF EXISTS
(
SELECT * FROM sys.tables AS T INNER JOIN sys.schemas AS S ON S.schema_id = T.schema_id WHERE S.name = 'dbo' AND T.name = 'IntOverfloweth'
)
BEGIN
DROP TABLE
dbo.IntOverfloweth;
END
CREATE TABLE
dbo.IntOverfloweth
(
IntOverflowethID int IDENTITY(2147483647,1) NOT NULL
, SomeValue varchar(30)
);
INSERT INTO
dbo.IntOverfloweth
(SomeValue)
OUTPUT
Inserted.*
VALUES
('Before');
BEGIN TRY
INSERT INTO
dbo.IntOverfloweth
(SomeValue)
OUTPUT
Inserted.*
VALUES
('Overflow');
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH
-- Push the pointer back around to the begining
DBCC CHECKIDENT('dbo.IntOverfloweth', RESEED, -2147483648);
-- Ensure uniqueness
CREATE UNIQUE INDEX UQ_IntOverfloweth
ON dbo.IntOverfloweth
(
IntOverflowethID
);
INSERT INTO
dbo.IntOverfloweth
(SomeValue)
OUTPUT
Inserted.*
VALUES
('Does not Overflow');