SQL Server:允许禁用/重新启用FK约束的权限,但没有其他更改

时间:2016-06-16 16:34:19

标签: sql sql-server tsql permissions

是否存在允许委托人禁用/启用外键约束但不允许其他表更改的权限设置?

例如:来自'dbo'校长:

create login ref_test with password = 'test1234'
create user ref_test

exec sp_addrolemember 'db_datareader', 'ref_test'
exec sp_addrolemember 'db_datawriter', 'ref_test'

create table A (ID int not null, constraint PK_A primary key (ID))
create table B (Aid int not null, constraint FK_Aid_AID foreign key (Aid) references A(ID))

来自ref_test登录连接:

insert A values (1)
insert B values (1)

现在,我需要能够更新FK关系中的密钥,如下所示:

-- will fail
ALTER TABLE B NOCHECK CONSTRAINT FK_Aid_AID 
update A set ID = ID + 1
update B set AID = AID + 1
ALTER TABLE B WITH CHECK CHECK CONSTRAINT FK_Aid_AID 

失败
  

Msg 1088,Level 16,State 13,Line ...
  无法找到对象“B”,因为它不存在或您没有权限

如果我添加

GRANT ALTER on B to ref_test

它可以工作,但不是没有启用ALTER TABLE B DROP CONSTRAINT FK_Aid_AID,以及在表上启用其他DDL - 添加/删除列,其他约束 - 尽管允许FK有问题需要重新添加 - 这需要额外的GRANT REFERENCES (ID) on A to ref_test

3 个答案:

答案 0 :(得分:2)

不,使用SQL Server的权限方案无法做到这一点。要执行任何特定的ALTER TABLE语句,您需要ALTER权限,这反过来允许您执行任何ALTER TABLE语句,保存那些需要更新列或引用外部类型或列的语句(需要单独的权利。)

授予帐户权限的一般方法是执行他们原本无法执行的操作(并且那些事情)是将它们封装在在特权帐户下执行的存储过程中。因此,假设您希望为帐户提供在任何表上禁用或启用任何约束的功能,但不要执行与这些表相关的任何其他DDL:

CREATE PROCEDURE nocheck_constraint(@table SYSNAME, @constraint SYSNAME)
WITH EXECUTE AS OWNER AS 
BEGIN
    SET NOCOUNT ON;
    DECLARE @SQL NVARCHAR(MAX);
    SET @SQL = REPLACE(REPLACE(
        'ALTER TABLE $table NOCHECK CONSTRAINT $constraint;', 
        '$table', QUOTENAME(@table)),
        '$constraint', QUOTENAME(@constraint))
    ;
    PRINT @SQL;
    EXEC(@SQL);
END;
GO
-- The following is necessary only for direct calls.
-- Note that ownership chaining will allow *any* stored procedure to call this one without 
-- a separate permission check, which is a double-edged sword.
GRANT EXECUTE ON nocheck_constraint TO [unprivileged_account];  

同样适用于check_constraint。当然,您可以根据需要使其更精细。

我通过利用EXECUTE AS OWNER在这里采取了一个潜在的危险捷径,因此我可以在没有安全限制的情况下执行动态SQL。如果您无法完全控制数据库及其中创建的所有过程,则这不仅会对数据库的安全性产生影响,还会对服务器的其余部分产生一些影响。在这种情况下,您可能希望考虑签署该过程并使用代理。我没有将这一切都散列到这里,而是引用你Erland Sommarskog's excellent writeup on the matter

答案 1 :(得分:0)

我有一些用户,我不会在Management Studio中授予权限以更改表的列的扩展属性。 因此,当对该用户的表赋予ALTER权限时,可以看到Keys,Indexes,Constraint,甚至无法更改。所以不要看到在sys.check_constraint,sys.foreignkeys,sys.key_constraint中的SELECT上有DENY .... 因此,可能在sys.columns,sys.foreignkeys,sys.check_constraint上使用ALTER ON表和DENY和GRANT的某种组合....可以允许主体禁用/启用外键约束,但不允许其他表改变

答案 2 :(得分:-1)

Msg 1088,Level 16,State 13,Line ... 无法找到对象“B”,因为它不存在或您没有权限

如果我在管理工作室这样做,我会注意到下一步: 如果我对特定表没有SELECT权限则会出现问题,所有ForeignKey都会消失 如果我没有SELECT权限,那么在CheckExistingData上创建或启用如果是,则应该在No中更改,并且EnforceForeignKey Constraint可以从Yes更改为No,或者相反 所以: 1.或表上的SELECT权限(CheckExistingDataOnCreatinon需要或如果设置为Yes则需要重新启用) 2.或CheckExistingDataOnCreation或Reanablig(再次创建)设置为否

相关问题