在SQL Server中将所有选择查询与动态表名称合并

时间:2018-10-11 21:42:15

标签: sql sql-server

我有一个带有列ID的帐户表

从所有@ID

保存,并保存为查询以供以后使用

(我有数千个帐户)

ID
------------------------------------
8C76EF27-3080-4DAA-881B-08CD2A1A558F
62FFCB40-AAB4-47A5-953A-08CD2A1A6A43
CFFD7C3C-FEFC-4E97-9970-08CD2A1A3A60
0F5ADAF3-32EF-4D43-BFBD-08CD2A1A5D88
4130153C-24C1-4914-A6F1-08CD2A16DF59

我发现类似这样的东西可以生成一个弹性查询来检索列ID  在要执行的sql中

with getAllAccount as(
select B.ID,B.DisplayName from (
select ID,DisplayName from u3_system.[dbo].[Account] with (nolock)
where ID = '8c76ef27-3080-4daa-881b-08cd2a1a555f' or ParentID = '8c76ef27-3080-4daa-881b-08cd2a1a555f') A
join u3_system.[dbo].[Account] B with (nolock)
on A.ID = B.ParentID
union 
select ID,DisplayName from u3_system.[dbo].[Account] with (nolock)
where ID = '8c76ef27-3080-4daa-881b-08cd2a1a555f'
)

--create pre script
Select 'if exists (select * from sys.tables where name = ''Maillog_' + replace(getAllAccount.ID,'-','') + ') begin Select CampaignID,mailoutID,deliveryDate from  u3_data.data.Maillog_' + replace(getAllAccount.ID,'-','') + ' with(nolock) end union '
from getAllAccount

我想选择所有存在的帐户,然后合并在一起, 并且会有成千上万的帐户,其中一些存在,一些不存在,

现在工会在这种情况下不起作用。 还有另一种方法吗?非常感谢

5 个答案:

答案 0 :(得分:1)

不确定“查询供以后使用”是什么意思。您可以使用以下简单查询为所有表生成选择查询-

Select CONCAT('select * from  u5_data.data.Mailtable_', ID)  from Account

它将生成以下输出,您可以将其保存在文件中以供以后使用。

select * from  u5_data.data.Mailtable_8C76EF27-3080-4DAA-881B-08CD2A1A558F
select * from  u5_data.data.Mailtable_62FFCB40-AAB4-47A5-953A-08CD2A1A6A43
select * from  u5_data.data.Mailtable_CFFD7C3C-FEFC-4E97-9970-08CD2A1A3A60
select * from  u5_data.data.Mailtable_0F5ADAF3-32EF-4D43-BFBD-08CD2A1A5D88
select * from  u5_data.data.Mailtable_4130153C-24C1-4914-A6F1-08CD2A16DF59

答案 1 :(得分:1)

这很有趣; I just tweeted today是我20年来作为SQL开发人员遇到的最糟糕的数据库设计,这个问题听起来很相似。听起来好像您有一堆表,除了名称相同,而且名称代表您要为其检索数据的实体。您现在正尝试批量处理,因此对于存储在帐户中的每个实体,您都希望为这些帐户拉回(我假设为)单个数据集。

这可以通过几种不同的方式来完成,所有这些方式都令人生厌。如果对该数据库的设计有影响,请尝试找出一种重构它的方法。我为此示例选择了CURSOR路由,但也可以使用视图或单个动态SQL语句来完成。但是,这两个选项仅在表的数量较小时才起作用(我过去使用90个或更少的表来完成)。因为我不知道,所以这里是CURSOR。

 USE tempdb;

/*set up demo up here*/
CREATE TABLE Account (ID uniqueidentifier)

INSERT INTO Account (ID)
VALUES ('8C76EF27-3080-4DAA-881B-08CD2A1A558F'),
('62FFCB40-AAB4-47A5-953A-08CD2A1A6A43'),
('CFFD7C3C-FEFC-4E97-9970-08CD2A1A3A60'),
('0F5ADAF3-32EF-4D43-BFBD-08CD2A1A5D88'),
('4130153C-24C1-4914-A6F1-08CD2A16DF59')

--these are not temp tables; be sure to clean up.  naming has hyphens
CREATE TABLE [MT_4130153C-24C1-4914-A6F1-08CD2A16DF59] (val varchar(20))
CREATE TABLE [MT_CFFD7C3C-FEFC-4E97-9970-08CD2A1A3A60] (val varchar(20))
CREATE TABLE [MT_8C76EF27-3080-4DAA-881B-08CD2A1A558F] (val varchar(20))
CREATE TABLE [MT_0F5ADAF3-32EF-4D43-BFBD-08CD2A1A5D88] (val varchar(20))
CREATE TABLE [MT_62FFCB40-AAB4-47A5-953A-08CD2A1A6A43] (val varchar(20))

INSERT INTO [MT_4130153C-24C1-4914-A6F1-08CD2A16DF59] VALUES ('This')
INSERT INTO [MT_CFFD7C3C-FEFC-4E97-9970-08CD2A1A3A60] VALUES ('is')
INSERT INTO [MT_8C76EF27-3080-4DAA-881B-08CD2A1A558F] VALUES ('a')
INSERT INTO [MT_0F5ADAF3-32EF-4D43-BFBD-08CD2A1A5D88] VALUES ('bad')
INSERT INTO [MT_62FFCB40-AAB4-47A5-953A-08CD2A1A6A43] VALUES ('design')


/*magic starts here*/
CREATE TABLE #output (val varchar(20), id uniqueidentifier)

DECLARE @sql nvarchar(200), @Id varchar(50)

DECLARE c CURSOR FOR
SELECT CONVERT(VARCHAR(50), ID) FROM account 

OPEN C

FETCH NEXT FROM C INTO @ID
WHILE @@FETCH_STATUS = 0
BEGIN 

SET @SQL = 'SELECT val, ''' + @ID + ''' FROM [MT_' + @ID + ']'      

INSERT INTO #output (val, id)
exec sp_executesql @SQL


FETCH NEXT FROM C INTO @ID
END

CLOSE C
DEALLOCATE C


/*output comes next*/
SELECT *
FROM #output
ORDER BY ID

DROP TABLE #output


/*clean up demo*/
DROP TABLE Account

DROP TABLE [MT_4130153C-24C1-4914-A6F1-08CD2A16DF59]
DROP TABLE [MT_CFFD7C3C-FEFC-4E97-9970-08CD2A1A3A60]
DROP TABLE [MT_8C76EF27-3080-4DAA-881B-08CD2A1A558F]
DROP TABLE [MT_0F5ADAF3-32EF-4D43-BFBD-08CD2A1A5D88]
DROP TABLE [MT_62FFCB40-AAB4-47A5-953A-08CD2A1A6A43]

长话短说,您遍历accounts表中的每个值并编写动态SQL语句。您可以按ID执行该操作,然后将该SQL语句的输出插入临时表中,然后从该临时表中选择结果。

答案 2 :(得分:0)

在脚本下方使用光标

create table tbl(ID varchar(max))
insert into tbl values('8C76EF27-3080-4DAA-881B-08CD2A1A558F')
insert into tbl values('62FFCB40-AAB4-47A5-953A-08CD2A1A6A43')
insert into tbl values('CFFD7C3C-FEFC-4E97-9970-08CD2A1A3A60')
insert into tbl values('0F5ADAF3-32EF-4D43-BFBD-08CD2A1A5D88')
insert into tbl values('4130153C-24C1-4914-A6F1-08CD2A16DF59')


DECLARE @sql varchar(max)
SELECT  CONCAT('SELECT * FROM ',[ID], CHAR(13) + CHAR(10)  ) as execRecord
into #tmp
from tbl
select * from #tmp

    DECLARE ID_Cursor CURSOR FOR
        SELECT execRecord from #tmp
    DECLARE @tmpID varchar(max)
    OPEN ID_Cursor   
        FETCH NEXT FROM ID_Cursor INTO @tmpID
        WHILE @@FETCH_STATUS = 0   
        BEGIN   
            SET @sql = @tmpID
            EXECUTE SP_EXECUTESQL @sql
            SET @sql = ''
            FETCH NEXT FROM ID_Cursor INTO @tmpID  
        END   

    CLOSE ID_Cursor   
    DEALLOCATE ID_Cursor

DROP TABLE #tmp
DROP TABLE tbl

答案 3 :(得分:0)

您无法在SQL中参数化对象标识符(即,不能为此使用SqlParameter),而必须使用“动态SQL”-这意味着您必须小心避免SQL注入。

假设您必须完全在T-SQL中完成此操作,那么我强烈建议您使用SQL Server 2017,因为它引入了非常有用 STRING_AGG函数(相当于MySQL的{{1} }函数)。

像这样:

GROUP_CONCAT

答案 4 :(得分:0)

找到答案

Select * from 
(   Select case when exists (select * from sys.tables where name = 'Maillog_' + replace(getAllAccount.ID,'-',''))
        Then 'Select CampaignID,mailoutID,deliveryDate from  u3_data.data.Maillog_' + replace(getAllAccount.ID,'-','') + ' with(nolock) union ' End execQuery
    from getAllAccount
) A
where execQuery is not null