anonymous block completed in oracle SQL - oracle

Whilst trying to create a query cursor as follows:
DECLARE CURSOR Query1
IS
SELECT * FROM RACE
WHERE Race_Time='22-SEP-14 12.00.00.000000000';
BEGIN
OPEN Query1;
END;
I get the following error. anonymous block completed. Does anyone know how to fix this? I tried setting the
'SET SERVEROUTPUT ON;'
before the declare but this did not seem to fix the error. Thanks in advance!

It seems that dbms_output is turned off
you can see you out put if you put SET SERVEROUTPUT ON; in the beginning of your script.
or you can view dbms_output window (View then DBMS Output) then press the "+" at the top of the Dbms Output window and then select an open database

"anonymous block completed" means your PL/SQL code was successfully executed.
To Display: try using a output statement...
For example:
BEGIN
dbms_output.put_line ('Hello, world!');
END;

If you want to control the process in PL/SQL, you could do something like
DECLARE
l_race_rec race%rowtype;
CURSOR Query1
IS
SELECT *
FROM RACE
WHERE Race_Time='22-SEP-14 12.00.00.000000000';
BEGIN
OPEN Query1;
LOOP
FETCH query1 INTO l_race_rec;
EXIT WHEN query1%notfound;
dbms_output.put_line( l_race_rec.column1 || ' ' || l_race_rec.column2 || ... || l_race_rec.columnN );
END LOOP;
CLOSE Query1;
END;
Unless your assignment requires the use of explicit cursors, though, implicit cursors are likely easier to use
BEGIN
FOR x IN( SELECT *
FROM RACE
WHERE Race_Time='22-SEP-14 12.00.00.000000000')
LOOP
dbms_output.put_line( x.column1 || ' ' || x.column2 || ... || x.columnN );
END LOOP;
END;
If you are using SQL*Plus, you can also do something like
VAR rc REFCURSOR;
BEGIN
OPEN :rc
FOR SELECT *
FROM race
WHERE race_time = '22-SEP-14 12.00.00.000000000';
END;
PRINT rc
If race_time is really a timestamp, you should really be comparing a timestamp with another timestamp rather than comparing a timestamp to a string. Use explicit conversion with an explicit format mask to avoid errors due to different sessions having different NLS settings
WHERE race_time = to_timestamp( '22-SEP-14 12.00.00.000000000',
'DD-MON-RR HH24:MI:SS.FF9' )
Of course, I'm not sure why you would use a timestamp in the first place here-- it seems unlikely that you really know the nanosecond at which a race started.

Related

How to call a stored procedure in pl/sql developer

I am new at this and have a simple question.
I have created a procedure like so in pl/sql developer
CREATE OR REPLACE PROCEDURE myproc2 AS
BEGIN
SELECT cd_desc des, cd_value cd FROM v_codes WHERE cd_type='CVS02'
END;
Now I want to call the procedure and see the output however when I run this
BEGIN
myproc2;
END;
in Pl/sql I am getting an error saying object myproc2 is invalid
How do I call a stored procedure in PL/SQL?
You're calling it right, but the procedure is wrong. If you check its status, it is invalid.
In PL/SQL, a SELECT requires INTO:
CREATE OR REPLACE PROCEDURE myproc2 AS
l_cd_desc v_codes.cd_desc%type;
l_cd_value v_codes.cd_value%type;
BEGIN
SELECT v.cd_desc, v.cd_value
INTO l_cd_desc, l_cd_value
FROM v_codes v
WHERE v.cd_type = 'CVS02';
END;
Beware of possible NO_DATA_FOUND or TOO_MANY_ROWS exception.
Also, although it'll now run OK (I guess), you won't see anything because it is unknown what you'll do next. You could, for example, choose to display values you fetched. In that case, add
<snip>
WHERE v.cd_type = 'CVS02';
dbms_output.put_line(l_cd_desc ||', '|| l_cd_value);
END;
Don't forget to enable serveroutput.
As you commented, you got too_many_rows. How to handle it? It depends on what you want to do. One option is to switch to a cursor FOR loop; now you don't need local variables and - as there's no SELECT statement itself - no INTO clause either:
CREATE OR REPLACE PROCEDURE myproc2
AS
BEGIN
FOR cur_r IN (SELECT v.cd_desc, v.cd_value
FROM v_codes v
WHERE v.cd_type = 'CVS02')
LOOP
DBMS_OUTPUT.put_line (cur_r.cd_desc || ', ' || cur_r.cd_value);
END LOOP;
END;
One great thing about Oracle SQL Developer is the GUI and that it does things for you.
You can open a sheet and run it the traditional way:
BEGIN
PROCEDURENAME(PARAM);
END;
or you can use the GUI, find the object with the (View->) Find DB object, find it, click on it and use the green arrow in the toolbar. It will open a UI for any parameters you used within the procedure.
In SQL Developer, if you want to see the output then you can return a cursor:
CREATE OR REPLACE PROCEDURE myproc2(
o_cursor OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN o_cursor FOR
SELECT cd_desc AS des,
cd_value AS cd
FROM v_codes
WHERE cd_type='CVS02'; -- You need a ; statement terminator here.
END;
/
Then you can use:
-- Declare a cursor bind variable
VARIABLE cur SYS_REFCURSOR;
BEGIN
-- Call the cursor outputting into the bind variable.
myproc2(:cur);
END;
/
-- Print the cursor
PRINT :cur;
And run it as a script (using F5).

My long time SQL*Plus loop doesn't print DBMS_OUTPUT.PUT_LINE output during execution

I know that in order to print something on sqlplus like below:
begin
dbms_output.put_line('Hello!');
end;
/
I need to call
set serveroutput on;
before that.
I also know that is not needed, but I can also call
DBMS_OUTPUT.enable;
before, just in case. This is working for me.
But what if I want to keep printing the progress of a long loop? It seems impossible to me. I've tried everything to print some progress on the loop below but just doesn't work. Is there some way of doing that? I even tried to spool to a file and didn't work.
Note 1: I can't truncate or partition this table as the DBA doesn't want to help me with that, so I have to use this nasty loop...
Note 2: I've noticed that once the loop is done, the whole output is printed. Looks like oracle is buffering the output and printing everything at the end. I'm not sure how to avoid that and print on every loop iteration.
set serveroutput on;
declare
e number;
i number;
nCount number;
f number;
begin
DBMS_OUTPUT.enable;
dbms_output.put_line('Hello!');
select count(*) into e from my_big_table where upd_dt < to_date(sysdate-64);
f :=trunc(e/10000)+1;
for i in 1..f
loop
delete from my_big_table where upd_dt < to_date(sysdate-64) and rownum<=10000;
commit;
DBMS_OUTPUT.PUT_LINE('Progress: ' || to_char(i) || ' out of ' || to_char(f));
end loop;
end;
Thank you for any answer.
There are 2 standard ways for such things:
set module and action in your session DBMS_APPLICATION_INFO.SET_MODULE:
SQL> exec DBMS_APPLICATION_INFO.SET_MODULE('my_long_process', '1 from 100');
PL/SQL procedure successfully completed.
SQL> select action from v$session where module='my_long_process';
ACTION
----------------------------------------------------------------
1 from 100
set session_longops:
DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS
I'd recommend it in your case since that is exactly designed for long operations.
Example on Oracle-Base.
----
PS: dbms_output,put_line saves all output in a collection (nested table) variable of dbms_output package, so you can't get it from another session and client can't get it during user call (execution). In addition to set serveroutput on you can also get the output using dbms_output.get_lines: http://orasql.org/2017/12/10/sqlplus-tips-8-dbms_output-without-serveroutput-on/
Btw, in case if you need to filter or analyze output from dbms_output, sometimes it's convenient to get output in a query, so you can use filter strings in where clause or aggregate them: https://gist.github.com/xtender/aa12b537d3884f4ba82eb37db1c93c25
DBMS_OUTPUT will only ever be displayed after the PL/SQL code has terminated and control has returned to the calling program.
Output is, as you found, buffered. When your PL/SQL code finishes, then the calling program (e.g. SQL*Plus) can go and fetch that output.
Insert into another table, maybe call it "MYOUTPUT".
Create the table:
create table myoutput (lineno number, outline varchar2(80));
Add this after your delete:
insert into MYOUTPUT values (i,'Progress: ' || to_char(i) || ' out of ' || to_char(f));
Then select from MYOUTPUT periodically to see progress.
select outline from myoutput order by lineno;
Bobby
You can use UTL_FILE to write output to an external file, as in:
DECLARE
fh UTL_FILE.FILE_TYPE;
nRow_count NUMBER := 0;
BEGIN
fh := UTL_FILE.FOPEN('DIRECTORY_NAME', 'some_file.txt', 'w');
FOR aRow IN (SELECT *
FROM SOME_TABLE)
LOOP
nRow_count := nRow_count + 1;
IF nRow_count MOD 1000 = 0 THEN
UTL_FILE.PUT_LINE(fh, 'Processing row ' || nRow_count);
UTL_FILE.FFLUSH(fh);
END IF;
-- Do something useful with the data in aRow
END LOOP; -- aRow
UTL_FILE.FCLOSE_ALL; -- Close all open file handles, including
-- the ones I've forgotten about...
END;

how do I use if condition in cursor because our professor don't allow us use where clause in the select statement

Our question is showing all the countries that have names that are exactly 5 letter long. This is the cursor code and I want add if condition into it.
declare
cursor cursor_full is select * from country_cont;
begin
for counter in cursor_full
loop
dbms_output.put_line(counter.country|| ' ' || counter.continent);
end loop;
end;
However my professor said that you can't using where clause within the select statement and you should display all the countries and continent.
so i tried this code:
declare
country varchar(50);
cursor cursor_full is select * from country_cont;
begin
if length(country)=5 then
for counter in cursor_full
loop
dbms_output.put_line(counter.country|| ' ' || counter.continent);
end loop;
end if;
end;
the script output show that PL/SQL procedure successfully completed but nothing return in DBMS output
Hope someone can help me, I spent whole night to think about it,please!
Variable country doesn't contain any value, it is null so if condition is never true and loop is never executed. Sample data would help; meanwhile, see if this helps.
begin
for cur_r in (select * from country_cont) loop
if length(cur_r.country) > 5 then
dbms_output.put_line(cur_r.country|| ' ' || cur_r.continent);
end loop;
end;
Don't forget to set serveroutput on.

How to create an alias from an select result in oracle?

I want to create an alias from an select result.I've tried to use oracle dynamic query but doesn't working.Here is my sql:
declare
v_a varchar2(50);
sql_smt varchar2(200);
begin
select TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd')) INTO v_a from dual;
sql_smt :='SELECT sysdate as :1 FROM dual';
execute immediate sql_smt using v_a;
end;
I want to reach to an result like in the photo.
Thanks for any help!
As you've tagged this for SQL Developer you could use (ab)use substitution variables for this; in your worksheet do:
column x_title new_value y_title noprint;
select TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd'))
as x_title
from dual;
set verify off
select sysdate as "&y_title" from dual;
which when you run as a script (F5) produces this in the Script Output window:
<blank lines ...>
#20190126-
----------
2019-02-25
and then if you run the last line again as a statement (control-enter) the Query Result window shows it as you wanted, from the image in your question.
You could also use the column command which makes the output in the Script Output closer to what you wanted when run as a script:
column sysdate heading &y_title
select sysdate from dual;
#20190126-20190227
------------------
2019-02-25
but then when run as a statement the Query Results window doesn't honour that heading.
Note that this is all client-specific functionality, not SQL - it will work in SQL Developer, and the script versions will work in SQL*Plus and SQLcl, but not in other clients (unless they have tried to feature-match SQL*Plus to some extent).
If you aren't only going to be viewing the results in one of those clients but actually want to end up, say, pulling them into an application over JDBC or whatever, then other solutions would be more appropriate. Generating a ref cursor with the column as the name you want would be fairly simple. But that's not what you've asked for...
OK, since you asked in a comment, you can open a ref cursor in an anonymous block:
var rc refcursor
declare
l_alias varchar2(50);
begin
select TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd'))
into l_alias
from dual;
open :rc for 'SELECT sysdate as "' || l_alias || '" FROM dual';
end;
/
PL/SQL procedure successfully completed.
print rc
#20190127-
----------
2019-02-26
or without the local variable:
var rc refcursor
begin
open :rc for 'SELECT sysdate as "'
|| TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd'))
|| '" FROM dual';
end;
/
PL/SQL procedure successfully completed.
print rc;
#20190127-
----------
2019-02-26
Again var[iable] and print are client-specific commands; and I don't think there's a way to get the results in the Query Results grid with this approach. But you can use the same anonymous block approach from other clients or applications; e.g. from JDBC you could have a statement as:
String sql = "begin open ? for 'SELECT sysdate as \"'"
+ "|| TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd'))"
+ "|| '\" FROM dual'; end;";
and then bind the ? parameter placeholder as a cursor type before executing. That probably isn't very useful though as you'd have to examine the metadata to find the column alias anyway, and you could generate it on the application side using the application language tools (e..g Java date manipulation).
You could also create a function that returns a ref cursor, which you could then call from a plain query (instead of an anonymous block), which would allow you to see it in the Query Results grid - possibly with an extra step to show the cursor result. But you made not need that extra level of code or want another object to be created in your DB.
Would something like this work?
declare
col_hdr varchar2(50);
sys_date varchar2(26);
sql_smt varchar2(200);
begin
select TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd')) INTO col_hdr from dual;
sql_smt :='SELECT sysdate ' || ' as "' || col_hdr || '" FROM dual';
dbms_output.put_line(sql_smt);
execute immediate sql_smt into sys_date;
dbms_output.put_line('done');
end;

How to fetch values from cursor into variables?

I have problems fetching values from cursor into variables:
create or replace
procedure projectinfo(num clubs.clubid%type)
as
--identify variables
p_cln clubs.clubname%type;
p_projn projects.projectname%type;
p_projnum number;
p_taskn tasks.taskname%type;
p_tasknum number;
cursor cur is
select c.clubname, p.projectname, t.taskname
from clubs c join projects p on c.clubid=p.clubid
join tasks t on t.projectid=p.projectid
where c.clubid=num;
--I have checked the above cursor and it's worked fine!!!
begin
p_projnum:=0;
p_tasknum:=0;
open cur;
loop
fetch cur into p_cln,p_projn, p_taskn;
dbms_output.put_line(p_cln|| ' ' ||p_projn|| ' ' || p_taskn);
-- the above command does not print variable values!!!
exit when cur%notfound;
p_projnum:=p_projnum+1;
dbms_output.put_line(' ************************ ');
dbms_output.put_line(' club name : ' ||p_cln);
dbms_output.put_line( ' project ' ||p_projnum|| ' ' || p_projn);
loop
p_tasknum:=p_tasknum+1;
dbms_output.put_line('Task: ' ||p_tasknum|| ' ' || p_taskn);
fetch cur into p_cln,p_projn, p_taskn;
exit when cur%notfound;
end loop;
end loop;
close cur;
end projectinfo;
I have checked my cursor and itdoes contain all values that I need. My programm compiles FINE but does not print any output!!!
What tool are you using to run your procedure? By default, most tools will not allocate a buffer for dbms_output to write to and will not display anything written to dbms_output. That's why you'd never depend on dbms_output for any real code.
If you are using SQL*Plus, you need to enable serveroutput before executing your procedure
SQL> set serveroutput on;
SQL> exec projectinfo( <<some number>> );
If you are using a GUI, the GUI will almost certainly have a way to enable dbms_output. But that will be very different for different applications. In SQL Developer, for example, you'd need to ensure that the DBMS Output window is visible, click the green "plus sign" icon, and choose your connection to enable dbms_output.

Resources