【问题标题】:Create / Alter procedure referencing non-existing table or view创建/更改引用不存在的表或视图的过程
【发布时间】:2020-09-01 09:42:51
【问题描述】:

根据MSDN

过程可以引用尚不存在的表。创作时 时间,只执行语法检查。程序未编译 直到它第一次被执行。只有在编译期间 过程中引用的所有对象都已解析。因此,一个 语法正确的过程,它引用的表不 可以成功创建exist;但是,该程序在 如果引用的表不存在,则执行时间。

我一直认为引用的表 已检查。例如,如果您在现有视图中引用了不正确的列,它会在编译时抱怨

那么这里发生了什么,为什么在过程中检查列而不是视图/表?

【问题讨论】:

  • A VIEW 不是存储过程,它们是完全不同的对象。您也真的使用 SQL Server 2005 吗?近 5 年没有支持,您应该紧急寻找升级路径。
  • @Larnu 抱歉,我已经更新了标签。 SP 正在使用其中的视图。

标签: sql-server sql-server-2017


【解决方案1】:

该文档引用的是,在创建存储过程时,它没有经过验证。拿下这批:

USE Sandbox;
GO


CREATE PROC dbo.MyProc @ID int AS
BEGIN

    SELECT *
    FROM dbo.MyTable 
    WHERE ID = @ID;
END;

GO

CREATE TABLE dbo.MyTable (ID int, 
                          SomeValue varchar(20));
INSERT INTO dbo.MyTable
VALUES(1,'asdjka'),
      (2,'asdkj');
GO

EXEC dbo.MyProc 1;
GO

DROP TABLE dbo.MyTable;
DROP PROC dbo.MyProc;

请注意,我 CREATE dbo.MyProc 之前 dbo.MyTable,即使它引用了该对象。这是因为在创建或更改过程时并未检查过程中对象的有效性。

另一方面,VIEW 在创建时进行检查。

CREATE TABLE dbo.MyTable (ID int, 
                          SomeValue varchar(20));
INSERT INTO dbo.MyTable
VALUES(1,'asdjka'),
      (2,'asdkj');

GO
--Fails
CREATE VIEW dbo.MyView AS

    SELECT ID,
           SomeValue,
           SomeInt
    FROM dbo.MyTable;
GO
--Fails
CREATE VIEW dbo.MyOtherView AS

    SELECT *
    FROM dbo.MyOtherTable;
GO

DROP TABLE dbo.MyTable;

取决于对象类型,取决于发出 DDL 语句时验证的内容和不验证的内容。


编辑:似乎 OP 所质疑的是,如果该对象确实存在,为什么会出现错误,但他们引用了一个不存在的列。以以下批次为例:

USE Sandbox;
GO

CREATE TABLE dbo.MyTable (ID int, 
                          SomeValue varchar(20));
INSERT INTO dbo.MyTable
VALUES(1,'asdjka'),
      (2,'asdkj');
GO

CREATE PROC dbo.MyProc @ID int AS
BEGIN

    SELECT ID,
           SomeValue,
           AnotherValue
    FROM dbo.MyTable 
    WHERE ID = @ID;
END;
GO

DROP TABLE dbo.MyTable;
GO
DROP PROC dbo.MyProc;
GO

这会失败,因为 AnotherValue 列不存在。这实际上包含在您引用的文档中:

过程可以引用尚不存在的表。在创建时,只执行语法检查。

它明确指出您可以引用一个不存在的。它没有提到没有的对象,或者(更具体地说)表/对象中的列。引用确实存在的表在创建时进行验证。

【讨论】:

  • 谢谢,虽然我认为你误解了一点。我可以创建一个过程,它引用一个不存在的视图。但是,如果该视图确实存在,它会告诉我(在编译时)我的列名不正确。
  • 如果您引用的对象确实存在,那么语法必须正确,@m.edmondson。不会检查表是否存在,但如果存在,则需要引用有效列。如果您的VIEW/TABLE 定义一直在变化,则表明存在更大的潜在问题/
  • 正确我知道这正在发生,但为什么会这样?当然要么总是在编译时检查,要么总是在执行时检查,而不是某种混合?
  • 你没有引用一个不存在的表,@m.edmondson 所以你引用的文档是不相关的,正如我在编辑中指出的那样回答。您正在引用一个 确实存在 的表并传递了一个无效的列名。一列一个表。
  • 这真是令人惊讶
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多