Running Microsoft SQL Server 11.0.3128
on Windows Server 2012 R2 Essentials
我试图根据提供的变量(调用SQL脚本的批处理文件)返回特定数据库的名称。
在我看来,这个过程应该是这样的:
For each database in instance
Look in the current database
Return databasename if variable is found in column
到目前为止,我一直在使用的代码如下所示:
EXEC dbo.sp_MSForeachdb '
USE [?];
SELECT DB_NAME() AS DBName
UNION SELECT
ColumnName
FROM dbo.Items
WHERE ColumnName =''variable''
'
问题是,这比我想要的要多得多,因为它返回" null"不包含"变量"的数据库的值并为不包含" ColumnName"。
的数据库创建消息但我似乎无法弄清楚如何在没有其他东西的情况下获得我想要的具体信息。第一次海报,如果我能改进这个问题,请告诉我。
谢谢!
答案 0 :(得分:0)
这是一种没有sp_MSForeachdb
的方法。请注意,您需要首先清理参数。
delimiter $$
create procedure FindDatabases
(
in varName varchar(2000),
in tableName varchar(2000),
in columnName varchar(2000)
)
begin
declare selectQuery varchar(2000);
select group_concat(
concat('select ''',
table_schema,
''' as DatabaseName from ',
table_schema,
'.',
tableName,
' where ',
columnName,
' = ''',
varName,
'''')
separator ' union ') as DatabaseNames
from information_schema.tables
where table_name = tableName
into @selectQuery;
prepare preparedSql from @selectQuery;
execute preparedSql;
deallocate prepare preparedSql;
end $$
delimiter ;
使用示例:
call FindDatabases ( 'variable', 'Items', 'ColumnName' )
此过程为每个数据库生成一个sql查询,其表名与提供的表名相匹配,将它们组合在一起,然后执行它们。如果该数据库中的指定表具有与包含与指定变量名匹配的值的指定名称匹配的列,则union中的每个查询都将返回其数据库名称。只有符合这些要求的数据库才会出现在查询结果中,因此您不必担心结果中的空值。
附加编辑:正如所承诺的,这是一个sqlserver版本。
create procedure FindDatabases
(
@varName varchar(2000),
@tableName varchar(2000),
@columnName varchar(2000)
)
as
begin
declare @selectQuery nvarchar(2000)
-- first, get a list of database names that contain the specified table
IF OBJECT_ID('tempdb.dbo.#db_temp') IS NOT NULL
DROP TABLE #db_temp
CREATE TABLE #db_temp (DatabaseName SYSNAME)
SELECT @selectQuery = (
SELECT '
USE [' + d.name + '];
INSERT INTO #db_temp (DatabaseName)
SELECT DB_NAME() as DatabaseName
WHERE EXISTS(
SELECT 1
FROM sys.objects
WHERE [object_id] = OBJECT_ID(''' + @tableName + ''')
AND [type] = ''U''
)'
FROM sys.databases d
WHERE d.name NOT IN ('master', 'tempdb', 'model', 'msdb')
AND d.state_desc != 'OFFLINE'
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
EXEC sys.sp_executesql @selectQuery
-- use something like mysql's group_concat function to turn that list into a bunch of union all select statements
select
@selectQuery =
(
SELECT LEFT(database_names , LEN(database_names ) - 10) AS database_names
FROM #db_temp AS extern
CROSS APPLY
(
SELECT 'select ''' + DatabaseName + ''' as DatabaseName from ' + DatabaseName + '.dbo.' + @tableName +
' where ' + @columnName + ' = ''' + @varName + '''' + ' union all '
FROM #db_temp AS intern
FOR XML PATH('')
) pre_trimmed (database_names)
GROUP BY database_names
)
drop table #db_temp
-- run those select statements
exec sp_executesql @selectQuery
end
运行它:
exec FindDatabases 'someVar', 'Items', 'ColumnName'
我无耻地从here和here中删除了一些片段,以解决缺少group_concat函数和sqlserver的information_schema问题,该函数只包含本地数据库的信息,而不是跨数据库共享信息。