Зачем использовать varchar2 вместо char для констант пакетов?

Просто наткнулся на пакет, который определяет большое количество глобальных константных строк как таковых:

DESTINATION_1 CONSTANT VARCHAR2(13) := '515 Pine Lane';
DESTINATION_2 CONSTANT VARCHAR2(18) := '670 Woodhaven Lane';

Есть ли польза от использования varchar2 как тип данных для этих более char?

Использование Oracle 11g, выпуск 2.

3 ответа

Решение

В общем, я использую VARCHAR2 вместо CHAR для всех объявлений строковых переменных или констант по той простой причине, что семантика VARCHAR2 более соответствует моим ожиданиям. Проблема здесь заключается в том, что если разработчик менее точен в подсчете длины константы, он будет заполнен справа пробелами, если объявлен как CHAR, в то время как он будет просто сохранен без заполнения, если объявлен как VARCHAR2. Рассматривать:

DECLARE
  strFixed    CHAR(20) := 'This is a string';
  strVariable VARCHAR2(20) := 'This is a string';
BEGIN
  IF strFixed = strVariable THEN
    DBMS_OUTPUT.PUT_LINE('Equal');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Not equal');
  END IF;
END;

На первый взгляд вы можете ожидать, что это напечатает "Равно", но на самом деле будет "Не равно". Это так, потому что strFixed не хранится как "Это строка"; вместо этого он сохраняется как "Это строка", потому что переменные CHAR дополняются справа пробелами до размера, указанного в объявлении переменной. Да, я мог бы тщательно подсчитать количество символов в строке (их 17, между прочим), а затем тщательно скорректировал декларацию, но это всего лишь СО 1970-х годов (десятилетие, которое я помню довольно смутно, и не хочу к нему возвращаться:-). И, о боже, я не учел количество символов в строке, поэтому фиксированная строка была бы дополнена справа, чтобы заполнить ее до заявленной длины, и мое сравнение все равно не сработало бы.

Единственный случай, когда я буду использовать CHAR вместо VARCHAR2, это если переменная константы должна иметь длину только один символ. IMO объявлять что-то как VARCHAR2(1) просто неправильно.:-)

Просто мимоходом отмечу, что если вы посмотрите в пакет SYS.STANDARD, вы обнаружите, что CHAR объявлен как

subtype CHAR is VARCHAR2;

Таким образом, CHAR - это VARCHAR2. Не уверен, как выполняется заполнение пробелами, но вполне возможно, что заполнение пробелами выполняется во время выполнения и, таким образом, добавляет дополнительное время.

Есть ли преимущество в производительности для одного или другого? В лучшем случае это не будет много. Я полагаю, что если переменная CHAR имеет некоторый пробел, для сравнения потребуется больше времени, чем для эквивалентного незаполненного значения VARCHAR2, но на практике я не верю, что это будет иметь значение. Кроме того, поскольку заполнение пробелами выполняется во время выполнения, это добавит время. Я подозреваю, что это стирка, и она наверняка будет затоплена эффектами SQL.

Поделитесь и наслаждайтесь.

Тип данных CHAR и тип данных VARCHAR2 хранятся одинаково... Таким образом, в случае, который вы описываете, нет никакой разницы.

Разница между CHAR и VARCHAR заключается в том, что CHAR(n) ВСЕГДА будет иметь длину N байтов, для вставки он будет заполнен пробелом, чтобы обеспечить это. Varchar2(n), с другой стороны, будет иметь длину от 1 до N байтов, он НЕ будет дополнен пробелами.

Привет, это может быть моим предположением, но varchar2, возможно, был использован из-за производительности,

char - это просто бланк varchar2, дополненный до максимальной длины.

create table t ( x varchar2(30), y char(30) ); 
insert into t (x,y) values ( rpad('a',' ',30), 'a' ); 

АБСОЛЮТНО НИЧЕГО, а учитывая, что разница между столбцами X и Y ниже:

insert into t (x,y) values ('a','a') 

X потребляет 3 байта (нулевой индикатор, длина старшего байта, 1 байт для "a"), а Y потребляет 32 байта (нулевой индикатор, длина старшего байта, 30 байт для "a")

Хм, varchar2 будет несколько "с точки зрения производительности". Нам совсем НЕ помогает то, что char(30) всегда составляет 30 байтов - для нас это просто varchar2, который заполнен пробелами до максимальной длины.

Другие вопросы по тегам