我有一个SQL Server 2008数据库,其中对基础表的所有访问都是通过存储过程完成的。一些存储过程只是从表中SELECT记录,而其他存储过程是UPDATE,INSERT和DELETE。
如果存储过程更新了表,那么执行存储过程的用户是否还需要对受影响的表具有UPDATE权限,或者他们对存储过程具有EXECUTE权限这一事实呢?
基本上我想知道给用户EXECUTE权限是否足够,或者我是否需要为表提供SELECT,UPDATE,DELETE和INSERT权限才能使存储过程正常工作。谢谢。
[编辑] 在我的大多数存储过程中,确实看起来EXECUTE就足够了。但是,我确实发现在使用“执行sp_Executesql”的存储过程中,EXECUTE是不够的。涉及的表需要具有在“sp_Executesql”中执行的操作的权限。
答案 0 :(得分:24)
如果表和proc具有相同的所有者,则不会检查表的权限(包括DENY)。只要模式具有相同的所有者,它们也可以使用不同的模式。
请参阅MSDN上的Ownership chaining
根据已删除答案的评论进行编辑。
除非使用EXECUTE AS
,否则上下文始终是当前登录:仅检查引用的对象DML权限。在存储过程中尝试OBJECT_ID(可引用),其中没有权限分配给referencedtable。它给出了NULL。如果由存储过程的所有者执行,那么它将给出一个值,因为owener拥有可引用的权限
答案 1 :(得分:12)
对存储过程执行权限就足够了。
CREATE TABLE dbo.Temp(n int)
GO
DENY INSERT ON dbo.Temp TO <your role>
GO
CREATE PROCEDURE dbo.SPTemp(@Int int)
AS
INSERT dbo.Temp
SELECT @Int
GO
GRANT EXEC ON dbo.SPTemp TO <your role>
GO
然后(非db_owner)用户将拥有以下权限:
EXEC dbo.SPTemp 10
GO
INSERT dbo.Temp --INSERT permission was denied on the object 'Temp'
SELECT 10
但是,如果dbo.SPTemp中存在尝试插入dbo.Temp的动态SQL,则会失败。在这种情况下,需要授予对表的直接许可。
答案 2 :(得分:3)
也许你可以使用
“with execute as owner”
创建存储过程时,如下所示:
create procedure XXX
with execute as owner
as
begin
...
end
go
然后,您只需向用户授予存储过程EXECUTE
的{{1}}权限。
答案 3 :(得分:2)
执行插入,更新或删除的存储过程的执行权限就足够了。您不需要在表级别授予这些权限。事实上,我会劝阻这种做法。使用存储过程可以更好地控制更改的发生方式。例如,您可能希望在允许更新之前进行一些检查。使用存储过程还可以帮助防止重大事故 - 比如删除表中的所有行,因为有人忘记了WHERE子句!
答案 4 :(得分:1)
非常感谢你!我遇到了类似的问题。这引出了我的答案。
我试图在存储过程中转换一个表,该存储过程调用嵌套在IF语句中的其他存储过程。
我的错误是
服务器主体“domain \ my_id”无法访问当前安全上下文下的数据库“2nd_DB”。
我已经给出了调用存储过程权限来执行truncate( EXECUTE AS SELF ),这会导致问题,因为SELF没有第二个DB的权限。我们的解决方案是将截断移动到另一个SP,包括EXECUTE AS SELF。我们现在调用截断SP,执行我们的数据处理,进行逻辑确定,并调用相应的第3个SP。