2017-05-14 14 views
3

これはStackOverflowへの最初の投稿です。私はこの驚くべきリソースを何百年にもわたって何百ものSQLとPowerShellの質問に答えてきましたが、これは私に数日間困惑しています。SQL Update複数のテーブルを結合する(フィールドが存在する場合)

SQL Server 2014 SP2を使用していますが、DATABASE1、FIELD1、FIELD2、FIELD3の更新を複数の他のデータベースから実行しようとしています。

FIELD1は他の複数のデータベースのいずれかに存在する可能性があります。 FIELD1はすべてのデータベースに存在しない可能性があります。問題が発生している場所です。

Database Design Link

私は(匿名の​​)次のクエリを持っており、それが動作するように表示されます。私はそれがDATABASE1ではなく、データベース2に存在しているとして、FIELD8を言ってもらうまで

EXEC sp_MSforeachdb 'IF ''?'' IN (''DATABASE2'',''DATABASE3'',''DATABASE4'') 
BEGIN 
    UPDATE DATABASE1.PARAMETER 
    SET B.[VALUE] = A.[FIELD1] 
    FROM DATABASE1.TABLE1 B 
    INNER JOIN ?.dbo.[TABLE2] A 
    ON A.JOINVALUE = B.JOINVALUE 
    WHERE B.COLUMN2 = ''SOMETHING'' 
    AND COLUMN3= ''PF.T.FIELD1'' 
END ;' 

、DATABASE3かDATABASE4。私は本当に苦労し始めたところ

IF EXISTS (SELECT COLUMN1 FROM Database2.Table2 WHERE Column1='Field8') 
    EXEC ....... 

しかし、それはです:私は次のエラーを取得:私のGoogleとのStackOverflow検索から

Msg 207, Level 16, State 1, Line 30  
Invalid column name 'FIELD8'. 

を、私は(初めて)を使用しようとしました。

上記が意味をなさないことを望みます。 ヒントやご協力をいただければ幸いです。

N.B.データベース1には更新が必要な約3000のフィールドがあります。私はそれまでにすべての私のUPDATE文を動的に構築しました。

+0

..だからフィールドには、いくつかのDBあなたの中に存在していない場合それを作成して更新する必要がありますか?またはフィールドが存在する場合のみ更新する必要がありますか? – gofr1

+0

ちょっと@ gofr1 - それが存在しない場合、私は更新をスキップする必要があります。フィールドが「DATABASE2」、「DATABASE3」、または「DATABASE4」の場合は、「DATABASE1」を更新する必要があります。 – Simon

答えて

1

まず、sp_MSforeachdbは信頼できません。作業の代替については、こちらをご確認ください:

if exists (
    select 1 
    from sys.columns c 
    where c.name = 'pilots_id' /* column name */ 
    and c.object_id = object_id(N'pilots') /* table name */ 
    ) 
    begin 
    select 'Pilots_Id exists' /* do stuff */ 
    end 

rextesterデモ:http://rextester.com/UUXCB18567

1

Making a more reliable and flexible sp_MSforeachdb - Aaron Bertrand

第二に、あなたは列がそうのようなsys.columnsを使用して、指定されたテーブルに存在するかどうかを確認するためのシステム・ビューを使用することができますストアドプロシージャを作成すると、システムテーブルの列とテーブルを検索できます。

ALTER PROCEDURE dbo.check_table_exists 
    -- Add the parameters for the stored procedure here 
     @table_name nvarchar(255), 
     @column_name nvarchar(255) 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    -- Insert statements for procedure here 
    DECLARE @SQLString nvarchar(max), 
      @ParmDefinition nvarchar(500) = N'@table_name nvarchar(255), @column_name nvarchar(255)'; 

    IF OBJECT_ID(N'tempdb..#check_column_exists') is not null DROP TABLE #check_column_exists 
    CREATE TABLE #check_column_exists (
     db nvarchar(500) NULL, 
     column_exists bit NULL 
    ) 

    SELECT @SQLString = 
    (
     SELECT N'USE '+QUOTENAME([name]) +'; '+ 
     'INSERT INTO #check_column_exists '+ 
     'SELECT '''+[name]+''' as [db], '+ 
     '  COUNT(*) as column_exists ' + 
     'FROM sys.tables t ' + 
     'INNER JOIN sys.columns c ' + 
     ' ON t.[object_id] = c.[object_id] ' + 
     'WHERE t.[name] = @table_name and c.[name] = @column_name; ' 
     FROM sys.databases 
     WHERE [name] NOT IN (
      'msdb', 
      'model', 
      'tempdb', 
      'master' 
     ) 
     FOR XML PATH('') 
    ) + 'SELECT [db] FROM #check_column_exists WHERE column_exists = 1; DROP TABLE #check_column_exists;' 

    EXEC sp_executesql @SQLString, @ParmDefinition, @table_name = @table_name, @column_name = @column_name 
END 
GO 

それだけで列を検索し、データベースとテーブル名などを出力します。

出力は次のようになります。その後

db 
----------- 
DATABASE1 
DATABASE4 
... 
etc 

あなたがテーブルにこれを書いて、動的SQL更新クエリのために使用することができます。

DECLARE @table_name nvarchar(255) = 'SomeTable', 
     @column_name nvarchar(255) = 'SomeField' 

DECLARE @results TABLE (
    db nvarchar(500) 
) 

INSERT INTO @results 
EXEC dbo.check_table_exists @table_name, @column_name 

--...Here goes building of dynamic SQL query to update data 
関連する問題