ALTER TRIGGER t1
ON dbo.Customers
FOR INSERT
AS
BEGIN TRANSACTION
/* variables */
DECLARE
@maxid bigint
SELECT @customerid = id FROM inserted
SET IDENTITY_INSERT dbo.new_table ON
DECLARE
@maxid bigint
SELECT @maxid = MAX(ID) FROM new_table
INSERT INTO new_table (ID, ParentID, Foo, Bar, Buzz)
SELECT ID+@maxid, ParentID+@maxid, Foo, Bar, Buzz FROM initial_table
SET IDENTITY_INSERT dbo.new_tableOFF
/* execute */
COMMIT TRANSACTION
GO
失败了:
SQL Server子查询返回的值超过1 . 当子查询遵循=,!=,<,<=,>,> =或子查询用作表达式时,不允许这样做
怎么解决?
我想做的是
-
插入
id
和parentid
,每个增加@maxid
-
来自
initial_table
-
成
new_table
日Thnx
new_table
id (bigint)
parentid (bigint - linked to id)
foo | bar | buzz (others are nvarchar, not really important)
initial table
id (bigint)
parentid (bigint - linked to id)
foo | bar | buzz (others are nvarchar, not really important)
5 回答
你正在与我怀疑的一些错误作斗争 .
1.您正在插入违反new_table中唯一约束的值 . 通过加入要插入的表来避免存在错误 . 调整连接条件以匹配表的约束:
在某个地方,子查询返回了您期望的多行 . 子查询错误在插入dbo.Customer(触发t1)的代码中,或者可能在new_table中定义的触发器中 . 我没有在发布的代码中看到任何会抛出子查询异常的内容 .
插入到其上定义了触发器的表中的触发器(也就是地雷)是一种痛苦的处方 . 如果可能的话,尝试从触发器中重构一些逻辑,并在逻辑上遵循代码 .
首先,您必须假设插入或删除的记录不止一条 . 您不应该在插入或删除的表中将值设置为SQL Server触发器中的标量变量 . 如果插入包含多个记录并且迟早会出现问题,则会导致问题 .
接下来,您不应该考虑在触发器中设置标识插入 . 你在想什么?如果您有一个标识字段然后使用它,请不要尝试手动创建一个值 .
接下来,子查询问题显然与另一个触发器相关联,您还假设一次只处理一个记录 . 我怀疑你需要检查数据库中的每个触发器并修复这个基本问题 .
现在当你运行这部分代码时:
您试图在表中插入所有记录,而不仅仅是插入的记录 . 因此,由于您在另一个表上的触发器是无法编写的,所以您遇到的错误实际上隐藏了当您尝试将具有相同PK的2000条记录插入新表时会出现的错误,或者更糟糕的是如果您没有PK,每次插入一条记录时都会很乐意插入它们 .
你有一个包含语句的触发器:
inserted
表包含插入(或更新UPDATE
触发器)的每一行的行 . 执行的语句插入多行,触发器触发,并且您的假设已暴露 .重新编码触发器以对行集进行操作,而不是单行 .
在任何类型的select中使用子查询时,尝试调整查询,以便子查询只返回1个值而不是多个 .
如果需要多个,则以表格成为主查询的一部分的方式重构查询 .
我给出了SQL的例子:从table1中选择col1,(从table2中选择col2,其中table2.col3 = table1.col4);如果col2返回多行,则查询失败,然后将其重新写入:
从table1,table2中选择col1,col2,其中table2.col3 = table1.col4;
我希望你明白这一点 .
你不应该选择它,你应该设置它 .