Смешение значений CHAR и VARCHAR2 в PL/SQL

Если в коде PL/SQL используются строки как фиксированной (CHAR), так и переменной (VARCHAR2) длины, программист должен учитывать особенности выполнения в базе данных Oracle операций, в которых участвуют оба типа строк.


Оглавление статьи[Показать]


Перенос информации из базы данных в переменную

При выборке (SELECT или FETCH) данных из столбца базы данных типа CHAR и присваивании их переменной типа VARCHAR2 завершающие пробелы сохраняются. Если же перенести данные из столбца типа VARCHAR2 в переменную типа CHAR, PL/SQL автоматически дополнит извлекаемое значение пробелами до максимальной длины переменной. Таким образом, итоговое значение переменной определяется ее типом, а не типом столбца.

 

Перенос информации из переменной в базу данных

Когда вы помещаете (INSERT или UPDATE) значение переменной типа CHAR в столбец базы данных типа VARCHAR2, ядро SQL не подавляет завершающие пробелы. Например, при выполнении следующего кода PL/SQL столбцу company_name базы данных присваивается значение ACME SHOWERS........ (где символ «.» обозначает пробел). Иначе говоря, столбец дополняется пробелами до 20 символов, хотя исходным значением была строка из 12 символов.

DECLARE
comp_id# NUMBER;
comp_name CHAR(20) := 'ACME SHOWERS';
BEGIN
SELECT company_id_seq.NEXTVAL
INTO comp_id#
FROM dual;
INSERT INTO company (company_id, company_name)
VALUES (comp_id#, comp_name);
END;

С другой стороны, при помещении значения переменной типа VARCHAR2 в столбец базы данных типа CHAR ядро SQL автоматически дополняет строку переменной длины пробелами до максимальной длины столбца (заданной при создании таблицы) и записывает результат в базу данных.

 

Сравнения строк

Предположим, некоторая программа содержит следующий оператор сравнения строк:

IF company_name = parent_company_name ... 

PL/SQL должен сравнить значения company_name и parent_company_name. Эта операция выполняется одним из двух способов в зависимости от типов переменных:

  • При сравнении двух переменных типа CHAR PL/SQL дополняет их завершающими пробелами.
  • Если хотя бы одна из строк имеет переменную длину, PL/SQL выполняет сравнение без дополнения завершающими пробелами.

Различие между этими двумя методами сравнения продемонстрировано в следующем фрагменте кода: 

DECLARE
company_name CHAR(30)
:= 'Feuerstein and Friends';
char_parent_company_name CHAR(35)
:= 'Feuerstein and Friends';
varchar2_parent_company_name VARCHAR2(35)
:= 'Feuerstein and Friends';
BEGIN
-- Сравниваются два значения CHAR, строки дополняются пробелами
IF company_name = char_parent_company_name THEN
DBMS_OUTPUT.PUT_LINE ('Результат первой проверки равен TRUE');
ELSE
DBMS_OUTPUT.PUT_LINE ('Результат первой проверки равен FALSE');
END IF;
-- Сравниваются CHAR и VARCHAR2, поэтому строки не дополняются пробелами
IF company_name = varchar2_parent_company_name THEN
DBMS_OUTPUT.PUT_LINE ('Результат второй проверки равен TRUE');
ELSE
DBMS_OUTPUT.PUT_LINE ('Результат второй проверки равен FALSE');
END IF;
END

Результат:

Результат первой проверки равен TRUE
Результат второй проверки равен FALSE 

В первом сравнении участвуют два значения типа CHAR, поэтому используется дополнение завершающими пробелами: PL/SQL дополняет более короткое из двух значений до длины более длинного значения, после чего они сравниваются. В данном примере PL/SQL добавляет пять пробелов в конец значения переменной company_name, а затем сравнивает значения company_name и char_parent_company_name.

Проверка дает положительный результат. Обратите внимание: PL/SQL не изменяет значение переменной company_name. Это значение просто копируется в другую структуру памяти, где оно модифицируется для сравнения.

Во второй операции участвуют значения типов CHAR и VARCHAR2, поэтому PL/SQL выполняет сравнение без дополнения завершающими пробелами. Ни одно из значений не изменяется, а в сравнении используется их текущая длина. В данном случае первые 22 символа обеих строк одинаковы (Feuerstein and Friends), но значение переменной фиксированной длины company_name дополнено восемью пробелами, а значение переменной varchar2_parent_company_name — нет. В результате строки оказываются не равными.

Участие в проверке значения типа VARCHAR2 приводит к тому, что сравнение выполняется без дополнения завершающими пробелами. Это верно и для выражений, содержащих более двух переменных, а также для выражений с оператором IN. Пример:

IF menu_selection NOT IN
(save_and_close, cancel_and_exit, 'OPEN_SCREEN')
THEN ...

Если хотя бы одна из четырех строк (menu_selection, две именованные константы и один литерал) объявлена как VARCHAR2, точное сравнение будет выполнено без модификации значений. Обратите внимание: строковые литералы (такие, как OPEN_SCREEN) всегда рассматриваются как строки фиксированной длины, то есть CHAR.

Вас заинтересует / Intresting for you:

Встроенные методы коллекций PL...
Встроенные методы коллекций PL... 14838 просмотров sepia Tue, 29 Oct 2019, 09:54:01
Управление приложениями PL/SQL...
Управление приложениями PL/SQL... 4651 просмотров Stas Belkov Thu, 16 Jul 2020, 06:20:48
Основы языка PL/SQL: использов...
Основы языка PL/SQL: использов... 4700 просмотров Ирина Светлова Tue, 06 Feb 2018, 14:04:03
Символьные функции и аргументы...
Символьные функции и аргументы... 18586 просмотров Анатолий Wed, 23 May 2018, 18:54:01
Войдите чтобы комментировать