从sp_prepexec运行时,SQL Select失败

时间:2013-10-04 16:04:07

标签: sql sql-server stored-procedures

方案: SQL 2005 表VR_MQLOAD有2列 - MQKEY(PK,int,not null)和MQDATA(varchar(8000),null)

此表触发oninsert,此触发器调用存储过程。

在查询窗口中,我运行:

declare @P0 as nvarchar(4000)
set @P0 = N'TRIG1420441662MF1991782 CAROLYN 201310021356449320131002Y'
insert into dbo.VR_MQLOAD (MQDATA) values(@P0) 

触发器运行,调用sp,一切正常。

这是问题...... 我们有一个失败的外部程序。在profiler中,我可以看到正在运行此命令:

声明@ p1 int 设为@ p1 = 17 exec sp_prepexec @ p1输出,N'@ P0 nvarchar(4000)',N'插入dbo.VR_MQLOAD(MQDATA)值(@ P0)',N'TRIG1420473882MF1993755 CAROLYN 201310031519469020131002Y' 选择@ p1

对我来说,这看起来完全一样。但是,执行此操作时,触发器会运行,调用sp,SP将失败。见下面的SP ......

USE [VEHICLE]
GO
/****** Object:  StoredProcedure [dbo].[VR_UpdateTrigLog]    Script Date: 10/04/2013 11:22:24 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO

ALTER PROCEDURE [dbo].[VR_UpdateTrigLog]
              @sMQData varchar(53),
              @sErrorMsg varchar(255)  OUTPUT
    AS
--
    DECLARE @currentDate datetime
    DECLARE @iCount as integer
--
    DECLARE @sPVI varchar(9)
    DECLARE @sCSN varchar(11)   
    DECLARE @sInputAddress varchar(8)                                
    DECLARE @sTrigDate varchar(8)
    DECLARE @sTrigTime varchar(6)
    DECLARE @sProdDate varchar(8)
    DECLARE @sEventNum varchar(6)
    DECLARE @tmp_TrigDate varchar(9)
    DECLARE @tmp_TrigTime varchar(8)
    DECLARE @tmp_ProdDate varchar(8)
    DECLARE @tmp_CSN varchar(11)
    DECLARE @sUpdateVBI varchar(1)
--
    SELECT @currentDate = GETDATE()
--
    SELECT @sPVI = substring(@sMQData,1,9)
    SELECT @sCSN = substring(@sMQData,10,11)
    SELECT @sInputAddress = substring(@sMQData,21,8)
    SELECT @sTrigDate = substring(@sMQData,29,8)
    SELECT @sTrigTime = substring(@sMQData,37,6)
    SELECT @sEventNum = substring(@sMQData,43,2)
    SELECT @sProdDate = substring(@sMQData,45,8)
    SELECT @sUpdateVBI = substring(@sMQData,53,1)
--
--  Check if rows PVI exists in VBI. 
--  If PVI does not exist, send error message to client, roll back tran
--

    SELECT * 
    FROM vehicle.dbo.vr_VBI
    WHERE pvi=@sPVI

如果我在上面的select语句之前放置了一个“GoTo Finalize”,那么表中的初始插入将完成而不会回滚。如果没有,那么它在此选择上失败并将所有内容卷回来。

那么......这个外部程序通过sp_prepexec进行插入的方式与通过查询窗口手动运行的方式有什么不同?

有关如何查看错误消息的任何建议与为何在这里失败有关?我在SQL代码中进行故障排除是绿色的...不确定当从外部程序运行时如何查看此代码的错误。 BTW ...在外部程序的日志中返回的错误是“db_write操作已完成,业务错误:0已生成结果集以进行更新。”

提前致谢!

2 个答案:

答案 0 :(得分:1)

您应该避免返回结果的触发器的操作。

来自Create Trigger

常规触发注意事项

返回结果

将在SQL Server的未来版本中删除从触发器返回结果的功能。返回结果集的触发器可能会在未设计为使用它们的应用程序中导致意外行为。避免在新的开发工作中从触发器返回结果集,并计划修改当前执行此操作的应用程序。要防止触发器返回结果集,请将“禁止触发结果”选项设置为1。

答案 1 :(得分:0)

FYI ...事实证明,存储过程将从“SELECT”语句返回的内容返回到Trigger,然后又返回到调用应用程序。我们修复它的方法是创建一个参数并将SELECT中的结果返回到参数中,然后相应地处理它。通过将结果返回到参数,它阻止它返回到调用应用程序。