Oracle 数据类型比较规则

时间:2020-12-23 14:54:56

数值

较大的值被认为大于较小的值。所有负数都小于零,所有正数都小于零。因此,-1小于100;-100小于-1。

浮点值NaN(not a number))大于任何其他数值,且等于自身。

日期时间值

较迟的日期或时间戳被认为大于较早的日期或时间戳。例如,等价于 '29-MAR-2005' 的日期小于 '05-JAN-2006' ,等价于 '05-JAN-2006 1:35pm'的时间戳大于 '05-JAN-2005 10:09am'。

当比较两个带有时区的时间戳时,它们首先被标准化为UTC,即时区偏移量“+00:00”。例如,时区等于 '16-OCT-2016 05:59am Europe/Warsaw' 的时间戳等于

'15-OCT-2016 08:59pm US/Pacific'。两者代表相同的绝对时间点,用UTC表示的时间是 October 16th, 2016, 03:59am 。

二进制值

数据类型raw或blob的二进制值是一个字节序列。当比较两个二进制值时,依次比较两个字节序列的相应连续字节。如果两个比较值的第一个字节不同,则包含数值较低的字节的二进制值被认为较小。如果第一个字节相等,则类似地比较第二个字节,依此类推,直到比较的字节不同或比较过程到达其中一个字节的值末尾。在后一种情况下,较短的值被认为较小。

无法在比较条件下直接比较数据类型BLOB的二进制值。但是,它们可以通过 PL/SQL 函数DBMS_LOB.COMPARE进行比较。

字符值

字符值基于两个度量进行比较:

  • 二进制或语言排序
  • 空白填充或非填充的比较语义

下面的小节描述了这两个度量。

二进制和语言排序

在默认的二进制排序规则中,Oracle比较字符值像二进制值一样。构成存储字符集中两个字符值编码的两个字节序列被视为二进制值,并按照二进制值中的描述进行比较。此比较的结果返回源字符值的二进制比较的结果。

对于许多语言,二进制排序规则可能会产生语言上不正确的字符值排序。例如,在最常见的字符集中,所有大写拉丁字母的字符代码的值都低于所有小写拉丁字母的值。因此,二进制排序规则生成以下顺序:

MacDonald
MacIntosh
Macdonald
Macintosh

但是,大多数用户希望按以下顺序显示这四个值:

MacDonald
Macdonald
MacIntosh
Macintosh

这表明二进制排序规则可能不适用于英文字符值。

Oracle数据库支持根据各种语言的规则对字符串进行语言排序。它还支持匹配字符值 case- 和 accent-insensitively的排序规则变体。语言排序比较昂贵,但它们提供了优越的用户体验。

语言排序的限制

比较条件、 ORDER BY, GROUP BY 和 MATCH_RECOGNIZE 查询子句、COUNT(DISTINCT) 和统计聚合函数 、LIKE 条件、以及 ORDER BY 和PARTITION BY分析子句在使用语言排序时生成排序键。

排序键与函数NLSSORT 返回的值相同,并且受 NLSSORT 中描述的相同限制的约束。

空白填充或非填充的比较语义

使用空白填充语义,如果这两个值的长度不同,那么Oracle首先在较短值的末尾添加空白,以使它们的长度相等。然后,Oracle逐字符比较值,直到第一个不同的字符。在第一个不同位置具有较大字符的值被认为较大。如果两个值没有不同的字符,则认为它们相等。这条规则意味着,如果两个值仅末尾空格数不同,那么它们是相等的。只有当比较的表达式中的两个值都是数据类型 CHAR,、NCHAR、文本或 USER 函数返回的值时,Oracle才使用空白填充的比较语义。

使用非填充语义,Oracle将两个值逐字符比较,直到第一个不同的字符。在该位置具有较大字符的值被认为较大。如果两个不同长度的值在较短值的末尾相同,则较长的值被认为较大。如果两个长度相等的值没有不同的字符,则认为这些值相等。当比较中的一个或两个值的数据类型为 VARCHAR2 or NVARCHAR2.时,Oracle使用非填充的比较语义。

使用不同的比较语义比较两个字符值的结果可能会有所不同。下表显示了使用每个比较语义比较五对字符值的结果。通常,空白填充和非填充比较的结果是相同的。表中的最后一个比较说明了空白填充和非填充比较语义之间的差异。

Blank-Padded

Nonpadded
'ac' > 'ab' 'ac' > 'ab'
'ab' > 'a '  'ab' > 'a '
'ab' > 'a'  'ab' > 'a'
'ab' = 'ab'  'ab' = 'ab'
'a ' = 'a'  'a ' > 'a'

数据绑定排序

从 Oracle Database 12c Release 2 (12.2)开始,比较或匹配给定字符值时使用的排序规则与该值本身关联。它被称为数据绑定排序。可以将数据绑定排序视为值的数据类型的属性。

在先前的Oracle数据库版本中,会话参数 NLS_COMP 和 NLS_SORT粗略地确定了数据库会话中所有排序规则敏感的SQL操作的排序规则。数据绑定排序体系结构使应用程序能够一致地将特定于语言的比较规则应用于需要这些规则的数据。

Oracle Database 12c Release 2 (12.2)允许声明表列的排序规则。当列作为参数传递给排序规则敏感的SQL操作时,SQL操作使用该列声明的排序规则来处理该列的值。如果SQL操作有多个相互比较的字符参数,排序规则确定规则将确定要使用的排序规则。

有两种类型的数据绑定排序规则:

  • 命名排序:这是一个由指定了排序名称的排序规则组成的特殊集合。“排序规则排序规则是一样的,都是specified AS值的参数nls _黑色。一个名叫collation可以或者A或A BINARY collation collation的语言。命名排序规则与指定为nls_sort参数值的排序规则相同。命名排序规则可以是二进制排序规则,也可以是语言排序规则。
  • 伪排序:这种排序不是为SQL操作直接指定排序规则。相反,它指示操作检查会话参数nls_sort和nls_comp的值,以便使用实际命名的排序规则。伪排序是指定排序的新声明方法与使用会话参数的旧方法之间的桥梁。特别是,使用 USING_NLS_COMP 的伪排序规则指导SQL操作的行为与Oracle Database 12c Release 2 之前的行为完全相同。 

为列声明命名排序规则时,将静态确定列值的比较方式。声明伪排序规则时,可以使用会话参数nls_comp和nls_sort动态控制比较行为。但是,在用伪排序规则声明的列上定义的静态对象(如索引和约束)会返回到使用二进制排序规则。动态可设置的排序规则不能用于比较静态对象的值。

表达式中使用的字符文本或绑定变量的排序规则是从包含表达式的数据库对象的默认排序规则派生,例如视图或物化视图查询、PL/SQL存储单元代码、用户定义的类型方法代码,或独立的DML或查询语句。在Oracle Database 12c Release 2中,pl/sql存储单元的默认排序规则,用户定义的类型方法和独立的SQL语句总是使用 USING_NLS_COMP的伪排序规则。视图和物化视图的默认排序规则可以在CREATE VIEW 和 CREATE MATERIALIZED VIEW 声明的DEFAULT COLLATION子句中指定。

如果SQL操作返回字符值,则排序规则派生规则将确定结果的派生排序,以便在将结果作为参数传递给表达式树中另一个对排序规则敏感的SQL操作或*使用者(如SELECT语句中的SQL语句子句)时知道其排序规则。如果SQL操作对字符参数值进行操作,则其字符结果的派生排序规则基于参数的排序规则。否则,派生规则与字符文本相同。

可以使用 COLLATE 运算符重写表达式节点的派生排序规则,例如简单表达式或运算符结果。

Oracle数据库允许为列、表或模式声明不区分大小写的排序规则,以便可以始终以不区分大小写的方式比较表或模式中的列或所有字符列。