Почему порядок сортировки varchar в Oracle не соответствует поведению сравнения varchar? - PullRequest
8 голосов
/ 25 августа 2011

SQL-оператор, такой как:

select * from (
  select '000000000000' as x from dual
  union
  select '978123456789' as x from dual
  union 
  select 'B002AACD0A' as x from dual
) /*where x>'000000000000'*/ order by x;

Урожайность:

B002AACD0A
000000000000
978123456789

После раскомментирования WHERE-ограничения получается:

B002AACD0A
978123456789

Я ожидал бы, что результат будет 978123456789, поскольку B002AACD0A возвращается до 000000000000 при выполнении запроса без ограничений.

Как это поведение можно объяснить? И как я должен сортировать и сравнивать varchars, чтобы они могли работать вместе, как я могу делать с целыми числами?

Достаточно забавно, при изменении ограничения на x>'B002AACD0A' результат будет пустым. Изменение его на x>978123456789 возвращает B002AACD0A.

т.е. при сравнении:

B002AACD0A > 978123456789 > 000000000000

Но при сортировке:

978123456789 > 000000000000 > B002AACD0A 

При явном использовании двоичной сортировки (order by NLSSORT(x,'NLS_SORT=BINARY_AI')) результат равен B002AACD0A>978123456789>000000000000 и соответствует поведению сравнения. Но я до сих пор не знаю, почему это происходит.

1 Ответ

14 голосов
/ 25 августа 2011

Питер,

поведение сортировки регулируется параметром сеанса NLS_SORT, тогда как поведение для сравнения зависит от NLS_COMPпараметр.У вас должно быть несоответствие.

Я получаю тот же результат, что и вы, со следующими параметрами:

SQL> SELECT *
  2    FROM nls_session_parameters
  3   WHERE parameter IN ('NLS_COMP', 'NLS_SORT');

PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_SORT                       FRENCH
NLS_COMP                       BINARY

Однако, когда оба сопоставлены, результат согласуется:

SQL> alter session set nls_comp=LINGUISTIC;

Session altered

SQL> select * from (
  2    select '000000000000' as x from dual
  3    union
  4    select '978123456789' as x from dual
  5    union
  6    select 'B002AACD0A' as x from dual
  7  ) /*where x>'000000000000'*/ order by x;

X
------------
B002AACD0A
000000000000
978123456789

SQL> select * from (
  2    select '000000000000' as x from dual
  3    union
  4    select '978123456789' as x from dual
  5    union
  6    select 'B002AACD0A' as x from dual
  7  ) where x > '000000000000' order by x;

X
------------
978123456789
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...