Oracle 排序顺序和大于运算符在 varchar 列上不一致
Oracle sort order and greater than operator are not consistent on varchar column
我有一个简单的table
CREATE TABLE TRIAL
( "COL" VARCHAR2(20 BYTE)
)
然后我在其中插入两个值,“0”和 'A'。
查询
select * from trial order by col
returns
A
0
按此顺序,而查询
select * from trial where col>'A'
returns 没有结果。
这种行为的原因可能是什么,是否有一些简单的技巧,无需更改数据库配置,即可使 order by
和 >
以一致的方式运行?
编辑:
回复评论:
select * from v$parameter where name like 'nls_sort'
returns
和
select dump(col,16),col from trial
returns
Typ=1 Len=1: 30 0
Typ=1 Len=1: 41 A
应该按字符串的binary/ASCII值排序。
翻译值
0
=> 48
A
=> 65
当您按 col
排序时,默认为升序,所以我希望 0
排在第一位,然后是 A
。
当您要求 > 'A' 时,您要求的是 > 65,并且 'A' 或 '0' 都不是更大的,所以这是有道理的。
如评论中所述,我会检查您的排序 NLS_SORT
值,看看排序是否有问题:
https://docs.oracle.com/cd/B19306_01/server.102/b14237/initparams130.htm#REFRN10127
您还可以确保这符合您的 NLS_COMP
值:
https://docs.oracle.com/cd/B19306_01/server.102/b14237/initparams120.htm#REFRN10117
您可以在这个答案中找到更多信息:
注意:实际问题出在 NLS_SORT
参数上。请查看 Oracle – Case Insensitive Sorts & Compares/ 以获得对特定参数值的良好把握和理解。
实际问题
问题实际上是由于NLS_SORT
参数值由'BINARY'
修改为'WEST_EUROPEAN'
。
设置
SQL> CREATE TABLE TRIAL
2 ( "COL" VARCHAR2(20 BYTE)
3 );
Table created.
SQL> INSERT INTO trial(col) VALUES('0');
1 row created.
SQL> INSERT INTO trial(col) VALUES('A');
1 row created.
SQL> COMMIT;
Commit complete.
SQL> SELECT * FROM trial ORDER BY col;
COL
--------------------
0
A
NLS 参数值
SQL> SHOW PARAMETER NLS_SORT;
NAME TYPE VALUE
------------------------------------ ----------- ------
nls_sort string BINARY
SQL> SHOW PARAMETER NLS_COMP;
NAME TYPE VALUE
------------------------------------ ----------- ------
nls_comp string BINARY
让我们更改 NLS_SORT
参数值:
SQL> ALTER SESSION SET NLS_SORT='WEST_EUROPEAN';
Session altered.
重现错误
SQL> SELECT * FROM trial ORDER BY col;
COL
--------------------
A
0
因此,现在值的排序随着 NLS_SORT
参数值的变化而变化。
我有一个简单的table
CREATE TABLE TRIAL
( "COL" VARCHAR2(20 BYTE)
)
然后我在其中插入两个值,“0”和 'A'。
查询
select * from trial order by col
returns
A
0
按此顺序,而查询
select * from trial where col>'A'
returns 没有结果。
这种行为的原因可能是什么,是否有一些简单的技巧,无需更改数据库配置,即可使 order by
和 >
以一致的方式运行?
编辑:
回复评论:
select * from v$parameter where name like 'nls_sort'
returns
和
select dump(col,16),col from trial
returns
Typ=1 Len=1: 30 0
Typ=1 Len=1: 41 A
应该按字符串的binary/ASCII值排序。
翻译值
0
=>48
A
=>65
当您按 col
排序时,默认为升序,所以我希望 0
排在第一位,然后是 A
。
当您要求 > 'A' 时,您要求的是 > 65,并且 'A' 或 '0' 都不是更大的,所以这是有道理的。
如评论中所述,我会检查您的排序 NLS_SORT
值,看看排序是否有问题:
https://docs.oracle.com/cd/B19306_01/server.102/b14237/initparams130.htm#REFRN10127
您还可以确保这符合您的 NLS_COMP
值:
https://docs.oracle.com/cd/B19306_01/server.102/b14237/initparams120.htm#REFRN10117
您可以在这个答案中找到更多信息:
注意:实际问题出在 NLS_SORT
参数上。请查看 Oracle – Case Insensitive Sorts & Compares/ 以获得对特定参数值的良好把握和理解。
实际问题
问题实际上是由于NLS_SORT
参数值由'BINARY'
修改为'WEST_EUROPEAN'
。
设置
SQL> CREATE TABLE TRIAL
2 ( "COL" VARCHAR2(20 BYTE)
3 );
Table created.
SQL> INSERT INTO trial(col) VALUES('0');
1 row created.
SQL> INSERT INTO trial(col) VALUES('A');
1 row created.
SQL> COMMIT;
Commit complete.
SQL> SELECT * FROM trial ORDER BY col;
COL
--------------------
0
A
NLS 参数值
SQL> SHOW PARAMETER NLS_SORT;
NAME TYPE VALUE
------------------------------------ ----------- ------
nls_sort string BINARY
SQL> SHOW PARAMETER NLS_COMP;
NAME TYPE VALUE
------------------------------------ ----------- ------
nls_comp string BINARY
让我们更改 NLS_SORT
参数值:
SQL> ALTER SESSION SET NLS_SORT='WEST_EUROPEAN';
Session altered.
重现错误
SQL> SELECT * FROM trial ORDER BY col;
COL
--------------------
A
0
因此,现在值的排序随着 NLS_SORT
参数值的变化而变化。