数据类型之间的转换
在许多情况下,需要将具有给定数据类型的值强制类型转换为另一种数据类型,或者转换为长度、精度或小数位不同的同一数据类型。
数据类型提升是一个示例,将一种数据类型提升为另一种数据类型时需要将值强制转换为新的数据类型。 可强制转换为另一种数据类型的一种数据类型可从源数据类型强制类型转换为目标数据类型。
可以将一种数据类型隐式或显式地强制转换为另一种数据类型。 根据涉及到的数据类型,可以使用强制类型转换函数、CAST 规范或 XMLCAST 规范来显式更改数据类型。 另外,当创建了用户定义的有源函数时,必须能够将源函数的参数的数据类型强制转换为正在创建的函数的数据类型。
如果将任何数据类型强制转换为字符或图形数据类型时任何非空白字符被截断,就会返回警告。 此截断行为与对字符或图形数据类型赋值时任何非空白字符被截断而发生错误的情况不同。
在 Unicode 数据库中,可将字符和图形字符串源值强制转换为各种不同字符串单元。 将根据目标数据类型的字符串单元应用相应的截断。
涉及到强类型单值类型的下列强制类型转换是受支持的(除非另有声明,否则都使用 CAST 规范来进行强制类型转换):
- 从单值类型 DT 强制转换为它的源数据类型 S
- 从单值类型 DT 的源数据类型 S 强制转换为单值类型 DT
- 从单值类型 DT 强制转换为同一单值类型 DT
- 从数据类型 A 强制转换为单值类型 DT;其中,可将 A 提升为单值类型 DT 的源数据类型 S
- 从 INTEGER 强制转换为一种源数据类型为 SMALLINT 的单值类型 DT
- 从 DOUBLE 强制转换为一种源数据类型为 REAL 的单值类型 DT
- 从 DECFLOAT 强制转换为源数据类型为 DEFLOAT 的单值类型 DT
- 从 VARBINARY 强制转换为具有源数据类型 BINARY 的单值类型 DT
- 从 VARCHAR 强制转换为一种源数据类型为 CHAR 的单值类型 DT
- 从 VARGRAPHIC 强制转换为一种源数据类型为 GRAPHIC 的单值类型 DT
- 对于 Unicode 数据库,从 VARCHAR 或 VARGRAPHIC 强制转换为一种源数据类型为 CHAR 或 GRAPHIC 的单值类型 DT
- 使用 XMLCAST 规范从一种具有源数据类型 S 的单值类型 DT 强制转换为 XML
- 根据 XML 值的 XML 模式数据类型,使用 XMLCAST 规范从 XML 强制转换为具有可为任何内置数据类型的源数据类型的单值类型 DT
对于涉及到将弱类型单值类型作为目标的强制类型转换,必须能够将数据类型强制类型转换为该弱类型单值类型的源类型,并且数据类型约束求值必须为 true 或未知值。 仅在一种情况下可以操作数隐式地强制类型转换为弱类型单值类型,那就是当源操作数分配给一个目标,该目标的数据类型为弱类型单值类型。
不能将 FOR BIT DATA 字符类型强制转换为 CLOB。
对于涉及到将数组类型作为目标的强制类型转换,必须能够将源数组的元素的数据类型强制转换为目标数组数据的元素的数据类型 (SQLSTATE 42846)。 如果目标数组类型是一个普通数组,那么源数组值必须是一个普通数组 (SQLSTATE 42821),并且源数组值的基数必须小于或等于目标数组数据类型的最大基数 (SQLSTATE 2202F)。 如果目标数组类型是一个联合数组,那么必须能够将源数组值的索引的数据类型强制转换为目标数组类型的索引的数据类型。 只能将用户定义的数组类型值强制转换为用户定义的相同数组类型 (SQLSTATE 42846)。
不能将游标类型作为 CAST 规范的源数据类型或目标数据类型,除非将参数标记强制转换为游标类型。
对于涉及到将行类型作为目标的强制类型转换,源行值表达式的等级必须与目标行类型的等级相匹配,并且必须能够将源行值表达式中的每个字段强制转换为相应的目标字段。 只能将用户定义的行类型值强制转换为用户定义的另一种同名的行类型 (SQLSTATE 42846)。
无法将结构化类型值强制转换为其他类型值。 不应将结构化类型 ST 强制转换为其超类型之一,因为 ST 超类型上的所有方法都适用于 ST。 如果所需操作仅适用于 ST的子类型,请使用 subtype-treatment 表达式将 ST 视为其子类型之一。
当未使用模式名来对强制类型转换中涉及到的用户定义的数据类型加以限定时,使用 SQL 路径来查找包括该用户定义的数据类型的具有该名称的第一种模式。
- 从引用类型 RT 强制转换为它的表示数据类型 S
- 从引用类型 RT 的表示数据类型 S 强制转换为引用类型 RT
- 从目标类型为 T 的引用类型 RT 强制转换为目标类型为 S 的引用类型 RS,其中 S 是 T 的超类型。
- 从数据类型 A 强制转换为引用类型 RT,其中,可将 A 提升为引用类型 RT 的表示数据类型 S。
当未使用模式名来对强制类型转换中涉及到的参考数据类型的目标类型加以限定时,使用 SQL 路径来查找包括该用户定义的数据类型的具有该名称的第一种模式。
| 源数据类型 | 目标数据类型 | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
小
中 大 小 中 大 |
I
N T E G E R |
B
I G I N T |
D
E C I M A L |
R
E A L |
双
|
D
E C F L O A T |
H A R |
C
H A R F B D2 |
V
A R C H A R |
V
A R C H A R F B D 2 |
C
L O B |
图
表 |
V
A R G R A P H I C |
D
B C L O B |
巴纳
里 |
变
化 期 |
B
L O B |
日期
|
I M E |
时
刻 烙 印 |
X
M L |
布尔
莱恩 |
|
| SMALLINT | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | - | Y1 | Y1 | - | - | - | - | - | - | - | Y3 | Y |
| INTEGER | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | - | Y1 | Y1 | - | - | - | - | - | - | - | Y3 | Y |
| BIGINT | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | - | Y1 | Y1 | - | - | - | - | - | - | - | Y3 | Y |
| DECIMAL | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | - | Y1 | Y1 | - | - | - | - | - | - | - | Y3 | - |
| REAL | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | - | Y1 | Y1 | - | - | - | - | - | - | - | Y3 | - |
| 双 | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | - | Y1 | Y1 | - | - | - | - | - | - | - | Y3 | - |
| DECFLOAT | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | - | Y1 | Y1 | - | - | - | - | - | - | - | - | - |
| CHAR | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y1 | Y | Y | Y | Y | Y | Y | Y4 | Y |
| CHAR FOR BIT DATA | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | - | - | - | - | Y | Y | Y | Y | Y | Y | Y3 | - |
| VARCHAR | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y1 | Y | Y | Y | Y | Y | Y | Y4 | Y |
| VARCHAR FOR BIT DATA | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | - | - | - | - | Y | Y | Y | Y | Y | Y | Y3 | - |
| CLOB | - | - | - | - | - | - | - | Y | - | Y | - | Y | Y1 | Y1 | Y1 | Y | Y | Y | - | - | - | Y4 | - |
| GRAPHIC | Y1 | Y1 | Y1 | Y1 | Y1 | Y1 | Y1 | Y1 | - | Y1 | - | Y1 | Y | Y | Y | Y | Y | Y | Y1 | Y1 | Y1 | Y3 | Y1 |
| VARGRAPHIC | Y1 | Y1 | Y1 | Y1 | Y1 | Y1 | Y1 | Y1 | - | Y1 | - | Y1 | Y | Y | Y | Y | Y | Y | Y1 | Y1 | Y1 | Y3 | Y1 |
| DBCLOB | - | - | - | - | - | - | - | Y1 | - | Y1 | - | Y1 | Y | Y | Y | Y | Y | Y | - | - | - | Y3 | - |
| BINARY | - | - | - | - | - | - | - | - | Y | - | Y | - | - | - | - | Y | Y | Y | - | - | - | - | - |
| VARBINARY | - | - | - | - | - | - | - | - | Y | - | Y | - | - | - | - | Y | Y | Y | - | - | - | - | - |
| BLOB | - | - | - | - | - | - | - | - | Y | - | Y | - | - | - | - | Y | Y | Y | - | - | - | Y4 | - |
| 日期 | - | Y | Y | Y | - | - | - | Y | Y | Y | Y | - | Y1 | Y1 | - | - | - | - | Y | - | Y | Y3 | - |
| 时间 | - | Y | Y | Y | - | - | - | Y | Y | Y | Y | - | Y1 | Y1 | - | - | - | - | - | Y | - | Y3 | - |
| TIMESTAMP | - | - | Y | Y | - | - | - | Y | Y | Y | Y | - | Y1 | Y1 | - | - | - | - | Y | Y | Y | Y3 | - |
| XML | Y5 | Y5 | Y5 | Y5 | Y5 | Y5 | Y5 | Y5 | Y5 | Y5 | Y5 | Y5 | Y5 | Y5 | Y5 | - | - | Y5 | Y5 | Y5 | Y5 | Y | - |
| 布尔值 | Y | Y | Y | - | - | - | - | Y | - | Y | - | - | Y1 | Y1 | - | - | - | - | - | - | - | - | Y |
注
1 仅支持对 Unicode 数据库进行强制类型转换。 2 FOR BIT DATA 3 只能使用 XMLCAST 来执行强制类型转换。 4 隐式处理 XMLPARSE 函数,以便在对 XML 列的赋值(INSERT 或 UPDATE)为字符串时将字符串转换为 XML。 字符串必须是结构良好的 XML 文档,赋值才能成功。 5 只能使用 XMLCAST 并且根据 XML 值的底层 XML 模式数据类型来执行强制类型转换。 有关详细信息,请参阅 6 不能将游标类型作为 CAST 规范的源数据类型或目标数据类型,除非将参数标记强制转换为游标类型。 |
|||||||||||||||||||||||
表 2 显示了在强制类型转换为所标识的目标数据类型时,在何处查找有关应用的规则的信息。
| 目标数据类型 | 规则 |
|---|---|
| SMALLINT | SMALLINT 标量函数。 |
| INTEGER | INTEGER 标量函数。 |
| BIGINT | BIGINT 标量函数。 |
| DECIMAL | DECIMAL 或 DEC 标量函数 |
| 数值 | DECIMAL 或 DEC 标量函数 |
| REAL | REAL 标量函数 |
| 双 | DOUBLE_PRECISION 或 DOUBLE 标量函数 |
| DECFLOAT | DECFLOAT 标量函数 |
| CHAR | CHAR 标量函数 |
| VARCHAR | VARCHAR 标量函数 |
| CLOB | CLOB 标量函数 |
| GRAPHIC | GRAPHIC 标量函数 |
| VARGRAPHIC | VARGRAPHIC 标量函数 |
| DBCLOB | DBCLOB 标量函数 |
| BINARY | BINARY 标量函数 |
| VARBINARY | VARBINARY 标量函数 |
| BLOB | BLOB 标量函数 |
| 日期 | DATE 标量函数 |
| 时间 | TIME 标量函数 |
| TIMESTAMP | 如果源类型是字符串,请参阅 TIMESTAMP 标量函数,其中指定了一个操作数。 如果源数据类型为 DATE,那么时间戳记由指定的日期和时间 00:00:00 组成。 |
| 布尔值 | BOOLEAN 标量函数 |
将非 XML 值强制转换为 XML 值
| 源数据类型 | 目标数据类型 | |
|---|---|---|
| XML | 获得的 XML 模式类型 | |
| SMALLINT | Y | xs:short |
| INTEGER | Y | xs:int |
| BIGINT | Y | xs:long |
| DECIMAL 或 NUMERIC | Y | xs:decimal |
| REAL | Y | xs:float |
| 双 | Y | xs:double |
| DECFLOAT | N | - |
| CHAR | Y | xs:string |
| VARCHAR | Y | xs:string |
| CLOB | Y | xs:string |
| GRAPHIC | Y | xs:string |
| VARGRAPHIC | Y | xs:string |
| DBCLOB | Y | xs:string |
| 日期 | Y | xs:date |
| 时间 | Y | xs:time |
| TIMESTAMP | Y | xs: 日期时间1 |
| BLOB | Y | xs:base64Binary |
| 布尔值 | Y | xs:boolean |
| 字符类型 FOR BIT DATA | Y | xs:base64Binary |
| 单值类型 | 将此图表与单值类型的源类型配合使用 | |
| 注 1 源数据类型 TIMESTAMP 支持的时间戳记精度为 0 到 12。 xs:dateTime 的最大分数秒精度为6。 若TIMESTAMP源数据类型的时间戳精度超过6位,则在转换为 xs:dateTime 时该值将被截断。 |
||
LONG VARCHAR 和 LONG VARGRAPHIC 数据类型继续受支持但是不推荐使用,并且在将来的发行版中可能会除去。
当将字符串值强制转换为 XML 值时,获得的 xs:string 原子值不能包含非法 XML 字符 (SQLSTATE 0N002)。 如果输入字符串不是采用 Unicode,那么会将输入字符转换为使用 Unicode。
对 SQL 二进制类型进行强制类型转换时将获得类型为 xs:base64Binary 的 XQuery 原子值。
将 XML 值强制转换为非 XML 值
可以认为通过 XMLCAST 将 XML 值转换为非 XML 值这一过程包含两个强制类型转换:一个是 XQuery 强制类型转换,它将源 XML 值转换为对应于 SQL 目标类型的 XQuery 类型;接着是从相应的 XQuery 类型强制转换为真正的 SQL 类型。
如果目标类型具有相应的受支持的 XQuery 目标类型,并且具有受支持的用于从源值类型转换为相应的 XQuery 目标类型的 XQuery 强制类型转换,那么 XMLCAST 是受支持的。 在 XQuery 强制类型转换中使用的目标类型依赖于相应的 XQuery 目标类型,并且可能包含一些附加限制。
下表列示了通过这种转换获得的 XQuery 类型。
| 目标数据类型 | 源数据类型 | |
|---|---|---|
| XML | 相应的 XQuery 目标类型 | |
| SMALLINT | Y | xs:short |
| INTEGER | Y | xs:int |
| BIGINT | Y | xs:long |
| DECIMAL 或 NUMERIC | Y | xs:decimal |
| REAL | Y | xs:float |
| 双 | Y | xs:double |
| DECFLOAT | Y | 没有匹配类型1 |
| CHAR | Y | xs:string |
| VARCHAR | Y | xs:string |
| CLOB | Y | xs:string |
| GRAPHIC | Y | xs:string |
| VARGRAPHIC | Y | xs:string |
| DBCLOB | Y | xs:string |
| 日期 | Y | xs:date |
| TIME(不带时区) | Y | xs:time |
| TIMESTAMP(不带时区) | Y | xs: date Time2 |
| BLOB | Y | xs:base64Binary |
| 布尔值 | Y | xs:boolean |
| CHAR FOR BIT DATA | N | 不可执行强制类型转换 |
| VARCHAR FOR BIT DATA | Y | xs:base64Binary |
| 单值类型 | 将此图表与单值类型的源类型配合使用 | |
| 行、引用、结构化或抽象数据类型(ADT),或者其他 | N | 不可执行强制类型转换 |
| 注 支持 1 XML 模式 1.0 ,这不会为 DECFLOAT 提供匹配的 XML 模式类型。 按以下方式处理 XMLCAST 的 XQuery 强制类型转换步骤:
2 xs:dateTime 的最大分数秒精度为 6。 源数据类型 TIMESTAMP 支持时间戳记精度 0 到 12。 如果目标数据类型 TIMESTAMP 的时间戳记精度小于 6,那么值在从 xs:dateTime 强制转换时将被截断。 如果目标数据类型 TIMESTAMP 的时间戳记精度超过了 6,那么值在从 xs:dateTime 强制转换时将对它填充 0。 |
||
- 要转换为 CHAR 和 VARCHAR 以外的字符串类型的 XML 值必须符合这些数据类型的长度限制,而不截断任何字符或字节。 派生的 XML 模式类型的名称是大写的 SQL 类型名称加上下划线字符和字符串的最大长度;例如,如果 XMLCAST 目标数据类型是 CLOB(1M),那么派生的 XML 模式类型的名称是 CLOB_1048576。
如果将 XML 值转换成过小而无法包含所有数据的 CHAR 或 VARCHAR 类型,那么截断该数据以适合指定的数据类型,且不会返回任何错误。 如果截断所有非空字符,那么将返回一个警告 (SQLSTATE 01004)。 如果截断值会导致截断多字节字符,那么将删除全部的多字节字符。 因此,在某些情况下,截断可产生低于预期的较短字符串。 例如,字符 "ñ" 以 UTF-8 表示,由 2 字节 "C3 B1" 表示。 当此字符强制转换为 VARCHAR (1) 时,将 "C3 B1" 截断为 1 字节将保留部分字符 "C3"。 此不完整的字符“C3”也会被除去,因此最终的结果是成为空字符串。
- 要转换为 DECIMAL 值的 XML 值一定不得超过小数点前面的(精度 - 小数位数)数字;将截断小数点后超过小数位数的过多数字。 派生的 XML 模式类型的名称是 DECIMAL_precision_scale,其中 precision 是目标 SQL 数据类型的精度,而 scale 是目标 SQL 数据类型的小数位;例如,如果 XMLCAST 目标数据类型为 DECIMAL(9,2),那么派生的 XML 模式类型的名称为 DECIMAL_9_2。
- 要转换为 TIME 值的 XML 值不能在小数点后面包含具有非零位数的秒部分。 派生的 XML 模式类型的名称为 TIME。
如果 XML 值不满足任何这些限制,那么派生的 XML 模式类型名将只出现在消息中。 此类型名可帮助用户了解错误消息,但是不对应于已定义的任何 XQuery 类型。 如果输入值不符合派生的 XML 模式类型(相应的 XQuery 目标类型)的基本类型,那么错误消息可能会指示该类型。 由于此派生 XML 模式类型名的格式将来可能会更改,因此不应将它用作编程接口。
在 XQuery 强制类型转换处理 XML 值之前,将除去序列中的任何文档节点,而被除去的文档节点的每个直接子代将成为该序列中的一项。 如果文档节点具有多个直接子代节点,那么修改之后的序列比原始序列具有更多项。 没有任何文档节点的 XML 值就会通过使用 XQuery fn:data 函数被原子化,并将获得的原子化序列值用于 XQuery 强制类型转换。 如果原子化的序列值是一个空序列,那么强制类型转换将返回空值,并且不会执行任何进一步处理。 如果原子化的序列值中有多个项,那么会返回错误 (SQLSTATE 10507)。
如果用于 XMLCAST 的目标类型是 SQL 数据类型 DATE、TIME 或 TIMESTAMP,那么 XQuery 强制类型转换产生的 XML 值也会被调整为 UTC,并且会除去该值的时区部分。
当相应的 XQuery 目标类型值被转换为 SQL 目标类型时,二进制 XML 数据类型(例如,xs:base64Binary 或 xs:hexBinary)就会从字符格式转换为实际的二进制数据。
如果(通过使用 XMLCAST)将 INF、-INF 或 NaN 这些 xs:double 或 xs:float 值强制转换为 SQL 数据类型 DOUBLE 或 REAL 值,那么会返回错误 (SQLSTATE 22003)。 xs:double 或 xs:float 值 -0 将被转换为 +0。
如果源操作数不是用户定义的单值类型,那么目标类型可以是用户定义的单值类型。 在此情况下,将使用 XMLCAST 规范将源值强制转换为用户定义的单值类型(即,目标类型)的源类型,然后,将使用 CAST 规范将此值强制转换为用户定义的单值类型。
在非 Unicode 数据库中,从 XML 值强制转换为非 XML 目标类型涉及将代码页从内部 UTF-8 格式转换为数据库代码页。 如果 XML 值中的任何代码点不出现在数据库代码页中,那么这种转换可能会导致引入替换字符。