使用动态表更新
Update with dynamic tables
我必须使用动态 sql 编写更新,因为我只知道要更新的列的名称以及我将用于在我的更新中加入 table 的列的名称。但是我不知道 table 的数量和名字。 tables 的名称我将以这种方式获取程序的参数
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
我知道每个 table 都有列 RecordId 并且想将此 tables 左连接到我在该列上的 TemporaryTable 但我不知道 [=22] 的名称和编号=]秒。例如,我将有一个、两个或十个具有不同名称的 table。我知道这个 tables 名称将以这种方式保存在参数 @Tables 中:
@Tables = N'Customer,Employee,Owner'
有可能以动态方式编写此更新吗?
这是一个答案,它有助于...使用动态编写更新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
备注:
请注意,我认为很重要 - 考虑使用 table 值类型作为参数传递 table 的名称,而不是 comma-separated 文本。
这似乎能满足您的需求,但我不完全理解您的意图。在这里,我们将最终的 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)
我必须使用动态 sql 编写更新,因为我只知道要更新的列的名称以及我将用于在我的更新中加入 table 的列的名称。但是我不知道 table 的数量和名字。 tables 的名称我将以这种方式获取程序的参数
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
我知道每个 table 都有列 RecordId 并且想将此 tables 左连接到我在该列上的 TemporaryTable 但我不知道 [=22] 的名称和编号=]秒。例如,我将有一个、两个或十个具有不同名称的 table。我知道这个 tables 名称将以这种方式保存在参数 @Tables 中:
@Tables = N'Customer,Employee,Owner'
有可能以动态方式编写此更新吗?
这是一个答案,它有助于...使用动态编写更新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
备注:
请注意,我认为很重要 - 考虑使用 table 值类型作为参数传递 table 的名称,而不是 comma-separated 文本。
这似乎能满足您的需求,但我不完全理解您的意图。在这里,我们将最终的 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)