2015-03-06 4 views
1

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

Пример код:

 create table abc(aa char(10)); 
     insert into abc values('ABC'); 
     --ABC will be padded with 7 blank spaces 
     Issue: 
     Select * from abc where aa in ('ABC'); 
     --This above statement returns one row with value ABC 
     Declare 
     v_temp varchar2(10); 
     v_aa varchar2(10) := 'ABC'; 
     Begin 
     select aa into v_temp from abc where aa in (v_aa); 
     dbms_output.put_line(v_temp); 
     end; 

--The выше PL/SQL блок один исполнение печатает ничего, но если я заменить выберите внутри этот блок с «выберите aa в v_temp из abc, где aa in ('ABC'); значение будет напечатано.

Просьба сообщить мне о поведении.

ответ

0

Объявляет таблицу с varchar2:

create table abc (
    aa varchar2(10) 
); 

В качестве альтернативы, объявить v_aa, как char(10). Но я бы сильно предположил, что вы должны пойти по маршруту varchar2.

Update

Итак, я понимаю ваши символы стволовых назад от миграции, и вы хорошо, чтобы переключить их varchar2. Вы можете запустить

select 
    'alter table ' || table_name || 
    ' modify '  || column_name || 
    ' varchar2(' || char_length ||');' stmt 
from 
    user_tab_columns 
where 
    data_type = 'CHAR'; 

Это произведет alter table заявления (как так :)

alter table ABC modify AA varchar2(10); 

, который вы можете запустить, чтобы изменить определение.

Конечно, это (почти) само собой разумеется, что вы хотите тщательно протестировать это, прежде чем применять его в своей производственной базе данных.

+0

ya это будет работать, настоящая проблема заключается в том, что мы перешли с ms sql server на oracle, столбцы с типом char в ms sql server были перенесены в oracle как сам тип char. мы перенесли многие хранимые процедуры, в которых возникает ситуация, аналогичная той, которую я задал. Итак, столбец в sql с типом char должен быть перенесен в varchar2 ?? –

+1

В конечном счете, я считаю, что вам будет намного лучше, если вы измените данные в таблицах на varchar2. –

0

даже если вы используете select aa from abc where aa in (cast('ABC' as varchar2(10))); вы не получите никаких данных, так как:

with varcha2(10) the length of the value of the field is 3 but with char(10) it is is 10 

вам нужно определить v_aa, как char(10):

Declare 
    v_temp varchar2(10); 
    v_aa char(10) := 'ABC'; 
    Begin 
    select aa into v_temp from abc where aa in (v_aa); 
    dbms_output.put_line(v_temp); 
    end; 

ВЫВОД: ABC

1

вопрос сводится к тому, используете ли вы char или varchar2 сравнительная семантика в ваших запросах. Если у вас есть стробированный строковый литерал или переменная char(10), Oracle использует сравнительную семантику char, которая должна игнорировать конечное пустое пространство. Если у вас есть переменная varchar2(10), Oracle использует сравнительную семантику varchar2, которая включает в себя завершающее пробел. Таким образом,

select aa 
    into v_temp 
    from abc 
    where aa in (v_aa); 

возвращает строку, если v_aa определяется как char(10) (или, если это заменить строку буквального), но не если она определена как varchar(10).

Это одна из (многих) причин, по которым большинство людей полностью исключает типы данных . Лично я не против случайных char для действительно данных фиксированной ширины (т.char(1) для флагов и char(2) для государственных кодов), хотя нет пользы от использования char по сравнению с varchar2 в этих сценариях. Однако для всего, что не является фиксированной шириной, использование char не имеет смысла. Вы просто заставляете Oracle потреблять больше места, чем нужно, и создавать больше работы для себя, имея дело с двумя наборами семантики сравнения строк (среди прочих проблем).

+0

Спасибо Джастину за разъяснение. –

0

Если значение VARCHAR2 сравнивается со значением CHAR, используется семантика без пробелов. Но, помните, когда вы назначаете значение символа переменной CHAR, если значение короче объявленной длины переменной, PL/SQL пустые значения составляют объявленную длину. Принимая во внимание заявления

v_aa1 VARCHAR2(10) := 'ABC'; 
v_aa2 CHAR(10)  := 'ABC'; -- PL/SQL blank-pads value 

следующих Если условие ложно, поскольку значение v_aa2 включает пять завершающих пробелов:

IF v_aa1 = v_aa2 THEN ... 

Все строковые литералы имеют тип данных CHAR. Если оба значения в сравнении являются литералами, используется семантика пробела. Если одно значение является литералом, семантика пустого пробела используется только в том случае, если другое значение имеет тип данных CHAR.

Смежные вопросы