0

我有一个带有 char(20) 数据类型列的表,我为此列编制了索引。当我这样做时:

select * from ex_table where charColumn = 'abc'

引发异常 No_Data_Found。因为数据是 'abc'。我如何在不丢失索引的情况下进行这样的搜索?感谢您的帮助!

4

1 回答 1

2

CHAR使用数据类型很少是一个好主意。你几乎总是想用 aVARCHAR2代替。ACHAR(20)总是存储 20 字节的数据。如果没有足够的数据,该CHAR列将在字符串的右侧附加额外的 17 个空格字符,以将其填充到所需的 20 个字节。

话虽如此,如果您确实按照您所说的去做,那么无论数据类型如何,您都会正确地恢复行。

SQL> create table foo( col1 char(20), col2 varchar2(20) );

Table created.

SQL> insert into foo values( 'abc','abc' );

1 row created.

SQL> select * from foo where col1 = 'abc';

COL1                 COL2
-------------------- --------------------
abc                  abc

SQL> select * from foo where col2 = 'abc';

COL1                 COL2
-------------------- --------------------
abc                  abc

但是,我怀疑您真正在做的是尝试将CHAR(20)列中的数据与VARCHAR2局部变量中的数据进行比较。如果是这种情况,那么 Oracle 使用VARCHAR2 比较语义,并且列末尾的额外 17 个空格字符CHAR(20)会导致匹配失败

SQL> declare
  2    l_str varchar2(20) := 'abc';
  3    l_row foo%rowtype;
  4  begin
  5    select *
  6      into l_row
  7      from foo
  8     where col1 = l_str;
  9    dbms_output.put_line( l_row.col1 );
 10  end;
 11  /
declare
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 5

您可以将列中的数据与CHAR(20)局部变量中的数据进行比较(在实际代码中,您希望使用锚定类型foo.col1%type而不是硬编码长度,我只是使用硬编码类型来强调)

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_str char(20) := 'abc';
       -- In real code, this would be
       -- l_str foo.col1%type := 'abc';
  3    l_row foo%rowtype;
  4  begin
  5    select *
  6      into l_row
  7      from foo
  8     where col1 = l_str;
  9    dbms_output.put_line( l_row.col1 );
 10* end;
SQL> /
abc

PL/SQL procedure successfully completed.

或者你可以拉出合适RPADVARCHAR2长度

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_str varchar2(20) := 'abc';
  3    l_row foo%rowtype;
  4  begin
  5    select *
  6      into l_row
  7      from foo
  8     where col1 = RPAD(l_str,20);
  9    dbms_output.put_line( l_row.col1 );
 10* end;
SQL> /
abc

PL/SQL procedure successfully completed.

但是,正确的答案几乎总是避免使用CHAR数据类型。

于 2013-04-01T17:03:10.750 回答