字符串

字符串 是代码单元序列。 字符串的长度是序列中的代码单元数。 如果长度为零,那么该值称为 空字符串,不应与空值混淆。

固定长度字符串 (CHAR)

固定长度字符串列中的所有值都具有相同的长度,这由列的长度属性确定。 长度属性必须在 1-255 范围内,包括 除非字符串单元为 CODEUNITS32,其范围为 1-63 (含)。

变长字符串

有两种类型的变长字符串:
VARCHAR
VARCHAR 值可长达 32,672 字节。 如果字符串单元为 CODEUNITS32,那么长度最多可以为 8,168 个字符串单元。
CLOB
字符大对象 (CLOB) 值最多可以是 2 千兆字节减去 1 字节 (2,147,483,647 字节) 的长度 ,如果字符串单元是 CODEUNITS32,那么最多可以是 536,870,911 个字符串单元。 CLOB 用于存储基于字符的大型 SBCS 或混合 (SBCS 和 MBCS) 数据 (例如使用单个字符集编写的文档) ,因此具有与其关联的 SBCS 或混合代码页。
特殊限制适用于表达式 导致 CLOB 数据类型和结构化类型列; 在下列情况下不允许使用此类表达式和列:
  • 以 DISTINCT 子句作为前缀的 SELECT 列表
  • GROUP BY 子句
  • ORDER BY 子句
  • 除 UNION ALL 以外的集合运算符的子查询
  • 基本,量化, BETWEEN 或 IN 谓词
  • 聚集函数
  • VARGRAPHIC , TRANSLATE 和日期时间标量函数
  • LIKE 谓词中的模式操作数或 POSSTR 函数中的搜索字符串操作数
  • 日期时间值的字符串表示。

以 VARCHAR 作为自变量的 SYSFUN 模式中的函数将不接受长度超过 4000 字节的 VARCHARs 作为自变量。 但是,其中许多函数还具有接受 CLOB (1M) 的备用签名。 对于这些函数,用户可以显式地将大于 4000 个 VARCHAR 字符串强制转换为 CLOB ,然后将结果重新强制转换为所需长度的 VARCHARs。

根据预编译选项的标准级别,以不同方式处理在 C 中找到的 NUL 终止的字符串。

每个字符串进一步定义为下列其中一项:
BIT DATA
未与代码页关联的数据。
单字节字符集 (SBCS) 数据
其中每个字符用单字节表示的数据。
混合数据
可能包含来自单字节字符集和多字节字符集 (MBCS) 的混合字符的数据。
Unicode 数据
包含由一个或多个字节表示的字符的数据。 每个Unicode字符串都使用 UTF-8 编码。 UTF-8 的CCSID为1208。
注: LONG VARCHAR 数据类型仍然受支持,但不推荐使用,建议不要使用,并且在将来的发行版中可能会将其除去。

字符串的字符串单元规范

字符串数据类型的长度单位为 OCTETS 或 CODEUNITS32。 长度单位定义用于确定数据长度的计数方法。
OCTETS
指示长度属性的单位是字节。 该长度单位适用于所有非Unicode字符串数据类型。 对于Unicode字符串数据类型,OCTETS可以明确指定或根据环境设置确定。
CODEUNITS32
指示长度属性的单位是以字符进行近似计数的 Unicode UTF-32 代码单位。 此长度单位不会影响数据类型的底层代码页。 数据值的实际长度通过统计 UTF-32 代码单元确定,就像已将数据转换为 UTF-32 一样。 CODEUNITS32字符串单元只能 用于Unicode字符串数据类型。 可以根据环境设置显式指定或确定 CODEUNITS32 。

对于非Unicode字符串数据类型,字符串单元始终为OCTETS,且不可更改。 对于Unicode字符串数据类型,字符串单元可以通过字符串数据类型的长度属性进行明确指定,也可以根据环境设置进行默认。 如果还为字符串数据类型指定了 FOR BIT DATA ,那么无法指定 CODEUNITS32 ,并且环境设置 CODEUNITS32 不适用。

字符串单元的环境设置基于 NLS_STRING_UNITS 全局变量的值或 string_units 数据库配置参数。 可以将数据库配置参数设置为 SYSTEM 或 CODEUNITS32。 全局变量也可以设置为 SYSTEM 或 CODEUNITS32,但也可以设置为 NULL。 NULL 值指示 SQL 会话应使用 string_units 数据库配置参数设置。 如果环境设置的值为 SYSTEM ,那么 OCTETS 将用作缺省字符串单元设置。

内置函数中的字符串单元

为某些内置字符串函数指定字符串单元的能力使您能够以比 "基于字节的方式" 更 "基于字符的方式" 处理字符串数据。 string unit 确定 执行函数时用于长度或位置的单元。 可以指定 CODEUNITS16, CODEUNITS32或 OCTETS 作为某些字符串函数的字符串单元。 如果未指定字符串单元,那么缺省字符串单元通常由源字符串自变量的字符串单元确定 (请参阅您正在使用的函数的描述以获取详细信息)。 可以为支持 Unicode 或非 Unicode 数据库中的参数的字符串函数指定字符串单元参数。

CODEUNITS16
指定 Unicode UTF-16 是操作的单元。 当应用程序正在处理宽度为 2 字节的代码单元中的数据时, CODEUNITS16 很有用。 请注意,某些字符 (称为 补充字符) 需要对两个 UTF-16 代码单元进行编码。 例如,音乐符号G谱号需要两个 UTF-16 代码单元( UTF-16BE 中的 D834X'DD1E' )。
CODEUNITS32
指定 Unicode UTF-32 是操作的单元。 CODEUNITS32 对于以简单的固定长度格式处理数据的应用程序很有用,无论数据的存储格式 (ASCII , UTF-8或 UTF-16) 如何,这些应用程序都必须返回相同的答案。
注: 磁盘上的存储器使用 UTF-8 编码。
OCTETS
指定字节是操作的单位。 当应用程序对分配缓冲区空间感兴趣或当操作需要使用简单字节处理时,通常会使用 OCTETS。

使用 OCTETS 计算的字符串的计算长度 (字节) 可能与使用 CODEUNITS16 或 CODEUNITS32计算的长度不同。 当您使用 OCTETS 时,字符串的长度是通过简单地计算字符串中的字节数来确定的。 当您使用 CODEUNITS16 或 CODEUNITS32时,将通过计算在 UTF-16 或 UTF-32中表示字符串所需的 16 位或 32 位代码单元的数目来确定字符串的长度。 使用 CODEUNITS16 和 CODEUNITS32 确定的长度相同,除非数据包含补充字符 (请参阅 CODEUNITS16 和 CODEUNITS32之间的差异)。

例如,假定以 Unicode UTF-8编码的 VARCHAR (128) 列 NAME 包含值 "J ü r g e n"。 以下两个查询 (计算 CODEUNITS16 或 CODEUNITS32中字符串的长度) 返回相同的值 (6)。
   SELECT CHARACTER_LENGTH(NAME,CODEUNITS16) FROM T1
     WHERE NAME = 'Jürgen'

   SELECT CHARACTER_LENGTH(NAME,CODEUNITS32) FROM T1
     WHERE NAME = 'Jürgen'
下一个查询 (计算 OCTETS 中字符串的长度) 将返回值 7。
   SELECT CHARACTER_LENGTH(NAME,OCTETS) FROM T1
     WHERE NAME = 'Jürgen'
这些值表示以指定字符串单位表示的字符串长度。
下表显示了名称 "J ü r g e n" 的 UTF-8, UTF-16BE (big-endian)和 UTF-32BE (big-endian) 表示法:
Format    Representation of the name 'Jürgen'
--------  --------------------------------------
UTF-8	  X'4AC3BC7267656E'
UTF-16BE 	X'004A00FC007200670065006E'
UTF-32BE 	X'0000004A000000FC0000007200000067000000650000006E'
字符 "ü" 的表示在三个字符串单元之间不同:
  • UTF-8 字符“ü”的表示形式为 X'C3BC'
  • UTF-16BE 字符“ü”的表示形式为 X'00FC'
  • UTF-32BE 字符“ü”的表示形式为 X'000000FC'

为内置函数指定字符串单元不会影响数据类型, 字符串单元 或函数结果的代码页。 如果需要,当指定 CODEUNITS16 或 CODEUNITS32 时,会将数据转换为 Unicode 以进行求值。

为 LOCATE 或 POSITION 函数指定 OCTETS 时,如果字符串自变量的代码页不同,那么会将数据转换为 source-string 自变量的代码页。 在这种情况下,函数的结果在 source-string 自变量的代码页中。 当为采用单个字符串自变量的函数指定 OCTETS 时,将在字符串自变量的代码页中对数据进行求值,而该函数的结果在字符串自变量的代码页中。

CODEUNITS16 与 CODEUNITS32 之间的差异

当指定 CODEUNITS16 或 CODEUNITS32 时,除数据包含 Unicode 补充字符外,结果相同。 这是因为一个补充字符由两个 UTF-16 代码单元或一个 UTF-32 代码单元表示。 在 UTF-8中,非补充字符由 1 到 3 字节表示,补充字符由 4 字节表示。 在 UTF-16中,非补充字符由一个 CODEUNITS16 代码单元或 2 字节表示,补充字符由两个 CODEUNITS16 代码单元或 4 字节表示。 在 UTF-32中,字符由一个 CODEUNITS32 代码单元或 4 字节表示。

例如,下表显示了数学粗体大写 A 和拉丁字母大写字母 A 的十六进制值。 数学粗体大写 A 是一个补充字符,由 UTF-8, UTF-16和 UTF-32中的 4 字节表示。
字符 UTF-8 表示 UTF-16BE 表示 UTF-32BE 表示
Unicode值 X'1D400' - 'A'; 数学大写粗体A X'F09D9080' X'D835DC00' X'0001D400'
Unicode 值 X'0041 ' -'A'; 拉丁大写字母 A X'41' X'0041' X'00000041 '
假设 C1 是一个VARCHAR(128)列,使用 UTF-8 编码,并且T1 包含一行,其值为数学大写粗体A X'F09D9080' )。 以下查询返回不同的结果:
Query                                                Returns
-----                                                -------
SELECT CHARACTER_LENGTH(C1,CODEUNITS16) FROM T1      2

SELECT CHARACTER_LENGTH(C1,CODEUNITS32) FROM T1      1

SELECT CHARACTER_LENGTH(C1,OCTETS) FROM T1           4