我有一个表格,例如临时
Id Col1 Col2 Col3
1 1 2 3
我有另一张表加入信息
Id SourceKey Table TargetKey
1 Col1 A ColA
2 Col2 B ColB
3 Col3 C ColC
我想生成一个查询,它将动态添加内部联接子句,看起来像这个
SELECT * FROM temp
INNER JOIN A ON Col1=ColA
INNER JOIN B ON Col2=ColB
INNER JOIN C ON Col3=ColC
有什么帮助吗?
做不到。
SQL需要在查询编译时了解这些内容,在查看任何数据之前,这样它就可以验证安全性并检查可能的索引。唯一接近于在查询编译时将数据视为列的查询元素是PIVOT
关键字。
否则,您只需要使用CASE
表达式列出每一组可能的列比较,或者在多个步骤上编写动态SQL,首先执行查询以查找所需的列/联接,使用这些结果构建新的查询字符串,然后执行刚创建的字符串。
根据Charlieface的评论,使用string_agg 更新答案
declare
@dsql nvarchar(max)
select @dsql = 'select * from temp ' + string_agg(' join '+ Table + ' on ' + c ,' ')
from (
select Table , string_agg ( SourceKey + ' = ' + TargetKey,' and ') c
from table1
group by Table ) t
select @dsql
EXECUTE sp_executesql @dsql
使用字符串聚合可以非常巧妙地构建动态SQL查询:
尽量弄清楚哪些位是静态的,哪些位是动态的。并使用PRINT @sql
对生成的代码进行测试
DECLARE @sql nvarchar(max) = N'
SELECT *
FROM temp s
' +
(
SELECT STRING_AGG(CAST(
N'JOIN ' + QUOTENAME(SCHEMA_NAME(t.schema_id)) + N'.' + QUOTENAME(t.name) + N' AS T' + CAST(t.object_id AS nvarchar(10)) + N'
ON s.' + QUOTENAME(j.SourceKey) + N' = T' + CAST(t.object_id AS nvarchar(10)) + N'.' + QUOTENAME(c.name)
AS nvarchar(max)), N'
') WITHIN GROUP (ORDER BY j.Id)
FROM sys.tables t
JOIN sys.columns c ON c.object_id = t.object_id
JOIN joininfo j ON OBJECT_ID(j.[Table]) = t.object_id
AND j.TargetKey = c.name
);
PRINT @sql; -- for testing
EXECUTE sp_executesql @sql;
如果您的SQL Server版本不支持STRING_AGG
,则可以使用FOR XML PATH('')
。