2

假设 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
4

1 回答 1

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

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

于 2013-02-20T10:03:42.187 回答