动态查询符合特定条件的所有 SQL 个表

Dynamically Query All SQL Tables Matching Certain Criteria

我有一个 SQL 服务器数据库,其中包含许多包含 HTML 内容的表。我需要查询这些表以查看它们的 content 字段中是否包含特定的电子邮件地址。

我能够识别需要使用此查询搜索的表和列:

SELECT
  sys.columns.name AS ColumnName,
  tables.name AS TableName
FROM
  sys.columns JOIN sys.tables ON sys.columns.object_id = tables.object_id
WHERE
  sys.columns.name LIKE '%content%'
  AND (sys.columns.max_length = -1 OR sys.columns.max_length > 100)

上面的查询 returns 86 tables/columns 应该搜索。我能够手动查询这些表以检查各个列是否包含相关的电子邮件地址。这是一个例子:

SELECT *
FROM TableContainingContent
WHERE SomeContent LIKE '%@mail-domain-of-concern.com%' OR SomeContent LIKE '%mailto:%'

我想避免手动进行其中的 86 次查询。我的第一个想法是将 tables/columns 的列表从第一个查询中提取到电子表格中,以简化手动形成这些查询的过程。虽然,如果能找到一种方法来动态查询所有这些 tables/columns 使用类似 sp_executesql 的方法会很棒,因为 tables/columns 的数量每天都在变化。

任何有关实现此目标的最佳方法的想法都将不胜感激。

更新: 这与评论中发布的类似问题不同。我不打算搜索所有表格,只搜索包含符合指定条件的列的表格。

这个怎么样:

SELECT
  REPLACE(REPLACE(REPLACE(
    'SELECT "{t}.{c}" as whereisit, * FROM [{t}] WHERE [{c}] LIKE "%@mail-domain-of-concern.com%" OR [{c}] LIKE "%mailto:%";'
    ,'{t}', t.name)
    ,'{c}', c.name)
    ,'"', '''')
FROM
  sys.columns c JOIN sys.tables t ON c.object_id = t.object_id
WHERE
  c.name LIKE '%content%'
  AND (c.max_length = -1 OR c.max_length > 100)

如果您 运行 它会在网格中生成 85 select 条语句。复制网格,粘贴到新查询 window 和 运行

它是 SQL 等同于您在 Excel 中要执行的操作。你可以看看把它变成一个可执行字符串并执行它..我不确定我会不会

您可以先使用元数据表为这 86 列创建查询字符串,然后 运行 一次性完成查询。

select 'select * from '+table_name+' where '+ column_name +' like ''%@mail-domain-of-concern.com%'' OR ' + column_name +' like ''%mailto:%'''
  from information_schema.tables
where (<your first query>)

还没有测试过这个,我假设多个列可以有一个像content这样的名字单身 table:

DECLARE @SQL nvarchar(MAX),
        @CRLF nchar(2) = NCHAR(13) + NCHAR(10);

SET @SQL = STUFF((SELECT @CRLF +
                         N'SELECT *' + @CRLF +
                         N'FROM ' + QUOTENAME(s.[name]) + N'.' + QUOTENAME(t.[name]) + @CRLF +
                         N'WHERE ' + 
                         STUFF((SELECT @CRLF +
                                       N'   OR ' + QUOTENAME(c.[name]) + N' LIKE ''%@mail-domain-of-concern.com%'' OR ' + QUOTENAME(c.[name]) + N' LIKE ''%mailto:%'''
                                FROM sys.columns c
                                WHERE c.object_id = t.object_id
                                  AND c.[name] LIKE '%content%'
                                  AND (c.max_length = -1 OR c.max_length > 100)
                                FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,8,N'') + N';'
                  FROM sys.tables t 
                       JOIN sys.schemas s ON t.schema_id = s.schema_id
                  WHERE EXISTS(SELECT 1
                               FROM sys.columns c
                               WHERE c.object_id = t.object_id
                                 AND c.[name] LIKE '%content%'
                                 AND (c.max_length = -1 OR c.max_length > 100))
                  FOR XML PATH(N''),TYPE).value(N'.','nvarchar(MAX)'),1,2,N'')

--PRINT @SQL; --Your best friend. Use SELECT if over 4,000 characters

EXEC sp_executesql @SQL;

使用你最好的朋友来调试语法错误,因为我无法生成语句。

编辑:这似乎有效:db<>fiddle