2012-01-26 19 views
4

Microsoft SQL 2000を使用して、倍数テーブル(A、B、C、およびD)を一緒に結合したいと考えています。私はテーブルAが常に存在することを知っています。しかし、私はテーブル形式(B、C、D)の少なくとも1つが存在することを知っています。複数のテーブルを結合するSQL

私がしようとしていることを達成するためにこれを行う方法はありますか?

Select * form table a  
If table b exists left Join table b on a.id = b.id  
If table c exists left Join table c on a.id = c.id  
If table d exists left Join table d on a.id = d.id 

答えて

5
私は、しかし、あなたが代わりに

Information Schema Viewsを使用することを奨励し、DYNAMIC ON BIG DISCLAINERされ、sysobjectsを使用しました

declare @myquery varchar(1000) 

set @myquery = 'Select * from a ' 
if exists (select * from sysobjects where xtype='U' and name = 'b') 
begin 
    set @myquery = @myquery + 'inner join b on b.id = a.id ' 
end 
if exists (select * from sysobjects where xtype='U' and name = 'c') 
begin 
    set @myquery = @myquery + 'inner join c on c.id = a.id ' 
end 
if exists (select * from sysobjects where xtype='U' and name = 'd') 
begin 
    set @myquery = @myquery + 'inner join d on d.id = a.id ' 
end 

exec(@myquery) 

をそのためのデータ・ディクショナリ・ビューをチェックして、動的SQLを使用する必要があります

SQL

利点

  • それが書かれたコードの行数を減らすことができ、柔軟性とスケーラビリティ
  • を与える

デメリット

  • それは非常にになることができます複雑な読みにくい。引用符などに埋め込まれた引用符について考えてみましょう。
  • コードの安定性に悪影響を与える可能性があります。一部の動的SQLエラーは、実行時まで認識されません。 (これは、存在しない表を参照する例です)
  • 動的SQLコードは、同等の静的SQLよりもテストするのが難しいです。ダイナミックSQLが遭遇する可能性のあるあらゆる状況をテストすることも不可能なので、固有のリスクが発生します。
  • コードベースで動的SQLの効果的な影響分析を行うのは難しくなります。
  • ダイナミックSQLは誤用されやすく、静的SQLより常に安全性が劣ります。
  • ダイナミックSQL内のクエリコードはクエリプランの対象ではないため、最適化が失われる可能性があります。同等の静的SQLよりも遅い可能性があります
  • 実行時までSQLクエリがわからないため、SQL動的コードをパフォーマンスチューニングするのは難しい場合があります(たとえば、テーブルで必要となる可能性のあるインデックス)
+2

+1 - 私はこのリンクを追加します:www.sommarskog.se/dynamic_sql.html – Lamak

+0

ここでは*の使用を避けてください。代わりにObject_IDを使用してください。 – Pankaj

+0

@StackOverflowユーザー:そうではありません。 select *はフィールド名の選択と区別できません:http://milambda.blogspot.com/2008/01/whats-wrong-with-count.html –

0

このように条件付き結合を行うことはできません。

通常のLEFT JOINを実行できます。何行が参加基準に一致しない場合、これらの列はNULLになります。

Select * 
from table a 
left Join table b on a.id = b.id 
left Join table c on a.id = c.id 
left Join table d on a.id = d.id 

b *の列がNULLであるか、またはCできる*列はNULLまたはDであってもよい*列はNULLであってもよいです。コメンターが言ったようにテーブルが存在しない場合

Select *, COALESCE(b.SOMECOLUMN, c.SOMECOLUMN, d.SOMECOLUMN) AS SOMECOLUMN 
from table a 
left Join table b on a.id = b.id 
left Join table c on a.id = c.id 
left Join table d on a.id = d.id 

、これは動作しません:あなたは最初の非NULL列を選択する必要がある場合は

、COALESCEを使用します。あなたのスキーマが常に期待通りになるように、私は実際に先を進めてテーブルを作成することを主張します。動的SQLは、メンテナンスやデバッグに苦労し、静的SQLとスキーマを調べてメタデータを使用して期待通りの結果を得ることができます(つまり、テーブルがなくなり、依存関係を明示的に表示できる場合はプロシージャやビューは無効です)。

+0

はおそらく*、COALESCE ... –

+1

@Cadeルーをしたいです。これを解決するには、動的SQLを使用する方法があります。 –

+1

これは機能しますか? *テーブル*が存在しない場合でも(テーブルの行*ではなく) – adelphus

-1

私は、結果が表自体ではないことを意味すると思います。

SELECT * FROM TABLEA 
OUTER JOIN TABLEB ON TABLEA.id = TABLEB.id 
OUTER JOIN TABLEC ON TABLEA.id = TABLEC.id 
OUTER JOIN TABLED ON TABLEA.id = TABLED.id 

値が一致しなかった列に対しては、nullが返されます。

ので、あなたは以下

WHERE TABLEB.id is not null 

など

+1

いいえ、彼はテーブル自体について話しています –

1

でフィルタリングすることができますが、クエリです。 *は決してクエリの一部であってはいけません。 *テーブル* B、C&Dが存在する場合OPは知らない、私はあなたが読み違えると思う - 。

declare @query varchar(1000) 

set @query = 'Select ColumnName from a ' 
if exists (select Object_ID from sys.tables where name = 'b') 
begin 
    set @query = @query + 'inner join b on b.id = a.id' 
end 
if exists (select Object_ID from sys.tables where name = 'c') 
begin 
    set @query = @query + 'inner join c on b.id = c.id' 
end 
if exists (select Object_ID from sys.tables where name = 'd') 
begin 
    set @query = @query + 'inner join d on d.id = a.id' 
end 

exec(@query) 
+0

そのSQL 2000、 'sys.tables'はSQL 2005にのみ付属しました –

+0

はい:) sysobjectsは非常に一般的な用語です。だから、特定の文脈で開発者の視点として理解できる開発中に特定の言葉を使用する方が良いでしょう。 – Pankaj

+0

@JamesWisemanはあなたが 'sys.tables'を使用していると言っていますSQL 2000で、クエリが機能しない – Lamak

関連する問題