【问题标题】:GRANTing permissions across different databases (schemas)跨不同数据库(模式)授予权限
【发布时间】:2010-10-05 04:31:11
【问题描述】:

我只允许通过一系列 Sproc 与 DB 交互来保护 DB;很普通的票价。

我已经挖掘并修改了一个脚本,该脚本循环并为所有非系统 SProcs 分配用户 EXECUTE 权限。它是一种享受,除了我希望将它添加到主数据库中,以便我可以轻松地将它用于任何后续项目。是的,我可以将 simple 保存为 .sql 文件,但我更喜欢这种方式。

问题是我不知道如何动态引用另一个数据库中的对象。例如,我可以在 MyDB.dbo.INFORMATION_SCHEMA.ROUTINES 上轻松查询,但如果 DB 名称是动态的(例如 @MyDBName),如何查询此 DB 中的对象?

编辑:感谢下面的海报,我现在有了一个可行的解决方案:

USE [master]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


ALTER PROCEDURE [dbo].[spGrantExec] 
@User sysname,
@DB varchar(50),
@Target varchar(50)
AS 
/*---------------------------- SQL 2005 + -------------------------------*/

SET NOCOUNT ON

-- 1 - Variable declarations
DECLARE @SQL varchar(8000)

-- 2 - Create temporary table
Set @SQL =
'USE @DB

DECLARE @MAXOID int
DECLARE @OwnerName varchar(128)
DECLARE @ObjectName varchar(128)
DECLARE @CMD1 varchar(8000)

CREATE TABLE #StoredProcedures
(OID int IDENTITY (1,1),
StoredProcOwner varchar(128) NOT NULL,
StoredProcName varchar(128) NOT NULL)

-- 3 - Populate temporary table

INSERT INTO #StoredProcedures (StoredProcOwner, StoredProcName)
SELECT ROUTINE_SCHEMA, ROUTINE_NAME
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE ROUTINE_NAME LIKE ''' + @Target + '%''
 AND ROUTINE_TYPE = ''PROCEDURE''

-- 4 - Capture the @MAXOID value
SELECT @MAXOID = MAX(OID) FROM #StoredProcedures

-- 5 - WHILE loop
WHILE @MAXOID > 0
 BEGIN 

    -- 6 - Initialize the variables
    SELECT @OwnerName = StoredProcOwner,
    @ObjectName = StoredProcName
    FROM #StoredProcedures
    WHERE OID = @MAXOID

    -- 7 - Build the string

    SELECT @CMD1 = ''GRANT EXEC ON '' + ''['' + @OwnerName + '']'' + ''.'' + ''['' + @ObjectName + '']'' + '' TO @user''

    -- 8 - Execute the string
    Print @CMD1
    EXEC(@CMD1)

    -- 9 - Decrement @MAXOID
    SET @MAXOID = @MAXOID - 1
 END

-- 10 - Drop the temporary table
DROP TABLE #StoredProcedures'

Set @SQL = REPLACE(REPLACE(REPLACE(@SQL, '@DB', @DB), '@User', @User), '@Target', @Target)
--Select @SQL
--Print @SQL
Exec (@SQL)
SET NOCOUNT OFF

【问题讨论】:

  • 你可能想看看我找到的更干净的:SELECT @sp_executesql = quotename(@dbname) + '..sp_executesql' EXEC @sp_executesql @CMD1

标签: sql-server sql-server-2005 tsql permissions


【解决方案1】:

您可以使用the double exec technique

在你的情况下,不仅仅是:

EXEC(@CMD1)

你会:

SET @CMD1 =
    'USE OtherDatabase;
    EXEC (''' + REPLACE(@CMD1, '''', '''''') + ''')'
EXEC(@CMD1)

【讨论】:

  • 有趣。我可以看到原理,但还没有消化更精细的细节。但看起来很有希望......
  • 我希望我可以为接受的答案分配奖励 - 无论如何谢谢。
【解决方案2】:

类似于@Cade 的回答,这样做的方法是使用动态sql。在每次调用数据库表之前,添加“@DbName”。然后将@DbName替换为实际的数据库名称(数据库名称在SQL中不能作为变量传递,所以必须进行替换)。

出于性能原因,游标通常被认为是邪恶的,但是在这种情况下使用游标是有意义的。一方面,它会大大简化程序,而且由于您只会在应用程序更新期间运行一次,您可能不会注意到性能下降,即使它增加了一两秒(我怀疑它会添加接近那么多的任何地方)。

ALTER PROCEDURE [dbo].[spGrantExec]
@User SysName,
@DbName VarChar(512)
AS
BEGIN
DECLARE @Sql VarChar(1024)

SET @Sql = 'DECLARE @OwnerName varchar(128) DECLARE @ObjectName varchar(128) DECLARE @Cmd1 VarChar(128) DECLARE ProcCursor CURSOR FOR SELECT ROUTINE SCHEMA, ROUTINE NAME FROM @DbName.INFORMATION SCHEMA.ROUTINES WHERE ROUTINENAME NOT LIKE ''dt %'' AND ROUTINE TYPE = ''PROCEDURE'' OPEN ProcCursor FETCH NEXT FROM ProcCursor INTO @OwnerName, @ObjectName WHILE @@FETCH STATUS = 0 BEGIN SET @CMD1 = ''GRANT EXEC ON '' + ''['' + @OwnerName + '']'' + ''.'' + ''['' + @ObjectName + '']'' + '' TO '' + ''@user'' EXEC (@CMD1)

FETCH NEXT FROM ProcCursor INTO @OwnerName, @ObjectName END CLOSE ProcCursor DEALLOCATE ProcCursor '

SET @Sql = Replace(Replace(@Sql, '@DbName', @DbName), '@user', @User) EXEC (@Sql)

END



您可以使用以下命令调用它:EXEC [spGrantExec] 'bob', 'Northwind'

抱歉,sp 中的间距有点偏离。使用 Sql 2005 开发。

【讨论】:

    【解决方案3】:

    我找到another technique, which I think is cleaner

    SELECT @sql = 'CREATE VIEW ...'
    SELECT @sp_executesql = quotename(@dbname) + '..sp_executesql'
    EXEC @sp_executesql @sql 
    

    这依赖于通过在另一个数据库中调用 sp_executesql 来设置数据库上下文(就像在任何数据库中都可以调用 SP)。

    在你的情况下,它相当于:

    SELECT @sp_executesql = quotename(@dbname) + '..sp_executesql'
    EXEC @sp_executesql @CMD1 
    

    【讨论】:

    • 谢谢。下周我会看看这个。
    猜你喜欢
    • 2014-08-16
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    相关资源
    最近更新 更多