2017-09-21 167 views
1

我在SQL服务器上创建行级安全2014年只有在存在过滤器过滤器的情况下才可以使用过滤器过滤器?

它能够丢弃过滤谓词上我的客户表是这样的:

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

但是,如果我连续两次执行该代码,我有错误

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

有没有一种方法可以在DROP存在时才删除它?

+0

你确定你正在使用' SQL Server 2014'而不是'SQL Server 2016'? – lad2025

+0

@ lad2025当我做“SELECT @@ VERSION”时,我得到了“Microsoft SQL Azure(RTM) - 12.0.2000.8 Aug 29 2017 13:06:11 Copyright(C)2017 Microsoft Corporation”,它似乎是从SQL Server 2014该网站:https://support.microsoft.com/en-ca/help/321185/how-to-determine-the-version--edition-and-update-level-of-sql-server-a – pikarie

回答

1

我找到了解决办法!我需要使用动态SQL才能工作,因为SECURITY POLICY关键字在SELECT之前执行,或者导致我的错误。

此代码只检查是否filter谓词是存在的,但因为我总是在同一时间加入filterblock,验证,我无所谓:

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 
+0

很高兴听到你解决了它:) – lad2025

+0

@ lad2025感谢您的帮助!对此,我真的非常感激! – pikarie

2

我会使用的方法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 
+0

我仍然出现错误“安全策略'rls.tenantAccessPolicy'在表'dbo.Client'上不包含谓词。”当我运行你的第一个脚本(一个去除FILTER PREDICATE)。我会试着玩一下,看看我能否找到解决方案。 – pikarie

+0

@pikarie我无权访问SQL Server,因此我无法检查它。我建议运行**'SELECT OBJECT_NAME(object_id),OBJECT_NAME(target_object_id)FROM sys.security_predicates)**以匹配条件。 – lad2025

+0

该变量都是正确的。我在DROP后添加了一个SELECT 1,我创建了一个ELSE语句并添加了一个SELECT 2,并且第二次在我的SELECT 1所在的位置运行时发生崩溃(这很奇怪,因为当我评论ALTER,DROP时,结果是“2”,表示代码通过ELSE) – pikarie