使用 MS SQL 服务器搜索具有已知值范围的 table 和列名称
Search table and column names having some known range of values using MS SQL server
环境:SQL Server 2016 (v13.00.4259),其中我有只读权限(基本上只是来自多个 table 的 SELECT
)。
用例:我想从数据库中查找所有 table 和列名,其中列类型为 datetime
并且列名中包含 %END%
,并且任何发现值(在 table.column 中)介于某个时间范围(在本例中为一天)之间。
我可以使用以下命令从数据库中找到所有 table 和列名:
SELECT TABLE_NAME as tab, COLUMN_NAME as col
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'datetime' and COLUMN_NAME like '%END%';
我想我需要一个动态查询,因为 table 和列名在静态 SQL 查询中应该是静态的,所以:
WITH enddates AS
(
SELECT TABLE_NAME AS tab, COLUMN_NAME AS col
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'datetime' AND COLUMN_NAME LIKE '%END%'
)
exec('select tab, col
from enddates
where ' + tab + '.' + col + ' >= ''2019-10-21'' and '
+ tab + '.' + col + '< ''2019-10-22'' ')
-- would want it to eval to:
-- SELECT tab, col FROM enddates
-- WHERE $tab.$col >= '2019-10-21' AND $tab.$col < '2019-10-22'
想要获取 table 和列名称的列表,其中某些 %END% 日期时间在 2019-10-21。
但是不行:
"SQL Error [156] [S1000]: Incorrect syntax near the keyword 'exec'."
一个原因可能是,EXEC 中没有看到子查询的 'enddates' 别名,但我认为这不是唯一的问题。为了清楚起见,我认为它显示了我所追求的。
我更多地使用 PostgreSQL,但现在我需要从具有只读访问权限的 SQL 服务器检索此类数据,因此不能在那里制作玩具数据 tables去测试,也没有意见。当然首先创建一个 table 那些有趣的 table.column 对并避免需要子查询会更简单。但是我不知道如何从那些 table 和列名然后在 SQL 服务器中进行动态查询。
编辑:另一个语义上更正确的 "pseudo-code" 想法,使用之前的 WITH-子查询:
SELECT tab, col
FROM enddates
WHERE EXEC('select ' + tab + '.' + col + ' >= ''2019-10-21'' and ' + tab + '.' + col + ' < ''2019-10-22''') = True
一种可能的方法是生成并执行动态语句:
-- Dynamic statement
DECLARE @stm nvarchar(max) = N''
SELECT @stm = CONCAT(
@stm,
CASE WHEN @stm = N'' THEN N'' ELSE N' UNION ALL ' END,
N'SELECT ''',
QUOTENAME(TABLE_NAME),
N''' AS Tab, ''',
QUOTENAME(COLUMN_NAME),
N''' AS Col, COUNT(*) AS Cnt FROM ',
QUOTENAME(TABLE_NAME),
N' WHERE ',
QUOTENAME(COLUMN_NAME),
N' >= ''20191021'' AND ',
QUOTENAME(COLUMN_NAME),
N' < ''20191022'' ',
N'HAVING COUNT(*) > 0'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'datetime' and COLUMN_NAME LIKE '%END%'
-- Validate and execute
PRINT @stm
EXEC sp_executesql @stm
环境:SQL Server 2016 (v13.00.4259),其中我有只读权限(基本上只是来自多个 table 的 SELECT
)。
用例:我想从数据库中查找所有 table 和列名,其中列类型为 datetime
并且列名中包含 %END%
,并且任何发现值(在 table.column 中)介于某个时间范围(在本例中为一天)之间。
我可以使用以下命令从数据库中找到所有 table 和列名:
SELECT TABLE_NAME as tab, COLUMN_NAME as col
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'datetime' and COLUMN_NAME like '%END%';
我想我需要一个动态查询,因为 table 和列名在静态 SQL 查询中应该是静态的,所以:
WITH enddates AS
(
SELECT TABLE_NAME AS tab, COLUMN_NAME AS col
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'datetime' AND COLUMN_NAME LIKE '%END%'
)
exec('select tab, col
from enddates
where ' + tab + '.' + col + ' >= ''2019-10-21'' and '
+ tab + '.' + col + '< ''2019-10-22'' ')
-- would want it to eval to:
-- SELECT tab, col FROM enddates
-- WHERE $tab.$col >= '2019-10-21' AND $tab.$col < '2019-10-22'
想要获取 table 和列名称的列表,其中某些 %END% 日期时间在 2019-10-21。
但是不行:
"SQL Error [156] [S1000]: Incorrect syntax near the keyword 'exec'."
一个原因可能是,EXEC 中没有看到子查询的 'enddates' 别名,但我认为这不是唯一的问题。为了清楚起见,我认为它显示了我所追求的。
我更多地使用 PostgreSQL,但现在我需要从具有只读访问权限的 SQL 服务器检索此类数据,因此不能在那里制作玩具数据 tables去测试,也没有意见。当然首先创建一个 table 那些有趣的 table.column 对并避免需要子查询会更简单。但是我不知道如何从那些 table 和列名然后在 SQL 服务器中进行动态查询。
编辑:另一个语义上更正确的 "pseudo-code" 想法,使用之前的 WITH-子查询:
SELECT tab, col
FROM enddates
WHERE EXEC('select ' + tab + '.' + col + ' >= ''2019-10-21'' and ' + tab + '.' + col + ' < ''2019-10-22''') = True
一种可能的方法是生成并执行动态语句:
-- Dynamic statement
DECLARE @stm nvarchar(max) = N''
SELECT @stm = CONCAT(
@stm,
CASE WHEN @stm = N'' THEN N'' ELSE N' UNION ALL ' END,
N'SELECT ''',
QUOTENAME(TABLE_NAME),
N''' AS Tab, ''',
QUOTENAME(COLUMN_NAME),
N''' AS Col, COUNT(*) AS Cnt FROM ',
QUOTENAME(TABLE_NAME),
N' WHERE ',
QUOTENAME(COLUMN_NAME),
N' >= ''20191021'' AND ',
QUOTENAME(COLUMN_NAME),
N' < ''20191022'' ',
N'HAVING COUNT(*) > 0'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'datetime' and COLUMN_NAME LIKE '%END%'
-- Validate and execute
PRINT @stm
EXEC sp_executesql @stm