DDL异常在表上捕获但不在列上捕获

时间:2013-02-19 11:42:11

标签: sql sql-server-2008-r2 ddl

假设MyTable表已经存在,为什么在第一个语句中打印“In catch”,而在第二个语句上不打印?

似乎是在重复的表名上捕获错误,而不是在重复的列名

首先:

BEGIN TRY

    BEGIN TRANSACTION 

    CREATE TABLE MyTable (id INT)

    COMMIT TRANSACTION

END TRY
BEGIN CATCH
    PRINT 'in Catch'
    ROLLBACK  TRANSACTION
END CATCH

第二

BEGIN TRY

    BEGIN TRANSACTION 

    ALTER TABLE MyTable ADD id INT

    COMMIT TRANSACTION

END TRY
BEGIN CATCH
    PRINT 'in Catch'
    ROLLBACK  TRANSACTION
END CATCH

1 个答案:

答案 0 :(得分:1)

不同之处在于alter table语句生成编译时错误,而不是运行时错误,因此catch块永远不会执行,因为批处理本身不会被执行。

您可以使用SQL Server Management Studio中的显示估计执行计划按钮来检查这一点,您将看到CREATE TABLE语句,显示估计计划,而对于ALTER TABLE语句,则在SQL Server之前抛出错误甚至可以生成计划,因为它无法编译批次。

编辑 - 说明: 这与延迟名称解析在SQL Server中的工作方式有关,如果要创建对象,SQL Server在运行时不会检查该对象是否已存在。但是,如果引用存在的对象中的列,则引用的列等必须正确,否则语句将无法编译。

这方面的一个例子是存储过程,比如你有下表:

create table t1
(
id int
)

然后你创建一个这样的存储过程:

create procedure p1
as
begin
select * from t2
end

它将起作用,因为延迟名称解析在创建过程时不需要对象存在,但如果执行过程则会失败

但是,如果您创建如下过程:

create procedure p2
as
begin
select id2 from t1
end

由于您引用了一个确实存在的对象,因此无法创建该过程,因此延迟名称解析规则不再适用。