如何使用游标在不同的数据库中创建过程
How to Create Procedures In Different Databases Using Cursor
所以我试图在不同的数据库中制作程序。我不应该知道数据库的名称。我尝试制作嵌套游标,第一个以动态方式获取数据库名称,另一个以 create/alter 过程;我使用 EXISTS 来创建过程,使用 NOT EXISTS 来改变它们。但不知何故数据库坚持 'master' 并且它永远不会循环遍历其他数据库。我知道我的内部嵌套光标有问题,但我不知道这是什么。
这是我的编码:
DECLARE GetDatabases CURSOR
FOR
SELECT name
FROM sys.databases
OPEN GetDatabases
DECLARE @DBName NVARCHAR(100)
DECLARE @cmd NVARCHAR(Max)
FETCH NEXT
FROM GetDatabases
INTO @DBName
WHILE @@FETCH_STATUS = 0
BEGIN
set @cmd='use ' + @DBName
print @cmd
exec sp_executesql @cmd
FETCH NEXT
FROM GetDatabases
INTO @DBName
DECLARE AutoProc CURSOR
FOR
SELECT TABLE_SCHEMA,TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE'
OPEN AutoProc
DECLARE @TableName NVARCHAR(100)
DECLARE @TableSchema NVARCHAR(100)
FETCH NEXT
FROM AutoProc
INTO @TableSchema,@TableName
WHILE @@FETCH_STATUS = 0
BEGIN
IF EXISTS(SELECT * FROM sys.objects WHERE type = 'P' AND OBJECT_ID = OBJECT_ID('@TableName'))
exec('ALTER PROCEDURE USP_SELECT_'+@TableName+' AS
BEGIN
SELECT *
FROM '+@TableSchema+'.'+@TableName+'
END ;')
IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND OBJECT_ID = OBJECT_ID('@TableName'))
exec('CREATE PROCEDURE USP_SELECT_'+@TableName+' AS
BEGIN
SELECT *
FROM '+@TableSchema+'.'+@TableName+'
END ;')
FETCH NEXT
FROM AutoProc
INTO @TableSchema,@TableName
END
CLOSE AutoProc
DEALLOCATE AutoProc
END
CLOSE GetDatabases
DEALLOCATE GetDatabases
P.S:我不应该知道数据库的名称,因为我正在尝试编写一个 "General" 程序以便它可以应用于所有 sql-服务器用户的数据库,不仅仅是我的。
P.S2:我使用了 Nesting Cursors,但由于其糟糕的性能,我也希望使用其他方式!
干杯!
尝试使用 while 语句并遍历临时变量 table,而不是使用游标。
DECLARE @Databases TABLE
(
ID int IDENTITY(1,1),
DatabaseName varchar(100)
)
INSERT INTO @Databases
SELECT name FROM sys.databases
DECLARE @Idx int = (select count(*) from @Databases)
WHILE(@Idx > 0)
BEGIN
DECLARE @CurrentDatabase varchar(100) = (select DatabaseName from @Databases where @Idx = ID )
DECLARE @SchemaData TABLE
(
ID int IDENTITY(1,1),
Table_Schema varchar(20),
Table_Name varchar(255)
)
DECLARE @Sql varchar(max) = 'SELECT [TABLE_SCHEMA],[TABLE_NAME] FROM [' + @CurrentDatabase + '].[INFORMATION_SCHEMA].[TABLES]'
INSERT INTO @SchemaData
EXEC (@Sql)
DECLARE @SchemaIdx int = (select count(*) from @SchemaData)
WHILE(@SchemaIdx > 0)
BEGIN
DECLARE @CurrentSchema varchar(20), @CurrentTable varchar(255)
SELECT @CurrentSchema = Table_Schema, @CurrentTable = Table_Name from @SchemaData where ID = @SchemaIdx
DECLARE @Sql2 varchar(max) =
'IF EXISTS(SELECT * FROM sys.objects WHERE type = ''P'' AND OBJECT_ID = OBJECT_ID(' + @CurrentTable + '))
exec(''ALTER PROCEDURE USP_SELECT_'+ @CurrentTable + ' AS
BEGIN
SELECT *
FROM '+ @CurrentSchema + '.'+ @CurrentTable + '
END ;'')'
PRINT @Sql2
SET @SchemaIdx = @SchemaIdx - 1;
END
SET @Idx = @Idx - 1;
END
所以我试图在不同的数据库中制作程序。我不应该知道数据库的名称。我尝试制作嵌套游标,第一个以动态方式获取数据库名称,另一个以 create/alter 过程;我使用 EXISTS 来创建过程,使用 NOT EXISTS 来改变它们。但不知何故数据库坚持 'master' 并且它永远不会循环遍历其他数据库。我知道我的内部嵌套光标有问题,但我不知道这是什么。 这是我的编码:
DECLARE GetDatabases CURSOR
FOR
SELECT name
FROM sys.databases
OPEN GetDatabases
DECLARE @DBName NVARCHAR(100)
DECLARE @cmd NVARCHAR(Max)
FETCH NEXT
FROM GetDatabases
INTO @DBName
WHILE @@FETCH_STATUS = 0
BEGIN
set @cmd='use ' + @DBName
print @cmd
exec sp_executesql @cmd
FETCH NEXT
FROM GetDatabases
INTO @DBName
DECLARE AutoProc CURSOR
FOR
SELECT TABLE_SCHEMA,TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE'
OPEN AutoProc
DECLARE @TableName NVARCHAR(100)
DECLARE @TableSchema NVARCHAR(100)
FETCH NEXT
FROM AutoProc
INTO @TableSchema,@TableName
WHILE @@FETCH_STATUS = 0
BEGIN
IF EXISTS(SELECT * FROM sys.objects WHERE type = 'P' AND OBJECT_ID = OBJECT_ID('@TableName'))
exec('ALTER PROCEDURE USP_SELECT_'+@TableName+' AS
BEGIN
SELECT *
FROM '+@TableSchema+'.'+@TableName+'
END ;')
IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND OBJECT_ID = OBJECT_ID('@TableName'))
exec('CREATE PROCEDURE USP_SELECT_'+@TableName+' AS
BEGIN
SELECT *
FROM '+@TableSchema+'.'+@TableName+'
END ;')
FETCH NEXT
FROM AutoProc
INTO @TableSchema,@TableName
END
CLOSE AutoProc
DEALLOCATE AutoProc
END
CLOSE GetDatabases
DEALLOCATE GetDatabases
P.S:我不应该知道数据库的名称,因为我正在尝试编写一个 "General" 程序以便它可以应用于所有 sql-服务器用户的数据库,不仅仅是我的。
P.S2:我使用了 Nesting Cursors,但由于其糟糕的性能,我也希望使用其他方式!
干杯!
尝试使用 while 语句并遍历临时变量 table,而不是使用游标。
DECLARE @Databases TABLE
(
ID int IDENTITY(1,1),
DatabaseName varchar(100)
)
INSERT INTO @Databases
SELECT name FROM sys.databases
DECLARE @Idx int = (select count(*) from @Databases)
WHILE(@Idx > 0)
BEGIN
DECLARE @CurrentDatabase varchar(100) = (select DatabaseName from @Databases where @Idx = ID )
DECLARE @SchemaData TABLE
(
ID int IDENTITY(1,1),
Table_Schema varchar(20),
Table_Name varchar(255)
)
DECLARE @Sql varchar(max) = 'SELECT [TABLE_SCHEMA],[TABLE_NAME] FROM [' + @CurrentDatabase + '].[INFORMATION_SCHEMA].[TABLES]'
INSERT INTO @SchemaData
EXEC (@Sql)
DECLARE @SchemaIdx int = (select count(*) from @SchemaData)
WHILE(@SchemaIdx > 0)
BEGIN
DECLARE @CurrentSchema varchar(20), @CurrentTable varchar(255)
SELECT @CurrentSchema = Table_Schema, @CurrentTable = Table_Name from @SchemaData where ID = @SchemaIdx
DECLARE @Sql2 varchar(max) =
'IF EXISTS(SELECT * FROM sys.objects WHERE type = ''P'' AND OBJECT_ID = OBJECT_ID(' + @CurrentTable + '))
exec(''ALTER PROCEDURE USP_SELECT_'+ @CurrentTable + ' AS
BEGIN
SELECT *
FROM '+ @CurrentSchema + '.'+ @CurrentTable + '
END ;'')'
PRINT @Sql2
SET @SchemaIdx = @SchemaIdx - 1;
END
SET @Idx = @Idx - 1;
END