【问题标题】:Create dynamic list of tables based on list with wildcards根据带有通配符的列表创建动态表列表
【发布时间】:2021-09-08 18:05:07
【问题描述】:

所以我有一个我想要的表列表(带有通配符)

CREATE TABLE [config].[datalist](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [order] [int] NULL,
    [dbname] sysname NULL,
    [schemaname] sysname NULL,
    [tablename] sysname NULL
) 
GO
SET IDENTITY_INSERT [config].[datalist] ON 
GO
INSERT [config].[datalist] ([id], [order], [dbname], [schemaname], [tablename]) VALUES (1, 1, N'TEST', N'audit*', N'*')
GO
INSERT [config].[datalist] ([id], [order], [dbname], [schemaname], [tablename]) VALUES (7, 2, N'TEST', N'conversie', N'BR')
GO
INSERT [config].[datalist] ([id], [order], [dbname], [schemaname], [tablename]) VALUES (8, 3, N'TEST', N'datalibrary', N'T*')
GO
INSERT [config].[datalist] ([id], [order], [dbname], [schemaname], [tablename]) VALUES (9, 3, N'BIML', N'*', N'*')
GO
SET IDENTITY_INSERT [config].[datalist] OFF
GO

SELECT  [id]
      ,[order]
      ,[dbname]
      ,[schemaname]
      ,[tablename]
  FROM [UITWISSEL].[config].[datalist]

这给了我

id  order   dbname  schemaname  tablename
1   1   TEST    audit*  *
7   2   TEST    conversie   BR
8   3   TEST    datalibrary T*
9   3   BIML    *   *

现在我需要的是表格config.datalist中提到的所有表格的列表

所以我想要一个列表:

id 1) 数据库TEST 中schemaname 以audit 开头的所有表

id 7) 模式 conversie 中数据库 TEST 中名称为 BR 的所有表

id 8) 数据库TEST 中模式“datalibrary”中名称以T 开头的所有表

id 9) 数据库BIML 中所有架构中的所有表

我有以下代码,但这仅适用于数据库BIML。 如何让这段代码适用于 config.datalist.dbname 中提到的所有数据库?

select distinct  t.name as TableName
, 'SELECT  * FROM ' + quotename(replace(replace(ds.[dbname] ,'[',''),']',''))+'.'+
quotename(s.name)+'.'+
quotename(t.name) AS selectquery 
,s.name as schemaname
,ds.[order]
from BIML.sys.schemas s
left join BIML.sys.tables t on s.schema_id = t.schema_id  
inner join [UITWISSEL].[config].[datalist] ds on s.name like  replace(ds.schemaname,'*','%') COLLATE DATABASE_DEFAULT
inner join [UITWISSEL].[config].[datalist] dt on t.name like  replace(ds.tablename,'*','%') COLLATE DATABASE_DEFAULT
order by ds.[order] , s.name, t.name

这给了我

TableName   selectquery schemaname  order
connections SELECT  * FROM [BIML].[config].[connections]    config  3
FilesToImport   SELECT  * FROM [BIML].[config].[FilesToImport]  config  3

【问题讨论】:

    标签: sql dynamic-sql sql-server-2019


    【解决方案1】:

    假设您正在对语句进行参数化以获取表列表,那么您可以这样做:

    DECLARE @ListID int = 8; --Your parameter
    
    DECLARE @SQL nvarchar(MAX),
            @CRLF nchar(2) = NCHAR(13) + NCHAR(10);
    
    DECLARE @DatabaseName sysname,
            @SchemaName sysname,
            @TableName sysname;
    
    SELECT @DatabaseName = REPLACE(dbname,'*','%'),
           @SchemaName = REPLACE(schemaname,'*','%'),
           @TableName = REPLACE(tablename,'*','%')
    FROM config.datalist
    WHERE id = @ListID;
    
    SET @SQL = N'SELECT s.[name] AS SchemaName,' + @CRLF +
               N'       t.[name] AS TableName' + @CRLF +
               N'FROM ' + QUOTENAME(@DatabaseName) + N'sys.schemas s' + @CRLF + 
               N'     JOIN ' + QUOTENAME(@DatabaseName) + N'sys.tables t ON s.schema_id = t.schema_id' + @CRLF +
               N'WHERE s.[name] LIKE @SchemaName' + @CRLF +
               N'  AND t.[name] LIKE @TableName;';
    
    PRINT @SQL;
    --EXEC sys.sp_executesql @SQL, N'@SchemaName sysname, @TableName sysname', @SchemaName, @TableName; --Uncomment to run
    

    【讨论】:

      【解决方案2】:
      declare @i as int = 1
      declare @db_list table (id int identity(1,1), dbname sysname, [order] int)
      declare @resultlist table ([order] int,dbname sysname, schemaname sysname, tablename sysname, selectquery  nvarchar(4000))
      declare @act_dbname sysname
      declare @act_order int =1
      declare @sql as nvarchar(4000)
      
      insert into @db_list 
      select distinct dbname, [order] from UITWISSEL.[config].[datalist] order by [order]
      
      while @i <= (select max(id) from @db_list)
      BEGIN
      
      set @act_dbname = (select dbname from @db_list where id = @i)
      set @act_order = (select [order] from @db_list where id = @i)
      set @sql = '
      
      select distinct  
      '+ cast(@act_order as varchar(4)) + ' as [order]
      ,'''+ @act_dbname +''' as dbname
      ,s.name as schemaname
      ,t.name as tablename
      , ''SELECT  * FROM '' + quotename('''+ @act_dbname + ''')+''.''+
          quotename(s.name)+''.''+
          quotename(t.name) 
      AS selectquery 
      
      from  '+ @act_dbname + '.sys.schemas s  
      left join '+ @act_dbname + '.sys.tables t on s.schema_id = t.schema_id  
      inner join [UITWISSEL].[config].[datalist] ds on s.name like  replace(ds.schemaname,''*'',''%'') COLLATE DATABASE_DEFAULT
      inner join [UITWISSEL].[config].[datalist] dt on t.name like  replace(ds.tablename,''*'',''%'') COLLATE DATABASE_DEFAULT
      order by [order] , s.name, t.name
      '
      print  @sql 
      insert into @resultlist exec sp_executesql @sql
      set @i = @i+1
      END
      
      select * from @resultlist order by [order], schemaname, tablename
      

      【讨论】:

      • 小心,这种尝试引入了注入问题。 OP 在注入值时正确使用了QUOTENAME,您也应该如此。
      • 我会补充一下,感谢您指出这一点。
      猜你喜欢
      • 2020-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2013-11-12
      相关资源
      最近更新 更多