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

问题描述 投票:0回答:1

我正在将一个小型数据库从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. 添加新记录时,它应该从Max existing增加值
  2. 当用户覆盖某个值时,应检查该值是否存在。如果找到则恢复现有值,否则允许更改。

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

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

sql-server triggers
1个回答
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

并在最后一个测试,这将是错误的。

© www.soinside.com 2019 - 2024. All rights reserved.