Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question.

Asked: October 12, 2010 - 1:46 pm UTC

Last updated: November 06, 2010 - 7:20 pm UTC

Version: 11.2

Viewed 1000+ times

You Asked

Hi Tom,

If we call pl/sql function from SQL - it will make a context switch from SQL engine to PL/SQL engine .but

1.What happens if we call SQL function built in functions such as truncate,substr(x,1,3) etc from SQL statement ? is there context switch from SQL engine ? if so -to where ??

2.Are the SQL functions such as DECODE,NVL,NVLIF etc written in C under the covers ? Is each and every SQL function written in C under the covers ?

3.Are the ANALYTICAL functions also written in C ? why the performance is good with the analytical functions ? below Q2 is slower than Q3 as emp table is scanned only once in the Q3 - but how ?How the analytics work under the covers ? Are they written in C as well ?

Q2:

select e1.emp_name,e1.sal from emp e1, (select avg(sal) sal ,dept_id from emp e2 group by dept_id )
e2
where e1.sal>e2.sal and e1.dept_id=e2.dept_id

Q3:

select e.emp_name,e.sal from (select emp_name,sal,avg(sal) over (partition by dept_id) avg_sal from
emp ) e
where sal>avg_sal

Many thanks Tom for the clarification ?


and Tom said...

1) the built-ins are in the sql engine

2) the built-ins are mostly written in C yes, there have been some written in java from time to time - but they eventually get implemented in C for the most part.

3) yes they are (the database is mostly written in C).

Why are the analytics "performing well" - they open up a new way to express what you want without having to hit the same table over and over and over again or process a potentially complex join. It isn't so much "because they are written in C", inasmuch as "they let us do things more efficiently in the query plan in some cases"


Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

New question

sriram, October 14, 2010 - 5:29 am UTC

Hi Tom.
Good afternoon.As I am newbie here I don`t know how to post a new question/thread.
I have a doubt regarding "Procedure Compilation".

Please See the below ..
SQL> create or replace procedure dawn_proc as
  2  d1 varchar2(10);
  3  d2 number;
  4  begin
  5  select 'sriram',y into d1,d2
  6  from table1
  7  group by y;
  8  end;
  9  /

Procedure created.

SQL> exec dawn_proc

PL/SQL procedure successfully completed.

SQL>  create or replace procedure dawn_proc as
  2   d1 number;
  3   d2 number;
  4   begin
  5   select x,y into d1,d2
  6   from table1
  7   group by x;
  8   end;
  9   /

Procedure created.

SQL> exec dawn_proc
BEGIN dawn_proc; END;

*
ERROR at line 1:
ORA-00979: not a GROUP BY expression
ORA-06512: at "SCOTT.DAWN_PROC", line 5
ORA-06512: at line 1


SQL> create or replace procedure dawn_proc as
  2  d1 varchar2(10);
  3  d2 number;
  4  begin
  5  select sriram,y into d1,d2
  6  from table1
  7  group by y;
  8  end;
  9  /

Warning: Procedure created with compilation errors.

SQL> sho err
Errors for PROCEDURE DAWN_PROC:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/1      PL/SQL: SQL Statement ignored
5/8      PL/SQL: ORA-00904: "SRIRAM": invalid identifier
SQL>



On the first execution....
procedure created,compiled and executed successfully without any warnings..
But at 2 time no compilation errors but run time errors.
when compared to 3, Procedure itself not compiled ....

Can you guide me with an URL or a sample test case with explanation...Why it is showing errors at runtime for some cases and at compilation errors for other cases...?
Waiting for your reply.

Thank you
sriram

Tom Kyte
October 15, 2010 - 7:42 am UTC

it is simply this:

there are compile time errors and there are runtime errors, just as there are in *every* programming language ever invented.

this compiles to:

begin
dbms_output.put_line( 'answer = ' || 1/0 );
end;


but it isn't going to run. The first SQL you provided is syntactically 'correct', it isn't until they go to run it (which they do not do during compilation, they parse it - but they do not RUN it) that they discover "it isn't going to work"


The second sql cannot be parsed - the parsing cannot resolve what sriram is in the context it was used. Hence, the sql is not parseable and that is known at compile time.


Can we rearrange lower case and upper case alphabets

Shankar, October 14, 2010 - 1:04 pm UTC

Hi Sir,

I am a regular visitor of your site , i have learned analytical functions from your book Expert One-on-One Oracle.

I am having a different alphabets jumbled followed by numbers like "adACBbcD32145" . I want to make it as aAbBcCdD12345 (in a alphabetical order with lower case followed by uppercase at last numbers are ordered)

Thanks for your help.
Tom Kyte
October 15, 2010 - 8:03 am UTC

<b>no version specified, so here it is for the current release:</b>

ops$tkyte%ORA11GR2> select listagg(column_value) within group (
  2   order by case when column_value between '0' and '9' then 2
  3                 else 1
  4              end,
  5            upper(column_value),
  6            case when column_value = lower(column_value) then 1
  7                 else 2
  8             end )
  9    from (
 10  select data, column_value
 11    from (select :x data from dual),
 12         TABLE( cast( multiset(
 13                select substr( data, level, 1 )
 14                  from dual
 15                connect by level <= length(data) ) as sys.odciVarchar2List ) )
 16         )
 17  /

LISTAGG(COLUMN_VALUE)WITHINGROUP(ORDERBYCASEWHENCOLUMN_VALUEBETWEEN'0'AND'9'THE
-------------------------------------------------------------------------------
aAbBcCdD12345


<b>this'll work in 10g</b>

ops$tkyte%ORA11GR2> select replace(max(sys_connect_by_path(column_value,',')),',','')
  2    from (
  3  select column_value, row_number() over (
  4   order by case when column_value between '0' and '9' then 2
  5                 else 1
  6              end,
  7            upper(column_value),
  8            case when column_value = lower(column_value) then 1
  9                 else 2
 10             end ) rn
 11    from (
 12  select data, column_value
 13    from (select :x data from dual),
 14         TABLE( cast( multiset(
 15                select substr( data, level, 1 )
 16                  from dual
 17                connect by level <= length(data) ) as sys.odciVarchar2List ) )
 18         )
 19         )
 20   start with rn = 1
 21   connect by prior rn = rn-1
 22  /

REPLACE(MAX(SYS_CONNECT_BY_PATH(COLUMN_VALUE,',')),',','')
-------------------------------------------------------------------------------
aAbBcCdD12345


If you are in 9i, search this site for stragg to replace listagg

Thanks Tom

Shankar, October 15, 2010 - 2:20 pm UTC

Thanks for your reply Sir.

I am a newbee ,using oracle since 6 months . i am finding difficulty in solving queries (correlated and inline views) . But i am glad that i can solve effectively using Analytical Functions (most of the questions). Can you give me any suggestions or links about inline views. I need to speed up on them

Thanks once again

Analytics and Tom rocks as always
Tom Kyte
October 15, 2010 - 2:59 pm UTC

inline views are just views you create in the context of a query - instead of standalone.

You query them in the from list:

select *
from (any query you want goes here, this is the inline view),
any_other_table_sources_you_want


there would be no books or lengthly (or even short) articles about them really - they are just what they are - nothing really fancy.

Re: Sirams ORA-00979 error

Kevin Kirkpatrick, November 05, 2010 - 11:46 am UTC

Hi Tom, 
In responding to Siram's question, you indicated 

"The first SQL you provided is syntactically 'correct', it isn't until they go to run it (which they do not do during compilation, they parse it - but they do not RUN it) that they discover "it isn't going to work" 

If I understand you properly, this is "syntactically 'correct'":

select dummy from dual
group by upper(dummy)


Hence I can compile:
CREATE OR REPLACE PROCEDURE P1 IS 
BEGIN
FOR L_ROW IN (
select dummy from dual
group by upper(dummy)
) 
LOOP NULL; END LOOP;
END; 

Though I can't say I understand fully WHY this is a runtime error that can only be detected at, well, runtime, I can at least accept that it is the case.  However, that leaves another mystery:  why do I get the ORA-00979 error when I attempt to Explain this query

select dummy from dual
group by upper(dummy)

The main way I ensure that I don't get ORA-00979 runtime errors in my programs is by pulling an explain plan of each individual query at compile time.  I guess my question comes down to: what is the difference between the parsing done for an explain plan and the parsing done by the PL/SQL compiler, such that the former can catch ORA-00979 errors but the latter cannot?


SQL> explain plan for select dummy from dual group by upper(dummy);
explain plan for select dummy from dual group by upper(dummy)
                        *
ERROR at line 1:
ORA-00979: not a GROUP BY expression

SQL> create or replace procedure kk_proc1 is
  2  begin  for l_row in 
  3  (select dummy from dual group by upper(dummy))
  4  loop null; end loop; end;
  5  /

Procedure created.

Tom Kyte
November 06, 2010 - 7:20 pm UTC

the syntax parse works.

the semantic check (access to the objects referenced) works.

optimization - during the "exectute" phase (or during explain plan - which optimizes) fails - it cannot compile the statement.


plsql just needs to check syntax and semantics - but doesn't optimize, doesn't try to generate a plan.


More to Explore

Analytics

Analytic SQL got you confused? Check out Connor McDonald's complete video course.