动态查询符合特定条件的所有 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
我有一个 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