DBbeaver PL/SQL why it doesnt use SET SERVEROUTPUT ON? - plsql

THIS WORKS
-- SET SERVEROUTPUT ON
DECLARE
v_num NUMBER := 0;
BEGIN
LOOP
dbms_output.put_line(' v_num : ' || v_num);
v_num := v_num + 1;
EXIT WHEN v_num > 4;
END LOOP;
END;
--/
THIS DOESNT AND I HAVE NO IDEA WHY
SET SERVEROUTPUT ON
DECLARE
v_num NUMBER := 0;
BEGIN
LOOP
dbms_output.put_line(' v_num : ' || v_num);
v_num := v_num + 1;
EXIT WHEN v_num > 4;
END LOOP;
END;
/
I WAS EXPECTING
1
2
3
4

SET SERVEROUTPUT ON
Is a command of SQLPLUS (Oracles "command line tool" to access the DB)
=> It is not SQL that you send to the server. It is used on your client.
As you use a different tool, I assume this is no implemented there...
And for the specific case ( = you want to view dbms_output output) :
There is an output tab in DBeaver where the dbms_output occurs ...

Related

How to create anonymous block in DB2 like as PL/SQL

Oracle PL/SQL Code:
declare
N integer not null := 0;
null_variable exception;
begin
select col1 into N from T;
if N is null then
raise null_variable;
end if;
exception
when null_variable then
dbms_output.put_line('Null variable detected');
end;
For DB2 unable to create.
Place the following to a file q1.sql:
--#SET TERMINATOR #
set serveroutput on#
BEGIN
DECLARE N INT DEFAULT 0;
select col1 into N from T;
IF N IS NULL THEN
CALL dbms_output.put_line ('Null variable detected');
END IF;
END#
set serveroutput off#
Run it:
db2 -f q1.sql
If you like to use an exception handler, then:
BEGIN
DECLARE N INT DEFAULT 0;
DECLARE null_variable CONDITION FOR '75001';
DECLARE EXIT HANDLER FOR null_variable
BEGIN
--DECLARE L_TEXT VARCHAR (32672) DEFAULT '*';
--GET DIAGNOSTICS EXCEPTION 1 L_TEXT = MESSAGE_TEXT;
--CALL dbms_output.put_line ('MSG: ' || L_TEXT);
CALL dbms_output.put_line ('Null variable detected');
END;
select col1 into N from T;
IF N IS NULL THEN
SIGNAL null_variable
SET MESSAGE_TEXT = 'Some message';
END IF;
END#
Refer the Compound SQL (compiled) statement topic for more details.

Loop cursor of ALL_MVIEWS generate PL/SQL Error ORA-06502

i wrote a procedure that deals with writing the contents of the QUERY column of ALL_MVIEWS to a file:
DECLARE
v_out_dir_name VARCHAR2(30) := 'DIR_TEST';
v_out_dir_path VARCHAR2(60);
v_count_object_elab NUMBER := 0;
CURSOR c_mviews IS
SELECT
LOWER(MVIEW_NAME) || '.sql' AS FILE_NAME
, QUERY AS SCRIPT
FROM ALL_MVIEWS
;
v_file UTL_FILE.file_type;
BEGIN
FOR r_mview IN c_mviews LOOP
v_file := UTL_FILE.fopen (v_out_dir_name, r_mview.FILE_NAME, 'w');
UTL_FILE.putf (v_file, r_mview.SCRIPT);
UTL_FILE.fclose (v_file);
v_count_object_elab := v_count_object_elab + 1;
END LOOP;
IF v_count_object_elab = 0
THEN
DBMS_OUTPUT.PUT_LINE('NESSUN FILE ELABORATO');
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERRORE = ' || SQLERRM);
IF UTL_FILE.IS_OPEN (v_file) THEN
UTL_FILE.FCLOSE (v_file);
END IF;
RAISE;
END;
/
But the "FOR r_mview IN c_mviews LOOP" statement generates the following error:
Report error -
ORA-06502: PL/SQL: errore di numero o valore
ORA-06512: a line 35
ORA-06512: a line 16
ORA-06512: a line 16
06502. 00000 - "PL/SQL: numeric or value error%s"
*Cause: An arithmetic, numeric, string, conversion, or constraint error
occurred. For example, this error occurs if an attempt is made to
assign the value NULL to a variable declared NOT NULL, or if an
attempt is made to assign an integer larger than 99 to a variable
declared NUMBER(2).
*Action: Change the data, how it is manipulated, or how it is declared so
that values do not violate constraints.
The error is thrown on a materialized view that has QUERY_LEN = 39000.
How can I solve the problem?
Many thanks in advance.
I don't think you are using UTL_FILE correctly. The putf() procedure is for writing and formatting (using printf() style). Try using just put() instead. I did run your script on my database and it executed fine with putf() and put(), but put() is more appropriate.
Also, beware that QUERY is a LONG. If you have a query over 32k I think you will get the error you are seeing. There are some great write-ups online about how awful LONGs are to work with.
I think easiest thing to do is convert the LONG to CLOB with a CREATE TABLE, read that table and then drop it. Here is a routine to do just that. It will create a copy of all_mviews and convert the query to a CLOB and write that in chunks to a file per view.
DECLARE
v_out_dir_name VARCHAR2(30) := 'MVIEW';
v_count_object_elab NUMBER := 0;
v_cursor SYS_REFCURSOR;
v_file utl_file.file_type;
v_start INTEGER;
v_buffer VARCHAR2(1024);
v_file_name VARCHAR2(1024);
v_query CLOB;
table_or_view_does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT(table_or_view_does_not_exist,
-00942);
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE all_mviews_clob';
EXCEPTION
WHEN table_or_view_does_not_exist THEN
NULL;
END;
EXECUTE IMMEDIATE 'CREATE TABLE all_mviews_clob AS SELECT mview_name, to_lob(query) AS query FROM all_mviews';
OPEN v_cursor FOR q'[SELECT lower(mview_name) || '.sql' AS file_name,
query AS script
FROM all_mviews_clob]';
LOOP
FETCH v_cursor
INTO v_file_name,
v_query;
EXIT WHEN v_cursor%NOTFOUND;
v_file := utl_file.fopen(location => v_out_dir_name,
filename => v_file_name,
open_mode => 'w');
v_start := 1;
FOR i IN 1 .. ceil(dbms_lob.getlength(lob_loc => v_query) / 1024)
LOOP
v_buffer := dbms_lob.substr(lob_loc => v_query,
amount => 1024,
offset => v_start);
IF v_buffer IS NOT NULL THEN
utl_file.put(file => v_file,
buffer => v_buffer);
utl_file.fflush(file => v_file);
END IF;
v_start := v_start + 1024;
END LOOP;
utl_file.fclose(v_file);
v_count_object_elab := v_count_object_elab + 1;
END LOOP;
IF v_count_object_elab = 0 THEN
dbms_output.put_line('no mviews');
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('eror = ' || SQLERRM);
IF utl_file.is_open(v_file) THEN
utl_file.fclose(v_file);
END IF;
RAISE;
END;
/

PLSQL Loop Through 100 Row at a time to delete

I tried below code to fetch the 1000 rows and loop through to delete 100 row at a time.
DECLARE
COUNTER INTEGER :=0;
v_delstr varchar2(2000);
v_countstr varchar2(2000);
SchemaName Varchar2(40):='Staging';
TableName Varchar2(100):='History';
BEGIN
LOOP
COUNTER := COUNTER + 1;
DBMS_OUTPUT.PUT_LINE('Counter: ');
v_delstr:= 'Delete FROM ' ||SchemaName ||'.'||TableName|| ' where rownum <= 1000 And startdate>=sysdate-731 and startdate<=sysdate-730';
execute immediate v_delstr;
dbms_output.put_line(v_delstr);
v_countstr:= 'BEGIN
DECLARE CANT INTEGER;
SELECT COUNT(*) INTO CANT FROM ' ||SchemaName ||'.'||TableName|| ' where rownum <= 1000 And startdate>=sysdate-731 and startdate<=sysdate-730;
EXIT WHEN CANT <= 100;
COMMIT;
END;';
execute immediate v_countstr;
dbms_output.put_line(v_countstr);
--dbms_output.put_line(v_delstr);
--dbms_output.put_line(v_countstr);
END LOOP;
END;
DECLARE
COUNTER INTEGER :=0;
v_delstr varchar2(2000);
v_countstr varchar2(2000);
SchemaName Varchar2(40):='Staging';
TableName Varchar2(100):='History';
BEGIN
LOOP
COUNTER := COUNTER + 1;
DBMS_OUTPUT.PUT_LINE('Counter: ');
v_delstr:= 'Delete FROM ' ||SchemaName ||'.'||TableName|| ' where rownum <= 10 And startdate>=sysdate-731 and startdate<=sysdate-730';
execute immediate v_delstr;
dbms_output.put_line(v_delstr);
v_countstr:= 'BEGIN
DECLARE CANT INTEGER;
SELECT COUNT(*) INTO CANT FROM ' ||SchemaName ||'.'||TableName|| ' where rownum <= 10 And startdate>=sysdate-731 and startdate<=sysdate-730;
EXIT WHEN CANT <= 1;
COMMIT;
END;';
execute immediate v_countstr;
dbms_output.put_line(v_countstr);
--dbms_output.put_line(v_delstr);
--dbms_output.put_line(v_countstr);
END LOOP;
END;
Got Error
Error report -
ORA-06550: line 3, column 23:
PLS-00103: Encountered the symbol "SELECT" when expecting one of the following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
exists prior
The symbol "begin" was substituted for "SELECT" to continue.
ORA-06550: line 6, column 18:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
( begin case declare end exception exit for goto if loop mod
null pragma raise return select update while with
<an identifier> <a double-quoted delimited-identifier>
<a bind variable> << continue close current delete fetch lock
insert open rollback savepoint set sql execute commit forall
merge pipe purge
ORA-06512: at line 22
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I am not sure what's your purpose on the code but try this. it will work most probably.
DECLARE
COUNTER INTEGER :=0;
v_delstr VARCHAR2(2000);
v_countstr VARCHAR2(2000);
SchemaName VARCHAR2(40) :='Staging';
TableName VARCHAR2(100):='History';
BEGIN
FOR COUNTER IN 0..9
LOOP
COUNTER := COUNTER + 1;
DBMS_OUTPUT.PUT_LINE('Counter: ');
v_delstr:= 'Delete FROM ' ||SchemaName ||'.'||TableName|| ' where rownum <= 1000 And startdate>=sysdate-731 and startdate<=sysdate-730';
EXECUTE immediate v_delstr;
dbms_output.put_line(v_delstr);
v_countstr:= 'DECLARE
CANT INTEGER;
BEGIN
SELECT COUNT(*) INTO CANT FROM ' ||SchemaName ||'.'||TableName|| ' where rownum <= 1000 And startdate>=sysdate-731 and startdate<=sysdate-730;
EXIT WHEN CANT <= 100;
COMMIT;
END;';
EXECUTE immediate v_countstr;
dbms_output.put_line(v_countstr);
--dbms_output.put_line(v_delstr);
--dbms_output.put_line(v_countstr);
END LOOP;
END;

Unable to find in oracle cursor update that how many records are updated?

Scenario:
Write a PL/SQL block that takes a department number from a user and increases the salary of all the employees belonging to the department by 10%. The block should display on the screen how many records are updated.
My Program:
DECLARE
V_TOT_ROWS NUMBER(3);
CURSOR emp_cursor IS
SELECT EMPSAL FROM emp WHERE deptno=&DEPT_NO
FOR UPDATE OF EMPSAL NOWAIT;
BEGIN
FOR emp_record IN emp_cursor
LOOP
UPDATE emp
SET EMPSAL=EMPSAL+emp_record.EMPSAL*0.1
WHERE CURRENT OF emp_cursor;
-- V_TOT_ROWS := SQL%ROWCOUNT;
-- DBMS_OUTPUT.PUT_LINE('TOTAL UPDATED RECORDS: ' || V_TOT_ROWS);
DBMS_OUTPUT.PUT_LINE('Updated ' || SQL%ROWCOUNT || ' salaries.');
END LOOP;
COMMIT;
-- DBMS_OUTPUT.PUT_LINE('Updated ' || SQL%ROWCOUNT || ' salaries.');
END;
It is giving 1 row updated every time the loop is executed but if I keep the dbms_output outside the loop, it gives 0.
Please help.
Thanks,
Please check below Script:
declare V_TOT_ROWS NUMBER(3) :=0;
CURSOR emp_cursor IS
SELECT EMPSAL FROM emp WHERE deptno=&DEPT_NO
FOR UPDATE OF EMPSAL NOWAIT;
begin FOR emp_record IN emp_cursor
LOOP
UPDATE emp
SET EMPSAL=EMPSAL+emp_record.EMPSAL*0.1
WHERE CURRENT OF emp_cursor;
V_TOT_ROWS := V_TOT_ROWS+SQL%ROWCOUNT;
-- DBMS_OUTPUT.PUT_LINE('TOTAL UPDATED RECORDS: ' || V_TOT_ROWS);
-- DBMS_OUTPUT.PUT_LINE('Updated ' || SQL%ROWCOUNT || ' salaries.');
END LOOP;
COMMIT;
DBMS_OUTPUT.PUT_LINE('Updated ' || V_TOT_ROWS || ' salaries.'); end;
Use simple update instead of a cursor + forall.
If you use FORALL ... UPDATE, then only 1 record is updated in each loop cycle, so UPDATE returns SQL%ROWCOUNT always = 1.
DECLARE
V_TOT_ROWS NUMBER(3);
BEGIN
UPDATE emp
SET EMPSAL= EMPSAL+ EMPSAL*0.1
WHERE deptno=&DEPT_NO;
V_TOT_ROWS := SQL%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE('TOTAL UPDATED RECORDS: ' || V_TOT_ROWS);
COMMIT;
END;
/

TOAD displaying cursor recordset returned by stored procedure

How I could print recorset result from the returning cursor, please.
Down below executes fine but I need to see result.
This is block in TOAD, calling package sp AMD_NEEDMSG:
DECLARE
RETURN_RECORDSET CTI_MATRIX.AMD.REF_CURSOR;
BEGIN
CTI_MATRIX.AMD.AMD_NEEDMSG ( '88888888885', RETURN_RECORDSET );
END;
This package spec:
CREATE OR REPLACE PACKAGE CTI_MATRIX.AMD AS
TYPE REF_CURSOR IS REF CURSOR;
PROCEDURE AMD_NEEDMSG (v_CRN IN VARCHAR2, return_recordset OUT REF_CURSOR);
END AMD;
This is package body:
CREATE OR REPLACE PACKAGE BODY CTI_MATRIX.AMD AS
PROCEDURE AMD_NEEDMSG (v_CRN IN VARCHAR2, return_recordset OUT REF_CURSOR) IS
return_flag INTEGER;
row_cnt INTEGER;
number_of_days INTEGER;
var_DATE DATE;
CURSOR ACCNTSEARCH (P_CRN IN VARCHAR2) IS
SELECT DISTINCT COUNT(*) , AMD.MSG_DATE
FROM TBL_AMD_NEEDMSG AMD
WHERE AMD.PHONE_NUMBER = P_CRN AND ROWNUM = 1;
BEGIN
OPEN ACCNTSEARCH(v_CRN);
FETCH ACCNTSEARCH INTO row_cnt, var_DATE;
CLOSE ACCNTSEARCH;
IF (row_cnt = 0)
THEN
INSERT INTO TBL_AMD_NEEDMSG (PHONE_NUMBER, MSG_DATE) VALUES (v_CRN , SYSDATE);
return_flag := 1;
ELSE
SELECT SYSDATE-var_DATE INTO number_of_days FROM dual;
IF (number_of_days>7)
THEN
UPDATE TBL_AMD_NEEDMSG SET MSG_DATE = SYSDATE WHERE PHONE_NUMBER = v_CRN;
return_flag := 1;
ELSE
return_flag := 0;
END IF;
END IF;
COMMIT;
OPEN return_recordset FOR
SELECT return_flag AS ReturnFLag FROM DUAL;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END AMD_NEEDMSG;
END AMD;
/
Bottom line is to return to client a value of return_flag in the form of record set.
To return the return_flag, which is int=1 or 0 you need function that returns a single value, not recordset. Below are general recordset examples - hope this helps:
DECLARE
TYPE empcurtyp IS REF CURSOR;
emp_cv empcurtyp;
--
TYPE namelist IS TABLE OF scott.emp.ename%TYPE;
TYPE sallist IS TABLE OF scott.emp.sal%TYPE;
names namelist;
sals sallist;
BEGIN
OPEN emp_cv FOR
SELECT ename, sal FROM scott.emp
WHERE job = 'MANAGER' ORDER BY sal DESC;
--
FETCH emp_cv BULK COLLECT INTO names, sals;
CLOSE emp_cv;
-- loop through the names and sals collections
FOR i IN names.FIRST .. names.LAST LOOP
DBMS_OUTPUT.PUT_LINE
('Name = ' || names(i) || ', salary = ' || sals(i));
END LOOP;
END;
/
-- SYS_REFCURSOR example --
DECLARE
p_rc_type SYS_REFCURSOR;
emp_rec scott.emp%ROWTYPE;
--
PROCEDURE p_Emp_Info (p_cur_var OUT SYS_REFCURSOR)
IS
BEGIN
OPEN p_cur_var FOR
SELECT ename, job FROM scott.emp WHERE job = 'MANAGER';
LOOP
FETCH p_cur_var INTO emp_rec.ename, emp_rec.job;
EXIT WHEN p_cur_var%NOTFOUND;
dbms_output.put_line(emp_rec.ename ||' '|| emp_rec.job);
END LOOP;
CLOSE p_cur_var;
END p_Emp_Info;
--
BEGIN
p_Emp_Info(p_rc_type);
END;
/

Resources