2

テーブルMyTableがすでに存在すると仮定すると、「In catch」が最初のステートメントに出力され、2番目のステートメントには出力されないのはなぜですか。

重複するテーブル名ではエラーをキャッチしているようですが、重複する列名ではエラーをキャッチしていないようです

初め:

BEGIN TRY

    BEGIN TRANSACTION 

    CREATE TABLE MyTable (id INT)

    COMMIT TRANSACTION

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

2番:

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 サーバーが生成する前にエラーがスローされます。バッチをコンパイルできないため、計画。

編集 - 説明: これは、遅延名前解決が SQL サーバーで機能する方法に関係しています。オブジェクトを作成している場合、SQL サーバーは実行時までオブジェクトが既に存在することを確認しません。ただし、存在するオブジェクトの列を参照する場合は、参照する列などが正しくなければ、ステートメントはコンパイルに失敗します。

この例はストアド プロシージャで、次のテーブルがあるとします。

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 に答える