是否可以仅在DROP FILTER PREDICATE存在的情况下进行预测?

时间:2017-09-21 15:35:59

标签: sql sql-server tsql

我正在SQL Server 2014中创建行级安全性。

可以在我的桌面上对DROP FILTER PREDICATE进行预测:

ALTER SECURITY POLICY rls.tenantAccessPolicy
    DROP FILTER PREDICATE ON dbo.Client,
    DROP BLOCK PREDICATE ON dbo.Client
GO

但如果我连续两次执行此代码,我就会出错

  

“安全策略'rls.tenantAccessPolicy'不包含表'dbo.Client'的谓词。”

有没有办法在它存在的情况下进行DROP?

2 个答案:

答案 0 :(得分:3)

我会使用方法IF EXISTS并检查sys.security_predicates元数据表:

IF EXISTS( SELECT 1
           FROM sys.security_predicates sp
           WHERE sp.predicate_type = 0 -- filter_predicate
             AND OBJECT_ID('rls.tenantAccessPolicy') = sp.object_id
             AND sp.target_object_id = OBJECT_ID('dbo.Client'))
BEGIN    
    ALTER SECURITY POLICY rls.tenantAccessPolicy
        DROP FILTER PREDICATE ON dbo.Client; 
END;
GO

IF EXISTS( SELECT 1
           FROM sys.security_predicates sp
           WHERE sp.predicate_type = 1 -- block_predicate
             AND OBJECT_ID('rls.tenantAccessPolicy') = sp.object_id
             AND sp.target_object_id = OBJECT_ID('dbo.Client'))
BEGIN
    ALTER SECURITY POLICY rls.tenantAccessPolicy
        DROP BLOCK PREDICATE ON dbo.Client;    
END;
GO

答案 1 :(得分:1)

我找到了解决方案!我需要使用动态SQL来实现这一点,因为SECURITY POLICY关键字在SELECT之前执行或导致我的错误。

此代码仅检查filter谓词是否存在,但由于我总是同时添加filterblock,因此验证对我来说没问题:< / p>

IF EXISTS( SELECT 1
            FROM sys.security_predicates sp
            WHERE sp.predicate_type = 0 -- filter_predicate
                AND OBJECT_ID('rls.tenantAccessPolicy') = sp.object_id
                AND sp.target_object_id = OBJECT_ID('dbo.Client'))
BEGIN 
    DECLARE @Sql NVARCHAR(MAX);

    SET @Sql = N'ALTER SECURITY POLICY rls.tenantAccessPolicy
                DROP FILTER PREDICATE ON dbo.Client,
                DROP BLOCK PREDICATE ON dbo.Client'

    EXECUTE sp_executesql @Sql
END
ELSE
BEGIN
    SET @Sql = N'ALTER SECURITY POLICY rls.tenantAccessPolicy
                ADD FILTER PREDICATE rls.fn_tenantAccessPredicateWithSuperUser(CompanyID) ON dbo.Client,
                ADD BLOCK PREDICATE rls.fn_tenantAccessPredicateWithSuperUser(CompanyID) ON dbo.Client'

    EXECUTE sp_executesql @Sql
END
GO