我寻找了答案,但是所有我找到的都是人们问如何在数据库中搜索所有表的所有列的值。我只想搜索特定表的所有列。人们为所有表问题想出的代码很复杂,让我很难弄清楚它究竟在哪里搜索特定的表。有人能帮帮我吗?谢谢。
我寻找了答案,但是所有我找到的都是人们问如何在数据库中搜索所有表的所有列的值。我只想搜索特定表的所有列。人们为所有表问题想出的代码很复杂,让我很难弄清楚它究竟在哪里搜索特定的表。有人能帮帮我吗?谢谢。
LIKE '%' + @SearchStr + '%'
。你必须编写许多复杂的代码来支持它,而且那种解决方案的性能也不好。我修改了这个存储过程,使其接受一个表名作为第二个参数,并仅在该表中搜索数据:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SearchOneTable]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[SearchOneTable]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROC [dbo].[SearchOneTable]
(
@SearchStr nvarchar(100) = 'A',
@TableName nvarchar(256) = 'dbo.Alerts'
)
AS
BEGIN
CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
--SET NOCOUNT ON
DECLARE @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
--SET @SearchStr2 = QUOTENAME(@SearchStr, '''') --exact match
SET @ColumnName = ' '
WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
BEGIN
SET @ColumnName =
(
SELECT MIN(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')
AND QUOTENAME(COLUMN_NAME) > @ColumnName
)
IF @ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC
(
'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630)
FROM ' + @TableName + ' (NOLOCK) ' +
' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
)
END
END
SELECT ColumnName, ColumnValue FROM #Results
END
GO
text
或xml
数据类型,而对于这样的要求,谁知道他们的表中可能有什么! - JNK这里有一个解决方案,类似于@Decker97的方法,从元数据中找出哪些列适合进行字符串搜索。假设是2005+版本。支持text
/ntext
(虽然您不应该再使用它们了),char
/nchar
/varchar
/nvarchar
,甚至在适当的情况下将前导N
放在搜索字符串上。不支持xml
列。
它所做的略有不同之处在于,它为每个表返回单个结果集,而不是为每个单独的列返回结果集,因此无论有多少列匹配,输出只有一行匹配结果。
DECLARE @SearchTerm nvarchar(255) = N'foo',
@TableName nvarchar(128) = NULL,
@sql nvarchar(max) = N'';
;WITH tables(obj_name, obj_id, columns) AS
(
SELECT obj_name = QUOTENAME(s.name) + N'.' + QUOTENAME(t.name),
obj_id = [object_id],
columns = (
SELECT N',' + QUOTENAME(c.name)
FROM sys.columns AS c
WHERE c.[object_id] = t.[object_id]
ORDER BY c.column_id FOR XML PATH(N''),
TYPE).value(N'./text()[1]', N'nvarchar(max)')
FROM sys.tables AS t INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE (t.name = @TableName OR @TableName IS NULL)
AND EXISTS
(
SELECT 1 FROM sys.columns AS c
WHERE c.[object_id] = t.[object_id]
AND c.system_type_id IN (35,99,167,175,231,239)
)
)
SELECT @sql += N'SELECT N' + char(39)
+ REPLACE(obj_name, char(39), char(39) + char(39))
+ char(39) + columns + N' FROM ' + obj_name + N' WHERE '
+ STUFF((
SELECT N' OR ' + QUOTENAME(name) + N' LIKE ' + CASE
WHEN c.system_type_id IN (99,231,239)
THEN 'N' ELSE N'' END
+ char(39) + N'%' + @SearchTerm + N'%' + char(39)
FROM sys.columns AS c WHERE c.[object_id] = tables.obj_id
AND c.system_type_id IN (35,99,167,175,231,239)
ORDER BY name FOR XML PATH(''), TYPE
).value(N'./text()[1]', N'nvarchar(max)')
+ char(59) + char(13) + char(10), 1, 4, N'')
FROM tables;
PRINT @sql;
--EXEC sys.sp_executeSQL @sql;
根据您系统中可搜索列的数量,PRINT
不一定会显示完整命令,您可能会认为代码存在错误(或者至少是 PRINT
存在截断文本的 bug)。您可以在 SSMS 设置中增加结果到文本输出的大小,但这仍然不够。您可以使用 SELECT CONVERT(xml, @sql);
代替(有关更多信息,请参见 this tip)。
新函数 STRING_AGG()
可以大大简化代码,如果您有很多现有代码使用 FOR XML PATH
连接字符串,则在重新访问它们时将其更新为更现代的方法可能会很有用。因此,以下是使用 STRING_AGG()
的版本:
DECLARE @SearchTerm nvarchar(255) = N'foo',
@TableName nvarchar(128) = NULL,
@sql nvarchar(max) = N'';
;WITH tables(obj_name, obj_id, columns) AS
(
SELECT obj_name = QUOTENAME(s.name) + N'.' + QUOTENAME(t.name),
obj_id = [object_id],
columns = (SELECT STRING_AGG(QUOTENAME(c.name), N',')
WITHIN GROUP (ORDER BY c.column_id)
FROM sys.columns AS c WHERE c.[object_id] = t.[object_id]
AND c.system_type_id IN (35,99,167,175,231,239))
FROM sys.tables AS t INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE (t.name = @TableName OR @TableName IS NULL)
)
SELECT @sql += N'SELECT N' + char(39)
+ REPLACE(obj_name, char(39), char(39) + char(39))
+ char(39) + N',' + columns + N' FROM ' + obj_name + N' WHERE '
+ (SELECT STRING_AGG(QUOTENAME(name) + N' LIKE ' + CASE
WHEN c.system_type_id IN (99,231,239)
THEN 'N' ELSE N'' END
+ char(39) + N'%' + @SearchTerm + N'%' + char(39),
N' OR ') + N';' + char(13) + char(10)
FROM sys.columns AS c WHERE c.[object_id] = tables.obj_id
AND c.system_type_id IN (35,99,167,175,231,239))
FROM tables WHERE columns IS NOT NULL;
PRINT @sql;
--EXEC sys.sp_executeSQL @sql;
我遇到了这个问题,通常是在从CSV文件上传数据后,我不得不修改文本字段中的逗号“,”,以便数据可以正确加载。一旦在SQL Server中,就需要将修改后的字符更改回逗号,并且能够搜索整个表格非常有帮助。Greg Robidoux在mssqltips上发布了一个存储过程,可以搜索指定表格的列以查找特定字符串值。您可以在此处找到它以及不使用游标的SPROC和更多详细信息:
我已经在下面发布了原始的 SPROC:
USE master
GO
CREATE PROCEDURE dbo.sp_FindStringInTable @stringToFind VARCHAR(100), @schema sysname, @table sysname
AS
DECLARE @sqlCommand VARCHAR(8000)
DECLARE @where VARCHAR(8000)
DECLARE @columnName sysname
DECLARE @cursor VARCHAR(8000)
BEGIN TRY
SET @sqlCommand = 'SELECT * FROM [' + @schema + '].[' + @table + '] WHERE'
SET @where = ''
SET @cursor = 'DECLARE col_cursor CURSOR FOR SELECT COLUMN_NAME
FROM ' + DB_NAME() + '.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = ''' + @schema + '''
AND TABLE_NAME = ''' + @table + '''
AND DATA_TYPE IN (''char'',''nchar'',''ntext'',''nvarchar'',''text'',''varchar'')'
EXEC (@cursor)
OPEN col_cursor
FETCH NEXT FROM col_cursor INTO @columnName
WHILE @@FETCH_STATUS = 0
BEGIN
IF @where <> ''
SET @where = @where + ' OR'
SET @where = @where + ' [' + @columnName + '] LIKE ''' + @stringToFind + ''''
FETCH NEXT FROM col_cursor INTO @columnName
END
CLOSE col_cursor
DEALLOCATE col_cursor
SET @sqlCommand = @sqlCommand + @where
PRINT @sqlCommand
EXEC (@sqlCommand)
END TRY
BEGIN CATCH
PRINT 'There was an error. Check to make sure object exists.'
PRINT error_message()
IF CURSOR_STATUS('variable', 'col_cursor') <> -3
BEGIN
CLOSE col_cursor
DEALLOCATE col_cursor
END
END CATCH
这是一个可爱的小技巧,可以减少一些复制粘贴的工作,因为可以使用查询轻松地生成命令。
将 WHERE
子句中的 IN
运算符反转为 VALUE IN <fields>
(而不是更常见的用法 FIELD IN <values>
)。
SELECT col_1, col_2, ... , col_n
FROM <table>
WHERE CAST(<value> AS varchar(max)) IN
(
CAST(col_1 AS varchar(max)),
CAST(col_2 AS varchar(max)),
...,
CAST(col_n AS varchar(max))
)
由于varchar是一种相当可塑的数据类型,因此这变得非常简单(您可以使用ISNULL
/NULLIF
进行必要的修改),并且根据用例,可能可以用于多个搜索值。
更加健壮的解决方案,使用动态执行和PL/SQL编写一个过程来动态构建目标表的视图(通过读取例如MySQL的information_schema模式、Oracle的SYS模式等),受限于包含输入字符串硬编码为一系列“OR”连接/IN子句的where子句作为过滤条件。
我发现最好的答案就是从表格中选择select *
,然后将其复制并粘贴到Excel中,再按下Ctrl+F。
varchar
或者其他类型吗? - JNK