采用动态连接数的存储过程

Stored procedure that takes in a dynamic number of joins

我正在尝试构建一个存储过程,它接收动态数量的表并将它们连接起来。

SELECT a.Account
FROM Database.Accounts a
JOIN (SELECT Table_Name FROM Database.TableStrings WHERE Row = 1) b ON a.Account = b.Account
JOIN (SELECT Table_Name FROM Database.TableStrings WHERE Row = 2) c ON a.Account = c.Account
JOIN (SELECT Table_Name FROM Database.TableStrings WHERE Row = 3) d ON a.Account = d.Account
...
/*Where the number of joins is equal to COUNT(Table_Name) FROM Database.TableStrings*/

first = SELECT a.Account
        FROM Database.Accounts a
        JOIN (SELECT Table_Name FROM Database.TableStrings WHERE Row = 1) b ON a.Account = b.Account

second = SELECT a.Account
         FROM first a
         JOIN (SELECT Table_Name FROM Database.TableStrings WHERE Row = 2) b ON a.Account = b.Account
...

下面是表格示例和预期输出:

---Database.Accounts---
Account (Integer)
------------------------
111
222
333
444
555

---Database.TableStrings---
Table_Name (String):
------------------------
'Database.HasPhoneNumber'
'Database.HasEmail'
'Database.HasBankAccount'

---Database.HasPhoneNumber---
Account (Integer)
------------------------
111
444

---Database.HasEmail---
Account (Integer)
------------------------
111
222


---Database.HasBankAccount---
Account (Integer)
------------------------
111
222
555

对于示例表,预期输出将是帐户 111。

我很难想象如何在存储过程中执行此操作,如果可能的话。

您可以考虑使用递归查询 (cte) 来处理字符串连接。和 运行 sp_executesql 执行生成的 sql 字符串查询

还可以使用 char()

生成您的 table 别名
declare @strSQL nvarchar(max), @strSQLjoin nvarchar(max)

set @strSQL = 'SELECT a.Account
    FROM Database.Accounts a ';

set @strSQLjoin = '';


with cte as (
    select 'Database.PhoneNumbers' as TableStrings
    union all select 'Database.Emails'
    union all select 'Database.BankAccounts'
), cte2 as (
    select TableStrings, (char(row_number() over (order by TableStrings) + 97)) as tbl 
    from cte)
    select @strSQLjoin = coalesce(@strSQLjoin 
        + ' JOIN (SELECT Table_Name FROM '+TableStrings+') '+tbl+' ON a.Account = '+tbl+'.Account '
        ,' JOIN (SELECT Table_Name FROM '+TableStrings+') '+tbl+' ON a.Account = '+tbl+'.Account')      
    from cte2;

set @strSQL=@strSQL + @strSQLjoin;
print @strSQL
exec sp_executesql @strSQL

我知道这不是您所要求的。但是由于向 TableStrings 添加新行 table 已经意味着架构更改(创建新的 tables),此时您最好相应地更新存储过程而不是使用动态 SQL

如果这是一个选项,那么例如您的查询可能看起来像

SELECT a.Account
FROM Database.Accounts a
 where exists (select 1 from Database.HasPhoneNumber e where e.Account = a.Account)
   and exists (select 1 from Database.HasEmaile e where e.Account = a.Account)
   and exists (select 1 from Database.HasBankAccount e where e.Account = a.Account)
...

根据您的示例数据和示例查询,您可以在不使用动态查询的情况下实现您想要的效果

-- sample table
declare @Accounts table
(
    Account int
)

declare @TableStrings table
(
    Table_Name  varchar(100),
    Account     int
)

-- sample data
insert into @Accounts
values (111), (222), (333), (444), (555)

insert into @TableStrings
values ('Database.HasPhoneNumber', 111), ('Database.HasPhoneNumber', 444),
       ('Database.HasEmail', 111),       ('Database.HasEmail', 222),
       ('Database.HasBankAccount', 111), ('Database.HasBankAccount', 222),
       ('Database.HasBankAccount', 555)

select  a.Account
from    @Accounts a
        inner join @TableStrings t  on  a.Account   = t.Account
group by a.Account
having count(*) = (select count(distinct Table_Name) from  @TableStrings)