sqloracle-databaseplsqlora-00933pls-00103

Oracle Statement doesn't work when put in a procedure


I am new to Oracle and experiencing this problem.

I created a procedure like this:

CREATE OR REPLACE PROCEDURE getArt 
as
begin
    select ar.artTitle, ar.artContent, ar.DateCreated, ar.artCategory, ac.accName 
      from hng_art ar 
           join HNG_ACCOUNTS ac 
             on ar.accNo = ac.accNo 
     order by ar.artNo desc
end getArt;

I tried to run the SELECT statement independently and it worked. However, when I put it in a procedure. I didn't work; Here are the errors:

Errors for "GETART"

ERROR at line 4: PL/SQL: SQL Statement ignored
ERROR at line 4: PL/SQL: ORA-00933: SQL command not properly ended
ERROR at line 5: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:     ; 

thank you


Solution

  • Several errors.

    At the moment, the compiler is objecting to the fact that you are missing a semicolon after your select statement. Every statement in PL/SQL needs to be terminated with a semicolon.

    Once you fix that, you'll get an error because a stored procedure cannot simply execute a select statement. It has to do something with the results. If you know that your query will always return exactly one row, you could declare some local variables and do a select into to populate those variables. I'm guessing, however, that your query might return more than 1 row. You could write a for loop in your procedure, iterate through the results, and do something with the rows. Or you could declare your procedure to have an OUT parameter of type SYS_REFCURSOR, open a cursor for your query, and return that cursor to the caller. If you're on 12.1 or later, Oracle has introduced a bit of syntactic sugar so that a procedure can return a result without declaring such an OUT parameter but I'm guessing that's probably not the situation you're in.

    Syntactically, you could do something like

    CREATE OR REPLACE PROCEDURE getArt( p_rc OUT sys_refcursor )
    as
    begin
      open p_rc
       for  
        select ar.artTitle, ar.artContent, ar.DateCreated, ar.artCategory, ac.accName 
          from hng_art ar 
               join HNG_ACCOUNTS ac 
                 on ar.accNo = ac.accNo 
         order by ar.artNo desc;
    end getArt;
    

    While that is legal, however, it is not particularly idiomatic. If you have code that is just executing a select statement, it would generally make much more sense to create a view rather than a stored procedure. If you are doing a large amount of PL/SQL processing of the results before returning them, a pipelined table function might make sense.