【发布时间】:2012-08-28 14:55:31
【问题描述】:
所以,我尝试使用以下触发器,以便在更新表中的行时,它将特定列设置为 8 个随机字母数字字符的字符串。触发器工作正常,只是结果必须是唯一的。在触发器之前它将是空白的,因此不会在服务器上强制执行此唯一性。这个想法是,一旦客户在流程中走得足够远,他们就会得到这个字符串,但之前不会,因为我们有很多没有走得那么远的客户。
触发器:
CREATE TRIGGER test_rand
ON test_trigger
AFTER UPDATE
AS
UPDATE test_trigger set col2=(select
Random_String =
substring(x,(abs(checksum(newid()))%36)+1,1)+
substring(x,(abs(checksum(newid()))%36)+1,1)+
substring(x,(abs(checksum(newid()))%36)+1,1)+
substring(x,(abs(checksum(newid()))%36)+1,1)+
substring(x,(abs(checksum(newid()))%36)+1,1)+
substring(x,(abs(checksum(newid()))%36)+1,1)+
substring(x,(abs(checksum(newid()))%36)+1,1)+
substring(x,(abs(checksum(newid()))%36)+1,1)
from
(select x='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ') a) WHERE col2='';
GO
这个触发器是我使用一个只有两列col1 和col2 的简单表运行的测试。我为一堆行更新col1,col2 获得看似随机的值,但我知道两行可能获得相同的数字,如果可能的话我想防止这种情况发生。
我曾想过在不存在该字符串的地方检查 select 语句本身,但我无法想出一个好方法来做到这一点。
我是触发器的新手,所以如果我遗漏了一些简单的东西或者应该搜索一下,那么我为浪费您的时间而道歉。据我所知,这甚至不可能,但我想我应该在放弃并尝试其他方法之前先问清楚。
此外,在执行更新的脚本中没有这样做的原因是,我无法从客户端得到关于哪些脚本实际执行此操作的直接答案。如果这不可能,我将只编写一个由 Windows 任务计划程序运行的任务,但我希望这样做。
我的解决方案
根据 usr 告诉我的内容,我创建了以下代码来满足我的需求:
CREATE TRIGGER test_rand
ON test_trigger
AFTER UPDATE
AS
DECLARE @Ins_Col3 int;
DECLARE Ins_Curs CURSOR FOR SELECT col3 FROM inserted;
DECLARE @Ref char(8);
OPEN Ins_Curs
FETCH NEXT FROM Ins_Curs
INTO @Ins_Col3;
WHILE @@FETCH_STATUS = 0
BEGIN;
SET @Ref = LEFT(NEWID(), 8);
WHILE(EXISTS(SELECT col2 from test_trigger WHERE col2=@Ref))
BEGIN;
SET @Ref = LEFT(NEWID(), 8);
END;
UPDATE test_trigger SET test_trigger.col2=@Ref FROM inserted WHERE test_trigger.col3=@Ins_Col3;
FETCH NEXT FROM Ins_Curs
INTO @Ins_Col3;
END;
我必须添加 col3 作为自动递增的 id 值,以便我可以识别每一行。
因此,col1 仅存在于此,以便我可以通过更新语句进行更改。
【问题讨论】:
-
您的代码应该可以工作,但我不确定您可以从 GUID 的前 8 个字节中获得多好的随机数。见blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx
-
我认为您应该尝试说服您的客户使用 UniqueIdentifier 字段。 NEWID() 函数将始终为您提供唯一的字符串。您将获得性能提升,因为您不会试图确保您的价值不在数据库中。 UniqueIdentifier 只有 128 位。您的八个字符字段至少为 64 位。额外的 64 位性能提升是值得的。
-
这与性能无关。这是关于让客户使用它作为识别推荐他们的人的一种方式,并且客户认为不再拥有它可能对人们输入或写下它是一个问题。这也适用于测试系统,甚至可能不会持续超过一两个月。如果他们确实决定保留更长时间,那么我可能会与他们讨论延长它的时间。
标签: sql-server sql-server-2008 triggers