Использование [A-Z]
должно включать только заглавные буквы и исключать все строчные.По крайней мере, это то, что он должен - и делает - делать на английском языке с двоичной сортировкой:
alter session set nls_language = 'ENGLISH';
select * from nls_session_parameters where parameter = 'NLS_SORT';
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_SORT BINARY
SELECT CHR(num), num
FROM (
SELECT LEVEL AS num FROM dual CONNECT BY LEVEL <= 200
) WHERE REGEXP_LIKE(CHR(num), '^[A-Z]+$');
C NUM
- ----------
A 65
...
Z 90
26 rows selected.
На немецком языке (или любом другом языке, который изменяет порядок сортировки по умолчанию), он делает то, что я считаю, выdescription:
alter session set nls_language = 'GERMAN';
select * from nls_session_parameters where parameter = 'NLS_SORT';
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_SORT GERMAN
SELECT CHR(num), num
FROM (
SELECT LEVEL AS num FROM dual CONNECT BY LEVEL <= 200
) WHERE REGEXP_LIKE(CHR(num), '^[A-Z]+$');
C NUM
- ----------
A 65
...
X 88
Y 89
Z 90
b 98
c 99
d 100
...
z 122
Переключение на классы символов делает его поведение более последовательным:
alter session set nls_language = 'GERMAN';
SELECT CHR(num), num
FROM (
SELECT LEVEL AS num FROM dual CONNECT BY LEVEL <= 200
) WHERE REGEXP_LIKE(CHR(num), '^[[:upper:]]+$');
C NUM
- ----------
A 65
...
Z 90
26 rows selected.
Если вы хотите включить все символы верхнего и нижнего регистра, тогда вы можете использовать [:alpha:]
вместо [:upper:]
.Обратите внимание, что любой из них будет включать в себя диакритические знаки (а lower
или alpha
будет включать 'ß');что может или не может быть желательным:
SELECT character
FROM (
SELECT CHR(LEVEL + 64) AS character
FROM dual CONNECT BY LEVEL <= 58
UNION ALL SELECT column_value
FROM TABLE(sys.odcivarchar2list('ß', 'ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü'))
)
WHERE REGEXP_LIKE(character, '^[[:upper:]]+$')
ORDER BY character;
CHARACTER
---------
A
Ä
B
...
Это объясняется в документации .
Традиционные механизмы регулярных выражений были разработаны для работы только с английским текстом,Однако реализации регулярных выражений могут охватывать широкий спектр языков с характеристиками, которые сильно отличаются от западноевропейского текста.Реализация регулярных выражений в базе данных Oracle основана на Руководстве по регулярным выражениям Unicode.Функции SQL REGEXP работают со всеми наборами символов, которые поддерживаются в качестве наборов символов базы данных и национальных наборов символов.Более того, Oracle Database расширяет возможности сопоставления конструкций регулярных выражений POSIX для обработки уникальных лингвистических требований сопоставления многоязычных данных.
и
Согласно стандарту POSIX,диапазон в регулярном выражении включает все элементы сопоставления между начальной и конечной точками диапазона в лингвистическом определении текущей локали.Поэтому диапазоны в регулярных выражениях означают лингвистические диапазоны, а не диапазоны значений байтов ...
... База данных Oracle интерпретирует выражения диапазонов в соответствии с параметром NLS_SORT, чтобы определить элементы сопоставления, охватываемые данным диапазоном.
Языковое сопоставление в основном основано на поведении языков или поведении их пользователей.
Если у вас двоичная сортировка, то символы упорядочиваютсяоснованный исключительно на кодовой точке (значение ASCII / Unicode) каждого символа;«a» равно 97, что, очевидно, после (численно выше) «A», равного 65. Если вы выберете все символы и используете двоичную сортировку, вы увидите:
alter session set nls_language = 'GERMAN';
alter session set nls_sort = 'BINARY';
SELECT CHR(LEVEL + 64) AS character, NLSSORT(CHR(LEVEL + 64)) AS sort
FROM dual CONNECT BY LEVEL <= 58
UNION ALL SELECT column_value, NLSSORT(column_value)
FROM TABLE(sys.odcivarchar2list('ß', 'ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü'))
ORDER BY character;
CHARACTER SORT
--------- ---------
A 4100
B 4200
C 4300
...
X 5800
Y 5900
Z 5A00
[ 5B00
\ 5C00
] 5D00
^ 5E00
_ 5F00
` 6000
a 6100
b 6200
c 6300
...
x 7800
y 7900
z 7A00
Ä C38400
Ö C39600
Ü C39C00
ß C39F00
ä C3A400
ö C3B600
ü C3BC00
65 rows selected.
The nlssort()
функция позволяет увидеть фактическое значение, которое Oracle использует для сортировки - здесь это двоичное значение для символов, поэтому «A» по-прежнему равно 65 (ну, 41 в шестнадцатеричном виде) плюс нулевой байт.Когда вы заказываете эти «а», все еще после «А».
При лингвистическом сопоставлении эти значения сортировки совершенно разные:
alter session set nls_sort = 'GERMAN';
SELECT CHR(LEVEL + 64) AS character, NLSSORT(CHR(LEVEL + 64)) AS sort
FROM dual CONNECT BY LEVEL <= 58
UNION ALL SELECT column_value, NLSSORT(column_value)
FROM TABLE(sys.odcivarchar2list('ß', 'ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü'))
ORDER BY character;
CHARACTER SORT
--------- ---------
[ 00005B00
\ 00005C00
] 00005D00
^ 00005E00
_ 00005F00
` 00006000
a 14000100
A 14000200
ä 14000900
Ä 14000A00
b 19000100
B 19000200
c 1E000100
C 1E000200
...
r 64000100
R 64000200
s 69000100
S 69000300
ß 69004400
t 6E000100
T 6E000200
u 73000100
U 73000200
ü 73000900
Ü 73000A00
v 78000100
V 78000200
w 7A000100
W 7A000200
x 7D000100
X 7D000200
y 82000100
Y 82000200
z 87000100
Z 87000200
65 rows selected.
«Лингвистическая» часть означает, что все варианты«a» вместе - «a», «A», «ä» и «Ä», в этом порядке.Затем все варианты 'b' и т. Д. С символами, специфичными для языка, сгруппированы с их родовыми отношениями.Об этом гораздо больше в документации, , включая примеры .
Поведение, которое вы видите, объясняется этим порядком.Посмотрите еще раз на начало этого отсортированного списка:
CHARACTER SORT
--------- ---------
...
a 14000100
A 14000200
ä 14000900
Ä 14000A00
b 19000100
B 19000200
c 1E000100
C 1E000200
Если вы попытаетесь использовать регулярное выражение с диапазоном [A-Z]
, тогда оно начинается с 'A', но в таком порядке сортировки, который после 'a' - так что нижний регистр 'a' исключается.Точно так же, если вы используете [B-Z]
, тогда вы начинаете с 'B', что после всех вариантов 'a' и строчной буквы 'b', так что теперь это исключено.