当记录更新时,会发生一个触发器,它会分配新记录,一个重要的生成号码(通过存储过程)。
工作正常。
但是,如果批量更新记录,INSERTED
表不仅包含触发器无法处理的一条记录。
如何循环或sql语句,将计算值应用于每个INSERTED
(更新)行。
SELECT @id = id FROM INSERTED -- Could contain multiple rows, but (wrongly) only applies to one
IF (@id IS NOT NULL)
BEGIN
DECLARE @No bigint
EXEC assignNo @No = @No OUTPUT
UPDATE myTable SET No = @No
WHERE id = @id
END
答案 0 :(得分:4)
以下是我试图通过我的质疑来解决的问题。如果您的中央IDENTITY
生成器有一个额外的无用列,这可以避免插入DEFAULT VALUES
的行,difficult, cumbersome and downright unintuitive to do with more than one row(也许不可能在SQL Server 2005上)。因此,假装此生成器表如下所示:
CREATE TABLE dbo.OtherTable(OtherTableID INT IDENTITY(1,1), UselessColumn BIT);
你插入的真实表格如下:
CREATE TABLE dbo.MyTable(ID INT IDENTITY(1,1), [No] INT, foo VARCHAR(32));
我们可以创建一个INSTEAD OF INSERT
触发器,将多行插入dbo.OtherTable
,捕获生成的IDENTITY
值的集,然后最终将这些值与实际数据,将每个生成的值任意分配给一行。
CREATE TRIGGER dbo.trMyTable
ON dbo.MyTable
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @newIDs TABLE(ID INT IDENTITY(1,1), [No] INT);
INSERT dbo.OtherTable(UselessColumn)
OUTPUT inserted.OtherTableID INTO @newIDs([No])
SELECT NULL FROM inserted;
INSERT dbo.MyTable([No],foo)
SELECT n.[No], i.foo FROM @newIDs AS n
INNER JOIN
(
SELECT *, rn = ROW_NUMBER() OVER (ORDER BY foo) FROM inserted
) AS i ON i.rn = n.ID;
END
GO
INSTEAD OF INSERT
触发器更好的原因是因为它避免了双重操作(插入一堆行,然后全部更新)。显然,您的列数多于foo
;这只是一个简单的演示。
如果您还需要对批量更新执行类似的操作,则必须更新具有更多要求的问题(并包括诸如目标表上的主键之类的信息)。
答案 1 :(得分:0)
这是我的解决方案。
我使用otherTable
中的IDs
插入我的INSERTED
以生成数字。另外,我附加了一个datetime
字符串,使其更加独特,因为单独搜索id
在此表中并不是唯一的。
然后,我使用myTable
中的IDs
更新INSERTED
,并使用唯一No
+ {在otherTable
中找到最大id
{1}}字符串标识符。这将被分配到正确的记录,并在批量插入/更新中工作。
datetime