Oracle 中字符串之间的不等式比较
Inequality comparison between strings in Oracle
SELECT LAST_NAME FROM Employees
WHERE last_name < 'King';
在书 'SQL Fundamentals I Exam Guide' 中它说在比较 LAST_NAME < 'King'
时在 NLS 设置中发生以下转换假设 US7ASCII 数据库字符集与美国 NLS 设置:
K + i + n + g = 75 + 105 + 110 + 103 = 393.
然后对于 table EMPLOYEES table 中的每一行,LAST_NAME 列类似地转换为数值。如果此值小于 393,则选择该行。
但是当我执行上面的 SELECT 命令时,在 SQL*PLUS 上,它 returns 行(例如 'Greenberg'、'Bernestein')不遵循规则书中提到。是否需要进行任何设置才能获得满足该规则的行?
如果这本书真的是这么说的,那这本书就大错特错了。如果我们谈论的是 Oracle Press 的书,我会强烈怀疑你误读了解释,因为我很难想象这个错误如何在不被作者、编辑或审稿人发现的情况下完成.
要比较两个字符串,您执行的操作与您手动将字符串按字母顺序排列时所做的操作完全相同。字符串 "B" 位于字符串 "All My Data" 之后和字符串 "Changes Constantly" 之前。您获取字符串的第一个字符并查看十进制表示形式('A' 是 65,'B' 是 66,'C' 是 67)并基于此进行排序。如果有平局,比如说 "All Data" 和 "All Indexes",你继续第二个字符并比较直到你可以打破平局 'D' 是 68,它小于 'I'是 73,所以 "All Data" < "All Indexes"。
这条规则肯定是无效的。如果是,那么你可以交换字符,你仍然会得到相同的结果 393
。但是在比较单词时字符顺序很重要。
要获得适合比较的值,您必须这样计算:
K + i + n + g = ((75 × 256 + 105) × 256 + 110) × 256 + 103
但是你会超出长单词的有效数值范围。对于 7 位 ASCII 码(严格在 0 ... 127 范围内),您还可以乘以 128 而不是 256。
--
实际中,值是一个一个比较的,即(伪代码):
valueOf(last_name[0]) < 75 OR
valueOf(last_name[1]) < 105 OR
valueOf(last_name[2]) < 110 OR
valueOf(last_name[3]) < 103
...比较在遇到第一个不等式时停止,或者如果到达其中一个单词的末尾,则比较单词的长度。
也就是说,将2个单词的字符一个字符一个字符地进行比较,直到遇到两个不同的字符。那么这两个字符的比较就得出了最终的结果。
以'Kelvin' < 'King'
为例:
'K' < 'K' ==> false
'e' < 'i' ==> true
final result = true
其他示例'King' < 'Kelvin'
(交换单词):
'K' < 'K' ==> false
'i' < 'e' ==> false, the characters are not equal, therefore stop
final result = false
其他例子'be' < 'begin'
:
'b' < 'b' ==> false
'e' < 'e' ==> false
end of first word reached, length('be') < length('begin') ==> true
final result = true
正如您已经提到的,两个字符的实际比较是通过比较它们的数值来执行的。
SELECT LAST_NAME FROM Employees
WHERE last_name < 'King';
在书 'SQL Fundamentals I Exam Guide' 中它说在比较 LAST_NAME < 'King'
时在 NLS 设置中发生以下转换假设 US7ASCII 数据库字符集与美国 NLS 设置:
K + i + n + g = 75 + 105 + 110 + 103 = 393.
然后对于 table EMPLOYEES table 中的每一行,LAST_NAME 列类似地转换为数值。如果此值小于 393,则选择该行。 但是当我执行上面的 SELECT 命令时,在 SQL*PLUS 上,它 returns 行(例如 'Greenberg'、'Bernestein')不遵循规则书中提到。是否需要进行任何设置才能获得满足该规则的行?
如果这本书真的是这么说的,那这本书就大错特错了。如果我们谈论的是 Oracle Press 的书,我会强烈怀疑你误读了解释,因为我很难想象这个错误如何在不被作者、编辑或审稿人发现的情况下完成.
要比较两个字符串,您执行的操作与您手动将字符串按字母顺序排列时所做的操作完全相同。字符串 "B" 位于字符串 "All My Data" 之后和字符串 "Changes Constantly" 之前。您获取字符串的第一个字符并查看十进制表示形式('A' 是 65,'B' 是 66,'C' 是 67)并基于此进行排序。如果有平局,比如说 "All Data" 和 "All Indexes",你继续第二个字符并比较直到你可以打破平局 'D' 是 68,它小于 'I'是 73,所以 "All Data" < "All Indexes"。
这条规则肯定是无效的。如果是,那么你可以交换字符,你仍然会得到相同的结果 393
。但是在比较单词时字符顺序很重要。
要获得适合比较的值,您必须这样计算:
K + i + n + g = ((75 × 256 + 105) × 256 + 110) × 256 + 103
但是你会超出长单词的有效数值范围。对于 7 位 ASCII 码(严格在 0 ... 127 范围内),您还可以乘以 128 而不是 256。
--
实际中,值是一个一个比较的,即(伪代码):
valueOf(last_name[0]) < 75 OR
valueOf(last_name[1]) < 105 OR
valueOf(last_name[2]) < 110 OR
valueOf(last_name[3]) < 103
...比较在遇到第一个不等式时停止,或者如果到达其中一个单词的末尾,则比较单词的长度。
也就是说,将2个单词的字符一个字符一个字符地进行比较,直到遇到两个不同的字符。那么这两个字符的比较就得出了最终的结果。
以'Kelvin' < 'King'
为例:
'K' < 'K' ==> false
'e' < 'i' ==> true
final result = true
其他示例'King' < 'Kelvin'
(交换单词):
'K' < 'K' ==> false
'i' < 'e' ==> false, the characters are not equal, therefore stop
final result = false
其他例子'be' < 'begin'
:
'b' < 'b' ==> false
'e' < 'e' ==> false
end of first word reached, length('be') < length('begin') ==> true
final result = true
正如您已经提到的,两个字符的实际比较是通过比较它们的数值来执行的。