ストアドプロシージャの作成時にテーブルが存在する場合でも、遅延名前解決を強制する方法はありますか?


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にはならないようです。
ダニエルジェームズブライアーズ

2
もちろん、ストアドプロシージャを動的SQLでいっぱいにすることで回避できますが、スキーマの変更を処理するスクリプトを生成すると、ストアドプロシージャはそれほど難しくなります。遅延名前解決がどのように機能するかを決定するために公開されているオプションはそれほど多くありません。私が知っている、または少なくとも娯楽に興味があると私が推測できる本に関する唯一の提案は、実際には別の方法です-より厳密にする-sommarskog.se/strict_checks.htmlを参照してください)。
アーロンバートランド

動的SQLについての良い考え。トリガー、インデックス、ビュー、Sproc、および関数についても同じ問題があります。しかし、コードを変更して、テーブル、インデックス、トリガー、関数、sprocの順に変更するようにしました。
ダニエルジェームズブライヤーズ

私はsommarskogの提案が好きです。間違いなくバグを回避するのに役立ちます。Strictオプションを実装した場合は、テーブルが変更されたときにすべての "Strict ON" sprocを再評価して、既存のsprocが壊れていないかどうかを確認することもできます。その後、テーブルとSprocを1つの単位として変更できます。
ダニエルジェームズブライヤーズ

回答:


6

番号。

入力するだけで本当に罪悪感を覚えますが、残念ながら違います。この使用例を聞いたのはこれが初めてであり、それは完全に理にかなっています。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 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.