在SQL数据库中搜索特定单词
我是SQL的新手,没有SQL方面的经验,所以请接受我的提问 我需要知道是否可以在SQL数据库中搜索特定单词,如果可以,如何搜索 我们目前正在经历一个品牌重塑项目,我需要在我们的CMS内容管理系统数据库中查找所有电子邮件地址的参考。我只需要搜索以下内容: .co.uk 下面是一个有问题的数据库的截图,其中包含了所有的表,我只是不能理解SQL,我对Google试图找到答案一点也不高兴 我需要搜索这个数据库中的所有内容,但我不知道内容所在的表、视图、列名等,因为它们都分布在这些表、视图、列名中在SQL数据库中搜索特定单词,sql,sql-server,tsql,Sql,Sql Server,Tsql,我是SQL的新手,没有SQL方面的经验,所以请接受我的提问 我需要知道是否可以在SQL数据库中搜索特定单词,如果可以,如何搜索 我们目前正在经历一个品牌重塑项目,我需要在我们的CMS内容管理系统数据库中查找所有电子邮件地址的参考。我只需要搜索以下内容: .co.uk 下面是一个有问题的数据库的截图,其中包含了所有的表,我只是不能理解SQL,我对Google试图找到答案一点也不高兴 我需要搜索这个数据库中的所有内容,但我不知道内容所在的表、视图、列名等,因为它们都分布在这些表、视图、列名中 我还需
我还需要搜索其他表,但希望能提供一个答案,我可以修改该答案来搜索这些表。我创建了一个似乎对我有用的快速查询:
--Search for a word in the current database
SET NOCOUNT ON;
--First make a hit list of possible tables/ columns
DECLARE @HitList TABLE (
Id INT IDENTITY(1,1) PRIMARY KEY,
TableName VARCHAR(255),
SchemaName VARCHAR(255),
ColumnName VARCHAR(255));
INSERT INTO
@HitList (
TableName,
SchemaName,
ColumnName)
SELECT
t.name,
s.name,
c.name
FROM
sys.tables t
INNER JOIN sys.columns c ON c.object_id = t.object_id
INNER JOIN sys.schemas s ON s.schema_id = t.schema_id
WHERE
c.system_type_id = 167;
--Construct Dynamic SQL
DECLARE @Id INT = 1;
DECLARE @Count INT;
SELECT @Count = COUNT(*) FROM @HitList;
DECLARE @DynamicSQL VARCHAR(1024);
WHILE @Id <= @Count
BEGIN
DECLARE @TableName VARCHAR(255);
DECLARE @SchemaName VARCHAR(255);
DECLARE @ColumnName VARCHAR(255);
SELECT @TableName = TableName FROM @HitList WHERE Id = @Id;
SELECT @SchemaName = SchemaName FROM @HitList WHERE Id = @Id;
SELECT @ColumnName = ColumnName FROM @HitList WHERE Id = @Id;
SELECT @DynamicSQL = 'SELECT * FROM [' + @SchemaName + '].[' + @TableName + '] WHERE [' + @ColumnName + '] LIKE ''%co.uk%''';
--PRINT @DynamicSQL;
EXECUTE (@DynamicSQL);
IF @@ROWCOUNT != 0
BEGIN
PRINT 'We have a hit in ' + @TableName + '.' + @ColumnName + '!!';
END;
SELECT @Id = @Id + 1;
END;
基本上,它会列出您可能需要更改的任何VARCHAR列,如果您有Unicode文本列,则可能需要将其包括NVARCHAR—只需将系统类型id的测试从167更改为231,然后对每个列执行搜索。当您从ManagementStudio运行此命令时,请切换到消息窗格以查看点击,而忽略结果
如果您的数据库有任何大小,它将很慢。。。但是这是可以预料到的吗?数据库并不是真正用于这种模糊的搜索描述,您应该有一些定义、模型或需求规范来描述这样的值可能存在的地方 但当然,您可以选择一种非常慢的方法,通过使用动态SQL来实现 我很快就做对了,并快速测试了它,但它应该可以工作:
SET NOCOUNT ON
IF OBJECT_ID('tempdb..#SEARCHTABLE') IS NOT NULL
DROP TABLE #SEARCHTABLE
IF OBJECT_ID('tempdb..#RESULTS') IS NOT NULL
DROP TABLE #RESULTS
CREATE TABLE #SEARCHTABLE (ROWNUM INT IDENTITY(1,1), SEARCHCLAUSE VARCHAR(2000) COLLATE DATABASE_DEFAULT)
INSERT INTO #SEARCHTABLE (SEARCHCLAUSE)
SELECT 'SELECT TOP 1 '''+TAB.name+''', '''+C.name+'''
FROM ['+S.name+'].['+TAB.name+']
WHERE '
+CASE WHEN T.name <> 'xml'
THEN '['+C.name+'] LIKE ''%.co.uk%'' AND ['+C.name+'] LIKE ''%@%'''
ELSE 'CAST(['+C.name+'] AS VARCHAR(MAX)) LIKE ''%.co.uk%'' AND CAST(['+C.name+'] AS VARCHAR(MAX)) LIKE ''%@%'''
END AS SEARCHCLAUSE
FROM sys.tables TAB
JOIN sys.schemas S on S.schema_id = TAB.schema_id
JOIN sys.columns C on C.object_id = TAB.object_id
JOIN sys.types T on T.user_type_id = C.user_type_id
WHERE TAB.type_desc = 'USER_TABLE'
AND (T.name LIKE '%char%' OR
T.name LIKE '%xml%')
AND CASE WHEN C.max_length = -1 THEN 10 ELSE C.max_length END >= 6 -- To only search through sufficiently long column
CREATE TABLE #RESULTS (ROWNUM INT IDENTITY(1,1), TABLENAME VARCHAR(256) COLLATE DATABASE_DEFAULT, COLNAME VARCHAR(256) COLLATE DATABASE_DEFAULT)
DECLARE @ROWNUM_NOW INT, @ROWNUM_MAX INT, @SQLCMD VARCHAR(2000), @STATUSSTRING VARCHAR(256)
SELECT @ROWNUM_NOW = MIN(ROWNUM), @ROWNUM_MAX = MAX(ROWNUM) FROM #SEARCHTABLE
WHILE @ROWNUM_NOW <= @ROWNUM_MAX
BEGIN
SELECT @SQLCMD = SEARCHCLAUSE FROM #SEARCHTABLE WHERE ROWNUM = @ROWNUM_NOW
INSERT INTO #RESULTS
EXEC(@SQLCMD)
SET @STATUSSTRING = CAST(@ROWNUM_NOW AS VARCHAR(25))+'/'+CAST(@ROWNUM_MAX AS VARCHAR(25))+', time: '+CONVERT(VARCHAR, GETDATE(), 120)
RAISERROR(@STATUSSTRING, 10, 1) WITH NOWAIT
SELECT @ROWNUM_NOW = @ROWNUM_NOW + 1
END
SET NOCOUNT ON
SELECT 'This table and column contains strings ".co.uk" and a "@"' INFORMATION, TABLENAME, COLNAME FROM #RESULTS
-- Uncomment to drop the created temp tables
--IF OBJECT_ID('tempdb..#SEARCHTABLE') IS NOT NULL
-- DROP TABLE #TABLECOLS
--IF OBJECT_ID('tempdb..#RESULTS') IS NOT NULL
-- DROP TABLE #RESULTS
它会在数据库中搜索所有用户创建的表及其模式,这些表具有足够长度的nchar/nvarchar/xml列,然后逐个搜索每个表,直到找到至少一个匹配项,然后移动到列表中的下一个。匹配定义为任何字符串或XML转换为字符串,其中包含text.co.uk和@符号
它将显示脚本的进度找到了多少个可搜索的TABLE.COLUMN组合,该列表上的哪个组合当前正在运行,以及messages选项卡上的当前时间戳(最短为秒)。准备好后,它将显示至少包含一个匹配项的所有表和列名
因此,从该列表中,您必须手动搜索表和列,以准确地找到有多少个匹配项以及哪些类型的匹配项,以及您实际想要做什么
编辑:我再次忽略了对sysobjects使用sysnames,但如果需要,我将稍后进行修改。您可以尝试SQL Search,这是Redgate提供的一个免费工具:@NickyvV我已经下载了它,但它说我搜索的每个词都没有匹配项,即使是“and”这个词