我正在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?
答案 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
谓词是否存在,但由于我总是同时添加filter
和block
,因此验证对我来说没问题:< / 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