I am just learning PL/SQL and I can't understand why the statement within this loop runs on its own, but the PL/SQL procedure executes without any results showing at all. Is anyone able to give me any advice? Thanks.
set serveroutput on size 2000
DECLARE
CURSOR money_cur IS
SELECT SUM(etotal) AS Total_income
FROM a_enrolment
GROUP BY etotal;
etotal a_enrolment%ROWTYPE;
total_income number;
BEGIN
DBMS_OUTPUT.PUT_LINE( chr(10) );
DBMS_OUTPUT.PUT_LINE( 'Displaying total income generated' || chr(10) );
FOR etotal IN money_cur LOOP
DBMS_OUTPUT.PUT_LINE('Total income is ' || Total_income);
END LOOP;
END;
/
DECLARE
CURSOR money_cur IS
SELECT SUM(etotal) AS Total_income
FROM a_enrolment
GROUP BY etotal;
--etotal a_enrolment%ROWTYPE;
--total_income number;
BEGIN
DBMS_OUTPUT.PUT_LINE( chr(10) );
DBMS_OUTPUT.PUT_LINE( 'Displaying total income generated' || chr(10) );
FOR etotal IN money_cur LOOP
DBMS_OUTPUT.PUT_LINE('Total income is ' || etotal.Total_income);
END LOOP;
END;
/
Thank you everyone for your help :) I really appreciate it. Below is another way I found I could solve the problem in case any of you ever face a similar issue.
DECLARE
CURSOR student_cur IS
SELECT sid, etotal, edate
FROM a_enrolment
ORDER BY sID;
grand_total number := 0;
total a_enrolment%ROWTYPE;
BEGIN -- this whole block is the proceedure
DBMS_OUTPUT.PUT_LINE( chr(10) );
DBMS_OUTPUT.PUT_LINE( 'Displaying student details' || chr(10) );
DBMS_OUTPUT.PUT_LINE(RPAD('ID',15) || RPAD('TOTAL',15) || 'DATE');
FOR total IN student_cur LOOP
DBMS_OUTPUT.PUT_LINE(RPAD(total.sID, 15) || RPAD(total.etotal, 15) ||
total.edate);
grand_total := grand_total + total.etotal; -- this is the function
END LOOP;
DBMS_OUTPUT.PUT_LINE('The grand total is $' || grand_total);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data has been returned');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Too much data has been returned');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Oracle error code: ' || SQLCODE || ' - Message: ' ||
SQLERRM);
END;
/
Related
I am trying to display like first screenshot below and I don't understand the output I am getting (second screenshot).
Below is my PLSQL code that I wrote based on my own database. How do I get rid of those weird blocks in my output? Thanks in advance ~
create or replace procedure numberOfSupplier (x int := 0 ) is
begin
for QRow in (SELECT REGION.R_NAME,NATION.N_NAME,COUNT(SUPPLIER.S_NATIONKEY) counter
FROM REGION
INNER JOIN NATION ON NATION.N_REGIONKEY=REGION.R_REGIONKEY
INNER JOIN SUPPLIER ON SUPPLIER.S_NATIONKEY=NATION.N_NATIONKEY
GROUP BY SUPPLIER.S_NATIONKEY,REGION.R_NAME,NATION.N_NAME
HAVING COUNT(SUPPLIER.S_NATIONKEY)> x)
loop
dbms_output.put_line ('R_NAME' || chr(18) || 'N_NAME' || chr(18) || 'COUNT(S_NATIONKEY)' || chr(10));
dbms_output.put_line (QRow.R_NAME || chr(18) || QRow.N_NAME || chr(18) || QRow.counter || chr(10));
end loop;
end;
/
show errors;
execute numberOfSupplier(130);
i am in the middle of studys and currently doing some exercises.
I am trying to make procedure that shows how many duplicats are in a row.
CREATE OR REPLACE PROCEDURE anzahl1(
tabelle VARCHAR2,
reihe VARCHAR2,
wieviel OUT NUMBER
)AS
test VARCHAR2(4000);
BEGIN
EXECUTE IMMEDIATE 'SELECT
reihe,
(COUNT(*)-1) AS Anzahl
INTO
wieviel
FROM
tabelle
GROUP BY
reihe
HAVING COUNT(*) > 1' using out wieviel;
DBMS_OUTPUT.PUT_LINE(wieviel);
END;
/
i tried many things but nothing worked...
even the result i was given by a teacher of my old school didnt work:
CREATE OR REPLACE PROCEDURE check_doppelte_Werte_p (
p_tabellenname IN USER_TAB_COLUMNS.TABLE_NAME%TYPE,
p_spaltenname IN USER_TAB_COLUMNS.COLUMN_NAME%TYPE,
p_ergebnis BOOLEAN
) OUT
IS
v_dummy NUMBER := 1;
v_sql_anweisung varchar2 (4000);
BEGIN
v_sql_anweisung :=
'SELECT MAX(COUNT ('
|| p_spaltenname
|| ')) '
|| ' FROM '
|| p_tabellenname
|| ' GROUP BY '
|| p_spaltenname;
DBMS_OUTPUT.PUT_LINE (v_sql_anweisung);
EXECUTE IMMEDIATE v_sql_anweisung INTO v_dummy;
IF v_dummy > 1 THEN
DBMS_OUTPUT.PUT_LINE( 'Die Tabelle '
|| 'hat mindestens '
|| TO_CHAR (V_DUMMY)
|| ' doppelte Werte in der Spalte '
|| p_spaltenname);
p_ergebnis := TRUE;
ELSE
p_ergebnis := FALSE;
END IF;
EXCEPTION
-- Keine Werte gefunden, da
WHEN NO_DATA_FOUND
THEN
p_ergebnis := FALSE;
DBMS_OUTPUT.PUT_LINE ('Tabellenname oder Spaltenname sind nicht vorhan-
den!!!');
END;
What would you do/change?
Your code doesn't substitute the variables in the dynamic sql.The query String has been to be appended with the input variables.
Please try the code below,
CREATE OR REPLACE PROCEDURE anzahl1(
tabelle VARCHAR2,
reihe VARCHAR2,
wieviel OUT NUMBER
)AS
test VARCHAR2(4000);
lv_query VARCHAR2(4000);
BEGIN
lv_query := 'SELECT (COUNT(*)-1) cnt FROM '||tabelle ||' GROUP BY '||reihe||' HAVING COUNT(*) > 1';
EXECUTE IMMEDIATE lv_query into wieviel;
DBMS_OUTPUT.PUT_LINE(wieviel);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR '||SQLCODE||' '||SUBSTR(SQLERRM,1,200));
END;
/
I create table and populate records as below,
CREATE TABLE EMP(ID NUMBER(10),NAME VARCHAR2(40));
INSERT INTO EMP VALUES (1, 'TEST');
INSERT INTO EMP VALUES (1, 'TEST');
INSERT INTO EMP VALUES (2, 'TEST2');
Now i call the stored procedure to test for EMP table for ID column,
declare
lv_cnt number(10);
begin
anzahl1('EMP','ID',lv_cnt);
dbms_output.put_line(lv_cnt);
end;
This give output as ,
1
I am trying to create an Oracle procedure to delete records from multiple tables of an owner based upon a distinct count condition:
Firstly I am trying to obtain the tables for which I want to delete those records with this query:
SELECT * FROM ALL_TABLES WHERE OWNER = 'Lorik' AND TABLE_NAME LIKE 'UT_%';
This results in a total of 300 tables, now all of those tables have a column named: DATE_INC
I am trying to delete records from all of the tables if this COUNT(DISTINCT DATE_INC) > 5.
Assuming that one of those 300 tables is named UT_NAMES:
SELECT COUNT(DISTINCT DATE_INC) FROM Lorik.UT_NAMES;
So if the count exceeds 5, then I want to delete the records with the minimum date:
DELETE MIN(DATE_INC) FROM Lorik.UT_NAMES;
Can someone please link these steps together so I can loop through each table of that owner and obtain the distinct date count and delete records based upon the above cited condition.
Thanks in advance!
You can use 'EXECUTE IMMEDIATE' in PL/SQL to accomplish your goal:
DECLARE
strTable VARCHAR2(32767);
nCount NUMBER;
BEGIN
FOR aRow IN (SELECT *
FROM ALL_TABLES
WHERE OWNER = 'Lorik' AND
TABLE_NAME LIKE 'UT_%')
LOOP
strTable := aRow.OWNER || '.' || aRow.TABLE_NAME;
EXECUTE IMMEDIATE 'SELECT COUNT(DISTINCT DATE_INC) FROM ' || strTable
INTO nCount;
IF nCount > 5 THEN
EXECUTE IMMEDIATE 'DELETE FROM ' || strTable ||
' WHERE DATE_INC = (SELECT MIN(DATE_INC) ' ||
'FROM ' || strTable || ')';
END IF;
END LOOP;
END;
Not tested on animals - you'll be first! :-)
As pointed out by #Andrew this seems to be very basic processes.
Declare some variables.
Open a cursor.
Use dynamic sql to count
Use dynamic sql to delete
Add some log information
_
declare
v_cnt number;
v_sql varchar2(1000);
begin
for cur in (SELECT * FROM ALL_TABLES WHERE OWNER = 'HR' AND TABLE_NAME LIKE 'E%')
loop
v_sql := 'select count(distinct department_id||''date_inc'') from '||cur.owner||'. '||cur.table_name;
execute immediate v_sql into v_cnt;
dbms_output.put_line (cur.table_name || ': ' || v_cnt);
if v_cnt > 5 then
v_sql := 'delete from '||cur.owner||'. '||cur.table_name || ' where date_inc = (select min (date_inc) from ' ||cur.owner||'. '||cur.table_name || ')';
dbms_output.put_line (v_sql);
-- execute immediate v_sql;
end if;
end loop;
rollback;
-- commit;
end;
A little bit simpler dynamic SQL for deleting rows, as it uses a local variable:
declare
l_cnt number; -- counter variable
l_min_date date; -- MIN(date_inc)
begin
for cur_t in (select table_name from all_tables
where owner = 'Lorik' -- are you sure it is not uppercase, LORIK?
and table_name like 'UT%' -- underline is wildcard character so you don't need it
)
loop
execute immediate 'select count(distinct date_inc), min(date_inc) from ' ||
cur_t.table_name into l_cnt, l_min_date;
if l_cnt > 5 then
execute immediate 'delete from ' || cur_t.table_name ||
' where date_inc = ' || l_min_date_inc;
end if;
end loop;
end;
/
Can you tell me what is wrong with this procedure that I'm trying to create?
CREATE OR REPLACE PROCEDURE create_audit_tables (table_owner VARCHAR2)
IS
CURSOR c_tables (
table_owner VARCHAR2)
IS
SELECT ot.owner AS owner, ot.table_name AS table_name
FROM all_tables ot
WHERE ot.owner = table_owner
AND ot.table_name NOT LIKE 'AUDIT_%'
AND ot.table_name <> 'EXAUDIT'
AND NOT EXISTS
(SELECT 1
FROM EXAUDIT efa
WHERE ot.table_name = efa.tname)
AND NOT EXISTS
(SELECT 1
FROM all_tables at
WHERE at.table_name = 'AUDIT_'||ot.table_name);
v_sql VARCHAR2 (8000);
v_count NUMBER := 0;
v_aud VARCHAR2 (30);
BEGIN
FOR r_table IN c_tables (table_owner)
LOOP
BEGIN
v_aud := 'AUDIT_'||r_table.table_name;
v_sql :=
'create table '
|| v_aud
|| ' as select * from '
|| r_table.owner
|| '.'
|| r_table.table_name
|| ' where 1 = 1';
DBMS_OUTPUT.put_line ('Info: ' || v_sql);
EXECUTE IMMEDIATE v_sql;
v_sql :=
'alter table '
|| v_aud
|| ' add ( AUDIT_ACTION char(1), AUDIT_BY varchar2(50), AUDIT_AT TIMESTAMP)';
EXECUTE IMMEDIATE v_sql;
v_count := c_tables%ROWCOUNT;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
'Failed to create table '
|| v_aud
|| ' due to '
|| SQLERRM);
END;
END LOOP;
IF v_count = 0
THEN
DBMS_OUTPUT.put_line ('No audit tables created');
ELSE
DBMS_OUTPUT.put_line (v_count || ' audit tables created.');
END IF;
END;
/
I checked it with show errors function and it gave me this:
LINE/COL ERROR
-------- --------------------------------------------
6/1 PL/SQL: SQL Statement ignored
16/3 PL/SQL: ORA-00906: missing left parenthesis
Perhaps the problem is quite simple, but I can't see it, so please help me if you can
I can compile procedure without problems after creating table
create table EXAUDIT (tname varchar2(100));
Check status of procedure:
select status from user_objects where lower(object_name) = 'create_audit_tables';
I had return a program it will check which file is present or not and it will check no of column
create or replace procedure chkcsvfile
(P_UTLDIR VARCHAR2,
P_FILENAME VARCHAR2,
P_tabnam VARCHAR2
)
is
P_fieldel varchar2(2):= ',';
V1 VARCHAR2(32767) ;
P_errlen number :=0;
lv_a number;
lv_b number;
lv_c number;
lv_d number;
lv_check_file_exist boolean;
v_file utl_file.file_type;
cursor c1 is
select count(*) from user_tables where TABLE_NAME =P_tabnam;
cursor c2 is
select count(*) from user_tab_columns where TABLE_NAME =P_tabnam;
begin
open c1;
fetch c1 into lv_c;
if lv_c = 0 then
dbms_output.put_line('table name is invalid : ' || P_tabnam);
end if;
--'test wheather file is available or not'
dbms_output.put_line ('test wheather file is available or not');
utl_file.fgetattr (P_UTLDIR,P_FILENAME, lv_check_file_exist, lv_a, lv_b );
if lv_check_file_exist then
dbms_output.put_line('file ' ||P_FILENAME ||' exists');
v_file := utl_file.fopen(P_UTLDIR,P_FILENAME, 'R');
UTL_FILE.get_line (v_file ,V1,32767);
DBMS_OUTPUT.put_line ('V1 :' || V1);
if (REGEXP_like (V1, ',',1))
then
P_errlen := P_errlen +1 ;
dbms_output.put_line ('errrooooooooooooooooooooooooooooooooooorr');
dbms_output.put_line (P_errlen );
end if;
end if;
if not lv_check_file_exist then
dbms_output.put_line('file ' || P_FILENAME ||' does not exist');
end if;
if lv_check_file_exist is null then
dbms_output.put_line('file check null');
end if;
if lv_check_file_exist is not null then
dbms_output.put_line('file check not null');
end if;
dbms_output.put_line('lv_a-->'||lv_a);
dbms_output.put_line('lv_b-->'||lv_b);
open c2;
fetch c2 into lv_d;
dbms_output.put_line ('No of columns in a table : ' || lv_d );
end;
/
NOW my problem is i have to match " , " in a string and i want the count of it . i had written the program but it not give me specific count .
data in string is given in below format
7839,KING ,PRESIDENT,0000,17-nov-1981, 005000.00 ,000000.00,10,
please help me
thanks in advance
Since you're using 11g, you can use the regexp_count function.
select regexp_count('7839,KING ,PRESIDENT,0000,17-nov-1981, 005000.00 ,000000.00,10,',',')
from dual