我需要搜索具有特定前缀的某些数据库。找到这些数据库后,我需要检查某个模式是否存在以及是否存在 - 使数据库脱机。我一直在尝试在Google上找到的各种建议,但没有任何效果。我有一个错误,我无法通过。错误是' XYZ'不是公认的选择。如果我将代码分开运行正常,但是当我添加sp_MSforeachdb时,错误会返回。
EXEC sp_msforeachdb 'IF ''?'' LIKE ''abc_%''
BEGIN
IF (NOT EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'XYZ'
BEGIN
ALTER DATABASE [abc_xxxxxxxxx] SET OFFLINE WITH
ROLLBACK IMMEDIATE
END'
此代码可以正常工作:
SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'XYZ'
答案 0 :(得分:6)
这是一种不依赖undocumented, unsupported and buggy system procedure sp_msforeachdb
的方法,也不依赖于similarly unreliable INFORMATION_SCHEMA
views。
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';
SELECT @sql = @sql + N'IF NOT EXISTS (SELECT 1 FROM '
+ QUOTENAME(name) + '.sys.tables AS t
INNER JOIN ' + QUOTENAME(name) + '.sys.schemas AS s
ON t.schema_id = s.schema_id
WHERE s.name = ''XYZ'')
BEGIN
EXEC sp_executesql N''ALTER DATABASE '
+ QUOTENAME(name) + ' SET OFFLINE;''
END
' FROM sys.databases WHERE name LIKE 'abc_%';
PRINT @sql;
-- EXEC sp_executesql @sql;
您的实际错误是因为字符串中包含字符串分隔符。你不能这样做:
SELECT ' WHERE TABLE_SCHEMA = 'XYZ' ... ';
错误:
Msg 102,Level 15,State 1,Line 1
“...”附近的语法不正确。
你需要这样做:
SELECT ' WHERE TABLE_SCHEMA = ''XYZ'' ... ';
然而,当您在命令中嵌入命令时,这会很快变得错综复杂,而这些命令是您发送给未记录的,不受支持且错误的系统过程的。我知道我在这里重复自己。我希望很明显,如果你想要可靠的结果,你不应该使用sp_msforeachdb
。
答案 1 :(得分:1)
试试这个 -
DECLARE
@schema_name SYSNAME
, @database_name SYSNAME
SELECT
@schema_name = 'XYZ'
--, @database_name = 'abc_%'
DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = (SELECT '
USE [' + d.name + '];
IF NOT EXISTS (
SELECT 1
FROM sys.objects o
JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
WHERE o.type = ''U''
AND s.name = ''' + @schema_name + '''
) EXEC sp_executesql N''ALTER DATABASE [' + d.name + '] SET OFFLINE;''
'
FROM sys.databases d
WHERE (@database_name IS NULL OR d.name LIKE @database_name)
AND d.[state] = 0
AND d.name NOT IN ('master', 'tempdb', 'model', 'msdb')
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
EXEC sp_executesql @sql
答案 2 :(得分:0)
你有一些小错误
EXEC sp_msforeachdb '
IF ''?'' LIKE ''abc_%''
BEGIN
IF NOT EXISTS ( SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = ''XYZ'')
ALTER DATABASE [abc_xxxxxxxxx] SET OFFLINE WITH ROLLBACK IMMEDIATE
END'
''?''
和''abc_%''
周围的引号,但忘记了'XYZ'
ALTER DATABASE
语句是一行,不需要BEGIN-END。删除BEGIN
允许END
与其他 BEGIN
匹配,但您可以完全删除BEGIN-END。