我正在将一个小型数据库从MS Access移动到SQL Server中。每年,用户都会创建一个新的Access数据库,并拥有干净的数据,但这一变化将把这些年份的数据放入一个锅中。用户依赖Access中的自动编号值作为记录的参考。如果删除了238条记录,这是非常不准确的。
所以我试图用他们可以控制的id列(稍微)来容纳它们。他们不会在SQL表中看到真正的主键,但我想给他们一个他们可以编辑的ID,但仍然是唯一的。
我一直在使用此触发器,但它花费的时间比我预期的要长。
所有东西看起来都很好,除了我不明白为什么我的INSERTED表中的数据与触发器所在的表一样。 (参见代码中的注释。)
ALTER TRIGGER [dbo].[trg_tblAppData]
ON [dbo].[tblAppData]
AFTER INSERT,UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @NewUserEnteredId int = 0;
DECLARE @RowIdForUpdate int = 0;
DECLARE @CurrentUserEnteredId int = 0;
DECLARE @LoopCount int = 0;
--*** Loop through all records to be updated because the values will be incremented.
WHILE (1 = 1)
BEGIN
SET @LoopCount = @LoopCount + 1;
IF (@LoopCount > (SELECT Count(*) FROM INSERTED))
BREAK;
SELECT TOP 1 @RowIdForUpdate = ID, @CurrentUserEnteredId = UserEnteredId FROM INSERTED WHERE ID > @RowIdForUpdate ORDER BY ID DESC;
IF (@RowIdForUpdate IS NULL)
BREAK;
-- WHY IS THERE A MATCH HERE? HAS THE RECORD ALREADY BEEN INSERTED?
IF EXISTS (SELECT UserEnteredId FROM tblAppData WHERE UserEnteredId = @CurrentUserEnteredId)
BEGIN
SET @NewUserEnteredId = (SELECT Max(t1.UserEnteredId) + 1 FROM tblAppData t1);
END
ELSE
SET @NewUserEnteredId = @CurrentUserEnteredId;
UPDATE tblAppData
SET UserEnteredId = @NewUserEnteredId
FROM tblAppData a
WHERE a.ID = @RowIdForUpdate
END
END
这是我想要完成的事情:
添加新记录时,应该从现有最大记录中增加值
当用户覆盖某个值时,应检查该值是否存在。如果找到则恢复现有值,否则允许更改。
此触发器允许一次添加多行。
这对于未来的使用效率很高,但实际上,它们每年只会增加1,000条记录。
答案 0 :(得分:0)
我不会使用触发器来完成此任务。
这是一个可用于创建序列的脚本(op没有标记版本),创建主键,使用序列作为特殊ID,并在列上添加约束。
create table dbo.test (
testid int identity(1,1) not null primary key clustered
, myid int null constraint UQ_ unique
, somevalue nvarchar(255) null
);
create sequence dbo.myid
as int
start with 1
increment by 1;
alter table dbo.test
add default next value for dbo.myid for myid;
insert into dbo.test (somevalue)
select 'this' union all
select 'that' union all
select 'and' union all
select 'this';
insert into dbo.test (myid, somevalue)
select 33, 'oops';
select *
from dbo.test
insert into dbo.test (somevalue)
select 'oh the fun';
select *
from dbo.test
--| This should error
insert into dbo.test (myid, somevalue)
select 3, 'This is NO fun';
以下是结果集:
testid myid somevalue
1 1 this
2 2 that
3 3 and
4 4 this
5 33 oops
6 5 oh the fun
最后一次测试,这将是错误的。