DBMS_OUTPUT.PUT_LINE not printing - plsql

When executing the following code, it just says the procedure is completed and doesn't print the infomation i want it to (firstName, lastName) and then the other values from the select query in a table below.
CREATE OR REPLACE PROCEDURE PRINT_ACTOR_QUOTES (id_actor char)
AS
CURSOR quote_recs IS
SELECT a.firstName,a.lastName, m.title, m.year, r.roleName ,q.quotechar from quote q, role r,
rolequote rq, actor a, movie m
where
rq.quoteID = q.quoteID
AND
rq.roleID = r.roleID
AND
r.actorID = a.actorID
AND
r.movieID = m.movieID
AND
a.actorID = id_actor;
BEGIN
FOR row IN quote_recs LOOP
DBMS_OUTPUT.PUT_LINE('a.firstName' || 'a.lastName');
end loop;
END PRINT_ACTOR_QUOTES;
/
When setting server output on, I get
a.firstNamea.lastName
a.firstNamea.lastName
a.firstNamea.lastName
a.firstNamea.lastName
multiple times!

What is "it" in the statement "it just says the procedure is completed"?
By default, most tools do not configure a buffer for dbms_output to write to and do not attempt to read from that buffer after code executes. Most tools, on the other hand, have the ability to do so. In SQL*Plus, you'd need to use the command set serveroutput on [size N|unlimited]. So you'd do something like
SQL> set serveroutput on size 30000;
SQL> exec print_actor_quotes( <<some value>> );
In SQL Developer, you'd go to View | DBMS Output to enable the DBMS Output window, then push the green plus icon to enable DBMS Output for a particular session.
Additionally, assuming that you don't want to print the literal "a.firstNamea.lastName" for every row, you probably want
FOR row IN quote_recs
LOOP
DBMS_OUTPUT.PUT_LINE( row.firstName || ' ' || row.lastName );
END LOOP;

Ensure that you have your Dbms Output window open through the view option in the menubar.
Click on the green '+' sign and add your database name.
Write 'DBMS_OUTPUT.ENABLE;' within your procedure as the first line.
Hope this solves your problem.

Set Query as below at first line
SET SERVEROUTPUT ON

this statement
DBMS_OUTPUT.PUT_LINE('a.firstName' || 'a.lastName');
means to print the string as it is.. remove the quotes to get the values to be printed.So the correct syntax is
DBMS_OUTPUT.PUT_LINE(a.firstName || a.lastName);

For SQL Developer
You have to execute it manually
SET SERVEROUTPUT ON
After that if you execute any procedure with DBMS_OUTPUT.PUT_LINE('info'); or directly .
This will print the line
And please don't try to add this
SET SERVEROUTPUT ON
inside the definition of function and procedure, it will not compile and will not work.

In Oracle SQL Developer, you can follow steps by steps as the below image:

I am using Oracle SQL Developer,
In this tool, I had to enable DBMS output to view the results printed by dbms_output.put_line
You can find this option in the result pane where other query results are displayed.
so, in the result pane, I have 7 tabs. 1st tab named as Results, next one is Script Output and so on. Out of this you can find a tab named as "DBMS Output" select this tab, then the 1st icon (looks like a dialogue icon) is Enable DBMS Output. Click this icon. Then you execute the PL/SQL, then select "DBMS Output tab, you should be able to see the results there.

All of them are concentrating on the for loop but if we use a normal loop then we had to use of the cursor record variable. The following is the modified code
CREATE OR REPLACE PROCEDURE PRINT_ACTOR_QUOTES (id_actor char)
AS
CURSOR quote_recs IS
SELECT a.firstName,a.lastName, m.title, m.year, r.roleName ,q.quotechar from quote q, role r,
rolequote rq, actor a, movie m
where
rq.quoteID = q.quoteID
AND
rq.roleID = r.roleID
AND
r.actorID = a.actorID
AND
r.movieID = m.movieID
AND
a.actorID = id_actor;
recd quote_recs%rowtype;
BEGIN
open quote_recs;
LOOP
fetch quote_recs into recs;
exit when quote_recs%notfound;
DBMS_OUTPUT.PUT_LINE(recd.firstName||recd.lastName);
end loop;
close quote_recs;
END PRINT_ACTOR_QUOTES;
/

Related

A cursor in a function - MariaDB

I have a task to use cursor to write a function that receives a movie title and then returns pay of actors involved in this movie.
I wrote something like this:
DELIMITER $$
CREATE FUNCTION getPay(movieTitle varchar(90))
RETURNS int;
BEGIN
DECLARE P int;
DECLARE done int DEFAULT FALSE;
DECLARE payCursor CURSOR FOR
(SELECT A.pay FROM actors A JOIN movie M ON M.id=A.movie WHERE M.title=movieTitle);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN payCursor;
loop_read : LOOP
FETCH payCursor INTO P;
IF done THEN
LEAVE loop_read;
END IF;
RETURN P;
END LOOP;
CLOSE payCursor;
END $$
DELIMITER ;
It's not a secret it's not working. I don't know how to return a set, moreover as I've read it's not possible in MariaDB. I tried to create temporary table but it's not good solution if you want to use this function several times. Also I would like to use this function in another task where I have to write a procedure to pay all the actors. I'm not sure I got the idea of cursors.
That function seems to be getting one (any one) row from the query. This would replace the function:
SELECT A.pay
FROM actors A
JOIN movie M ON M.id=A.movie
WHERE M.title=movieTitle)
LIMIT 1;
Or, since it is a function, get rid of the cursor, and have only that in the function.

APEX 5, change value of select list by button e text

I just start using apex from few time. So I hope you'll forgive me if I ask things that are very simple.
I have a select list populated by a SQL Query, my SQL instruction is SELECT NUM, ID FROM TABLE.
I'd like to change the query dynamically adding a " WHERE NUM LIKE %myVar%", where "MyVar" is the test of a text Item, so I'd like to change the content of the select list pressing the button.
Is it possible?
thanks in advance for any answer.
I find a partial solution. I bind to select list a PL/SQL function returning a SQL Script and I add an text item called filter.
My function is:
declare
q varchar2(4000);
begin
q:='select numero, ';
q:=q||'id from t_doc ';
q:=q||'where numero = :FILTROPT';
return q;
end;
But if I use like with a percent in the function instead of "=", apex raise me an error.
Any suggestion?

PLSQL FOR loop while executing CURSOR

I would like to know if there's any option to iterate a table while performing SELECT values into a CURSOR.
For example:
I have a table TEMP_NUMBERS which contains only numbers (single column).
I have to perform a SELECT from each number in the table (I do not know the amount of rows in the table in advance).
Here is basically what I'm attempting to do. Obviously this does not work, but can I do some kind of a workaround?
I need to SELECT the data into the p_cv_PermsNotifs which is a RETURN REF CURSOR.
IF NOT p_cv_PermsNotifs%ISOPEN THEN OPEN p_cv_PermsNotifs FOR
FOR i IN 1..TEMP_NUMBERS.NUMBER.COUNT LOOP
SELECT DISTINCT
SEC_USER_ROLE.ENTITY_TYP_CODE,
SEC_USER_ROLE.ENTITY_ID
FROM
SEC_USER_ROLE
WHERE
SEC_USER_ROLE.ENTITY_ID = i
END LOOP;
END IF;
Also tried this:
IF NOT p_cv_PermsNotifs%ISOPEN THEN OPEN p_cv_PermsNotifs FOR
SELECT DISTINCT
SEC_USER_ROLE.ENTITY_TYP_CODE,
SEC_USER_ROLE.ENTITY_ID
FROM
SEC_USER_ROLE
WHERE
SEC_USER_ROLE.ENTITY_ID IN
(SELECT * FROM TABLE (lv_ListOfEntities))
END IF;
Where lv_ListOfEntities is table of NUMBER indexed by BINARY INTEGER.
But I'm getting "ORA-22905: cannot access rows from a non-nested table item"
Thanks in advance.
In> Hey if you pass a single number at a time, everytime the refcursor
will be overwritten by the next value. So at the end you will only get
the value for last number in the refcursor. A better way is to use
some basic PL/SQL Bulk COLLECT logic which will give you the desired
output.
Hope this helps
--Creating sql type
CREATE OR REPLACE TYPE lv_num_tab IS TABLE OF NUMBER;
--plsql block
var p_lst refcursor;
DECLARE
lv_num lv_num_tab;
BEGIN
SELECT COL1 BULK COLLECT INTO lv_num FROM TEMP_NUMBERS;
OPEN p_lst FOR
SELECT DISTINCT SEC_USER_ROLE.ENTITY_TYP_CODE,
SEC_USER_ROLE.ENTITY_ID
FROM SEC_USER_ROLE
WHERE SEC_USER_ROLE.ENTITY_ID IN
(SELECT * FROM TABLE(cast(lv_num as lv_num_tab))
);
END;

Passing variable to a Select query in Oracle

I am working on Oracle 11g Db, Having trouble on writing Oracle syntax.
I am trying to pass a number variable to my select query and populate the select query to a cursor.
Declare yr_nr NUMBER;
Begin
yr_nr := 2014;
SELECT DCD.CCY ID, DCD.CCYCDDSC DSC
FROM CCYDCD DCD, CCYEXC EXC
WHERE DCD.CCY = EXC.CCY
AND EXC.YEARNR = yr_nr
End
This select query returns 80 records. How to rewrite this syntax.
Ok, so what you have here is an anonymous block and everything that happens in the block stays in that block. Kinda like Vegas.
In other words there is nothing to handle the result set from your query. When you do this:
declare
[varName] [type]
begin
select foo from bar where column = var ; <--- this has no place to go!
end
When you are at an sqlPlus prompt, sqlPlus has a default record set handler which then processes the returned record set and prints it to the screen.
When you use any third party tool like JDBC or Oracle's own OCI library those provide a record set handler then parse them to you with the appropriate calls to get the data, e.g.:
rs.getInteger([query],[column] ) //which returns the specific value.
That anonymous block is essentially a stored procedure. So you have to have something to do with the result set. This is the cause of the missing "into" error you are getting.
If on the other hand you did something like:
declare
[varName] [type]
result number ;
begin
select count(foo) into result from bar where column = var ;
end
The variable result would have the value of 80 since that is the number of records fetched.
declare
[varName] [type]
cursor thisCursor(p1 in number ) is select foo from bar where column = p1 ;
begin
for rec in thisCursor(varName) loop
If rec.column = [some value] then
doSomething
end if ;
end loop ;
end
Do this would allow you to do something with the result set.

PL/SQL variable scope in nested blocks

I need to run some SQL blocks to test them, is there an online app where I can insert the code and see what outcome it triggers?
Thanks a lot!
More specific question below:
<<block1>>
DECLARE
var NUMBER;
BEGIN
var := 3;
DBMS_OUTPUT.PUT_LINE(var);
<<block2>>
DECLARE
var NUMBER;
BEGIN
var := 200;
DBMS_OUTPUT.PUT_LINE(block1.var);
END block2;
DBMS_OUTPUT.PUT_LINE(var);
END block1;
Is the output:
3
3
200
or is it:
3
3
3
I read that the variable's value is the value received in the most recent block so is the second answer the good one? I'd love to test these online somewhere if there is a possibility.
Also, is <<block2>> really the correct way to name a block??
Later edit:
I tried this with SQL Fiddle, but I get a "Please build schema" error message:
Thank you very much, Dave! Any idea why this happens?
create table log_table
( message varchar2(200)
)
<<block1>>
DECLARE
var NUMBER;
BEGIN
var := 3;
insert into log_table(message) values (var)
select * from log_table
<<block2>>
DECLARE
var NUMBER;
BEGIN
var := 200;
insert into log_table(message) values (block1.var || ' 2nd')
select * from log_table
END block2;
insert into log_table(message) values (var || ' 3rd')
select * from log_table
END block1;
In answer to your three questions.
You can use SQL Fiddle with Oracle 11g R2: http://www.sqlfiddle.com/#!4. However, this does not allow you to use dbms_output. You will have to insert into / select from tables to see the results of your PL/SQL scripts.
The answer is 3 3 3. Once the inner block is END-ed the variables no longer exist/have scope. You cannot access them any further.
The block naming is correct, however, you aren't required to name blocks, they can be completely anonymous.
EDIT:
So after playing with SQL Fiddle a bit, it seems like it doesn't actually support named blocks (although I have an actual Oracle database to confirm what I said earlier).
You can, however, basically demonstrate the way variable scope works using stored procedures and inner procedures (which are incidentally two very important PL/SQL features).
Before I get to that, I noticed three issues with you code:
You need to terminate the insert statements with a semi-colon.
You need to commit the the transactions after the third insert.
In PL/SQL you can't simply do a select statement and get a result, you need to select into some variable. This would be a simple change, but because we can't use dbms_output to view the variable it doesn't help us. Instead do the inserts, then commit and afterwards select from the table.
In the left hand pane of SQL Fiddle set the query terminator to '//' then paste in the below and 'build schema':
create table log_table
( message varchar2(200)
)
//
create or replace procedure proc1 as
var NUMBER;
procedure proc2 as
var number;
begin
var := 200;
insert into log_table(message) values (proc1.var || ' 2nd');
end;
begin
var := 3;
insert into log_table(message) values (var || ' 1st');
proc2;
insert into log_table(message) values (var || ' 3rd');
commit;
end;
//
begin
proc1;
end;
//
Then in the right hand panel run this SQL:
select * from log_table
You can see that proc2.var has no scope outside of proc2. Furthermore, if you were to explicitly try to utilize proc2.var outside of proc2 you would raise an exception because it is out-of-scope.

Resources