需求:在不知表名、列名的情況下,搜尋全庫所有用戶表的所有字符型列,找出包含指定關鍵字的行。適用於數據治理、審計、敏感信息排查。
USE [YourDatabase];
GO
DECLARE @KeyFind NVARCHAR(MAX) = N'123'; -- 搜尋關鍵字
-- 1. 遍歷所有用戶表
DECLARE TableCur CURSOR LOCAL FAST_FORWARD READ_ONLY FOR
SELECT QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name)
FROM sys.tables
WHERE type = 'U' AND name <> 'dtproperties';
DECLARE @TableName NVARCHAR(MAX);
OPEN TableCur;
FETCH NEXT FROM TableCur INTO @TableName;
WHILE @@FETCH_STATUS = 0
BEGIN
-- 2. 遍歷該表所有字符型列
DECLARE @ColSql NVARCHAR(MAX) = N'
SELECT QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(''' + @TableName + ''', 2)
AND TABLE_NAME = PARSENAME(''' + @TableName + ''', 1)
AND DATA_TYPE IN (''char'',''varchar'',''nchar'',''nvarchar'',''text'',''ntext'',''xml'')';
DECLARE ColCur CURSOR LOCAL FAST_FORWARD READ_ONLY FOR
EXEC sp_executesql @ColSql; -- 動態執行獲取列名
DECLARE @ColName NVARCHAR(MAX);
OPEN ColCur;
FETCH NEXT FROM ColCur INTO @ColName;
WHILE @@FETCH_STATUS = 0
BEGIN
-- 3. 動態構建並執行模糊查詢
DECLARE @DynSql NVARCHAR(MAX) = N'
IF EXISTS (SELECT 1 FROM ' + @TableName + ' WHERE ' + @ColName + N' LIKE N''%' + @KeyFind + N'%'')
BEGIN
DECLARE @Cnt BIGINT = (SELECT COUNT(*) FROM ' + @TableName + ');
PRINT N''Found: Table [' + @TableName + '], Column [' + @ColName + '], Row Count: '' + CAST(@Cnt AS NVARCHAR(20)) + N''.'';
END';
EXEC sp_executesql @DynSql;
FETCH NEXT FROM ColCur INTO @ColName;
END
CLOSE ColCur;
DEALLOCATE ColCur;
FETCH NEXT FROM TableCur INTO @TableName;
END
CLOSE TableCur;
DEALLOCATE TableCur;
GO
| 技術 | 作用 |
|---|---|
sys.tables + INFORMATION_SCHEMA.COLUMNS | 標準元數據視圖,跨版本穩定獲取表/列信息 |
DATA_TYPE IN (...) | 僅搜尋字符型列,跳過數值/日期/二進制列,大幅降低掃描量 |
QUOTENAME() | 自動處理特殊字符表名/列名,防 SQL 注入 |
sp_executesql | 參數化執行動態 SQL,計劃重用、安全 |
LOCAL FAST_FORWARD READ_ONLY | 游標優化組合:僅順向、只讀、局部、輕量 |
sp_start_job 或 SQL Agent 多作業並行跑。CONTAINS/FREETEXT 秒級返回。PRINT 輸出難捕獲,建議 INSERT INTO #ResultLog ... 存表。LIKE '%...%' 會全表掃描,建議維護窗口執行並監控 MAXDOP。可一次性獲取所有表列元數據,減少游標層級,但動態構建查詢邏輯本質不變。