1

異なるスキーマに対して同じクエリ?

やあ、

質問があります。テーブルにいくつかのデータを照会します。ただし、データベースには2つの異なるバージョンがあるため、テーブルの列が変更されます。例えば:

バージョン#1の場合、table1には列があります:id、value、バージョン#2の名前、table1には列があります:id、value、title

(#2の場合、データベースに新しいtable2があります。私はそれが#1か#2かを判断するために使用します。)

ここで、1つのクエリで両方のバージョンに適応するクエリを作成する必要があります。

            IF OBJECT_ID('dbo.table2', 'U') IS NULL
            BEGIN
                -- version #1
                SELECT *
                FROM table1 t1 INNER JOIN table3 t3 on t1.Name = t3.Name ......
                ...

            END
            ELSE
            BEGIN
                -- version #2
                SELECT *
                FROM table1 t1 INNER JOIN table3 t3 on t1.title = t3.Name ......
                ...
            END

これをバージョン#2で実行すると、エラーが報告されます:t1.Name無効な列名。

おそらく、EXECを使用してこの問題を回避できると思います。これを行うためのよりエレガントな方法はありますか?

TRY CATCHを試しましたが、それでも同じエラーが報告されます。

私が見つけた奇妙なことは、次のとおりです。別のクエリがあります。

1)一時テーブル#Ldapを作成します。2)openquery(アクティブディレクトリ用)を使用して、一時テーブル#Ldapにデータを挿入します。3)次に、上記のロジックを使用して、バージョン#1か#2かを判断します。

管理スタジオのエディターでt1.Nameがエラーとして強調表示されますが、正常に動作します。エラーとしては報告されません。

これは私に不思議に思います:SQLは最初にクエリ全体をコンパイルしますか?または、他に?

誰かが解決策を知っていますか?

ありがとう

4

3 に答える 3

5

SQLは、すべての列参照を解析および評価しようとします。存在しないテーブルの参照(名前解決の延期)は回避できますが、存在するテーブルに存在しない列は回避できません。IFパーサーは、実行時にユーザーや他の条件付きロジックが何を生成するかを気にしません。これが、これもできない理由です。

IF (1=1)
  CREATE TABLE #foo...
ELSE
  CREATE TABLE #foo...

ELSEパーサーは、実行できなかったとしても、その単純なものでもブロックします。

はい、これを回避する方法は動的SQL(またはそもそもより安定した設計)です。

于 2013-03-25T18:33:27.870 に答える
2

これを回避するには、を使用する必要がありますexec。この問題は、処理のコンパイルフェーズで発生しています。テーブルに列が見つからないため(ありがとうAaron)、失敗します。

if残念ながら、ブロックを使用したり、ブロックを使用したりしても、コンパイル時のエラーを検出することはできませんtry catch

ただし、動的SQLを使用するという正しい解決策を理解しているようです。

t1両方のバージョンで同じ列名を持つビューを作成し、そのビューを使用することで、これを修正することもできます。

于 2013-03-25T18:33:37.240 に答える
0

title_Name別の解決策は、table1にデータベースビューを作成し、 (バージョン#1の場合はtable1.Name、バージョン#2の場合はtable1.titleとして定義)のようなフィールドを作成し、 table1の代わりにデータベースビューを使用することです。あなたのクエリは、次のように参加しました:

INNER JOIN table3 t3 on t1.title_Name = t3.Name 
于 2013-03-25T18:44:58.937 に答える