用动态表更新

时间:2019-06-05 06:18:04

标签: sql-server dynamic-sql

我必须使用动态sql编写更新,因为我只知道我要更新的列名以及将用于在更新中联接表的列名。但是我不知道表和名称的数量。这样我将在过程参数中得到的表名

declare @Tables = N'Customer,Employee,Owner'

所以我想要这样的更新:

update t 
    set [Status] = 100
from 
   TemporaryTable t 
   left join Customer t1 on t1.RecordId = t.RecordId 
   left join Employee t2 on t2.RecordId = t.RecordId 
   left join Owner t3 on t3.RecordId =t.RecordId

   where 
      t1.RecordId is null 
      and t2.RecordId is NULL
      and t3.RecordId is null 

我知道每个表都会有RecordId列,并希望将此表与我的TemporaryTable联接起来,但是我不知道表的名称和数量。例如,我将有一个,两个或十个名称不同的表。我知道该表名将以这种方式保存在参数@Tables中:

 @Tables = N'Customer,Employee,Owner'

有可能以动态方式编写此更新吗?

2 个答案:

答案 0 :(得分:0)

这是一个答案,可以帮助 ...使用动态sql ... 编写更新,并且仅显示如何生成动态语句。它基于字符串拆分。在SQL Server 2016+中,您可以使用STRING_SPLIT()(因为在此子字符串的顺序并不重要)。对于以前的版本,您需要找到一个字符串拆分功能。

T-SQL:

DECLARE @Tables nvarchar(max) = N'Customer,Employee,Owner'
DECLARE @join nvarchar(max) = N''
DECLARE @where nvarchar(max) = N''
DECLARE @stm nvarchar(max) = N''

SELECT 
   @join = @join + CONCAT(
      N' LEFT JOIN ',
      QUOTENAME(s.[value]),
      N' t',
      ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
      N' ON t',
      ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
      N'.RecordId = t.RecordId'
   ),
   @where = @where + CONCAT(
      N' AND t',
      ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
      N'.RecordId is NULL'
   )
FROM STRING_SPLIT(@Tables, N',') s
SET @stm = CONCAT(
   N'UPDATE t SET [Status] = 100 ',
   N'FROM TemporaryTable t',
   @join,
   N' WHERE ',
   STUFF(@where, 1, 5, N'')
)

PRINT @stm
EXEC sp_executesql @stm

注意:

请注意,我认为这很重要-考虑使用表值类型作为参数而不是逗号分隔的文本来传递表名。

答案 1 :(得分:0)

这似乎可以满足您的需求,尽管我不太了解您要做什么。在这里,我们将分两部分构造最终的SQL(@s@where),然后最后将其连接成最终的SQL。

declare @Tables varchar(100) = N'Customer,Employee,Owner'
declare @tablenames table (tablename nvarchar(100))

insert @tablenames (tablename)
select value
  from string_split(@Tables, ',');

declare @where varchar(max) = ''
declare @s varchar(max) = '
update t
   set [Status] = 100
  from TemporaryTable t'

select @s += '
  left join ' + tablename + ' on ' + tablename + '.RecordId = t.RecordId'
     , @where += case when @where = '' then '' else ' and ' end + tablename + '.RecordId is null
     '
  from @tablenames

print @s + char(13) + ' where ' + @where
exec( @s + char(13) + ' where ' + @where)