caching the last value
Alberto Dell'Era, March 16, 2004 - 6:12 pm UTC
I think they are caching the last value, reusing it until "n" changes (i'm on 9.2.0.4):
Only one distinct value:
SQL> insert into t_tmp select 1 from all_objects where rownum <= 100;
100 rows created.
SQL> exec dbms_application_info.set_client_info(0);
PL/SQL procedure successfully completed.
SQL> select count(*) from t_tmp t where 1=(select f_tmp(t.n) from dual);
COUNT(*)
----------
100
SQL> select userenv('client_info') from dual;
USERENV('CLIENT_INFO')
-------------------------------------------------------------------------
1
Two distinct values:
SQL> delete from t_tmp;
100 rows deleted.
SQL> insert into t_tmp select 1 from all_objects where rownum <= 50;
50 rows created.
SQL> insert into t_tmp select 2 from all_objects where rownum <= 50;
50 rows created.
SQL> exec dbms_application_info.set_client_info(0);
PL/SQL procedure successfully completed.
SQL> select count(*) from t_tmp t where 1=(select f_tmp(t.n) from dual);
COUNT(*)
----------
100
SQL> select userenv('client_info') from dual;
USERENV('CLIENT_INFO')
--------------------------------------------------------------------------------
2
Three distinct values:
SQL> delete from t_tmp;
100 rows deleted.
SQL> insert into t_tmp select 1 from all_objects where rownum <= 33;
33 rows created.
SQL> insert into t_tmp select 2 from all_objects where rownum <= 33;
33 rows created.
SQL> insert into t_tmp select 3 from all_objects where rownum <= 34;
34 rows created.
SQL> exec dbms_application_info.set_client_info(0);
PL/SQL procedure successfully completed.
SQL> select count(*) from t_tmp t where 1=(select f_tmp(t.n) from dual);
COUNT(*)
----------
100
SQL> select userenv('client_info') from dual;
USERENV('CLIENT_INFO')
----------------------------------------------------------------------------
3
Eleven distinct values:
SQL> delete from t_tmp;
100 rows deleted.
SQL> insert into t_tmp select trunc (rownum / 10) from all_objects where rownum <= 100;
100 rows created.
SQL> select count (distinct n) from t_tmp;
COUNT(DISTINCTN)
----------------
11
NB: count (distinct) is equal to the number of "changes" of n ONLY IN THIS CASE, since we know that they will full-scan, fetching the rows in the same order we inserted them (but only in this "dust clean" experiment).
SQL> exec dbms_application_info.set_client_info(0);
PL/SQL procedure successfully completed.
SQL> select count(*) from t_tmp t where 1=(select f_tmp(t.n) from dual);
COUNT(*)
----------
100
SQL> select userenv('client_info') from dual;
USERENV('CLIENT_INFO')
--------------------------------------------------------------------------------
11
bye
Alberto
essentially improves performance
Denis Kolesnikov, March 17, 2004 - 6:52 am UTC
Tom, thank you for the exhaustive answer.
I use this feature in my FGAC-like views and that essentially improves performance.
Validate dates using user-defined functions
Narendra, February 27, 2006 - 5:08 am UTC
Tom,
If it can not be relaibly determine how many times a function is called in a SQL, how do I handle following situation:
I want to validate a column defined as VARCHAR2 but containing a DATE value and log all rows having invalid date in a table. If I use TO_DATE, it goes in exception at first occurence. I am forced to use a PL/SQL function that will do this validation and then call the function in a SQL to add erroneous records to log table.
Thanks
February 27, 2006 - 7:16 am UTC
I don't follow you here. Not sure what you are asking/saying.
"I want to validate a column defined as a varchar2" - fine.
"but containing a date value" (apparently not, it SOMETIMES has text in it that can be intrpreted as a date, sometimes not)
"If I use to_date, it goes in exception as first (bad?) occurrence" - correct ? so?
I think you might be asking "how do I validate this information in a loop"
for x in ( select * from table_with_data )
loop
begin
l_date := to_date( x.string_that_might_have_date );
l_date_ok := true;
exception
when others then l_date_ok := FALSE;
end if;
.... process, look at boolean ....
end loop;
for example
Exactly
Narendra, February 27, 2006 - 7:38 am UTC
Tom,
You are bang on target.
for x in ( select * from table_with_data )
loop
begin
l_date := to_date( x.string_that_might_have_date );
l_date_ok := true;
exception
when others then l_date_ok := FALSE;
end if;
IF l_date_ok THEN
-- Add to log table.
END IF;
end loop;
Adding to log table will be deferred and be done after all rows are validated.
Thanks