1

I'm trying to create a stored function in Oracle that will count the table rows..i want to make the table name dynamic, so i passed it as a parameter, the stored function code looks like this

create type tes_jml_obj is object(jumlah integer);
create type tes_jml_table is table of tes_jml_obj;
create or replace function jumlahBaris(namatabel varchar)
return tes_jml_table
is
  tabel tes_jml_table := tes_jml_table();
begin
  for r in (execute immediate 'select count(*) as jumlah from' || namatabel)
  loop
    tabel.extend;
    tabel(1) := tes_jml_obj(r.jumlah);
  end loop;
  return tabel;
end;

But when i execute it, it returns errors. Am i missing something here? Is that the correct way to get the table rows dynamically?

3
  • What errors do you get. You definitely always want to post the errors, too.
    – DWright
    Commented Apr 30, 2015 at 4:29
  • i don't necessarily think this is the problem, but for safety you might put the sql string with the concatenate in parens: (execute immediate ('select count(*) as jumlah from ' || namatabel)). Also, put a space after the from (that might be a problem).
    – DWright
    Commented Apr 30, 2015 at 4:34
  • i'm sorry, my bad.. here are the errors Error(6,21): PLS-00103: Encountered the symbol "IMMEDIATE" when expecting one of the following: . ( ) , * @ % & = - + < / > at in is mod remainder not rem => <an exponent (**)> <> or != or ~= >= <= <> and or like like2 like4 likec as between || multiset member submultiset The symbol "( was inserted before "IMMEDIATE" to continue.
    – thekucays
    Commented Apr 30, 2015 at 4:36

2 Answers 2

3
  1. There is a space missing after FROM keyword in the EXECUTE IMMEDIATE statement.
  2. EXECUTE IMMEDIATE statement has a syntax error. You are missing the INTO clause.
  3. You cannot use EXECUTE IMMEDIATE inside a CURSOR FOR LOOP. Basically, you are returning nothing from the execute immediate statement as mentioned in point 2 above.
  4. The iteration syntax for the LOOP is not correct. The syntax is FOR r IN 1..COUNT().

After rectifying your code, this is how it would look like:

SQL> CREATE OR REPLACE TYPE TES_JML_OBJ IS OBJECT(JUMLAH NUMBER)
  2  /

Type created.

SQL> CREATE OR REPLACE TYPE TES_JML_TABLE IS TABLE OF TES_JML_OBJ
  2  /

Type created.

SQL> CREATE OR REPLACE
  2    FUNCTION jumlahBaris(
  3        namatabel VARCHAR2)
  4      RETURN tes_jml_table
  5    IS
  6      TABEL TES_JML_TABLE := TES_JML_TABLE();
  7      cnt NUMBER;
  8    BEGIN
  9      EXECUTE IMMEDIATE 'select count(*) as jumlah from ' || NAMATABEL INTO CNT;
 10      FOR R IN 1..CNT
 11      LOOP
 12        TABEL.EXTEND;
 13        TABEL(R) := TES_JML_OBJ(R);
 14        dbms_output.put_line(TES_JML_OBJ(R).jumlah);
 15      END LOOP;
 16      RETURN tabel;
 17    END;
 18    /

Function created.

SQL> SHO ERR
No errors.

So, the function compiled with no errors. Let's execute it and see the output:

SQL> SET SERVEROUTPUT ON
SQL> SELECT JUMLAHBARIS('EMP') FROM DUAL;

JUMLAHBARIS('EMP')(JUMLAH)
--------------------------------------------------------------------------------
TES_JML_TABLE(TES_JML_OBJ(1), TES_JML_OBJ(2), TES_JML_OBJ(3), TES_JML_OBJ(4), TE
S_JML_OBJ(5), TES_JML_OBJ(6), TES_JML_OBJ(7), TES_JML_OBJ(8), TES_JML_OBJ(9), TE
S_JML_OBJ(10), TES_JML_OBJ(11), TES_JML_OBJ(12), TES_JML_OBJ(13), TES_JML_OBJ(14
))


1
2
3
4
5
6
7
8
9
10
11
12
13
14
SQL>
2
  1. Your execute immediate will return only one value, the count, so what is there to loop over?
  2. Also I'm not sure that execute immediate works with an implicit cursor.
  3. In your SQL it looks like you don't have a space after the from keyword.

Try something like this instead:

create or replace function jumlahBaris(namatabel varchar)
return tes_jml_table
is
  tabel tes_jml_table := tes_jml_table();
  the_count integer;
  the_sql varchar(100);
begin
  the_sql := 'select count(*) as jumlah from ' || namatabel;
  execute immediate the_sql INTO the_count;

  if the_count IS NOT NULL THEN
      tabel.extend;
      tabel(1) := tes_jml_obj(the_count);
  end if;
  return tabel;
end;
4
  • my bad again, thanks for reminding me :) but the errors still the same, and there's a red underline between "execute" and "immediate" after i run it. Do you think that's the error?
    – thekucays
    Commented Apr 30, 2015 at 4:41
  • hmm.. i tried to replace the "for loop" with "if", but still no luck :(
    – thekucays
    Commented Apr 30, 2015 at 4:47
  • See my update. I'm definitely thinking the cursor may have problems working with the execute immediate.
    – DWright
    Commented Apr 30, 2015 at 4:48
  • Works like a charm!! Thanks! But you missed the "end if" there :)
    – thekucays
    Commented Apr 30, 2015 at 5:56

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.