即使在创建存储过程时表存在,是否有办法强制延迟名称解析?


10

在SQL Server中创建存储过程时,可以引用不存在的表。但是,如果该表确实存在,则该过程中引用的任何列都必须存在于该表中(“ 延迟名称解析”)。

是否可以指示SQL Server推迟过程中引用的所有表的名称解析,而不管它们是否存在?我确实希望保留常规语法检查,因此即使有可能,也无法将存储过程定义修改到系统表中。

我希望我的要求看起来有些怪异,所以这里有一些背景知识:我会从用C#编写的应用程序中自动生成表定义和存储过程,并且我很难更改代码以根据SQL的需要对更改进行排序他们。我的代码“保证”架构在事务中是一致的,但是目前,我无法保证在定义引用它们的存储过程之前已定义表列。

下面是C#创建的SQL的规范示例,“说明”了我要解决的问题。

--Say this table already exists.
CREATE TABLE myTable
(
    a NVARCHAR(MAX)
)
GO

--My C# code creates something like this
BEGIN TRAN 
GO

--the stored procedure gets generated first.
CREATE PROCEDURE mySproc
AS
BEGIN
    SELECT a,b FROM myTable
END

--then the table update
ALTER TABLE myTable
    ADD b nvarchar(MAX)

COMMIT TRAN 

我能够解决此问题在C#代码,但我希望有一个简单的“魔力”调整我可以在SQL拉。这将为我节省大量时间。


1
您能否在创建/更改任何过程之前仅处理所有模式更改?为什么在表正确之前必须存在该过程?
亚伦·伯特兰

我现在在代码中使用该选项。SQL的生成方式相当复杂(这是一个简单的示例),但看起来它不会像我想的那样多于PITA。
Daniel James Bryars 2012年

2
您当然可以通过在存储过程中填充动态SQL来解决此问题-但是我无法想象生成脚本来处理架构更改,那么存储过程将非常困难。没有太多选择可以指示延迟名称解析的工作方式。我所知道的书,或者至少可以推断出他们对娱乐感兴趣的唯一建议,实际上是另一种方法-使它更加严格-请参阅sommarskog.se/strict_checks.html)。
阿龙贝特朗

关于动态SQL的好主意。对于触发器,索引,视图,Sproc和函数,我遇到了同样的问题。但是我更改了代码,以便只更改表,索引,触发器,函数,存储程序。
Daniel James Bryars 2012年

我喜欢sommarskog的建议,绝对有助于避免错误。如果他们确实实现了Strict选项,那么当表发生变化时,他们也可以重新评估所有“ Strict ON”存储过程,以查看其是否破坏了现有存储过程-显然,您将需要在DDL上进行“逻辑事务”,因此然后可以将表和存储过程更改为一个单元。
Daniel James Bryars 2012年

Answers:


6

没有。

我只是键入该命令而感到内gui,但不幸的是,没有。这是我第一次听说此用例,这是很有意义的。最好在http://connect.microsoft.com上提交对此的请求,您的孙辈将可以执行此请求。;-)


5

万一您仍然有兴趣,可以采用一种可能的解决方法。这是更新的代码,它将#deferResolution临时表引入到过程中的每个查询。由于临时表仅在运行时存在,因此即使尚无适当的列,该过程也可以编译myTable

#deferResolution由于查询优化器可以证明此过程WHERE NOT EXISTS始终为true ,因此您甚至将为过程中的每个语句获得相同的执行计划(不引用表)。

话虽这么说,这是一个可怕的骇客,主要是出于智力兴趣而存在,并且可能会崩溃。正如亚伦(Aaron)所言,以适当的顺序进行所有模式更改可能会更好。

--Say this table already exists.
CREATE TABLE myTable
(
    a NVARCHAR(MAX)
)
GO

--My C# code creates something like this
BEGIN TRAN 
GO

--the sproc gets generated first.
CREATE PROCEDURE mySproc
AS
BEGIN
    CREATE TABLE #deferResolution (dummy INT NOT NULL)
    SELECT a,b FROM myTable WHERE NOT EXISTS (SELECT * FROM #deferResolution WHERE 0=1)
END

--then the table update
ALTER TABLE myTable
    ADD b nvarchar(MAX)

COMMIT TRAN 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.