比较的转换规则
在比较两个字符串时,如有必要,其中一个字符串会先转换为另一个字符串的编码字符集。 只有在某些规则适用的情况下,转换才是必要的。
只有在以下所有条件都满足时,才需要进行转换:
- 两个字符串的CCSID不同。
- 两个CCSID都不是 X'FFFF' (两个字符串都没有被定义为二进制字符串)。
- 转换所选的字符串既非空字符串,也非空字符串。
- 以下转换表 (表2 或表3 )显示了何时需要进行转换。
转换所选的字符串取决于操作数的类型。 为了确定CCSID,语句中的字符串表达式分为6种类型,如下表所示。
| 操作数类型 | 操作数类型的CCSID |
|---|---|
| 列 | 来自包含表的CCSID |
| 字符串常量 | CCSID与应用程序编码方案相关联。 对于动态语句,这是当前应用程序编码方案专用寄存器。 对于静态语句,这是本机 SQL 过程的 CREATE PROCEDURE 或 ALTER PROCEDURE 语句的 ENCODING 绑定选项或 APPLICATION ENCODING SCHEME 选项。 |
| 专用寄存器 | CCSID与应用程序编码方案相关联。 对于动态语句,这是当前应用程序编码方案专用寄存器。 对于静态语句,这是本机 SQL 过程的 CREATE PROCEDURE 或 ALTER PROCEDURE 语句的 ENCODING 绑定选项或 APPLICATION ENCODING SCHEME 选项。 |
| 主变量 | 在DECLARE VARIABLE语句中指定的CCSID,与应用程序编码方案相关联,或在SQLDAID或SQLDA中指定 |
| 全局变量 | UNICODE的CCSID |
| 基于列的派生值 | CCSID 源自派生值的来源。 基于列的派生值是一种表达式,其源直接或间接基于列。 这种表达的CCSID是源自其来源的CCSID。 例如:
|
| 非基于列的派生值 | CCSID 源自派生值的来源。 非基于列的派生值是指其来源不直接或间接基于任何列的表达式。 这种表达的CCSID是源自其来源的CCSID。
|
下表显示了当比较是涉及多个具有不同CCSID集的表的SQL语句的一部分时,哪个操作数提供了目标CCSID集。
| 第一个操作数 | 第二个操作数 | |||||
|---|---|---|---|---|---|---|
| 列值 | 字符串常量 | 专用寄存器 | 主变量 | 基于列的派生值 | 非基于列的派生值 | |
| 列值 | 1 | 第一个操作数 | 第一个操作数 | 第一个操作数, 2 | 1 | 第一个操作数 |
| 字符串常量 | 第二个操作数 | 1 | 1 | 1 | 第二个操作数 | 1 |
| 专用寄存器 | 第二个操作数 | 1 | 1 | 1 | 第二个操作数 | 1 |
| 主变量 | 第二个操作数 | 1 | 1 | 1 | 第二个操作数, 2 | 1 |
| 全局变量 | 第二个操作数 | |||||
| 基于列的派生值 | 1 | 第一个操作数 | 第一个操作数 | 第一个操作数, 2 | 1 | 第一个操作数 |
| 非基于列的派生值 | 第二个操作数 | 1 | 1 | 1 | 第二个操作数 | 1 |
注:
|
||||||
下表显示了当两个操作数都基于列或不基于列时,如上表所示,选择哪个操作数进行转换。
例如,假设比较的形式是:
string-constant-SBCS =derived-value-not-based-on-column-DBCS假设操作数具有不同的编码方案。 首先看表2。 相关表格条目位于第三行第二列。 此条目的值表明,如果CCSID集不同,则操作数将转换为Unicode。 第一个操作数(字符串常量-SBCS)如果还不是Unicode,则转换为 UTF-8 (混合)。 此外,第二个操作数(非基于DBCS列的派生值)在必要时转换为 UTF-16 (Unicode DBCS)。 在操作数转换为Unicode后,使用表3 确定哪个操作数提供转换所需的特定CCSID。 相关表格条目位于第二行和第三列。 这表明第二个操作数(非基于DBCS列的派生值)决定了CCSID,因为DBCS数据优先于混合数据。如果字符串中的某个字符无法转换,则会发生错误;使用了 SYSSTRINGS 表,但其中不包含任何关于被比较操作数的 CCSID 对的信息;或者 Db2 无法通过 z/OS® 对 Unicode 的支持进行转换。 如果字符串中的某个字符被转换为替换字符,则会发出警告。
基于列的派生值是一种表达式,它包含影响表达式 CCSID 的列。 例如,在表达式 COL1||'abc' 中, COL1 决定了结果CCSID。 因此, COL1||'abc' 表达式被视为基于列的派生值,在任何进一步比较中,该列将继续优先。 表达式 CASE
WHEN COL1 > 1 THEN 'abc' ELSE 'def' END 包含一列,该列不影响表达式的结果CCSID,因此不被视为基于列的派生值。
下表定义了哪些表达式被视为基于列的派生值。
| 表达式 | 条件 |
|---|---|
| expression1 || expression2 | expression1 或 expression2 是列或基于列的派生值 |
| CASE 当条件然后结果表达式否则结果表达式结束 | 任何结果表达式都是字符串表达式 ,它是一个列或基于列的派生值 |
| CAST(将表达式转换为数据类型 ) | 表达式 是一个字符串表达式 ,它是一个列或基于列和数据的派生值, 数据类型是字符串数据类型 |
| 标量全选:(SELECT expression FROM table ) | 表达式 是一个字符串表达式 ,它是一个列或基于列和数据的派生值, 数据类型是字符串数据类型 |
当语句包含多个CCSID集时,如果其中一个字符串的长度在CCSID转换后发生变化,则该字符串将成为一个长度可变的字符串。 也就是说,数据类型变为VARCHAR、CLOB、VARGRAPHIC或DBCLOB。 下表显示了CCSID转换的最坏情况下的结果长度,其中X为字节数。
| 源CCSID | 至CCSID | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| EBCDIC | ASCII | Unicode | ||||||||
| SBCS | 混合 | DBCS | SBCS | 混合 | DBCS | SBCS | UTF-8 | UTF-16 | ||
| EBCDIC | SBCS | X | X | X*21 | X | X | X*21 | X1 | X*3 | X*2 |
| 混合 | X | X | X*21 | X | X | X*21 | X1 | X*3 | X*2 | |
| DBCS | X*0.51 | X+2 | X | X*0.51 | X | X | X*0.5 | X*1.5 | X | |
| ASCII | SBCS | X | X | X*21 | X | X | X*21 | X1 | X*3 | X*2 |
| 混合 | X | X*1.8 | X*21 | X | X | X*21 | X1 | X*3 | X*2 | |
| DBCS | X*0.51 | X+2 | X | X*0.51 | X | X | X*0.5 | X*1.5 | X | |
| Unicode | SBCS | X | X | X*2 | X | X | X*2 | X | X | X*2 |
| UTF-8 | X | X*1.25 | X | X | X | X | X | X | X*2 | |
| UTF-16 | X*0.5 | X+2 | X | X*0.5 | X | X | X*0.5 | X*1.5 | X | |
注:
|
||||||||||