我有一个带有 char(20) 数据类型列的表,我为此列编制了索引。当我这样做时:
select * from ex_table where charColumn = 'abc'
引发异常 No_Data_Found。因为数据是 'abc'。我如何在不丢失索引的情况下进行这样的搜索?感谢您的帮助!
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.
或者你可以拉出合适RPAD
的VARCHAR2
长度
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
数据类型。