如何使用触发器来增加用户指定的ID?

时间:2018-03-05 20:25:45

标签: sql-server triggers

我正在将一个小型数据库从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. 添加新记录时,应该从现有最大记录中增加值

  2. 当用户覆盖某个值时,应检查该值是否存在。如果找到则恢复现有值,否则允许更改。

  3. 此触发器允许一次添加多行。

    这对于未来的使用效率很高,但实际上,它们每年只会增加1,000条记录。

1 个答案:

答案 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

最后一次测试,这将是错误的。