在oracle中查询具有char数据类型的列

时间:2015-03-06 07:46:43

标签: sql oracle plsql

我有以下情况:

示例代码:

        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;

- 上面的pl / sql块只执行一次打印,但如果我用&#34替换该块内的select;从abc中选择aa到v_temp,其中aa in(' ABC');& #34;该值将被打印。

请告诉我这个行为。

4 个答案:

答案 0 :(得分:1)

问题归结为您是否在查询中使用charvarchar2比较语义。如果您有一个硬编码的字符串文字或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用于真正的固定宽度数据(即char(1)表示标志,char(2)表示状态代码),即使使用{没有任何好处{1}}在这些情况下超过char。但是,对于任何非固定宽度的东西,使用varchar2都没有意义。您只是强迫Oracle占用超出需要的空间,并为自己创建更多工作来处理两组字符串比较语义(以及其他问题)。

答案 1 :(得分:0)

使用varchar2声明表格:

create table abc (
   aa varchar2(10)
);

或者,将v_aa声明为char(10)。但我会强烈假设你应该走varchar2路线。

<强>更新

所以,我理解你的字符会从迁移中恢复,你可以将它们切换到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);

然后您可以运行以更改定义。

当然,(几乎)不用说,在将其应用到生产数据库之前,你想彻底测试它。

答案 2 :(得分: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

答案 3 :(得分:0)

如果将VARCHAR2值与CHAR值进行比较,则使用非空白填充语义。但是,请记住,当您为CHAR变量分配字符值时,如果该值短于变量的声明长度,则PL / SQL会将值填充到声明的长度。鉴于声明

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

以下IF条件为false,因为v_aa2的值包含五个尾随空白:

IF v_aa1 = v_aa2 THEN ...

所有字符串文字都有数据类型CHAR。如果比较中的两个值都是文字,则使用空白填充语义。如果一个值是文字,则仅当另一个值具有数据类型CHAR时才使用空白填充语义。