Ich schreibe ein Skript, das bei Ausführung alle Tabellen in einer Liste der angegebenen DBs löscht, wenn das Kombinationsfeld DB-Name + Tabellenname nicht existiert eine Tabelle namens CleanUpTableList. Alle DBs befinden sich auf demselben Server. Ich benutze SQL Server 2014.Der Versuch, Datenbanken mithilfe der Cursorschleife zu ändern, aber die Datenbank ändert sich nicht.
Ich versuche, dies zu tun, indem Sie eine äußere Cursor-Schleife, die durch die Liste der DB-Namen und eine innere Cursor-Schleife, die eine Liste der Tabellennamen innerhalb der angegebenen Datenbank zieht, die sind nicht in CleanUpTableList gefunden und löscht diese Tabellen. Es scheint jedoch, dass die äußere Schleife die Datenbanken nicht ändern kann. Das Skript greift nur X-mal auf die relevanten Tabellen der Startdatenbank zu, wobei X jedoch viele Einträge des Datenbanknamens im äußeren Cursor enthält. So zum Beispiel, wenn ich starten in Database1, und ich habe drei Datenbanknamen Einträge in meinem äußeren Cursor, anstatt sich:
DROP TABLE Database1..TableB
DROP TABLE Database1..TableC
DROP TABLE Database2..TableE
DROP TABLE Database2..TableF
DROP TABLE Database3..TableH
DROP TABLE Database3..TableI
ich:
DROP TABLE Database1..TableB
DROP TABLE Database1..TableC
DROP TABLE Database1..TableB
DROP TABLE Database1..TableC
DROP TABLE Database1..TableB
DROP TABLE Database1..TableC
... Welche ist nicht wirklich, was ich will, also nehme ich an, dass etwas in der äußeren Schleife nicht stimmt. Ich weiß, dass der üblicher DB Änderungsbefehl
USE Database1;
GO
Aber ich war nicht in der Lage, herauszufinden, wie man das mit exec(). Es hat mir gesagt, dass es einen Syntaxfehler in der Nähe von GO gab, ich nehme an, weil GO nicht in der gleichen Zeile wie 'USE Database1;' sein kann, und ich weiß nicht, wie man eine neue Zeile mit EXEC() erstellt. Ich habe versucht,
SET @ChangeDB = 'USE ' + @DatabaseName + ';'
EXEC(@ChangeDB + CHAR(13) + 'GO')
und
SET @ChangeDB ='USE ' + @DatabaseName + ';' +CHAR(13) + 'GO'
EXEC(@ChangeDB)
aber diese auch wieder einen Syntaxfehler verwendet wird. Hier
ist der entsprechende Code:
DB/Tabellenerstellung Script:
CREATE DATABASE Database1;
CREATE DATABASE Database2;
CREATE DATABASE Database3;
CREATE DATABASE Database4;
CREATE TABLE Database1.dbo.TableA (Column1 INT, Column2 INT);
CREATE TABLE Database1.dbo.TableB (Column1 INT, Column2 INT);
CREATE TABLE Database1.dbo.TableC (Column1 INT, Column2 INT);
CREATE TABLE Database2.dbo.TableD (Column1 INT, Column2 INT);
CREATE TABLE Database2.dbo.TableE (Column1 INT, Column2 INT);
CREATE TABLE Database2.dbo.TableF (Column1 INT, Column2 INT);
CREATE TABLE Database3.dbo.TableG (Column1 INT, Column2 INT);
CREATE TABLE Database3.dbo.TableH (Column1 INT, Column2 INT);
CREATE TABLE Database3.dbo.TableI (Column1 INT, Column2 INT);
CREATE TABLE Database4.dbo.CleanUpTableList (DBName VARCHAR(20), TableName VARCHAR(20));
INSERT INTO Database4..CleanUpTableList VALUES ('Database1','TableA')
INSERT INTO Database4..CleanUpTableList VALUES ('Database2','TableD')
INSERT INTO Database4..CleanUpTableList VALUES ('Database3', 'TableG')
Clean Up Script:
DECLARE @fetch_database_cursor INT
DECLARE @DatabaseName VARCHAR(50)
DECLARE DatabaseList CURSOR FOR
select name from sys.databases
where
name IN ('Database1','Database2', 'Database3'
)
OPEN DatabaseList
FETCH NEXT FROM DatabaseList INTO @DatabaseName
/* Keep track of the outer loop FETCH_STATUS in a local variable */
SET @fetch_database_cursor = @@FETCH_STATUS
/* Use outer loop FETCH_STATUS local variable as condition for outer WHILE loop */
WHILE @fetch_database_cursor = 0
BEGIN
DECLARE @ChangeDB VARCHAR(2500)
DECLARE @TableName VARCHAR(50)
DECLARE @ExecuteSQL VARCHAR(2500)
DECLARE @fetch_table_cursor INT
/* Change DB here */
SET @ChangeDB = 'USE ' + @DatabaseName
EXEC(@ChangeDB)
/* Declare inner cursor */
DECLARE TableList CURSOR FOR
select table_name
from information_schema.tables
WHERE TABLE_TYPE = 'BASE TABLE'
AND table_name NOT IN (
SELECT TableName
FROM Database4..CleanUpTableList
WHERE DBName = @DatabaseName
)
ORDER BY table_name
OPEN TableList
FETCH NEXT FROM TableList INTO @TableName
/* Store inner cursor fetch_status in local variable */
SET @fetch_table_cursor = @@FETCH_STATUS
/* Use inner cursor fetch_status local variable as condition for inner WHILE loop */
WHILE @fetch_table_cursor = 0
BEGIN
SET @ExecuteSQL = 'DROP TABLE ' [email protected]
EXEC(@ExecuteSQL)
SELECT @Tablename, 'Has Been Successfully Dropped'
FETCH NEXT FROM TableList INTO @TableName
SET @[email protected]@FETCH_STATUS
END
/* Close and deallocate inner cursor */
CLOSE TableList
DEALLOCATE TableList
FETCH NEXT FROM DatabaseList INTO @DatabaseName
SET @fetch_database_cursor = @@FETCH_STATUS
END
/* Close and deallocate outer cursor */
CLOSE DatabaseList
DEALLOCATE DatabaseList
Irgendwelche Vorschläge geschätzt werden.
Ich versuche, dies nur für einige wenige Datenbanken auf dem Server zu tun.Es ist sehr wichtig, dass nur die explizit angegebenen Datenbanken betroffen sind, da andere Datenbanken auf dem Server keine Einträge in CleanUpTableList enthalten und somit das Durchlaufen dieses Skripts zu einem unbeabsichtigten Löschen von Tabellen führen würde. Ich nehme an, dass ich diese Datenbanken mithilfe des Abschnitts db_id() der Anweisung explizit identifizieren konnte? Wie 'EXECUTE master.sys.sp_MSforeachdb 'USE [?]; if db_id() IN (1,2,3) zurückgeben; Drop-Tabelle dbo.someable '' –
Siehe aktualisiert für Ihr spezifisches Szenario – TheGameiswar