首页 文章

子查询返回的值超过1 . 这是不允许的

提问于
浏览
-1
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 . 当子查询遵循=,!=,<,<=,>,> =或子查询用作表达式时,不允许这样做

怎么解决?

我想做的是

  • 插入 idparentid ,每个增加 @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 回答

  • -3

    你正在与我怀疑的一些错误作斗争 .

    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
    

    在某个地方,子查询返回了您期望的多行 . 子查询错误在插入dbo.Customer(触发t1)的代码中,或者可能在new_table中定义的触发器中 . 我没有在发布的代码中看到任何会抛出子查询异常的内容 .

    插入到其上定义了触发器的表中的触发器(也就是地雷)是一种痛苦的处方 . 如果可能的话,尝试从触发器中重构一些逻辑,并在逻辑上遵循代码 .

  • -1

    首先,您必须假设插入或删除的记录不止一条 . 您不应该在插入或删除的表中将值设置为SQL Server触发器中的标量变量 . 如果插入包含多个记录并且迟早会出现问题,则会导致问题 .

    接下来,您不应该考虑在触发器中设置标识插入 . 你在想什么?如果您有一个标识字段然后使用它,请不要尝试手动创建一个值 .

    接下来,子查询问题显然与另一个触发器相关联,您还假设一次只处理一个记录 . 我怀疑你需要检查数据库中的每个触发器并修复这个基本问题 .

    现在当你运行这部分代码时:

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

    您试图在表中插入所有记录,而不仅仅是插入的记录 . 因此,由于您在另一个表上的触发器是无法编写的,所以您遇到的错误实际上隐藏了当您尝试将具有相同PK的2000条记录插入新表时会出现的错误,或者更糟糕的是如果您没有PK,每次插入一条记录时都会很乐意插入它们 .

  • 3

    你有一个包含语句的触发器:

    SELECT @customerid = id FROM inserted
    

    inserted 表包含插入(或更新 UPDATE 触发器)的每一行的行 . 执行的语句插入多行,触发器触发,并且您的假设已暴露 .

    重新编码触发器以对行集进行操作,而不是单行 .

  • 2

    在任何类型的select中使用子查询时,尝试调整查询,以便子查询只返回1个值而不是多个 .

    如果需要多个,则以表格成为主查询的一部分的方式重构查询 .

    我给出了SQL的例子:从table1中选择col1,(从table2中选择col2,其中table2.col3 = table1.col4);如果col2返回多行,则查询失败,然后将其重新写入:

    从table1,table2中选择col1,col2,其中table2.col3 = table1.col4;

    我希望你明白这一点 .

  • 1

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

    SET @maxid = MAX(ID) FROM another_table
    

相关问题