SQL Update连接多个表(如果存在字段)

时间:2017-05-14 05:50:59

标签: sql-server

这是我向StackOverflow发表的第一篇文章。多年来,我一直在使用这个神奇的资源来回答数百个SQL和PowerShell问题,但是这个问题让我难以忍受了好几天。

我正在使用SQL Server 2014 SP2,我正在尝试更新DATABASE1,FIELD1,然后是FIELD2,然后是来自其他多个数据库的FIELD3。

FIELD1可能存在于多个其他数据库之一中。 FIELD1可能不存在于所有数据库中 - 这就是我遇到问题的地方。

Database Design Link

我有以下(匿名)查询,它似乎正在运行:

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 ;'

直到我说到FIELD8,因为它存在于DATABASE1中但不存在于DATABASE2,DATABASE3或DATABASE4中。然后我得到以下错误:

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

从我的Google和StackOverflow搜索中,我尝试使用(第一次)a:

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

但那是我开始真正挣扎的地方。

希望以上是有道理的。 任何提示或帮助将不胜感激。

N.B。我在Database1中有大约3,000个需要更新的字段。我已经动态地构建了所有的UPDATE语句。

2 个答案:

答案 0 :(得分:1)

首先,sp_MSforeachdb不可靠。如需工作替代方案,请点击此处:Making a more reliable and flexible sp_MSforeachdb - Aaron Bertrand

其次,您可以使用系统视图来检查给定表中是否存在使用sys.columns的列,如下所示:

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 :(得分:1)

您可以创建存储过程,它将搜索系统表中的列和表:

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