SQL Server 子查询返回了多个值,这是不允许的

fivyi3re  于 2023-02-03  发布在  其他
关注(0)|答案(5)|浏览(232)
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子查询返回了多个值。当子查询跟在=、!=、〈、〈=、〉、〉=之后或当子查询用作表达式时,不允许出现这种情况
怎么解决呢?
我想做的是

  • 插入idparentid,每个增加@maxid
  • initial_table开始
  • 转换为new_table

特恩克斯

    • 新建表格**
id (bigint) 
parentid (bigint - linked to id) 
foo | bar | buzz (others are nvarchar, not really important)
    • 初始表格**
id (bigint) 
parentid (bigint - linked to id)
foo | bar | buzz (others are nvarchar, not really important)
wydwbb8l

wydwbb8l1#

我怀疑你正在与一些错误作斗争。
1.您插入的值违反了new_table中的唯一约束条件。通过与要插入到其中的表进行联接来避免存在错误。调整联接条件以匹配表的约束条件:

insert into new_table (ID, ParentID, Foo, Bar, Buzz)
    select  ID+@maxid, ParentID+@maxid, Foo, Bar, Buzz 
    from    initial_table i
    left
    join    new_table N on 
            i.ID+@maxid = n.ID or 
            i.ParentID+@maxid = n.ParentId
    where   n.ID is null --make sure its not already there

2.在某个地方,子查询返回了多个预期的行。子查询错误可能出现在插入dbo.Customer(触发t1)的代码中,也可能出现在new_table上定义的触发器中。我在发布的代码中没有看到任何会引发子查询异常的内容。
触发器(又名地雷)插入到定义了触发器的表中是一件痛苦的事情。如果可能的话,尝试将触发器中的一些逻辑重构为您可以逻辑遵循的代码。

mrphzbgm

mrphzbgm2#

首先,你必须假设在inserted或deleted中有多个记录。你不应该在SQL Server触发器中将inserted或deleted表中的值设置为标量变量。如果插入包括多个记录,这将导致问题,迟早会出现问题。
接下来,你不应该考虑在触发器中设置标识插入。你在想什么?如果你有一个标识字段,那么就使用它,不要试图手动创建一个值。
接下来,子查询问题显然与另一个触发器有关,您也假设一次只处理一条记录,我怀疑您需要检查数据库中的每个触发器并解决这个基本问题。
现在,当您运行这部分代码时:

INSERT INTO new_table (ID, ParentID, Foo, Bar, Buzz) 
SELECT ID+@maxid, ParentID+@maxid, Foo, Bar, Buzz FROM initial_table

您试图插入表中的所有记录,而不仅仅是插入的记录。因此,由于您在另一个表上的触发器编写不正确,您遇到了一个错误,实际上隐藏了当您试图将具有相同PK的2000条记录插入到新表中时将遇到的错误,或者更糟的是,如果您没有PK,它将在每次插入一条记录时愉快地插入所有记录。

gt0wga4j

gt0wga4j3#

您有一个包含以下语句的触发器:

SELECT @customerid = id FROM inserted

inserted表中插入(或为UPDATE触发器更新)的每一行都包含一行。执行的语句插入了多行,触发器被激发,您的假设被公开。
重新编码触发器以在行集而不是单行上操作。

9ceoxa92

9ceoxa924#

当在任何类型的选择中使用子查询时,试着调整你的查询,使子查询只返回一个值而不是多个值。
如果需要多个表,则重新构造查询,使表成为主查询的一部分。
我给出的例子SQL:

Select col1, (select col2 from table2 where table2.col3=table1.col4) from table1;

如果col2返回多行,则查询失败,然后将其重写为:

Select col1, col2 from table1,table2 where table2.col3=table1.col4;

我希望你明白我的意思。

rdlzhqv9

rdlzhqv95#

你不应该选择它,你应该设置它。

SET @maxid = MAX(ID) FROM another_table

相关问题