Reputation: 129
I'm using Oracle SQL developer and I want to create a procedure to print the result of this SQL code:
SELECT Title , Name
FROM BOOK, BORROWER, BOOK_LOANS
WHERE Due_date = SYSDATE AND Return_date = NULL;
Here's my code. I keep getting "SQL statement ignored, statement ignored, LOOP index variable 'books' is invalid". Please tell me what I am missing here. I tried moving the SQL statement to a cursor, but it also doesn't work.
CREATE OR REPLACE PROCEDURE overdueToday IS
BEGIN
FOR books IN (SELECT Title , Name
FROM BOOK, BORROWER, BOOK_LOANS
WHERE Due_date = SYSDATE
AND Return_date = NULL)
LOOP
DBMS_OUTPUT.put_line(books.Title || ' -- ' || books.Name);
END LOOP;
END overdueToday;
/
Upvotes: 0
Views: 1758
Reputation: 2118
This is the simple way to loop in select statement:
CREATE OR REPLACE PROCEDURE overdueToday IS
CURSOR book_cur is
SELECT Title , Name
FROM BOOK, BORROWER, BOOK_LOANS
WHERE Due_date = SYSDATE
AND Return_date = NULL;
BEGIN
FOR book_rec IN book_cur loop
DBMS_OUTPUT.put_line(book_rec .Title || ' -- ' || book_rec .Name);
END LOOP;
END overdueToday;
Upvotes: 0
Reputation: 15094
If you're using SQL Developer, you can just run your query (hit F5 or Ctrl+Enter). You don't need to write a PL/SQL program.
That being said, your query is almost certainly wrong since you have three tables and no join conditions for them. But you should still get some output.
Upvotes: 0
Reputation: 31648
Oracle 12c and above, you may use DBMS_SQL.RETURN_RESULT
. You require proper join conditions and aliases in your query, which we are not aware of.
CREATE OR replace PROCEDURE OverdueToday
IS
rc SYS_REFCURSOR;
BEGIN
OPEN rc FOR
SELECT title, -- b.title ?
name -- br.name ?
FROM book b
join borrower br
ON ( 1 = 1 ) --Add proper join condition here
join book_loans bl
ON ( 1 = 1 ) --Add proper join condition here
WHERE due_date = TRUNC(SYSDATE)
AND return_date IS NULL;
DBMS_SQL.RETURN_RESULT(rc);
END overduetoday;
/
Upvotes: 0
Reputation: 142705
Apart from what you've already been told (cross-join), WHERE condition won't work. SYSDATE
is a function that returns both date and time, so there's no chance that it'll return anything. You should use TRUNC
function.
Moreover, when dealing with NULL values, they aren't "equal" (=) to anything - you should use IS NULL
(or IS NOT NULL
, depending on what you do).
The following example is kind of stupid; you didn't provide test case so I'm creating my own tables with absolutely minimal column set, just to be sure that the procedure won't fail.
SQL> create table book (title varchar2(20));
Table created.
SQL> create table borrower (name varchar2(20));
Table created.
SQL> create table book_loans (due_date date, return_date date);
Table created.
SQL>
SQL> insert into book values ('Pinky');
1 row created.
SQL> insert into borrower values ('Littlefoot');
1 row created.
SQL> insert into book_loans values (trunc(sysdate), null);
1 row created.
SQL>
The procedure; I marked places you should pay attention to:
SQL> set serveroutput on;
SQL> create or replace procedure overduetoday
2 is
3 begin
4 for books in ( select title,
5 name
6 from book,
7 borrower,
8 book_loans
9 where due_date = trunc(sysdate) --> trunc!
10 and return_date is null --> is!
11 ) loop
12 dbms_output.put_line(books.title ||' -- '|| books.name);
13 end loop;
14 end overduetoday;
15 /
Procedure created.
SQL>
SQL> exec overduetoday;
Pinky -- Littlefoot
PL/SQL procedure successfully completed.
SQL>
As you can see, it works (or, should I rather say, *doesn't fail". If there were more rows in those tables, the result would be really wrong).
Errors you mentioned can't be raised with code you posted. That's why it is important to post exactly what you do, just as I did. Doing so, there's no doubt in what you have, what you did and how Oracle responded. Anything else is just a matter of speculation.
Upvotes: 2