2016-08-23 1 views
1

サーバー上のほとんどのデータベースから特定のビューを削除しようとしています。私は現在持っているものを貼り付けました。それは正常に完了しますが、実際にはビューを削除しません。サーバー上のすべてのデータベースからビューを削除するには

私は何が失われていますか、なぜそれはエラーではなく、実際にビューを削除しないでしょうか?また、特定のデータベースでexec文を実行すると、ビューが削除されます。

USE [Master] 

DECLARE @DBname VARCHAR (128); 
DECLARE @NumDBs INT; 
DECLARE @Count  INT = 0; 


DECLARE getDBs CURSOR 
FOR 
SELECT name 
FROM sys.databases 
WHERE name NOT IN ('DBName1','DBName2') 
ORDER BY name; 

SET @NumDBs = (SELECT COUNT(9) FROM sys.databases WHERE 
name NOT IN ('DBName1','DBName2')) 
; 

OPEN getDBs 
FETCH NEXT FROM getDBs 
INTO @DBname; 

WHILE (@Count < @NumDBs) 
BEGIN 

Exec('IF EXISTS (SELECT * 
        FROM '[email protected]+'.sys.views 
        WHERE object_id= OBJECT_ID(N''[ViewName]''))              
DROP VIEW [ViewName]' 
); 

SET @Count = @Count + 1; 

FETCH NEXT FROM getDBs 
INTO @DBname; 
END; 

CLOSE getDBs; 
DEALLOCATE getDBs; 
+0

'..DROP VIEW '+ @ DBNAME +' .dbo。[ビュー名] ...'それは私がそれを試してみた3部構成の名前のdbname.schemaname.objectname – Serg

+0

でなければなりません。次のエラーが表示されます。 'DROP VIEW'では、オブジェクト名の接頭辞としてデータベース名を指定することはできません。 – Bgonzales

+0

sp_MSForEachDBはどうですか?または「USE database1」を使用してカーソルを更新してコンテキストを特定のデータベースに設定する –

答えて

1
EXECUTE master.sys.sp_MSforeachdb 
'USE [?];if db_id()>4 and db_name() not in (''somedb'',''somedb1'') drop view viewname;' 
+0

'DBName1'、 'DBName2'は除外する必要があります。 – Serg

0
Exec('USE ' [email protected]+'; IF EXISTS (SELECT * 
        FROM sys.views 
        WHERE object_id= OBJECT_ID(N''[ViewName]''))              
DROP VIEW [ViewName]' 
); 
+0

私たちは明らかに同時に同じことを考え出しました。再度、感謝します! – Bgonzales

+1

OPはあなたの答えから学ぶことができるように、コードを投稿して説明してください。 – EBH

0

以下貼り付けたように私は私の元EXEC文を交換し、私は必要なすべてが働きました。

Exec( 
    'Use ['[email protected]+'] ; 
    IF EXISTS (SELECT * FROM '[email protected]+'.sys.views WHERE object_id = OBJECT_ID(N''[ViewName]'')) 
     DROP VIEW [ViewName]' 
    ); 
0

データベースにはほとんど問題はありません。カーソルが絶対的に冗長であるので、カーソルをそこに使用しないことを除いて、行のセットをベースにしたロジックで何らかのコストをかけずに回避してみてください。

あなたはちょうどそのよう動的にクエリを構築することができます:私の地元のインスタンスで

DECLARE @SQL NVARCHAR(MAX) = N''; 

SELECT @SQL += N' 
    USE ' + QUOTENAME([name]) + '; 
    IF OBJECT_ID(''[ViewName]'', ''V'') IS NOT NULL 
     DROP VIEW [ViewName];' 
FROM sys.databases 
WHERE [name] NOT IN ('DBName1','DBName2') 
ORDER BY [name]; 

EXEC sys.sp_executesql @SQL; 

を、それは、このようなクエリを生成します:

USE [AdventureWorks2014]; 
IF OBJECT_ID('[ViewName]', 'V') IS NOT NULL 
    DROP VIEW [ViewName]; 
USE [master]; 
IF OBJECT_ID('[ViewName]', 'V') IS NOT NULL 
    DROP VIEW [ViewName]; 
USE [model]; 
IF OBJECT_ID('[ViewName]', 'V') IS NOT NULL 
    DROP VIEW [ViewName]; 
USE [msdb]; 
IF OBJECT_ID('[ViewName]', 'V') IS NOT NULL 
    DROP VIEW [ViewName]; 
USE [ReportServer]; 
IF OBJECT_ID('[ViewName]', 'V') IS NOT NULL 
    DROP VIEW [ViewName]; 
USE [ReportServerTempDB]; 
IF OBJECT_ID('[ViewName]', 'V') IS NOT NULL 
    DROP VIEW [ViewName]; 
USE [tempdb]; 
IF OBJECT_ID('[ViewName]', 'V') IS NOT NULL 
    DROP VIEW [ViewName]; 
USE [test]; 
IF OBJECT_ID('[ViewName]', 'V') IS NOT NULL 
    DROP VIEW [ViewName]; 

全体として、@TheGameiswarによって提案されたソリューションは、最高の一つであり、それはそのような使用例のために作成されたsys.sp_MSforeachdbを使用します。

+0

私は同意します。@ TheGameiswarとあなたの両方もこのトリックを行います。しかし私はまた、私がドロップしているビューの新しいバージョンを作成する必要があります。実際には2つのExec文、1つは削除し、1つは追加します。 – Bgonzales

+0

@Bgonzalesそれほど重要ではない。私はあなたがカーソルを避けるべきであることを指摘しようとしています、おそらくそのようなコマンドにパフォーマンスの影響はありませんが、カーソルをまったく使用しないように教える方が良いでしょう。 –

1

Powershell to the rescue!

push-location; 
import-module sqlps -disablenamechecking; 
pop-location; 

$s = new-object microsoft.sqlserver.management.smo.server 'yourServer'; 
foreach ($db in $s.Databases | where {$_.IsAccessible -eq $true}) { 
    $v = $db.Views['ViewName']; 
    if ($v -ne $null) { 
     $v.Drop(); 
    } 
} 
関連する問題