子查询返回的值超过1

时间:2013-12-18 04:02:37

标签: sql-server subquery

我更多地将其作为小费发布,因为我自己找到了答案(在同事的帮助下)。

我们公司的生产域(服务器P)中有一个SQL Server 2012系统,它将主数据库(M)的表(T)中的记录复制到业务域中的另一个SQL Server 2012系统(服务器B) ,相同的数据库和表名)。

我们正在业务服务器上的单独数据库(E)中安装新的ERP系统。供应商要求我将表T中的数据填充到数据库中,当它到达业务服务器时,包括来自连接表(J)和视图(V)的数据。我写了以下Trigger:

    CREATE TRIGGER [dbo].[After_Insert_T] ON  [dbo].[T] AFTER INSERT AS 
    BEGIN
      SET NOCOUNT ON;  -- Prevent extra result sets interfering with SELECT statements.
      SET XACT_ABORT OFF;  -- Avoid automatically rolling back current transaction

      BEGIN TRY
        INSERT E.dbo.T
        SELECT inserted.C1, inserted.C2, inserted.C3, J.C5, V.C7
        FROM inserted LEFT OUTER JOIN
             J ON inserted.C4 = J.C1 LEFT OUTER JOIN
             V ON inserted.C6 = V.C1 
             AND inserted.C3 BETWEEN J.C8 AND J.C9;
      END TRY

      BEGIN CATCH
        DECLARE @ErrorMessage NVARCHAR(4000);
        DECLARE @ErrorSeverity INT;
        DECLARE @ErrorState INT;

        SELECT @ErrorMessage = ERROR_PROCEDURE() + ':  ' + ERROR_MESSAGE(), 
               @ErrorSeverity = ERROR_SEVERITY(), 
               @ErrorState = ERROR_STATE();

        RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState ,16,1) WITH LOG;
      END CATCH
    END

这一切都运行了好几天,但随后记录不再在Business数据库中更新,事件查看器告诉我我收到了错误:

  

错误:50000严重性:16状态:1 After_Insert_T:子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

我无法为我的生活弄清楚如何从我编写的SQL中获得Subquery错误。我想也许V视图有一个子查询但事实并非如此。我在网上搜索并看到一个案例,实际系统复制表中的陈旧记录导致SQL Server返回重复记录,因此我检查了所有基于复制的表,但没有发现任何错误。

然后是答案......

1 个答案:

答案 0 :(得分:1)

ERP供应商已经在我插入的表格上编写了自己的触发器。他的SQL有一个子查询,在某些情况下会返回多行,但是他没有TRY / CATCH,所以它在我的触发器中回落到CATCH,记录了错误。我唯一感到困惑的是,我认为SET XACT_ABORT OFF语句应该允许将原始记录写入表中,尽管有错误,所以我重读了它的帮助,看到了这个:

  

THROW声明表示SET XACT_ABORT RAISERROR没有。新应用程序应使用THROW而不是RAISERROR。

我的CATCH例程几乎是从RAISERROR的帮助中复制的,所以我错过了这一点。

我从中学到的教训是,仅仅因为你的代码报告问题并不理所当然地认为你造成了它!

快乐的编码。

Wayne Ivory
Wespine Industries Pty Ltd