游标内的游标,用于数据库相关权限
Cursor within a cursor for database dependent permissions
我的代码似乎应该可以工作,但是测试表明来自内部游标的所有结果都基于脚本执行时的当前数据库,而不依赖于脚本中的 USE 语句。
我忘记了什么?
DECLARE @Debug BIT = 1
DECLARE @newgrp VARCHAR(100) = 'ChangeTrakingViewableRole'
DECLARE @obj VARCHAR(100)
DECLARE @tsql VARCHAR(900)
DECLARE @tsql2 VARCHAR(900)
DECLARE @msg VARCHAR(900)
DECLARE @SchName VARCHAR(55)
DECLARE @TblName sysname
IF @Debug = 'TRUE' PRINT 'Debuging ON'
IF COALESCE(@newgrp,'') = ''
BEGIN
PRINT 'There was no DatabaseRole, User or Group Specified to take the place of the Public Role'
SET NOEXEC ON
END
ELSE
BEGIN
DECLARE DbCursor CURSOR FOR
SELECT 'USE '+DB_NAME(database_id) FROM sys.change_tracking_databases
OPEN DbCursor
FETCH NEXT FROM DbCursor INTO @obj
WHILE @@Fetch_Status = 0
BEGIN
SET @tsql2 = @obj+'; '
RAISERROR (@tsql2, 0, 1) WITH NOWAIT
EXEC sp_sqlexec @tsql2
-----------Commands within this next section are all database dependent
BEGIN --GRANT [VIEW CHANGE TRACKING] TO Change Tracking Enabled Tables
IF NOT EXISTS (SELECT name FROM sys.database_principals where name = @newgrp)
BEGIN
SET @tsql = N'CREATE ROLE '+@newgrp+' AUTHORIZATION [dbo]'
IF @Debug = 'TRUE'
BEGIN
SET @Msg = @tsql
RAISERROR (@Msg, 0, 1) WITH NOWAIT
END
ELSE
BEGIN
EXEC sp_sqlexec @tsql
END
END
DECLARE TblCursor CURSOR FOR
SELECT sch.name, tbl.name
FROM sys.change_tracking_tables chg
JOIN sys.tables tbl ON chg.object_id=tbl.object_id
JOIN sys.schemas sch ON tbl.schema_id=sch.schema_id
ORDER BY sch.name, tbl.name
OPEN TblCursor
FETCH NEXT FROM TblCursor INTO @SchName,@TblName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @tsql = 'GRANT VIEW CHANGE TRACKING ON ['+@SchName+'].['+@TblName+'] TO '+@newgrp
IF @Debug = 'TRUE'
BEGIN
SET @Msg = @tsql
RAISERROR (@Msg, 0, 1) WITH NOWAIT
END
ELSE
BEGIN
EXEC sp_sqlexec @tsql
END
FETCH NEXT FROM TblCursor INTO @SchName,@TblName
END
CLOSE TblCursor
DEALLOCATE TblCursor
END
FETCH NEXT FROM DbCursor INTO @obj
END
CLOSE DbCursor
DEALLOCATE DbCursor
END
外部游标中的 USE
语句对后面生成的语句没有任何作用,因为它们是独立执行的。当您的外部游标执行 USE
时,它只对第一个 EXEC sp_sqlexec
调用的范围有效;它不会更改整个脚本的数据库上下文。其余脚本的上下文 运行s 仍然是整个脚本的上下文,这意味着这些语句每次都会在当前数据库中得到 运行。
基本上,您需要更改它以生成一个脚本,其中包含您要在动态数据库上下文中从上到下执行的全部内容,USE
在顶部,然后执行该脚本只需一次调用 EXEC
或 sp_executesql
.
我的代码似乎应该可以工作,但是测试表明来自内部游标的所有结果都基于脚本执行时的当前数据库,而不依赖于脚本中的 USE 语句。 我忘记了什么?
DECLARE @Debug BIT = 1
DECLARE @newgrp VARCHAR(100) = 'ChangeTrakingViewableRole'
DECLARE @obj VARCHAR(100)
DECLARE @tsql VARCHAR(900)
DECLARE @tsql2 VARCHAR(900)
DECLARE @msg VARCHAR(900)
DECLARE @SchName VARCHAR(55)
DECLARE @TblName sysname
IF @Debug = 'TRUE' PRINT 'Debuging ON'
IF COALESCE(@newgrp,'') = ''
BEGIN
PRINT 'There was no DatabaseRole, User or Group Specified to take the place of the Public Role'
SET NOEXEC ON
END
ELSE
BEGIN
DECLARE DbCursor CURSOR FOR
SELECT 'USE '+DB_NAME(database_id) FROM sys.change_tracking_databases
OPEN DbCursor
FETCH NEXT FROM DbCursor INTO @obj
WHILE @@Fetch_Status = 0
BEGIN
SET @tsql2 = @obj+'; '
RAISERROR (@tsql2, 0, 1) WITH NOWAIT
EXEC sp_sqlexec @tsql2
-----------Commands within this next section are all database dependent
BEGIN --GRANT [VIEW CHANGE TRACKING] TO Change Tracking Enabled Tables
IF NOT EXISTS (SELECT name FROM sys.database_principals where name = @newgrp)
BEGIN
SET @tsql = N'CREATE ROLE '+@newgrp+' AUTHORIZATION [dbo]'
IF @Debug = 'TRUE'
BEGIN
SET @Msg = @tsql
RAISERROR (@Msg, 0, 1) WITH NOWAIT
END
ELSE
BEGIN
EXEC sp_sqlexec @tsql
END
END
DECLARE TblCursor CURSOR FOR
SELECT sch.name, tbl.name
FROM sys.change_tracking_tables chg
JOIN sys.tables tbl ON chg.object_id=tbl.object_id
JOIN sys.schemas sch ON tbl.schema_id=sch.schema_id
ORDER BY sch.name, tbl.name
OPEN TblCursor
FETCH NEXT FROM TblCursor INTO @SchName,@TblName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @tsql = 'GRANT VIEW CHANGE TRACKING ON ['+@SchName+'].['+@TblName+'] TO '+@newgrp
IF @Debug = 'TRUE'
BEGIN
SET @Msg = @tsql
RAISERROR (@Msg, 0, 1) WITH NOWAIT
END
ELSE
BEGIN
EXEC sp_sqlexec @tsql
END
FETCH NEXT FROM TblCursor INTO @SchName,@TblName
END
CLOSE TblCursor
DEALLOCATE TblCursor
END
FETCH NEXT FROM DbCursor INTO @obj
END
CLOSE DbCursor
DEALLOCATE DbCursor
END
外部游标中的 USE
语句对后面生成的语句没有任何作用,因为它们是独立执行的。当您的外部游标执行 USE
时,它只对第一个 EXEC sp_sqlexec
调用的范围有效;它不会更改整个脚本的数据库上下文。其余脚本的上下文 运行s 仍然是整个脚本的上下文,这意味着这些语句每次都会在当前数据库中得到 运行。
基本上,您需要更改它以生成一个脚本,其中包含您要在动态数据库上下文中从上到下执行的全部内容,USE
在顶部,然后执行该脚本只需一次调用 EXEC
或 sp_executesql
.