存储过程是否有“签名”,它是如何定义的?

Eli*_*thH 5 sql-server stored-procedures

我有一个由第三方工具调用的存储过程。我相信它使用的是 ODBC,但它本质上是一个黑匣子。DBMS 是 SQL Server 2012。

当存储过程是一个简单的选择时,第三方工具接收结果集,但是当它首先访问一个临时表时,它不会。例如,以下两个存储过程从 SSMS 返回相同的结果,但只能从工具中成功调用第一个。

我不明白的是,从外部角度来看,这两个功能有何不同。它们都采用相同的参数,最后一个查询产生相同的结果。

存储过程在哪里执行?

--This one works when called both ways
CREATE PROC [dbo].[sp_GetUsers] 
AS
    Select Top 1000 userId 
    from Users

--This only works from SSMS. 
CREATE PROC [dbo].[sp_ComplicatedGetUsers] 
AS

    If OBJECT_ID('tempdb..#TMPUsers') IS NOT NULL
    BEGIN
        DROP TABLE #TMPUsers
    END

    Select Top 1000 userId 
    INTO #TMPUsers
    from Users 

    Select * from #TMPUsers
Run Code Online (Sandbox Code Playgroud)

Rem*_*anu 7

你的“工具”,不管它是什么,都不值得使用。它不遵循TDS 协议。基本上会发生什么,它从服务器获取结果并在解析它时停止,假设第一个条目也是最后一个条目。无论这个工具做什么,我相信那里有一个不错的替代品。

至于回答你的问题:这两个程序有不同的结果,从外面看是不一样的。第二个化身以来自SELECT ... INTO...语句的“xxx 行受影响”消息的形式创建了额外的“结果” 。这会破坏您的工具。NHibernate 因类似问题而臭名昭著,如果更新后缺少“受影响的 xx 行” (即,如果您使用具有 的存储过程进行更新),它就会中断SET NOCOUNT ON

向工具开发人员传递他们需要阅读有关处理结果的 ODBC 规范:

每个 INSERT、UPDATE 和 DELETE 语句都返回一个结果集,该结果集仅包含受修改影响的行数。当应用程序调用 SQLRowCount 时,此计数可用。ODBC 3.x 应用程序必须调用SQLRowCount以检索结果集或SQLMoreResults取消它。当应用程序执行包含多个 INSERT、UPDATE 或 DELETE 语句的批处理或存储过程时,必须使用SQLRowCount或取消使用每个修改语句的结果集SQLMoreResults。可以通过在批处理或存储过程中包含 SET NOCOUNT ON 语句来取消这些计数。