ПРИЛОЖЕНИЕ C ---------------------------------------------------------------- СЕМАНТИКА ПРИСВАИВАНИЯ И СРАВНЕНИЯ СТРОК В этом приложении объясняются семантические различия между базовыми типами данных CHAR и VARCHAR2. В ORACLE7 и PL/SQL версии 2 семантика типа CHAR была слегка изменена, чтобы привести ее в соответствие с текущим стандартом ANSI/ISO SQL. Эти изменения играют роль, когда вы сравниваете и присваиваете символьные значения (в частности, в операциях INSERT, UPDATE, SELECT или FETCH). Семантика присваивания и сравнения строк C-1 ---------------- Присваивание символьных значений Когда вы присваиваете символьное значение переменной CHAR, если это значение короче, чем объявленная длина переменной, PL/SQL дополняет его пробелами до объявленной длины. Поэтому информация о существующих хвостовых пробелах, если таковые имеются в присваиваемом значении, теряется. Например, рассмотрим следующие объявления: name1 CHAR(10); name2 CHAR(10); После присваиваний name1 := 'Tom & '; -- заметьте хвостовой пробел name2 := 'Jerry'; значения как name1, так и name2 будут иметь по пять хвостовых пробелов. Если символьное значение длиннее, чем объявленная длина переменной CHAR, то PL/SQL снимает операцию присваивания и возбуждает предопределенное исключение VALUE_ERROR. PL/SQL не усекает такое значение и даже не пытается отстричь хвостовые пробелы. Например, при объявлении переменной acronym CHAR(4); следующее присваивание возбудит исключение VALUE_ERROR: acronym := 'SPCA '; -- заметьте хвостовой пробел Когда вы присваиваете символьное значение переменной VARCHAR2, если это значение короче объявленной длины переменной, PL/SQL не дополняет его пробелами и не отстригает хвостовых пробелов. Значение присваивается как оно есть, так что никакая информация не теряется. Если символьное значение длиннее, чем объявленная длина переменной, то PL/SQL снимает операцию присваивания и возбуждает предопределенное исключение VALUE_ERROR. PL/SQL не усекает такое значение и не пытается отстричь хвостовые пробелы. C-2 Руководство пользователя и справочник по PL/SQL ---------------- Сравнение символьных значений Вы можете использовать операторы отношений для сравнения символьных значений на равенство или неравенство. Сравнения базируются на сопоставляющей последовательности, используемой набором символов базы данных. Одно символьное значение больше другого, если первое следует за вторым в сопоставляющей последовательности. Например, следующее условие IF дает TRUE: name1 := 'COLES'; name2 := 'COLEMAN'; IF (name1 > name2) THEN ... ANSI/ISO SQL требует, чтобы два сравниваемых символьных значения имели одинаковую длину. Поэтому, если оба значения в сравнении принадлежат типу CHAR, используется ДОПОЛНЯЮЩАЯ СЕМАНТИКА. Это значит, что перед сравнением символьных строк неодинаковой длины PL/SQL дополняет короткое значение пробелами до длины длинного. Например, при объявлениях name1 CHAR(4) := 'BELL'; name2 CHAR(6) := 'BELL '; -- заметьте хвостовые пробелы следующее условие IF дает TRUE: IF (name1 = name2) THEN ... Если хотя бы одно из сравниваемых значений принадлежит типу VARCHAR2, то используется НЕДОПОЛНЯЮЩАЯ СЕМАНТИКА. Это значит, что перед сравнением символьных строк неодинаковой длины PL/SQL не дополняет значений пробелами и использует их точные длины. Например, при объявлениях name1 VARCHAR2(10) := 'DOW'; name2 CHAR(10) := 'DOW '; -- заметьте хвостовые пробелы следующее условие IF дает FALSE: IF (name1 = name2) THEN ... Как указывалось в главе 2, все строковые литералы имеют тип CHAR. Следовательно, если оба значения в сравнении являются литералами, используется дополняющая семантика. Если литералом является лишь одно из значений, то дополняющая семантика используется только в том случае, когда второе значение принадлежит типу CHAR. Семантика присваивания и сравнения строк C-3 ---------------- Вставка символьных значений Когда вы выполняете операцию INSERT, вставляя значение символьной переменной PL/SQL в столбец базы данных ORACLE, будет ли это значение дополняться пробелами или нет - зависит от типа столбца, но НЕ от типа переменной. При вставке символьного значения в столбец базы данных CHAR ORACLE не отстригает хвостовых пробелов. Если значение короче объявленной ширины столбца, ORACLE дополняет значение до объявленной ширины. Как следствие, информация о хвостовых пробелах исходного значения теряется. Если символьное значение длиннее объявленной ширины столбца CHAR, ORACLE генерирует ошибку и отменяет операцию. ORACLE не усекает такое значение и не отстригает хвостовых пробелов. При вставке символьного значения в столбец базы данных VARCHAR2 ORACLE также не отстригает хвостовых пробелов. Если значение короче объявленной ширины столбца, ORACLE не дополняет значение до объявленной ширины. Символьное значение записывается как оно есть, и информация о хвостовых пробелах исходного значения сохраняется. Если символьное значение длиннее объявленной ширины столбца VARCHAR2, то ORACLE генерирует ошибку и отменяет операцию. ORACLE не усекает такое значение и не отстригает хвостовых пробелов. Те же правила действуют при операции UPDATE. ---------------- Выборка символьных значений Когда вы выполняете операцию SELECT, выбирая значение столбца базы данных ORACLE в символьную переменную PL/SQL, будет ли это значение дополняться пробелами или нет - зависит от типа переменной, но НЕ от типа столбца. При выборке значения столбца в переменную CHAR, если это значение короче объявленной длины переменной, ORACLE дополняет значение до объявленной длины. Как следствие, информация о хвостовых пробелах исходного значения теряется. Если символьное значение столбца длиннее объявленной длины переменной CHAR, ORACLE усекает значение, выполняет присваивание, а затем заставляет PL/SQL возбудить предопределенное исключение VALUE_ERROR. При выборке значения столбца в переменную VARCHAR2, если это значение короче объявленной длины переменной, ORACLE не дополняет это значение до объявленной длины и не отстригает хвостовых пробелов. Символьное значение присваивается как оно есть, так что информация о хвостовых пробелах исходного значения не теряется. Если символьное значение столбца длиннее объявленной длины переменной VARCHAR2, то ORACLE усекает значение, выполняет присваивание, а затем заставляет PL/SQL возбудить предопределенное исключение VALUE_ERROR. Те же правила действуют при операции FETCH. C-4 Руководство пользователя и справочник по PL/SQL ---------------- Рекомендации В данном исполнительном окружении, эквивалентность типов данных CHAR и VARCHAR2 определяется командой или опцией, которая устанавливает режим совместимости с версией 6 или режим ORACLE7. Например, в среде SQL*Plus вы выдаете команду SET COMPATIBILITY, специфицируя значение V6 или V7 (умолчание), например: SQL> SET COMPATIBILITY V6 Другим примером может служить среда прекомпилятора ORACLE, в которой вы указываете опцию режима выполнения DBMS в командной строке, например: ... DBMS=V6 ... Умалчиваемым режимом является DBMS=NATIVE, что специфицирует ту версию ORACLE, которая установлена в вашей системе (это может быть версия 6 или более поздняя). При вставке в базу данных символьных значений вы можете гарантировать, что хвостовые пробелы не будут сохраняться, с помощью функции RTRIM, которая отсекает хвостовые пробелы, например: my_empno := 7471; my_ename := 'LEE '; -- заметьте хвостовые пробелы ... INSERT INTO emp VALUES (my_empno, RTRIM(my_ename), ...); -- вставит 'LEE'