using cast function or UDF rpad or sys.standard.rpad instead of internal rpad,can get right result
--return 1 row
with tmp as (
select id, name from t2 where name = sys.standard.rpad('yang', 12)
)
select * from t1, tmp where t1.name = tmp.name and t1.name = sys.standard.rpad('yang', 10);
--return 1 row
with tmp as (
select id, name from t2 where name = cast('yang ' as varchar2(12))
)
select * from t1, tmp where t1.name = tmp.name and t1.name = cast('yang ' as varchar2(10));
--return 1 row
create or replace function RPAD2(STR1 VARCHAR2 CHARACTER SET ANY_CS,
LEN pls_integer,
PAD VARCHAR2 CHARACTER SET STR1%CHARSET)
return VARCHAR2 CHARACTER SET STR1%CHARSET is
begin
return rpad(STR1,len,pad);
end;
/
with tmp as (
select id, name from t2 where name = rpad2('yang', 12)
)
select * from t1, tmp where t1.name = tmp.name and t1.name = rpad2('yang', 10);
So, I guess the possible reasons are as follows:
when all the input parameters of the rpad function are constants, the SQL optimizer automatically optimizes it to a constant of type varchar2,
so the rpad function doesn't show up in the execution plan.
At this point, the filtering condition values are no longer a complex expression but just two simple constant values, making it quick to determine if these two constants are equal.
Since there's a condition "T1.NAME=NAME," the optimizer automatically adds the "NULL IS NOT NULL" filtering condition after comparing these two constants, leading to incorrect results.
If one of the parameters of the rpad function is changed to a non-constant value, like a column name, then the optimizer won't remove the rpad, so it can't compare the two values in advance, and "null is not null" won't be added.
--return 1 row
with tmp as (
select id, name from t2 where name = rpad(name, 12)
)
select * from t1, tmp where t1.name = tmp.name and t1.name = rpad(t1.name, 10);
Comparing different types of data like "char=varchar2" shouldn't lead to additional filtering conditions in the optimizer,but it do