CREATE MASK 语句

CREATE MASK语句在当前服务器上创建一个列掩码。 列掩码用于列访问控制,并指定应返回给指定列的值。

调用 CREATE MASK

此语句可嵌入应用程序中或者以交互方式发出。 这是一个可执行语句,只有在DYNAMICRULES RUN行为生效时才能动态准备。 更多信息,请参阅授权ID和动态SQL

授权 CREATE MASK

以下定义的特权集必须包含以下权限:

  • SECADM 权限

SECADM 权限可以在任何模式中创建列掩码。 在蒙版定义中引用其他对象无需其他权限。 例如,查询表不需要SELECT权限,调用用户定义的函数也不需要EXECUTE权限。

权限集: 如果该语句嵌入在应用程序中,则权限集是包的所有者所拥有的权限的集合。 如果语句是动态准备的,则权限集是指由进程的 SQL 授权 ID 持有的权限集。 但是,如果进程在可信环境中运行,且可信环境由 ROLE AS OBJECT OWNER AND QUALIFIER 子句定义,则权限集是指当前角色所拥有的一组权限。

语法 CREATE MASK

阅读语法图跳过可视化语法图CREATE MASK假名ONtable-name AS相关名称FOR COLUMN列名RETURNcase-expressionDISABLEENABLE

描述 CREATE MASK

假名
指定列掩码的名称。 名称(包括隐式或显式限定符)不得标识当前服务器上已存在的列掩码或行权限。
ON 表名
标识创建列掩码的表格。 名称必须标识当前服务器上存在的表。 不得识别以下任何物体:
  • 辅助表格
  • 已创建的临时表或者已声明的临时表
  • 一个视图
  • 目录表
  • 别名
  • 同义词
  • 在物化查询表的定义中直接或间接引用的物化查询表或表
  • 为 XML 列隐式创建的表
  • 包含一个句号的表格
  • 历史表
  • 只含加速器的表格
  • 启用存档功能的表格
  • 档案表
相关名称
指定一个可以在 case-expression 中使用的关联名称来指定表。 关于相关名称的信息,请参阅相关名称
FOR COLUMN 列名
标识蒙版所应用的列。 列名必须是一个无限制的名称,用于标识指定表的列。 该列不能已存在掩码。 专栏不得:
  • LOB列或基于LOB的独立类型列
  • XML 列
  • 由FIELDPROC定义
RETURN 案例表达
指定一个 CASE 表达式,用于确定列返回的值。 将返回 CASE 表达式的结果来代替行中的列值。 CASE 表达式的结果数据类型、空属性、数据长度、子类型、编码方案和CCSID必须与列名指定的列的属性相同。 如果列名的数据类型是用户定义的数据类型,则 CASE 表达式的结果数据类型必须与用户定义的类型相同。 CASE 表达不得涉及以下任何对象:
  • 一个遥远的物体
  • 定义列掩码的表格
  • 已创建的全局临时表或已声明的全局临时表
  • 辅助表格
  • 为 XML 列隐式创建的表
  • 使用 FIELDPROC 定义的列
  • 基于LOB的LOB列或单独类型列
  • XML 列
  • SELECT子句中的列表符号 *name.*
  • 表函数
  • 衍生自收藏的桌子(UNNEST)
  • 用户自定义函数,定义为不安全
  • 非确定性函数或具有外部作用或使用MODIFIES SQL DATA选项定义的函数
  • 聚合函数,除非在子查询中指定
  • 内置表格功能
  • XMLTABLE表函数
  • XMLEXISTS 谓词
  • OLAP 规范
  • ROW CHANGE 表达式
  • 顺序引用
  • 宿主变量、SQL变量、SQL参数或触发器转换变量
  • 参数标记
  • 包含时间规格的表格参考
  • 在定义中包含上述任何限制的观点
  • 只含加速器的表格

更改开始表格中的编码方案用于评估 CASE 表达式。 除了带有Unicode列的EBCDIC表之外, CASE 表达式中不得引用需要评估多种编码方案的表和语言元素。 请参阅确定字符串的编码方案和CCSID ,了解需要多次计算的语言元素。更改结束

如果 CASE 表达式引用了行或列访问控制处于活动状态的表,则这些表的访问控制不会级联。

禁用或 ENABLE
指定启用或禁用列掩码,以进行列访问控制。
禁用
指定在列访问控制中禁用列掩码。 无论是否启用表格的列访问控制,列掩码都将保持禁用状态。

默认值为禁用

ENABLE
指定启用列掩码以进行列访问控制。 如果当前未对表启用列访问控制,则在表启用列访问控制后,列掩码将启用。 如果当前对表启用了列访问控制,则列掩码立即启用,动态语句缓存中引用该表的所有程序包和语句都将失效。 更多信息,请参阅 “导致套餐失效的变更 ”。

备注 CREATE MASK

列掩码如何影响查询

启用列掩码的应用不会影响语句中其他子句的操作,例如WHERE、GROUP BY、HAVING、SELECT DISTINCT或ORDER BY。 最终结果表中返回的行保持不变,只是结果行中的值可能已被列掩码屏蔽。 因此,如果带掩码的列也出现在带有排序键表达式的 ORDER BY 子句中,则排序依据的是列的原始值,最终结果表中的掩码值可能无法反映该排序。 同样,隐藏的值可能无法反映 SELECT DISTINCT 语句或 COUNT (DISTINCT 表达式 ) 函数所强制的独特性。 如果将带掩码的列嵌入表达式中,则表达式的结果可能会有所不同,因为列掩码是在执行表达式计算之前应用的。

列掩码定义与SQL之间的冲突
柱面罩作为独立对象创建,不知道它可能被用于的所有上下文。 为了在最终结果表中隐藏列的值,列掩码的定义通过 Db2 合并到查询中。 当列掩码的定义与语句的上下文结合时,可能会与语句中的某些SQL语义相冲突。 因此,在某些情况下,语句和列掩码的应用组合可能会返回错误。 当出现这种情况时,要么需要修改语句,要么需要删除列掩码,或者使用不同的定义重新创建列掩码。 请参阅 ALTER TABLE语句 ,了解该语句可能出现的绑定时间错误。
列掩码和空列
如果列不可为空,那么列掩码的定义很可能不会考虑列的无效值。 在激活表的列访问控制后,如果该表是外部联接中的填充空值的表,则最终结果表中该列的值可能为空。 为了确保列掩码可以掩码空值,如果表是外部联接中的空值填充表,则 Db2 会将“WHEN 目标列 IS NULL THEN NULL ”作为第一个WHEN子句添加到列掩码定义中。 这迫使空值始终被屏蔽为空值。 对于可空列,这消除了将空值屏蔽为其他值的功能。 例5显示了新增的“当”子句。
SQL数据更改语句的列掩码值
当使用列来为INSERT、UPDATE、MERGE或SET 转换变量赋值语句求取新值时,将使用列的原始值(而非掩码值)来求取新值。 如果列有列掩码,则应用这些列掩码以确保在运行时访问控制规则的评估将列掩码应用于自身,而不是常量或表达式。 这是为了确保隐藏的值与原始列值相同。 如果列掩码不能对自身进行掩码,则现有行不会更新,或者新行不会被插入,并且在运行时返回错误。 用于应用列掩码以得出新值的规则与查询最终结果表的规则相同。
在启用列访问控制之前创建的列掩码
CREATE MASK语句是一个独立语句,可用于在激活表的列访问控制之前创建列访问控制掩码。 唯一的要求是,在创建蒙版之前,表格和列必须已经存在。 可以为表格创建多个列掩码,但一个列只能有一个掩码。

面罩的定义保存在 Db2 目录中。 记录了创建掩码的表依赖关系以及定义中引用的其他对象的依赖关系。 任何包或动态缓存语句都不会失效。 列掩码可以设置为启用或禁用,以进行列访问控制。 启用列掩码只有在使用带有激活列访问控制子句的ALTER TABLE语句激活表的列访问控制时才会生效。 SECADM 权限需要发布此类 ALTER TABLE 语句。 即使为桌子激活了列访问控制,损坏的列掩码仍然无效。 ALTER MASK语句可用于在ENABLE和DISABLE之间切换。

在激活了表的列访问控制后,当数据操作语句引用该表时, Db2 将隐式应用为该表创建的所有已启用列掩码,以掩蔽查询最终结果表中引用的列返回的值,或确定数据更改语句中使用的新的值。

提示 :为避免多次无效引用表和动态缓存语句,请在激活表的列访问控制之前创建列掩码。
启用列访问控制后创建的列掩码
启用后的列掩码一经提交立即生效。 引用该表的所有包和动态缓存语句均无效。 此后,当数据操作语句引用该表时, Db2 会将所有启用的列掩码隐式应用到该语句中。 即使为表格激活了列访问控制,任何无效的列掩码仍然无效。
当列掩码定义中引用了强制列或行访问控制表时,不会出现级联效应
列掩码定义可以引用当前通过行或列访问控制强制执行的表和列。 当在数据操作语句中引用了创建列掩码的表时,这些表和列的访问控制将被忽略。
多个列掩码和行权限共享相同的环境变量
可以为表创建多列掩码和行权限。 他们必须使用相同的环境变量集。 当为表创建第一列掩码或第一行权限时,环境变量集即被确定。

目录表 SYSENVIRONMENT 包含环境变量列表。 下表显示了在多列掩码和行权限中,哪些环境变量必须相同。

表 1. 环境变量 SYSIBM.SYSENVIRONMENT
环境变量以SYSENVIRONMENT列的形式显示 描述 静态创建语句 动态 CREATE 语句 多列掩码和行权限之间必须相同吗?
ENVID 环境的内部标识符 分配者 Db2 分配者 Db2
CURRENT_SCHEMA 限定词,用于限定不具有限定性的对象,如桌子、景观等。 等等 程序包所有者 当前模式特殊寄存器的值
PATHSCHEMAS 用于限定非限定对象(如用户定义的函数和用户定义的数据类型的CAST函数)的方案路径。 路径绑定选项 CURRENT_PATH特殊寄存器的值
应用程序_
编码_
CCSID
应用程序环境的CCSID 编码绑定选项 当前应用编码方案 特殊寄存器
ORIGINAL_
ENCODING_
CCSID
声明文本字符串的原始CCSID CCSID(n)预编译选项或DSNTIPF安装面板上的EBCDIC CCSID CCSID基于DSNTIPF安装面板上的DEF编码方案
小数点 小数点指示器 逗号或句号预编译选项或小数点位于DSNTIPF安装面板上 小数点位于DSNTIPF安装面板上
最小分割比例 最小分度 最小分度值, DSNTIP4 安装面板 最小分度值 DSNTIP4 安装面板v 是的
字符串分隔符 COBOL字符串常量中使用的字符串分隔符 APOST预编译选项或DSNTIPF安装面板上的字符串分隔符 DSNTIPF安装面板上的字符串分隔符 False
SQL_
STRING_
DELIMITER
常量中使用的SQL字符串分隔符 APOSTSQL预编译器选项或DSNTIPF安装面板上的SQL字符串分隔符 在DSNTIPF安装面板上设置SQL字符串分隔符
MIXED_DATA 使用混合DBCS数据 DSNTIPF安装面板上的混合数据 DSNTIPF安装面板上的混合数据
DECIMAL_
算术
当前精度规则,适用于十进制运算中两个操作数的精度均为15或更小的情况。 DEC(15)或DEC(31)预编译选项或小数点后保留两位小数,在 DSNTIP4 安装面板上 DSNTIP4 安装面板上的十进制运算
DATE_FORMAT 日期格式 DSNTIP4 安装面板上的预编译选项或日期格式 日期格式: DSNTIP4 安装面板
TIME_FORMAT 时间格式 在 DSNTIP4 安装面板上选择TIME pre-compiler选项或TIME FORMAT选项 时间格式在 DSNTIP4 安装面板上
FLOAT_FORMAT 浮点格式 FLOAT( S390 | IEEE)预编译器选项或FLOAT的默认值 S390 默认的浮动 S390 False
HOST_LANGUAGE 母语 在DSNTIPF安装面板上选择HOST预编译选项或LANGUAGE DEFAULT DSNTIPF安装面板上的语言默认设置 False
字符集 字符集 CCSID(n)预编译选项或DSNTIPF安装面板上的EBCDIC CCSID DSNTIPF安装面板上的EBCDIC CCSID False
FOLD FOLD仅适用于HOST_LANGUAGE为C或CPP的情况。 否则折叠为空白。 HOST(C(FOL D)预编译选项或默认选项NO FOLD 默认不折叠 False
四舍五入 在对DECFLOAT数据进行算术和转换操作时使用的舍入模式。 四舍五入绑定选项 当前 DECFLOAT 舍入模式 特殊寄存器
注意 :在数据共享环境中,如果为组中的每个成员提供了单独的DSNHDECP模块,则数据共享组中所有成员的每个环境变量的DSNHDECP设置应相同,否则在创建多个列掩码或行权限时可能会出现错误。
COBOL应用程序中静态CREATE MASK语句中指定的普通SQL标识符:
如果CREATE MASK语句是COBOL应用程序中的静态语句,则列掩码定义中使用的普通SQL标识符不得遵循COBOL单词的命名规则。 他们必须遵守 SQL中标识符命名的规则。 例如,在列掩码定义中,不允许将COBOL单词 1ST-TIME 作为普通的SQL标识符;将其更改为FIRST_TIME或将其放在分隔符中。
应用列掩码后的数据操作语句的编码方案和CCSID:
更改开始数据操作语句的编码方案和CCSID不受 Db2 为列访问控制隐式应用的列掩码的影响。 对于不是带有Unicode列的EBCDIC表的目标表或参考表,列掩码定义使用其表的编码方案和CCSID进行评估。 对于目标表或参考表是带有Unicode列的EBCDIC表,列掩码定义将使用多种编码方案的规则进行评估。更改结束
请注意 Db2 的限制:
如果数据操作语句已经接近语句中的某些 Db2 限制,则应注意,创建的列掩码和行权限越多,就越有可能影响某些限制。 例如,它们可能会导致语句超过需要排序和评估聚合函数(MULTIPLE DISTINCT和GROUP BY)的查询操作列的最大总长度(32600字节)。 这是因为当数据操作语句引用表时,启用的列掩码和启用的行权限定义会隐式合并到语句中。 有关语句的限制,请参阅SQL参考中的“ Db2 for z/OS® 中的限制”。
涉及待定义变更的限制:
如果定义在表中的掩码或引用了有待定义更改的表,则不允许创建掩码。

例子 CREATE MASK

更改开始在以下示例中,SSN列的数据类型为VARCHAR(11)。更改结束

示例 1
在员工表启用列访问控制后,薪资部门的保罗可以看到员工编号为123456的员工的社保号码。 身为经理的玛丽只能看到社会保险号码的最后四个字符。 彼得既看不到社保号。
CREATE MASK SSN_MASK ON EMPLOYEE
   FOR COLUMN SSN RETURN
     CASE 
          WHEN (VERIFY_GROUP_FOR_USER(SESSION_USER,'PAYROLL') = 1)
			      THEN SSN
          WHEN (VERIFY_GROUP_FOR_USER(SESSION_USER,'MGR') = 1)
           THEN 'XXX-XX-' || SUBSTR(SSN,8,4)
          ELSE NULL
     END
   ENABLE;

COMMIT;

ALTER TABLE EMPLOYEE 
    ACTIVATE COLUMN ACCESS CONTROL;

COMMIT;

SELECT SSN FROM EMPLOYEE 
    WHERE EMPNO = 123456;
示例 2
在 SELECT 语句中,SSN 列嵌入在表达式中,该表达式与列掩码 SSN_MASK 中使用的表达式相同。 在表 EMPLOYEE 中启用列访问控制后,SELECT 语句中的 SSN 列将应用列掩码 SSN_MASK。 对于这种特殊表达,SELECT语句在所有用户启用列访问控制之前产生的结果与之前相同。 用户可以用列SSN替换SELECT语句中的表达式,以避免相同的表达式被计算两次。
CREATE MASK SSN_MASK ON EMPLOYEE
    FOR COLUMN SSN RETURN
      CASE 
           WHEN (1 = 1) 
            THEN 'XXX-XX-' || SUBSTR(SSN,8,4)
           ELSE NULL
      END
    ENABLE;

COMMIT;

ALTER TABLE EMPLOYEE 
    ACTIVATE COLUMN ACCESS CONTROL;

COMMIT;

SELECT 'XXX-XX-' || SUBSTR(SSN,8,4) FROM EMPLOYEE 
    WHERE EMPNO = 123456;
示例 3
州政府针对每个城市的家庭图书馆使用情况进行了调查。 每个城市有50户家庭接受了调查。 每个家庭都可以选择是否在调查产生的报告中显示他们的使用情况。

SELECT语句用于生成报告,显示每个城市家庭平均使用的时间。 CITY_MASK列掩码用于根据抽样家庭选择的加入或退出信息来屏蔽城市名称。 然而,在表 LIBRARY_ USAGE 的列访问控制被激活后,SELECT 语句收到绑定时间错误。 这是因为列掩码 CITY_MASK 引用了另一列 LIBRARY_OPT,而 LIBRARY_OPT 不是分组列。

CREATE MASK CITY_MASK ON LIBRARY_USAGE
    FOR COLUMN CITY RETURN
      CASE 
           WHEN (LIBRARY_OPT = 'OPT-IN') 
            THEN CITY
           ELSE ' '
      END
    ENABLE;

COMMIT;

ALTER TABLE LIBRARY_USAGE
   ACTIVATE COLUMN ACCESS CONTROL;

COMMIT;

SELECT CITY, AVG(LIBRARY_TIME) FROM LIBRARY_USAGE 
   GROUP BY CITY;
示例 4
员工编号为EMPNO 123456的员工在5月份获得了8000美元的奖金和80000美元的工资。 当经理领取工资时,他收到的是工资,而不是零值。 这是因为当列掩码 SALARY_MASK 引用列 BONUS 时,列掩码 BONUS_MASK 已经定义,不会出现级联效应。
CREATE MASK SALARY_MASK ON EMPLOYEE
   FOR COLUMN SALARY RETURN 
       CASE 
            WHEN (BONUS < 10000) 
             THEN SALARY
            ELSE NULL
       END
   ENABLE;

COMMIT;

CREATE MASK BONUS_MASK ON EMPLOYEE
   FOR COLUMN BONUS RETURN
       CASE 
            WHEN (BONUS > 5000) 
             THEN NULL
            ELSE BONUS
       END
   ENABLE;

COMMIT;

ALTER TABLE EMPLOYEE 
    ACTIVATE COLUMN ACCESS CONTROL;

COMMIT;

SELECT SALARY FROM EMPLOYEE 
    WHERE EMPNO = 123456;
示例 5
这个示例显示, Db2 将“WHEN target-column IS NULL THEN NULL”作为第一个WHEN子句添加到列掩码定义中,然后将列掩码定义合并到语句中。
CREATE EMPLOYEE (EMPID INT,
                 DEPTID CHAR(8),
                 SALARY DEC(9,2) NOT NULL,
                 BONUS DEC(9,2));

CREATE MASK SALARY_MASK ON EMPLOYEE
    FOR COLUMN SALARY RETURN
       CASE 
            WHEN SALARY < 10000 
             THEN CAST(SALARY*2 AS DEC(9,2))
            ELSE COALESCE(CAST(SALARY/2 AS DEC(9,2)), BONUS)
       END
    ENABLE;

COMMIT;

CREATE MASK BONUS_MASK ON EMPLOYEE
    FOR COLUMN BONUS RETURN 
      CASE 
          WHEN BONUS > 1000 
           THEN BONUS
          ELSE NULL
      END
    ENABLE;

COMMIT;

ALTER TABLE EMPLOYEE
    ACTIVATE COLUMN ACCESS CONTROL;

COMMIT;

SELECT SALARY FROM DEPT 
    LEFT JOIN EMPLOYEE ON DEPTNO = DEPTID;

/* When SALARY_MASK is merged into the above statement,
 * 'WHEN SALARY IS NULL THEN NULL' is added as the 
 * first WHEN clause, as follows:
 */

SELECT CASE WHEN SALARY IS NULL THEN NULL
            WHEN SALARY < 10000 THEN CAST(SALARY*2 AS DEC(9,2))
            ELSE COALESCE(CAST(SALARY/2 AS DEC(9,2)), BONUS)
       END SALARY
       FROM DEPT 
         LEFT JOIN EMPLOYEE ON DEPTNO = DEPTID;