SQL Server:为啥要在存储过程名称的末尾添加“;1”?

Posted

技术标签:

【中文标题】SQL Server:为啥要在存储过程名称的末尾添加“;1”?【英文标题】:SQL Server: Why would i add ";1" to the end of a stored procedure name?SQL Server:为什么要在存储过程名称的末尾添加“;1”? 【发布时间】:2011-04-09 22:24:45 【问题描述】:

我今天遇到了一个兼容性问题,因为客户从 Windows XP 升级到 Windows 7。

(12 岁的代码)正在调用 SQL Server 上的存储过程,称为

ai_nextid

除了调用存储过程时使用的名称:

ai_nextid;1

是的,附加了“;1”。显然,Windows 95、Windows 2000、Windows XP 和可能的 Windows Vista 中的 SQL Server 驱动程序都可以使用这个特别添加的后缀。但 Windows 7 中的 SQL Server ODBC 驱动程序不同,导致错误:

一般 SQL 错误。 [Microsoft][ODBC SQL 驱动程序][SQL Server]找不到存储过程 'ai_nextid;1'。 [Microsoft][ODBC SQL 驱动程序][SQL Server]指示变量需要但未提供'。

带有原生错误2812。

这带来了 4 个问题:

为什么我们要在存储过程名称的末尾附加;1? (它的作用是什么) 为什么 SQL Server 驱动程序忽略它? 为什么在 Windows 7 中进行了重大更改? 是否记录了重大兼容性更改?

最后两个问题可能是相同的,因为如果他们记录它,他们会证明它是合理的。

【问题讨论】:

这是numbered stored procedures 的语法。您的存储过程是否实际编号或;1 是否只是默认为未编号版本? 什么都知道。存储过程实际上被声明为CREATE PROCEDURE ai_nextid;1 ...。谁知道? 如果他们都只使用;1,您可以将所有程序写入一个文件,然后搜索用空字符串替换;1。运行该脚本文件并在调用存储过程的应用程序中执行相同的搜索/替换。 令我感兴趣的是,Delphi 2010 仍然为新的 TADOStoredProcs 添加了后缀默认值,即使我们没有在我们的数据库中使用它们。该列表仍以 Foo;1、Bah;1 等形式返回。Martin 的链接对于找出这一点很有用。如何解决它...我不知道。但是我们的客户端应用程序可以在带有后缀的 XP 和 Win7 上运行。 【参考方案1】:

见CREATE PROCEDURE (Transact-SQL) SQL Server 2008 documentation

--Transact-SQL Stored Procedure Syntax
CREATE  PROC | PROCEDURE  [schema_name.] procedure_name            [ ; number ]  <<<<<<
    [  @parameter [ type_schema_name. ] data_type  
        [ VARYING ] [ = default ] [ OUT | OUTPUT ] [READONLY]
    ] [ ,...n ] 
[ WITH <procedure_option> [ ,...n ] ]
[ FOR REPLICATION ] 
AS  [ BEGIN ] sql_statement [;] [ ...n ] [ END ] 
[;]

<procedure_option> ::= 
    [ ENCRYPTION ]
    [ RECOMPILE ]
    [ EXECUTE AS Clause ]

;号码

一个可选的整数,用于对同名的过程进行分组。 可以使用一个 DROP PROCEDURE 语句将这些分组过程一起删除。

注意:

This feature will be removed in a future version of Microsoft SQL Server.
    Avoid using this feature in new development work, and plan to
    modify applications that currently use this feature.

编号过程不能使用 xml 或 CLR 用户定义类型,并且 不能在计划指南中使用。

您可以使用此系统视图找到所有这些并开始将它们重写为单独的过程:

sys.numbered_procedures (Transact-SQL)

【讨论】:

令人困惑的是客户端机器中的所有内容都发生了变化;升级到 Windows 7。所以该功能仍然存在在服务器上 - 但已从客户端驱动程序中删除。【参考方案2】: 为什么我们要在存储过程名称的末尾附加 ;1? (它的作用是什么)

;1 表示您正在调用编号存储过程。您可以将InsertOrders;1InsertOrders;2InsertOrders;3 作为具有相同名称的不同版本。当您对 InsertOrders 执行 DROP 时,所有编号的版本都将被删除。这是一个穷人的重载实现。

为什么 SQL Server 驱动程序忽略它?

旧的 SQL Server 驱动程序要么知道编号的 proc 是什么,要么不够聪明,无法解析和编译那部分代码。

为什么在 Windows 7 中进行了重大更改?

是否记录了重大兼容性更改?

未来版本将不支持此功能,但 R2 支持编号存储过程。我个人从未将编号的 proc 投入生产 - 只玩过它们,说“哦酷”然后继续前进。

【讨论】:

【参考方案3】:

我有同样的问题,直到我添加了一些代码,如果它仍然在 StoredProcName 的末尾,则删除“;1”:

strProcName := StoredProc.StoredProcName;

IF (length(strProcName) > 2) AND (copy(strProcName, length(strProcName) - 1, 2) = ';1') THEN

  BEGIN

    delete(strProcName, length(strProcName) - 1, 2);

    StoredProc.StoredProcName := strProcName;

  END IF;

StoredProc.Prepare;

StoredProc.ParamByName('@cntid').AsInteger := nCounterID;

StoredProc.ParamByName('@range').AsInteger := nRange;

StoredProc.ExecProc;

result := StoredProc.ParamByName('@Status').AsInteger;

【讨论】:

以上是关于SQL Server:为啥要在存储过程名称的末尾添加“;1”?的主要内容,如果未能解决你的问题,请参考以下文章

Vim 为啥要在文件末尾添加新行?

为啥我们不能在 SQL Server 中的函数内执行存储过程

为啥需要以只读方式输入 SQL Server 存储过程的表值参数?

为啥我的存储过程没有出现在我的 SQL Server 数据库中?

SQL Server2008 存储过程传入表名称和列名称,如何在语句中使用表明引用列名?

带参数的存储过程