我有以下情况:
示例代码:
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;该值将被打印。
请告诉我这个行为。
答案 0 :(得分: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
用于真正的固定宽度数据(即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时才使用空白填充语义。