Строковые функции языка PL/SQL на примерах

Использование русского языка и символов кириллицы в базах данных oracle | материализация идей

Установив все их, например, в кодировку UTF8 набора символов Юникод, мы сможем сохранять в базе, обрабатывать и выводить кириллические (и любые другие) символы на экран без потери их начального значения. Именно это и происходит, когда мы устанавливаем Линукс и Оракл “из коробки”, используя параметры по-умолчанию. Естественно, каждый кириллический символ в кодировке UTF8 занимает ровно 2 байта – как и на этой странице, например, каждая буква нашего алфавита представлена в виде последовательности двух байт. То есть, любой текст будет иметь в два раза больше байт, чем символов. В случае однобайтной кодировки КОИ-8, каждый символ представлен только одним байтом, и тот же самый текст занимает в два раза меньший объём. Зная всё это, перейдём к примерам.Multibyte – использование кодировки AL32UTF8Этот случай предсталяет собой “рекомендованный подход” и применяется практически везде. Установив rpm-пакет с Ораклом Экспресс 11.2, вы получите именно эту конфигурацию. Посмотрим как происходит работа с русским текстом в кодировке UTF8 набора символов Unicode.Прежде всего, проверим, что было использовано в качестве CHARACTERSET при создании базы данных (создаваемой в процессе установки со стандартным именем “XE”).

1 select * from nls_database_parameters
2* where parameter like ‘%CHARACTERSET’
15:14:49 SQL> /

PARAMETER VALUE
—————————— ————————-
NLS_CHARACTERSET AL32UTF8
NLS_NCHAR_CHARACTERSET AL16UTF16

Обратим внимание на значение параметра “NLS_CHARACTERSET” равное “AL32UTF8” (и проигнорируем “NLS_NCHAR_CHARACTERSET” – изучение этого параметра выходит за рамки нашей заметки. Также существует инициализационный параметр “NLS_LENGTH_SEMANTICS”, который нужно устанавливать только на уровне сессии пользователя, но не для всего экземпляра оракла, обязательно прочтите про “NLS_LENGTH_SEMANTICS” в документации). Кодировка AL32UTF8 – это “ораклячая” версия UTF8 кодировки для набора символов Unicode. AL32UTF8 использует один байт для ASCII символов и до четырёх байт для всех остальных. Не используйте “ораклячую” UTF8 никогда – несмотря на совпадение имени, эта кодировка может занимать до шести байт для одного символа. Ещё раз – название кодировки “utf8” в Oracle – AL32UTF8.Проверим, какую кодировку будут использовать наш клиент (sqlplus) и оболочка Линукс (bash).

[ora11@attack ~]$ env | grep LANG
NLS_LANG=English_America.AL32UTF8
LANG=en_US.utf8
[ora11@attack ~]$
[ora11@attack ~]$ locale -a | grep ru
ru_RU
ru_RU.iso88595
ru_RU.koi8r
ru_RU.utf8
russian
ru_UA
ru_UA.koi8u
ru_UA.utf8
[ora11@attack ~]$

Заметьте, что переменная NLS_LANG используется Ораклом и поэтому “играет по его правилам” – название кодировки Unicode в этой переменной обычно должно совпадать со значением NLS_CHARACTERSET в базе данных. Оболочка линукса bash использует значения, продиктованные стандартной библиотекой C (их можно вывести командой “locale -a”). В нашем примере мы не используем значение “ru_RU.utf8” чтобы не пугаться русских фраз в линуксе. Посмотрите ниже как это выглядит.

[ora11@attack ~]$ echo $LANG
en_US.utf8
[ora11@attack ~]$ ls $
ls: cannot access $: No such file or directory
[ora11@attack ~]$
[ora11@attack ~]$ export LANG=ru_RU.utf8
[ora11@attack ~]$ echo $LANG
ru_RU.utf8
[ora11@attack ~]$ ls $
ls: невозможно получить доступ к $: Нет такого файла или каталога
[ora11@attack ~]$

Таким образом, первая часть значения переменной LANG определяет на каком языке (и для какой страны) с вами будет разговаривать Линукс, а вторая часть после точки задаёт кодировку набора символов.Как мы убедились, и Оракл и Линукс будут разговаривать с нами используя одну и ту же кодировку UTF8 и набор символов Unicode. Таков же и формат текстовых записей внутри базы данных (NLS_CHARACTERSET). Установку кодовой страницы терминала Гном проверим зайдя в меню “Terminal”-“Set Character Encoding”. Должно быть отмечено значение “Unicode (UTF-8)”Проверим работу всей цепочки.

— Можно использовать “character semantics”:
— create table t (id number, msg varchar2(100 CHAR));
— В наших примерах мы используем “byte semantics”.
15:45:10 SQL> create table t (id number, msg varchar2(100));

Table created.

Elapsed: 00:00:00.37
15:45:42 SQL> insert into t values (1, ‘Тест 1’);

1 row created.

Elapsed: 00:00:00.01
15:46:02 SQL> insert into t values (2, ‘Проверка 2’);

1 row created.

Elapsed: 00:00:00.00
15:46:23 SQL> commit;

Commit complete.

Elapsed: 00:00:00.02
15:46:25 SQL> col msg for a25
15:46:39 SQL> select * from t;

ID MSG
———- ————————-
1 Тест 1
2 Проверка 2

2 rows selected.

Elapsed: 00:00:00.01
15:46:44 SQL>

15:48:01 SQL> select * from t where msg like ‘Про%’;

ID MSG
———- ————————-
2 Проверка 2

1 row selected.

Elapsed: 00:00:00.01
15:48:17 SQL> select * from t where upper (msg) = ‘ТЕСТ 1’;

ID MSG
———- ————————-
1 Тест 1

1 row selected.

Elapsed: 00:00:00.01
15:48:53 SQL> select lower(msg) from t;

LOWER(MSG)
————————————
тест 1
проверка 2

2 rows selected.

Elapsed: 00:00:00.01
15:49:05 SQL>

Очевидно, что мы не только можем сохранить и вновь прочесть введённые записи, но и в состоянии правильно обработать их, используя встроенные функции Оракла. Что произойдёт, если мы изменим одно из значений в нашей “цепи”?

[ora11@attack ~]$ env | grep LANG
NLS_LANG=English_America.AL32UTF8
LANG=ru_RU.koi8r
[ora11@attack ~]$

[ora11@attack ~]$ sqlplus -s / as sysdba
select * from t;

ID
———-
MSG
————————–
1
п╒п╣я│я┌ 1

2
п÷я─п╬п╡п╣я─п╨п╟ 2

2 rows selected.

[ora11@attack ~]$
[ora11@attack ~]$ env | grep LANG
NLS_LANG=English_America.CL8ISO8859P5
LANG=en_US.utf8
[ora11@attack ~]$sqlplus -s / as sysdba
select * from t;

ID
———-
MSG
—————————
1
���� 1

2
�������� 2

2 rows selected.

Если вы установите значение NLS_LANG в что-то несуществующее в представлении “v$NLS_VALID_VALUES”, на экране возникнет ошибка “ORA-12705: Cannot access NLS data files or invalid environment specified”. Но даже если одна из переменных окружения LANG или NLS_LANG будет установлена в правильное, но не совпадающее с базой данных (NLS_CHARACTERSET) значение – данные будет невозможно прочесть.Single byte – Данные сохраняются в КОИ-8Как сказано выше, сохранение русского текста в формате Юникод имеет нежелательный побочный эффект – объём данных удваивается. В большинстве случаев это не является проблемой и использование набора символов AL32UTF8 рекомендовано к использованию во всех базах данных Oracle.В то же время, я чётко вижу два сценария когда я бы предпочёл Юникоду какую-либо однобайтную кодировку, например КОИ-8. Во-первых, для очень большой базы с большим содержанием текстовой информации размером, скажем в 300Тб, разница в цене дисковой памяти между 600Тб и 300Тб слишком велика, чтобы пренебречь ею ради стандартизации. Во-вторых, при использовании Oracle XE, где максимальный размер хранимых данных ограничен производителем.В начале проверим, соответствует ли практика нашей теории.

:/>  Не запускается Windows после установки Windows 10

— Вставляем русский текст в кодировке AL32UTF8, 2 байта на символ

declare i number;
begin
for i in 1..400 loop
insert into t values (i, ‘тестируем’);
end loop;
commit;
end;
/
16:29:48 SQL> /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.07
16:29:49 SQL> select count(*) from t;

COUNT(*)
———-
400

1 row selected.

Elapsed: 00:00:00.00
16:29:56 SQL>
16:31:43 SQL> exec dbms_stats.gather_table_stats(‘SYS’, ‘T’);

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.97
16:31:53 SQL>
16:32:14 SQL> select NUM_ROWS, blocks, AVG_SPACE, AVG_ROW_LEN
16:32:55 2 from dba_tables
16:33:03 3 where table_name = ‘T’;

NUM_ROWS BLOCKS AVG_SPACE AVG_ROW_LEN
———- ———- ———- ———–
400 3 0 41

1 row selected.

Elapsed: 00:00:00.03
16:33:10 SQL>

16:33:10 SQL> truncate table t;

Table truncated.

Elapsed: 00:00:00.12
16:34:51 SQL>

— Теперь тот же текст, но в ASCII одно-байтных символах

declare i number;
begin
for i in 1..400 loop
insert into t values (i, ‘testiruem’);
end loop;
commit;
end;
/

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.06
16:36:02 SQL> exec dbms_stats.gather_table_stats(‘SYS’, ‘T’);

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.10
16:36:20 SQL> select NUM_ROWS, blocks, AVG_SPACE, AVG_ROW_LEN
16:36:27 2 from dba_tables
16:36:30 3 where table_name = ‘T’;

NUM_ROWS BLOCKS AVG_SPACE AVG_ROW_LEN
———- ———- ———- ———–
400 2 0 14

1 row selected.

Elapsed: 00:00:00.00
16:36:33 SQL>

Мы видим почти 3-х кратную разницу в размере одной записи. Дополнительное место занимают внутренние служебные структуры базы данных. Таким образом, наша терория подтверждена практикой. И, поскольку мы используем Oracle XE, посмотрим как можно использовать кодировку КОИ-8 чтобы снизить объём данных и в то же время не потерять функциональность работы с русскими символами.

………… == Послание к Ефесянам святого апостола Павла == …………….
=== Глава 3, Стих 17 ===
14 Для сего преклоняю колени мои пред Отцем Господа нашего Иисуса Христа,
15 от Которого именуется всякое отечество на небесах и на земле,
16 да даст вам, по богатству славы Своей, крепко утвердиться Духом Его во
внутреннем человеке,
17 верою вселиться Христу в сердца ваши,
18 чтобы вы, укорененные и утвержденные в любви, могли постигнуть со всеми
святыми, что широта и долгота, и глубина и высота,
19 и уразуметь превосходящую разумение любовь Христову, дабы вам
исполниться всею полнотою Божиею.

(b /b-, c /c-, /-, *) >
[oracle@attack ~]$
[oracle@attack ~]$ sqlplus

SQL*Plus: Release 11.2.0.2.0 Production on Wed Oct 12 16:56:09 2021

Copyright (c) 1982, 2021, Oracle. All rights reserved.

Enter user-name: / as sysdba

Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 – 64bit Production

16:56:18 SQL>
1 select * from nls_database_parameters
2* where parameter = ‘NLS_CHARACTERSET’
16:57:26 SQL> /

PARAMETER VALUE
————————- ————————-
NLS_CHARACTERSET CL8KOI8R

1 row selected.

Elapsed: 00:00:00.00
16:57:27 SQL>
16:57:27 SQL> !env | grep LANG
NLS_LANG=American_America.CL8KOI8R
LANG=en_US.koi8r

16:57:51 SQL>
16:57:51 SQL> create table t (id number, msg varchar2(100));

Table created.

Elapsed: 00:00:00.39
16:58:47 SQL> insert into t values (1, ‘Тестируем русский в КОИ-8’);

1 row created.

Elapsed: 00:00:00.01
16:59:16 SQL> commit;

Commit complete.

Elapsed: 00:00:00.02
16:59:18 SQL> select * from t;

ID
———-
MSG
—————————
1
Тестируем русский в КОИ-8

1 row selected.

Elapsed: 00:00:00.01
16:59:22 SQL>

Те же самые правила работают – кодировки всех “звеньев” в нашей цепи программных средств должны совпадать. База данных и клиент Оракла работают в кодировке “CL8KOI8R”, локаль системы установлена в “koi8r” и эмулятор терминала использует кодовую страницу “Cyrillic (KOI8-R)”. Удостоверимся, что использование одно-байтной кодировки позволяет нам существенно уменьшить размер записи.

declare i number;
begin
for i in 1..400 loop
insert into t values (i, ‘тестируем’);
end loop;
commit;
end;
/
PL/SQL procedure successfully completed.

Elapsed: 00:00:00.06
17:10:54 SQL> exec dbms_stats.gather_table_stats(‘SYS’, ‘T’);

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.07
17:11:01 SQL> select NUM_ROWS, blocks, AVG_SPACE, AVG_ROW_LEN
17:11:06 2 from dba_tables
17:11:11 3 where table_name = ‘T’;

NUM_ROWS BLOCKS AVG_SPACE AVG_ROW_LEN
———- ———- ———- ———–
400 2 0 14

1 row selected.

Elapsed: 00:00:00.01
17:11:15 SQL> select * from t where rownum <5;

ID
———-
MSG
—————————————-
1
Тестируем

2
Тестируем

3
Тестируем

4
Тестируем

4 rows selected.

Elapsed: 00:00:00.01
17:11:27 SQL>

В заключение надо отметить, что Оракл может конвертировать данные из одного набора симболов в другой “налету”, такой эффект достигается установкой переменных окружения LANG и NLS_LANG в одно значение, соответствующее текущей локали операционной системы. В это же время NLS_CHARACTERSET “внутри” базы данных может отличаться от среды окружения пользователя – и в этом случае Оракл произведёт конвертирование данных, как показано ниже.

:/>  Запуск от имени администратора программ и командной строки
[ora11@NAU ~]$ sqlplus

SQL*Plus: Release 11.2.0.2.0 Production on Чт Окт 13 12:03:37 2021

Copyright (c) 1982, 2021, Oracle. All rights reserved.

Введите имя пользователя: / as sysdba

Присоединен к:
Oracle Database 11g Release 11.2.0.2.0 – Production

12:03:40 SQL> select * from nls_database_parameters;

PARAMETER VALUE
—————————— —————————————-
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CHARACTERSET CL8ISO8859P5
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_RDBMS_VERSION 11.2.0.2.0

20 строк выбрано.

Затрач.время: 00:00:00.01
12:03:52 SQL> !env | grep LANG
NLS_LANG=Russian_Russia.CL8KOI8R
LANG=ru_RU.koi8r

12:04:00 SQL> select * from t where rownum <3;

ID
———-
MSG
——————————–
1
Тестируем

2
Тестируем

2 строк выбрано.

Затрач.время: 00:00:00.01
12:04:09 SQL> Отсоединено от Oracle Database 11g Release 11.2.0.2.0 – Production
[ora11@NAU ~]$

Как видно, работать с русскими символами в Оракле просто. Всё что необходимо – помнить о том, какую кодировку использует база данных и настраивать клиента, локаль и эмулятор терминала соответственно.Другие средства разработки также успешно будут работать с вашими данными – и в AL32UTF8, и в CL8KOI8R. В качестве упражнения я предлагаю читателю установить Oracle SQL Developer и проверить его работу с русским текстом в таблице “Т”. Не забудьте проверить какую кодировку (и как) устанавливает для вас эта java-программа.

Функции юникода

Поддержка Юникода в PL/SQL начинается с простейших строковых функций. Впрочем, в табл. 2 видны небольшие отличия этих функций от их хорошо известных аналогов.

К именам функций INSTR, LENGTH и SUBSTR добавляется суффикс B, C, 2 или 4; он озна­чает, что функция работает с байтами, символами, кодовыми единицами или кодовыми точками соответственно.

Функции INSTR, LENGTH и SUBSTR используют семантику длины, связанную с типом данных столбца или переменной. Эти базовые функции и версии с суф­фиксом C часто возвращают одинаковые значения — до тех пор, пока вы не начнете работать со значениями NCHAR или NVARCHAR.

Поскольку NLS_NCHAR_ CHARACTERSET и NLS_CHARACTERSET могут различаться, результат вызова INSTR, LENGTH и SUBSTR может отличаться (в зависимости от типа данных) от результата их символьных аналогов.

Таблица 2. Функции Юникода

Функция ЮникодаОписание
ASCIISTR(string)Преобразует строку string в ASCn-символы. Строки в Юникоде преобразуются в стандартный формат xxxx
COMPOSE(string)Преобразует строку string, полученную в результате декомпозиции, в полную композиционную форму
DECOMPOSE(string, [canonical | compatibility])Получает строку string и возвращает строку Юникода, полученную разложением составных символов на кодовые
INSTRB(string, substr, pos, occ)Возвращает позицию подстроки substr в строке string в байтах, на­чиная с позиции pos. Аргумент occ задает номер вхождения substr, если подстрока встречается более одного раза. По умолчанию аргументы pos и occ
INSTRC(string, substr, pos, occ)Аналог INSTRB — за исключением того, что возвращает позицию substr в string в символах, начиная с позиции pos (значение pos задается в символах)
INSTR2(string, substr, pos, occ)Возвращаемая позиция задается в кодовых единицах UTF-16
INSTR4(string, substr, pos, occ)Возвращаемая позиция задается в кодовых точках UTF-16
LENGTHB(string)Возвращает размер строки string в байтах
LENGTHC(string)Возвращает длину строки string в символах Юникода
LENGTH2(string)Возвращаемая длина задается в кодовых единицах UTF-16
LENGTH4(string)Возвращаемая длина задается в кодовых точках UTF-16
SUBSTRB(string, n, m)Возвращает часть строки string, состоящую из m символов, начиная
с позиции n. Значения n и m задаются в байтах
SUBSTRC(string, n, m)Возвращает часть строки string, состоящую из m символов, начиная
с позиции n. Значения n и m задаются в символах Юникода
SUBSTR2(string, n, m)Значения n и m задаются в кодовых единицах UTF-16
SUBSTR4(string, n, m)Значения n и m задаются в кодовых точках UTF-16
UNISTRПреобразует представление строки string из ASCII-формата (обрат-
ная косая черта, шестнадцатеричные цифры) в Юникод

Рассмотрим эти функции подробнее.

ASCIISTR

ASCIISTR пытается преобразовать полученную строку в ASCII-символы. Если строка содержит символы, отсутствующие в наборе ASCII, они представляются в формате xxxx. Как будет показано ниже при описании функции DECOMPOSE, такое форматирование иногда оказывается очень удобным.

BEGIN
   DBMS_OUTPUT.put_line ('ASCII Character: ' || ASCIISTR ('A'));
   DBMS_OUTPUT.put_line ('Unicode Character: ' || ASCIISTR ('Ä'));
END;

Результат:

ASCII Character: A
Unicode Character: 0C4

COMPOSE

Некоторые символы могут иметь несколько вариантов представления кодовых пун­ктов. Это создает проблемы при сравнении двух значений. Символ А может быть представлен как одним кодовым пунктом U 00C4, так и двумя кодовыми пунктами U 0041 (буква A) и U 0308. При сравнении PL/SQL считает, что эти два варианта представления не равны.

DECLARE
   v_precomposed   VARCHAR2 (20) := UNISTR ('0C4');
   v_decomposed    VARCHAR2 (20) := UNISTR ('A308');
BEGIN
   IF v_precomposed = v_decomposed
   THEN
      DBMS_OUTPUT.put_line ('==EQUAL==');
   ELSE
      DBMS_OUTPUT.put_line ('<>NOT EQUAL<>');
   END IF;
END;

Результат:

Однако после использования функции COMPOSE эти две версии равны:

DECLARE
   v_precomposed   VARCHAR2 (20) := UNISTR ('0C4');
   v_decomposed    VARCHAR2 (20) := COMPOSE (UNISTR ('A308'));
BEGIN
   IF v_precomposed = v_decomposed
   THEN
      DBMS_OUTPUT.put_line ('==EQUAL==');
   ELSE
      DBMS_OUTPUT.put_line ('<>NOT EQUAL<>');
   END IF;
END;

На этот раз сравнение дает другой результат:

==EQUAL==

DECOMPOSE

:/>  Win 10 Tweaker 10.7 Portable by XpucT Ru/En скачать торрент файл бесплатно

Как нетрудно догадаться, функция DECOMPOSE является обратной по отношению к COMPOSE: она разбивает составные символы на отдельные кодовые точки или элементы:

DECLARE
   v_precomposed   VARCHAR2 (20) := ASCIISTR (DECOMPOSE ('Ä'));
   v_decomposed    VARCHAR2 (20) := 'A308';
BEGIN
   IF v_precomposed = v_decomposed
   THEN
      DBMS_OUTPUT.put_line ('==EQUAL==');
   ELSE
      DBMS_OUTPUT.put_line ('<>NOT EQUAL<>');
   END IF;
END;

Результат:

==EQUAL==

INSTR/INSTRB/INSTRC/INSTR2/INSTR4

Все функции INSTR возвращают позицию подстроки внутри строки и различаются лишь по способу определения позиции. Для демонстрации мы воспользуемся таблицей publication из схемы g11n.

DECLARE
   v_instr    NUMBER (2);
   v_instrb   NUMBER (2);
   v_instrc   NUMBER (2);
   v_instr2   NUMBER (2);
   v_instr4   NUMBER (2);
BEGIN
   SELECT INSTR (title, 'グ'),
 INSTRB (title, 'グ'),
 INSTRC (title, 'グ
'),
 INSTR2 (title, 'グ'),
 INSTR4 (title, 'グ
')
     INTO v_instr, v_instrb, v_instrc,
          v_instr2, v_instr4
     FROM publication
    WHERE publication_id = 2;

   DBMS_OUTPUT.put_line ('INSTR of グ: ' || v_instr);
   DBMS_OUTPUT.put_line ('INSTRB of グ: ' || v_instrb);
   DBMS_OUTPUT.put_line ('INSTRC of グ: ' || v_instrc);
   DBMS_OUTPUT.put_line ('INSTR2 of グ: ' || v_instr2);
   DBMS_OUTPUT.put_line ('INSTR4 of グ: ' || v_instr4);
END;
/

Результат:

INSTR of グ: 16
INSTRB of グ: 20
INSTRC of グ: 16
INSTR2 of グ: 16
INSTR4 of グ: 16

Позиция символа У отличается только для INSTRB. Одна из полезных особенностей INSTR2 и INSTR4 заключается в том, что они могут использоваться для поиска кодовых точек, не представляющих полные символы. Возвращаясь к примеру с символом А, умляут можно включить как подстроку для выполнения поиска.

LENGTH/LENGTHB/LENGTHC/LENGTH2/LENGTH4

Функции LENGTH возвращают длину строки в разных единицах:

LENGTH — возвращает длину строки в символах;

LENGTHB — возвращает длину строки в байтах;

LENGTHC — возвращает длину строки в символах Юникода;

LENGTH2 — возвращает количество кодовых единиц в строке;

LENGTH4 — возвращает количество кодовых точек в строке.

Если строка состоит из композиционных символов, функция LENGTH эквивалентна LENGTHC.

DECLARE
   v_length    NUMBER (2);
   v_lengthb   NUMBER (2);
   v_lengthc   NUMBER (2);
   v_length2   NUMBER (2);
   v_length4   NUMBER (2);
BEGIN
   SELECT LENGTH (title), LENGTHB (title), lengthc (title), length2 (title),
          length4 (title)
     INTO v_length, v_lengthb, v_lengthc, v_length2,
          v_length4
     FROM publication
    WHERE publication_id = 2;

   DBMS_OUTPUT.put_line ('LENGTH of string: ' || v_length);
   DBMS_OUTPUT.put_line ('LENGTHB of string: ' || v_lengthb);
   DBMS_OUTPUT.put_line ('LENGTHC of string: ' || v_lengthc);
   DBMS_OUTPUT.put_line ('LENGTH2 of string: ' || v_length2);
   DBMS_OUTPUT.put_line ('LENGTH4 of string: ' || v_length4);
END;

Результат:

LENGTH of string: 28
LENGTHB of string: 52
LENGTHC of string: 28
LENGTH2 of string: 28
LENGTH4 of string: 28

В данном примере только функция LENGTHB дает другой результат. Как и ожидалось, LENGTH и LENGTHC вернули одинаковые результаты. Впрочем, при работе с декомпозицион­ными символами ситуация меняется. Пример:

DECLARE
   v_length   NUMBER (2);
BEGIN
   SELECT LENGTH (UNISTR ('A308'))
     INTO v_length
     FROM DUAL;

   DBMS_OUTPUT.put_line ('Decomposed string size using LENGTH: ' || v_length);

   SELECT lengthc (UNISTR ('A308'))
     INTO v_length
     FROM DUAL;

   DBMS_OUTPUT.put_line ('Decomposed string size using LENGTHC: ' || v_length);
END;

Функции возвращают следующие значения длины:

Decomposed string size using LENGTH: 2
Decomposed string size using LENGTHC: 1

Функция LENGTH возвращает количество символов, но считает A и умляут разными символами. LENGTHC возвращает длину в символах Юникода и видит только один символ.

SUBSTR/SUBSTRB/SUBSTRC/SUBSTR2/SUBSTR4

Разные версии SUBSTR определяются по тому же принципу, что и их аналоги у функций INSTR с LENGTH. SUBSTR возвращает часть строки заданной длины начиная с заданной позиции. Функции этого семейства работают следующим образом:

SUBSTR — определяет позицию и длину по символу;

SUBSTRB — определяет позицию и длину в байтах;

SUBSTRC — определяет позицию и длину в символах Юникода;

SUBSTR2 — использует кодовые единицы;

SUBSTR4 — использует кодовые точки.

Использование этих функций продемонстрировано в следующем примере:

DECLARE
   v_substr    VARCHAR2 (20);
   v_substrb   VARCHAR2 (20);
   v_substrc   VARCHAR2 (20);
   v_substr2   VARCHAR2 (20);
   v_substr4   VARCHAR2 (20);
BEGIN
   SELECT SUBSTR (title, 13, 4), SUBSTRB (title, 13, 4),
          substrc (title, 13, 4), substr2 (title, 13, 4),
          substr4 (title, 13, 4)
     INTO v_substr, v_substrb,
          v_substrc, v_substr2,
          v_substr4
     FROM publication
    WHERE publication_id = 2;

   DBMS_OUTPUT.put_line ('SUBSTR of string: ' || v_substr);
   DBMS_OUTPUT.put_line ('SUBSTRB of string: ' || v_substrb);
   DBMS_OUTPUT.put_line ('SUBSTRC of string: ' || v_substrc);
   DBMS_OUTPUT.put_line ('SUBSTR2 of string: ' || v_substr2);
   DBMS_OUTPUT.put_line ('SUBSTR4 of string: ' || v_substr4);
END;

Обратите внимание на отличие SUBSTRB от других функций в результатах выполнения сценария:

SUBSTR of string: Lプログ
SUBSTRB of string: Lプ
SUBSTRC of string: Lプログ
SUBSTR2 of string: Lプログ
SUBSTR4 of string: Lプログ

UNISTR

Функция UNISTR преобразует строку в Юникод. Эта функция использовалась в ряде предыдущих примеров для вывода символов строки, подвергнутой декомпозиции. В разделе «Кодировка символов» в качестве примера была приведена строка, состоя­щая из кодовых пунктов. Чтобы привести ее к понятному виду, можно воспользоваться функцией UNISTR:

DECLARE
   v_string   VARCHAR2 (20);
BEGIN
   SELECT UNISTR ('05307406507606506E')
     INTO v_string
     FROM DUAL;

   DBMS_OUTPUT.put_line (v_string);
END;

Результат:

Steven

Оставьте комментарий

Adblock
detector