テーブルの半分に列 A と列 B があるように、約 +100 のテーブルを持つデータベースがあります。
私の質問は、特定の値を持つこの列を持つすべてのテーブルにクエリを実行できますか?
選択 * データベースから
どこ
EACHTABLE HAS COLUMN A = 21 //テーブルに列と値がある場合のみ
と
列 B = 13
私はそれをどの程度正確に行うかわかりません.Googleでも何も出てきません
テーブルの半分に列 A と列 B があるように、約 +100 のテーブルを持つデータベースがあります。
私の質問は、特定の値を持つこの列を持つすべてのテーブルにクエリを実行できますか?
選択 * データベースから
どこ
EACHTABLE HAS COLUMN A = 21 //テーブルに列と値がある場合のみ
と
列 B = 13
私はそれをどの程度正確に行うかわかりません.Googleでも何も出てきません
sp_MSforeachtable
無謀な生活をしたい場合は、文書化されていない MS ストアド プロシージャを使用できます。
create table T1 (
ColumnA int not null,
ColumnB int not null
)
go
create table T2 (
ColumnA int not null,
Column2 int not null
)
go
create table T3 (
Column1 int not null,
ColumnB int not null
)
go
create table T4 (
ColumnA int not null,
ColumnB int not null
)
go
insert into T1 values (1,2);
insert into T2 values (3,4);
insert into T3 values (5,6);
insert into T4 values (7,8);
go
create table #Results (TableName sysname,ColumnA int,ColumnB int)
exec sp_MSforeachtable 'insert into #Results select ''?'',ColumnA,ColumnB from ?',
@whereand = ' and syso.object_id in (select object_id from sys.columns where name=''ColumnA'') and syso.object_id in (select object_id from sys.columns where name=''ColumnB'')'
select * from #Results
drop table #Results
結果:
TableName ColumnA ColumnB
------------------------------------- ----------- -----------
[dbo].[T1] 1 2
[dbo].[T4] 7 8
デフォルトでsp_MSforeachtable
は、その名前が示すように、データベース内の各テーブルに対して同じタスクを実行します。ただし、このプロシージャの 1 つのオプション パラメータである を使用して、データベース内のテーブルを列挙する内部クエリ@Whereand
の句を変更できます。WHERE
この内部クエリは、いくつかのシステム ビューに対して既に 2 つのエイリアスを確立していることを知っておくと役立ちます。(従来のシステム ビュー)o
のエイリアスです。(より現代的なシステム ビュー)のエイリアスです。sysobjects
syso
sys.all_objects
は、実行するテーブルを決定するとsp_MSforeachtable
、最初のパラメーターとして指定されたクエリを実行します。ただし、?
スキーマとテーブル名に置き換えられます (?
はデフォルトの置換文字です。これは必要に応じて変更できます)。
この場合、一時テーブルを作成し、選択した各テーブルの結果をこの一時テーブルに保存し、sp_MSforeachtable
実行が終了したら、それ以上処理せずに結合された結果を選択することにしました。
sp_MSforeachdb
サーバー上の各ユーザーデータベースにアクセスするために呼び出される同様の (そして同様に文書化されていない) プロシージャがあります。これらは組み合わせることもできます (ただし、'
引用符を 2 回重ねる場合には注意が必要です)。ただし、同等のものはありませんsp_MSforeachcolumn
。
これを試して:
select t.name from sys.objects t inner join sys.columns c
on t.name=OBJECT_NAME(c.object_id)
where t.type='U'
and c.name in('col1','col2')
group by t.name
having COUNT(*) = 2
order by 1
次に、すべてのテーブルをループして、これらの列の値を微調整します。
お気に入り
Declare @out TABLE(tblname varchar(100))
if exists(select * from tbl1 where col1='21' and col2='22')
BEGIN
INSERT INTO @out
select tbl1
END
動的クエリを使用して、このように試すことができます。
select 'select * from '+table_name+ ' where'+column_name+'=21'
from information_schema.columns where column_name = 'A'
2 つの手順を使用することをお勧めします。まず、これら 2 つの列を持つデータベース内のすべてのテーブルを見つけて、一時的な派生テーブルに使用します。私は SQL-Server 2008 の専門家ではないので、ホワイトページを確認することをお勧めします。
式は次のようになります。
SELECT tablename
FROM information_schema.tables sdbt
WHERE "column a" IN
(SELECT columns
FROM information_schema.columns col
WHERE col.tablename = sdbt.tablename)
次に、式を使用して、必要な値に従って結果をフィルタリングします。
このコマンドは、列 A に対してのみ、一度にトリックを実行する必要があります。必要に応じて、必要な他の列を含めるように修正します。
exec sp_MSforeachtable
@command1=N'SELECT * FROM ? WHERE A = 21',
@whereand=' and o.name IN (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = ''A'') '