Statement ignored error while inserting data - oracle

I am writing procedure to insert data to one table by fetching data from another table. While inserting the data an error occurs (SQL Statement ignored) and (in this place, this column is forbidden). Can you suggest what I am doing wrong
SET SERVEROUTPUT ON;
CREATE OR REPLACE PROCEDURE KOL2
IS
CURSOR CUR IS SELECT empno, ename, SUM(SAL) sal FROM EMP where job =
'MANAGER';
nr_kier NUMBER; nazwisko_kier varchar(20); suma_pensji int;
ostatnia_mod date;
BEGIN
OPEN CUR;
LOOP
FETCH CUR INTO nr_kier, nazwisko_kier, suma_pensji;
EXIT WHEN CUR%NOTFOUND;
INSERT INTO statystyka_kierownikow (nr_kier , naziwsko_kier,
suma_pensji, ostatnia_mod)
VALUES (nr_kier, nazwisko_kier, sal, sysdate);
END LOOP;
CLOSE CUR;
COMMIT;
END;

what you are trying to do is time consuming task. It is not even suitable for SQL. You are trying to fetch every record and make insertion one-by-one.
Check my solution below.
INSERT INTO statystyka_kierownikow
(nr_kier , naziwsko_kier, suma_pensji, ostatnia_mod)
SELECT empno, ename, SUM(SAL) sal
FROM EMP where job = 'MANAGER'
GROUP BY empno, ename;

Related

FORALL INSERT Not Inserting Rows

I have the following code snippet to insert rows into t1 table, however when I execute the procedure no rows are getting populated in t1 table.
CREATE OR REPLACE PROCEDURE my_proc
IS
TYPE rt_t1 IS TABLE OF t1%ROWTYPE
INDEX BY BINARY_INTEGER;
vrt_t1 rt_t1;
TYPE t_emp_no_list IS TABLE OF t1.emp_no%TYPE
INDEX BY BINARY_INTEGER;
TYPE t_emp_name_list IS TABLE OF t1.emp_name%TYPE
INDEX BY BINARY_INTEGER;
TYPE t_loc_name_list IS TABLE OF t1.loc_name%TYPE
INDEX BY BINARY_INTEGER;
TYPE t_hire_date_list IS TABLE OF t1.hire_date%TYPE
INDEX BY BINARY_INTEGER;
l_emp_no t_emp_no_list;
l_emp_name t_emp_name_list;
l_loc_name t_loc_name_list;
l_hire_date t_hire_date_list;
BEGIN
SELECT empno,
ename,
loc,
hiredate
BULK COLLECT INTO l_emp_no,
l_emp_name,
l_loc_name,
l_hire_date
FROM (SELECT empno,
ename,
dept.loc,
emp.hiredate
FROM emp JOIN dept ON emp.deptno = dept.deptno);
FORALL i IN vrt_t1.FIRST .. vrt_t1.LAST
INSERT INTO t1 (emp_no,
emp_name,
loc_name,
hire_date)
VALUES (l_emp_no (i),
l_emp_name (i),
l_loc_name (i),
l_hire_date (i));
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
RAISE;
END;
You should use cursor to achieve your requirement. See below:
CREATE OR REPLACE PROCEDURE my_proc
IS
TYPE rt_t1 IS TABLE OF t1%ROWTYPE
INDEX BY BINARY_INTEGER;
vrt_t1 rt_t1;
cursor cur is
SELECT empno,
ename,
dept.loc,
emp.hiredate
FROM emp JOIN dept ON emp.deptno = dept.deptno;
BEGIN
OPEN cur;
fetch cur BULK COLLECT INTO vrt_t1;
close cur;
FORALL i IN 1 .. vrt_t1.count
INSERT INTO t1
VALUES vrt_t1(i);
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
RAISE;
END;
PS: the above code will work if the number of columns of both the tables are same;
EDIT..In case you are inserting specific rows to a table then you need to create a RECORD to do so. See below example. Your code is failing coz you are trying to inserting multiple collection in one go. In your case first colelction would be an insert and others should be an update.
CREATE TABLE t1
(
emp_no NUMBER,
emp_name VARCHAR2 (30),
loc_name VARCHAR2 (30),
hire_date DATE
);
--------------
SQL> select * from t1;
no rows selected
CREATE OR REPLACE PROCEDURE my_proc
IS
TYPE TBL IS RECORD
(
emp_no number,
emp_name varchar2(100),
loc_name varchar2(100),
hire_date date
);
TYPE t_emp IS TABLE OF TBL INDEX BY PLS_INTEGER;
var_emp_det t_emp;
BEGIN
SELECT ENO,
ENAME,
JOB,
HIREDATE
BULK COLLECT INTO var_emp_det
from emp_sal;
FORALL i IN 1..var_emp_det.count
INSERT INTO t1 (emp_no,
emp_name,
loc_name,
hire_date)
values (var_emp_det(i).emp_no,
var_emp_det(i).emp_name,
var_emp_det(i).loc_name,
var_emp_det(i).hire_date);
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
RAISE;
END;
Output:
SQL> execute my_proc;
PL/SQL procedure successfully completed.
SQL> select * from t1;
EMP_NO EMP_NAME LOC_NAME
---------- ------------------------------ ------------------------------
HIRE_DATE
---------
2 Thomas IT
03-JAN-14

I want to return top 4 highest salaries from each dept along with deptno and dname in a stored procedure

I want to return top 4 highest salaries from each dept along with deptno and dname in a stored procedure.
when deptno is not included there is no error but
When including deptno im getting an error invalid number.
ORA-01722: invalid number
Here is the code
create or replace procedure tpro2(dno in emp.deptno%type,dnum out dept.deptno%type, name out emp.ename%type, sal out emp.sal%type,dname out dept.dname%type, cur out sys_refcursor)
is begin
open cur for select ename , sal, dname, dept.deptno from (select * from emp order by sal desc)emp, dept where emp.deptno=dept.deptno and emp.deptno=dno and rownum<=4;
end tpro2;
/
declare
dnum dept.deptno%type;
name emp.ename%type;
sal emp.sal%type;
dname dept.dname%type;
cur sys_refcursor;
begin
tpro2(&dno,dnum,name,sal,dname,cur);
loop
fetch cur into dnum,name,sal,dname;
exit when cur%notfound;
dbms_output.put_line(dnum||' '||name||' '||sal||' '||dname);
end loop;
close cur;
end;
/
Please help!!!
open cur for select ename, sal, dname, dept.deptno
fetch cur into dnum, name, sal, dname;
Does you see nothing suspicious here? :)
I would use window functions to get the information you need without writing a stored procedure at all:
SELECT ename, sal, dname, deptno
RANK() OVER (PARTITION BY deptno ORDER BY sal DESC) "Rank"
FROM emp e inner join dept d using (deptno)

pl/sql query which takes deptno from emp as input and return ename, sal all the columns from dept table

Can anyone please help me in solving this.
I need to write a pl/sql query which takes deptno from emp as input and returns ename, sal plus all the columns from dept table.(I don't want to declare the columns individually, instead I want to use %rowtype).
I have tried it in several ways. one of them is mentioned below.
Creation--
CREATE OR REPLACE PROCEDURE PROC01(
DNO EMP.DEPTNO%TYPE,
REC OUT DEPT%ROWTYPE,
NAME OUT EMP.ENAME%TYPE,
SAL OUT EMP.SAL%TYPE
, MY_CURSOR OUT SYS_REFCURSOR)
IS
BEGIN
OPEN MY_CURSOR FOR
SELECT D.*, ENAME, SAL
FROM EMP, DEPT D
WHERE EMP.DEPTNO = D.DEPTNO
AND D.DEPTNO = DNO;
END PROC01;
/
--Declare & Execution
DECLARE
REC DEPT%ROWTYPE;
NAME EMP.ENAME%TYPE;
SAL EMP.SAL%TYPE;
MY_CURSOR SYS_REFCURSOR;
BEGIN
PROC01(&DNO,REC, NAME, SAL, MY_CURSOR);
LOOP
FETCH MY_CURSOR INTO REC, NAME, SAL;
EXIT WHEN MY_CURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(REC.DNAME||' '||NAME||' '||SAL);
END LOOP;
CLOSE MY_CURSOR;
END;
/
ERROR :--
expression 'REC' in the INTO list is of wrong type
Thanks in advance...
The error is because of oracle can't fetch cursor in both rec type and normal type together.
I changed your query and it's working NOW!
Procedure :
CREATE OR REPLACE PROCEDURE PROC01(DNO IN emp.deptno%TYPE,
/*REC OUT DEPT%ROWTYPE,
NAME OUT EMP.ENAME%TYPE,
SAL OUT EMP.SAL%TYPE,*/
MY_CURSOR OUT SYS_REFCURSOR) IS
BEGIN
OPEN MY_CURSOR FOR
SELECT D.*, ENAME, SAL
FROM EMP, DEPT D
WHERE EMP.DEPTNO = D.DEPTNO
AND D.DEPTNO = DNO;
END PROC01;
Test code :
DECLARE
REC DEPT%ROWTYPE;
DEPTNO DEPT.deptno%TYPE;
DNAME DEPT.dname%TYPE;
LOC DEPT.loc%TYPE;
NAME EMP.ENAME%TYPE;
SAL EMP.SAL%TYPE;
MY_CURSOR SYS_REFCURSOR;
BEGIN
PROC01(&DNO, /*REC, NAME, SAL,*/ MY_CURSOR);
LOOP
FETCH MY_CURSOR
INTO /*REC*/ DEPTNO, DNAME, LOC, NAME, SAL;
EXIT WHEN MY_CURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( /*REC.*/ DNAME || ' ' || NAME || ' ' || SAL);
END LOOP;
CLOSE MY_CURSOR;
END;

Oracle update lock

I am in bit confusion regarding update lock, in the below program
CREATE OR REPLACE
PROCEDURE pro_cedure(
p_dept_id NUMBER )
IS
CURSOR mycursor
IS
SELECT deptno,comm,extra
FROM emp
WHERE comm IS NULL
AND extra IS NOT NULL
AND deptno = p_dept_id
FOR UPDATE OF comm;
BEGIN
FOR emp_rec IN mycursor
LOOP
UPDATE emp SET comm = extra
WHERE CURRENT OF mycursor;
INSERT INTO changed
(
deptno,
oldval,
newval,
seq_nextval
)
VALUES
(
emp_rec.deptno,
emp_rec.comm,
emp_rec.extra,
sequence_name.nextval
);
END LOOP;
END;
if some other user try to update the same table or the same row while I am updating does it causes a lock with this program?
If you run this procedure 2 times parallel, the second wont execute the select until the first commits. (Of course if you run other statements with the same for update of comm clause they will be queued the same way.)

Nested cursors in oracle

I got this stored procedure in oracle
create or replace
procedure mayor_sueldo
as
cursor c_depto is select deptno from dept;
c_deptno dept.deptno%type;
c_empno number;
c_ename emp.ename%type;
c_job emp.job%type;
c_sal emp.sal%type;
begin
open c_depto;
fetch c_depto into c_deptno;
while ( c_depto%found )loop
select empno, ename, job, sal into c_empno, c_ename, c_job, c_sal from emp where sal = (select max(sal) from emp where(deptno = c_deptno) );
dbms_output.put_line( c_empno||'-'||c_ename||'-'||c_job||' '||c_sal );
fetch c_depto into c_deptno;
end loop;
close c_depto;
end;
the problem is inside the query inside the while block if the query returns one and only one row there is no problem but what about when the query return more than one row i was thinking that i could use another cursor but idk how.
please help me
maybe this will help: for _row in (select ....) loop dbms_output(_row.a || ..); end loop;

Resources