us2*_*012 4 sql-server-2008 sql-server primary-key unique-constraint
检查我系统上某些软件使用的相当关键的数据库,我发现其中一个表在列上有一个主键Id
,其中Id
使用checksum(newid())
. 这让我感到不安;在newid
s的保证是独一无二的,但通过将校验和(一个32位整数,大概是出于性能的原因?),你有一些机会,你在表中得到的碰撞(用1M行,我把那大约 1:4000 的机会,对我来说太多了)。
所以:
checksum(newid())
给出一个已经存在的主键,会发生什么?我的桌子会炸吗?插入是否会失败并将其留给应用程序如何处理?我必须假设应用程序的编写方式是尝试插入,如果失败,它只会再试一次。否则插入将失败(PK 违规)并且您的用户将抱怨并提交错误。
如果这样做的目的只是以随机顺序分配唯一编号,那么应用程序可能工作正常。我认为你应该只提交错误报告,如果你能证明应用程序在发生碰撞时做错了 - 考虑到可能的故障率并不容易。如果您有源代码访问权限,一个更简单的方法是查看他们执行插入的代码部分(或找出它是否调用存储过程来执行此操作)。
请记住,有一种更简单且容错的方法可以做到这一点。在前面建一张桌子,随机排列大量数字,然后在需要时从顶部拔出一个数字。
CREATE TABLE dbo.Destination(ID INT /*, other columns */);
CREATE TABLE dbo.Source
(
RowNum INT PRIMARY KEY,
ID INT, -- UNIQUE
Used BIT NOT NULL DEFAULT 0
);
INSERT dbo.Source(RowNum, ID)
SELECT ROW_NUMBER() OVER (ORDER BY NEWID()), ID
FROM
(
SELECT ID = CHECKSUM(NEWID())
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
-- should produce about 4 million rows,
-- on my crappy VM this took two minutes,
-- add another cross join if you need more
)
AS x GROUP BY ID;
Run Code Online (Sandbox Code Playgroud)
然后当你需要添加一行时,你可以说:
UPDATE TOP (1) dbo.Source SET Used = 1
OUTPUT inserted.ID /*, @params */
INTO dbo.Destination
WHERE Used = 0;
Run Code Online (Sandbox Code Playgroud)
(DELETE TOP (1)
不过,您也可以让它们对审计等有用。)
归档时间: |
|
查看次数: |
1824 次 |
最近记录: |