tags:

views:

247

answers:

3

Here is my simple PL/SQL program:

DECLARE

    CURSOR c1 is
        SELECT typ, specifikacia_typu, spz FROM Auta
            WHERE (substr(spz, 1, 2) = 'KE' OR substr(spz, 1, 2) = 'KS') AND ROWNUM <= 2;
    CURSOR c2 is
        SELECT typ, specifikacia_typu, spz FROM Auta
            WHERE substr(spz, 1, 2) <> 'KE' AND substr(spz, 1, 2) <> 'KS';
    my_typ CHAR(10);
    my_specifikacia_typu CHAR(15);
    my_spz CHAR(8);

BEGIN

    -- vytovirt potrebne tabulky pre kosicke a nekosicke auta
    CREATE TABLE Kosicke (
    typ CHAR(10),
    specifikacia_typu CHAR(15),
    spz CHAR(8)
    );
    CREATE TABLE Ostatne (
    typ CHAR(10),
    specifikacia_typu CHAR(15),
    spz CHAR(8)
    );

    -- prve dve auta z Kosic vlozit do tabulky Kosicke
    OPEN c1;
    FOR i IN 1..2 LOOP
        FETCH c1 INTO my_typ, my_specifikacia_typu, my_spz;
        EXIT WHEN c1%NOTFOUND;
        INSERT INTO Kosice VALUES(my_typ, my_specifikacia_typu, my_spz);
        COMMIT;
    END LOOP;
    CLOSE c1;

    -- auta, ktore nie su z Kosic vlozit do tabulky Ostatne
    OPEN c2;
    LOOP
        FETCH c2 INTO my_typ, my_specifikacia_typu, my_spz;
        EXIT WHEN c2%NOTFOUND;
        INSERT INTO Ostatne VALUES(my_typ, my_specifikacia_typu, my_spz);
        COMMIT;
    END LOOP;
    CLOSE c1;

END;
/

When I run it Oracle 10g Express Edition, I get this error:

ORA-06550: line 16, column 5:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:

   begin case declare exit for goto if loop mod null pragma
   raise return select update while with 
     <<
   close current delete fetch lock insert open rollback
   savepoint set sql execute commit forall merge pipe

1. DECLARE
2.     
3.     CURSOR c1 is

I'm not sure where the problem is and this is my first program I wrote in PL/SQL so I'm a little lost. I have used this example programs from Oracle website to write this program: http://download.oracle.com/docs/cd/B10501%5F01/appdev.920/a96624/a%5Fsamps.htm#563

EDIT:

Also, when I create the tables outside the program first and then run the program, I get this error:

ORA-06550: line 17, column 21:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 17, column 9:
PL/SQL: SQL Statement ignored

1. DECLARE    
2.     CURSOR c1 is
3.         SELECT typ, specifikacia_typu, spz FROM Auta

Which doesn't make sense because table "Auta" exists, all tables used in the program do exist.

+3  A: 

You cannot perform DDL like CREATE TABLE directly in PL/SQL. However, you can do it using dynamic PL/SQL like this:

-- vytovirt potrebne tabulky pre kosicke a nekosicke auta
EXECUTE IMMEDIATE 'CREATE TABLE Kosicke (
typ CHAR(10),
specifikacia_typu CHAR(15),
spz CHAR(8)
)';

Your inserts will also need to be dynamic, since the tables don't exist at compile time and so the code isn't valid:

EXECUTE IMMEDIATE 'INSERT INTO Ostatne VALUES(:p1, :p2, :p3)'
   USING my_typ, my_specifikacia_typu, my_spz;

It would be interesting to know why you need to do this, though: there is almost never any need to create tables "on the fly" in Oracle and it isn't generally a good idea to do so.

Tony Andrews
+4  A: 

Aside from your syntax issue, which Tony has explained, this code ought to just be straight SQL inserts without any cursors. If you really did need a cursor then try to use an implicit one before using an explicit one.

David Aldridge
The cursors are there for SELECT queries. I have already solved this problem myself, I have posted the working program.
Richard Knop
A: 

Ok, so just to let you know how I solved the problem (I have already solved it before anyone aswered).

First, I created the tables outside of the program with a normal SQL queries:

CREATE TABLE Kosicke (
typ CHAR(10),
specifikacia_typu CHAR(15),
spz CHAR(8)
);
CREATE TABLE Ostatne (
typ CHAR(10),
specifikacia_typu CHAR(15),
spz CHAR(8)
);

And I edited the program like this (it works already):

DECLARE

    CURSOR c1 is
        SELECT typ, specifikacia_typu, spz FROM Auta
            WHERE (substr(spz, 1, 2) = 'KE' OR substr(spz, 1, 2) = 'KS') AND ROWNUM <= 2;
    CURSOR c2 is
        SELECT typ, specifikacia_typu, spz FROM Auta
            WHERE substr(spz, 1, 2) <> 'KE' AND substr(spz, 1, 2) <> 'KS';
    my_typ CHAR(10);
    my_specifikacia_typu CHAR(15);
    my_spz CHAR(8);

BEGIN

    /* prve dve auta z Kosic vlozit do tabulky Kosicke */
    OPEN c1;
    FOR i IN 1..2 LOOP
        FETCH c1 INTO my_typ, my_specifikacia_typu, my_spz;
        EXIT WHEN c1%NOTFOUND;
        INSERT INTO Kosicke VALUES(my_typ, my_specifikacia_typu, my_spz);
        COMMIT;
    END LOOP;
    CLOSE c1;

    /* auta, ktore nie su z Kosic vlozit do tabulky Ostatne */
    OPEN c2;
    LOOP
        FETCH c2 INTO my_typ, my_specifikacia_typu, my_spz;
        EXIT WHEN c2%NOTFOUND;
        INSERT INTO Ostatne VALUES(my_typ, my_specifikacia_typu, my_spz);
        COMMIT;
    END LOOP;
    CLOSE c2;

END;
/
Richard Knop
It works, but it is still the wrong approach. The explicit cursors are an unnecessary overhead, and the in-loop COMMIT statements can cause ORA-1002 exceptions. You will get away with it when you are only inserting two rows, but not with larger volumes.
APC
APC and other posters are right, not quite sure why you'd use 2 cursors like this in what can be done as 2 insert statements. If you're still following the thread Richard...whats wrong with just doing : insert into ostane (SELECT typ, specifikacia_typu, spz FROM Auta WHERE substr(spz, 1, 2) <> 'KE' AND substr(spz, 1, 2) <> 'KS'; ) then repeat for the other table you have. Any reason why you'd need those cursors?
M.E.