我有一个创建可打印表单的Web应用程序,这些表单上有唯一的编号,问题是我有2个表单需要为它们创建单独的数字。 即)
Form1-编号2000000-2999999
Form2-编号3000000-3999999
dbo.test2 - 是我的表单信息表
Tsel - 是我3000000系列号的autoinc表
Tadv - 是我2000000系列号码的autoinc表
我所做的是创建2个只有autoinc行的表(一个用于2000000个系列号,一个用于3000000个系列号),然后我创建了一个触发器,将记录添加到相应的表中,读回autoinc号并添加它存储在我的表中,用于存储表单信息,包括刚刚为正确的表单系列创建的autoinc编号。
虽然它确实有效,但我担心这些数字会在负载下混乱。 当很多人使用系统时,我不确定@@ IDENTITY是否会始终返回正确的值。 (我不能重复,我需要使用上面的编号表格。
见下面的代码。 **** TRIGGER ****
CREATE TRIGGER MAKEANID2 ON dbo.test2
AFTER INSERT
AS
SET NOCOUNT ON
declare @someid int
declare @someid2 int
declare @startfrom int
declare @test1 varchar(10)
select @someid=@@IDENTITY
select @test1 = (Select name1 from test2 where sysid = @someid )
if @test1 = 'select'
begin
insert into Tsel Default values
select @someid2 = @@IDENTITY
end
if @test1 = 'adv'
begin
insert into Tadv Default values
select @someid2 = @@IDENTITY
end
update test2
set name2=(@someid2) where sysid = @someid
SET NOCOUNT OFF
答案 0 :(得分:1)
保持两个ID同步的最佳方法是根据实际标识列创建持久Computed Column。其中Col1是标识列,Col2是持久计算列,它是基于Col1的某些公式的结果。然后你甚至可以Create Indexes on Computed Columns。
测试一下:
CREATE TABLE YourTable
(Col1 int not null identity(2000000,1)
,Col2 AS (Col1-2000000+3000000) PERSISTED
,Col3 varchar(5)
)
GO
insert into YourTable (col3) values ('a')
insert into YourTable (col3) SELECT 'b' UNION SELECT 'c'
SELECT * FROM YourTable
输出:
Col1 Col2 Col3
----------- ----------- -----
2000000 3000000 a
2000001 3000001 b
2000002 3000002 c
(3 row(s) affected)
编辑在OP评论之后,我仍然不能100%确定你的目标。
我从未使用过SQL Server 2000(我们跳过了那个版本),我真的不想查看如何在该版本中执行所有操作,如果没有OUTPUT子句和ROW_NUMBER(),CTE等,它是如此有限
我可以想到三种方法:
1)你可以创建一个序列表,你有两行一个用于A,一个用于B,每次你需要插入一个,查找,增加和保存你需要的seq类型的值然后插入该值。例如,如果要插入类型“A”行,请执行以下操作:
INSERT INTO test2
(col1, col2, col3,...)
SELECT
ISNULL(MAX(NextSeq),0)+1, col2, col3,...
FROM YourSequenceTable WITH (UPDLOCK, HOLDLOCK)
WHERE SequenceType='A'
UPDATE YourSequenceTable
SET NextSeq=ISNULL(NextSeq,0)+1
WHERE SequenceType='A'
2)更改您的表结构,只需将数据保存在Tsel或Tadv中,并将触发器插入到第三个公用表表中,您可以在其中获得额外的“公共”标识。普通表就像
CommonTable
ID int not null indentity(1,1) primary key
TselID int null FK to Tsel.PK
TadvID int null FK to Tadv.PK
3)如果你需要一个表,试试这个,这是一个真正的黑客。更改您的Tsel和Tadv表以包含所有必需的列,并在值为INSERT INTO Tsel
时从应用程序select
更改并触发获取该标识值,然后将其插入test2,然后从中删除数据TSEL。然后,从值为adv
INSERT INTO Tadv
的应用程序中,只有CREATE Trigger MAKEANID2_Tsel ON dbo.Tsel
AFTER INSERT
AS
--copy data from Tsel into test2., test2 can still have its own identity value
INSERT INTO test2
(PK, col1, col2, col3,...)
SELECT
col0, col1, col2, col3,....
FROM INSERTED
--remove rows from Tsel, which were just copied and not needed anymore.
DELETE Tsel
WHERE PK IN (SELECT PK FROM INSERTED)
GO
的触发器将该数据插入test2,并从Tadv中删除数据。您需要在Tsel和Tadv中包含所有数据列,以便触发器可以将值复制到test2,但触发器将从那里删除行(即使删除了原始行,标识也将是顺序的。)
您的Tsel触发器如下所示:
{{1}}
答案 1 :(得分:0)
你担心@@ identity是正确的,它不是一个推荐的代码,如果somone在其他地方添加了一个不同的触发器,它会使一个身份不相关而且首先会触发,这就是你将获得的价值。
但是你有更大的问题。您的触发器被定义为一次只能处理一个记录。这对触发器来说非常非常糟糕。触发器对数据集进行操作,并且即使您认为一次插入的记录永远不会超过一个,也必须始终设置为处理数据集而不是一个记录。此外,您不需要询问身份,您可以将所有记录中的所有记录的标识插入到名为inserted的触发器中的可伪造的availlble中。
现在阅读你的一条评论,你说你根本没有任何遗漏的价值。在任何情况下,您不能使用标识列,因为如果任何事务被回滚,它将有间隙。您必须编写自己的流程以根据最后一个数字创建数字,并注意竞争条件。