我有多个数据库,我想创建一个临时存储过程(##SearchAllTables
),该过程在数据库的所有表中搜索值。
我面临的问题是,如果我针对master数据库创建了临时存储过程,那么当我针对另一个数据库运行它时,它将不起作用,因为它不会显示任何发现。
如果我针对那个特定的数据库创建了相同的临时存储过程,它将正常工作。
我正在使用此网站上的存储过程: https://thesitedoctor.co.uk/blog/search-every-table-and-field-in-a-sql-server-database-updated/
你知道我为什么有这种行为吗?
答案 0 :(得分:0)
查看存储过程,似乎将过程代码第33行的此过滤器应用于master
数据库时会出现问题:
OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0
master
数据库中的表都随MS SQL安装一起提供,因此将具有等于1的IsMSShipped
属性,因此将其排除在搜索之外。您可以通过运行以下命令进行测试:
select
*,
OBJECTPROPERTY(OBJECT_ID(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)), 'IsMSShipped')
from
master.INFORMATION_SCHEMA.TABLES
如果要搜索这些表,请从WHERE
子句中删除该过滤器。
答案 1 :(得分:0)
免责声明:这是您要执行的非常繁重的任务。我不建议在生产环境中运行。
您所引用的代码仅用于查询当前数据库中的表。
为当前用户拥有权限的当前数据库中的每个表或视图返回一行。
如果希望它为每个数据库运行,则必须对其进行修改以遍历所有数据库。像这样:
DECLARE @dbName NVARCHAR(256)
DECLARE db_cursor CURSOR FOR
SELECT name
FROM sys.databases
WHERE state_desc = 'ONLINE'
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @dbName
WHILE @@FETCH_STATUS = 0
BEGIN
--Code from proc here
END
然后,您需要修改将@TableName变量放在一起以包含数据库名称的查询:
...
BEGIN
SET @ColumnName = ''
SET @TableName =
(
SELECT QUOTENAME(@dbName)+ '.' + MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0
)
WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
...