我正在编写一个脚本,如果在名为CleanUpTableList的表中不存在DB Name + Table Name组合,则执行该脚本时将删除给定DB列表中的任何表。所有DB都驻留在同一台服务器上。我正在使用SQL Server 2014。
我试图通过创建一个外部游标循环来执行此操作,该循环遍历数据库名称列表和一个内部游标循环,该循环拉入给定数据库中的表名列表,这些表名称在CleanUpTableList中找不到并删除这些表。但是,外部循环似乎无法更改数据库。该脚本仅访问起始数据库的相关表X次,但是外部游标中有许多数据库名称条目。因此,例如,如果我在Database1中启动,并且在我的外部游标中有三个数据库名称条目,而不是获取:
DROP TABLE Database1..TableB
DROP TABLE Database1..TableC
DROP TABLE Database2..TableE
DROP TABLE Database2..TableF
DROP TABLE Database3..TableH
DROP TABLE Database3..TableI
我明白了:
DROP TABLE Database1..TableB
DROP TABLE Database1..TableC
DROP TABLE Database1..TableB
DROP TABLE Database1..TableC
DROP TABLE Database1..TableB
DROP TABLE Database1..TableC
......这不是我想要的,所以我假设外循环中有些不对劲。我知道通常的DB更改命令是
USE Database1;
GO
但是我无法通过EXEC()弄清楚如何做到这一点。它一直告诉我GO附近有一个语法错误,我认为因为GO不能和“使用数据库1”在同一行;'我不知道使用EXEC()时的新行。我尝试使用
SET @ChangeDB = 'USE ' + @DatabaseName + ';'
EXEC(@ChangeDB + CHAR(13) + 'GO')
和
SET @ChangeDB ='USE ' + @DatabaseName + ';' +CHAR(13) + 'GO'
EXEC(@ChangeDB)
但这些也返回了语法错误。
以下是相关代码:
数据库/表创建脚本:
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')
清理脚本:
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 ' +@Tablename
EXEC(@ExecuteSQL)
SELECT @Tablename, 'Has Been Successfully Dropped'
FETCH NEXT FROM TableList INTO @TableName
SET @fetch_table_cursor=@@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
任何建议都表示赞赏。
答案 0 :(得分:2)
从您的代码中,我了解到您正在尝试在所有数据库中执行相同的操作,这可以通过sp_msforeachdb实现..
- 所有数据库
gradlew assembleRelease -P production=flavor1
- 只运行少数数据库..
EXECUTE master.sys.sp_MSforeachdb
'USE [?];
if db_id()<=4 return;
drop table dbo.sometable'
您还可以使用Aaron Bertrand重写Sp_msforeachDB,它也可以处理Sp_msforeachdb的一些限制:Making a more reliable and flexible sp_MSforeachdb
答案 1 :(得分:0)
尝试完全限定drop语句中的database.dbo.tablename
,而不是尝试执行Use database语句。您拥有所有数据库和表名。