PL/SQL: Statement ignored - plsql

create or replace trigger perform_validations
after insert or update on xx_hr_employee
for each row
begin
validation;
END;
/
and my procedure validation is:
declare
E_ID xx_hr_employee.emp_id%type;
E_NAME xx_hr_employee.emp_name%type;
D_ID xx_hr_employee.dept_id%type;
D_NAME xx_hr_employee.dept_name%type;
S_ID xx_hr_employee.supervisor_id%type;
S_NAME xx_hr_employee.supervisor_name%type;
P_ID xx_hr_employee.project_id%type;
P_NAME xx_hr_employee.project_name%type;
SAL xx_hr_employee.salary%type;
A xx_hr_employee.age%type;
l_count number;
e_count number;
procedure validation
is
cursor my_cursor is
select EMP_ID, EMP_NAME, DEPT_ID, DEPT_NAME, SUPERVISOR_ID, SUPERVISOR_NAME, PROJECT_ID, PROJECT_NAME, SALARY, AGE
from xx_hr_employee E;
begin
open my_cursor;
loop
fetch my_cursor into E_ID, E_NAME, D_ID, D_NAME, S_ID, S_NAME, P_ID, P_NAME, SAL, A;
exit when my_cursor%notfound;
if(E_ID = 0000) then
insert into xx_stg_hr_employee( EMP_ID, EMP_NAME, DEPT_ID, DEPT_NAME, SUPERVISOR_ID, SUPERVISOR_NAME, PROJECT_ID, PROJECT_NAME, SALARY, AGE)
select EMP_ID, EMP_NAME, DEPT_ID, DEPT_NAME, SUPERVISOR_ID, SUPERVISOR_NAME, PROJECT_ID, PROJECT_NAME, SALARY, AGE from xx_hr_employee
where emp_id <> 0000;
end if;
end loop;
close my_cursor;
delete from xx_stg_hr_employee WHERE (Emp_name like '% %');
UPDATE xx_stg_hr_employee SET mycol=seq_id3.NEXTVAL;
Select count(*) into l_count From xx_hr_employee
Group By EMP_ID, EMP_NAME, DEPT_ID, DEPT_NAME, SUPERVISOR_ID, SUPERVISOR_NAME, PROJECT_ID, PROJECT_NAME, SALARY, AGE
Having Count(*) > 1;
if(l_count <> 0) then
delete from xx_stg_hr_employee where mycol NOT IN (SELECT MIN(mycol)
FROM xx_stg_hr_employee GROUP BY EMP_ID, EMP_NAME, DEPT_ID, DEPT_NAME, SUPERVISOR_ID, SUPERVISOR_NAME, PROJECT_ID, PROJECT_NAME, SALARY, AGE);
end if;
end;
begin
validation;
end;
/
it is showing Error at line 2: PL/SQL: Statement ignored..
here validation is a procedure which should get called when any insert(or update) is performed on xx_hr_employee..
I don't know how to proceed further.
I am using oracle apex.

i've tested the following and it worked for me, so please see what you missed:
For example
Your table is like Create table TEST_TABLE (X Number);
Then your stored procedure is
CREATE OR REPLACE PROCEDURE VALIDATIONS IS
BEGIN
--Do your validation over here..
UPDATE TEST_TABLE SET X = 1;
END;
then your code should work as you written:
CREATE OR REPLACE TRIGGER PERFORM_VALIDATIONS
AFTER INSERT OR UPDATE ON TEST_TABLE
FOR EACH ROW
BEGIN
VALIDATIONS;
END;
/
Important: If you create the procedure in a package, then make sure that the Package head has the declaration, and then call it like YourPackageName.VALIDATIONS instead of VALIDATIONS only

Related

Nested For Loops with Recursive Subquery

How can I run the below statement returning one or multiple rows for each employee in a different table and each date in a week or other range?
DECLARE
CURSOR emps_in IS
SELECT EMPLOYEE_ID FROM EMPLOYEES;
CURSOR days_in IS
SELECT TO_CHAR(DAYS, 'YYYYMMDD') FROM WEEKS WHERE WEEK_NUM=1;
BEGIN
FOR e IN emps_in LOOP
FOR d IN days_in LOOP
INSERT INTO acc_out_time (ROW_NUM, ENTRY_ID, ENTRY_DATE, ENTRY_TIME, TIME, PIN, DEVICE_ID, STATE, EVENT_POINT_NAME, DUPLICATE)
WITH BDEV_RPT2 AS
(SELECT *
FROM (SELECT ROW_NUMBER()OVER(ORDER BY TIME DESC) ROW_NUM, a.* FROM acc_time_logs a WHERE PIN=e AND ENTRY_DATE=d AND STATE IN ('1','2') AND DEVICE_ID IN ('18','10','6','9') ORDER BY TIME DESC)
WHERE ROW_NUM IN ('1','2') AND DEVICE_ID='18' OR (ROW_NUM='1' AND DEVICE_ID IN ('10','6','9') AND NOT EXISTS(SELECT NULL FROM (SELECT ROW_NUMBER()OVER(ORDER BY TIME DESC) ROW_NUM, a.* FROM acc_time_logs a WHERE PIN=e AND ENTRY_DATE=d AND STATE IN ('1','2') AND DEVICE_ID IN ('18','10','6','9') ORDER BY TIME DESC) WHERE ROW_NUM IN ('1','2') AND DEVICE_ID='18')))
SELECT ROW_NUMBER()OVER(ORDER BY TIME ASC) ROW_NUM, ENTRY_ID, ENTRY_DATE, ENTRY_TIME, TIME, PIN, DEVICE_ID, STATE, EVENT_POINT_NAME, DUPLICATE FROM BDEV_RPT2;
END LOOP;
END LOOP;
COMMIT;
END;

Create table and then insert data into the new table from another table

I am creating one table name emp_inforamtion with checking that table is exist in database or not ,and if not then creating table then inserting the data from bank table in to emp_information table.
DECLARE
ncount NUMBER;
v_sql VARCHAR2(4000);
CURSOR c1
IS
SELECT bank_code,
center_code,
bank_name,
logo
FROM bank
WHERE bank_code ='607143';
BEGIN
SELECT COUNT(1) INTO ncount FROM tab WHERE tname LIKE '%EMP_INFORMATION%';
IF (ncount <= 0) THEN
DBMS_OUTPUT.PUT_LINE (ncount || 'count');
BEGIN
v_sql :=' CREATE TABLE EMP_INFORMATION
(
emp_id VARCHAR2(3),
emp_name VARCHAR2(20),
emp_salary VARCHAR2(3),
emp_department VARCHAR2(3)
)';
EXECUTE immediate v_sql;
COMMIT;
BEGIN
FOR i IN c1
LOOP
INSERT
INTO EMP_INFORMATION
(
emp_id,
emp_name,
emp_salary,
emp_department
)
VALUES
(
i.bank_code,
i.bank_name,
i.center_code,
i.logo
);
END LOOP;
END;
END;
END IF;
end;
/
found below error after executing the above cursor:
ORA-06550: line 30, column 16: PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 29, column 11: PL/SQL: SQL Statement ignored
When you create a table using execute immediate in an anonymous block, use execute immediate to insert the data into it.
DECLARE
ncount NUMBER;
v_sql VARCHAR2(4000);
CURSOR c1
IS
SELECT bank_code,
center_code,
bank_name,
logo
FROM bank
WHERE bank_code ='607143';
BEGIN
SELECT COUNT(1) INTO ncount FROM tab WHERE tname LIKE '%EMP_INFORMATION%';
IF (ncount <= 0) THEN
DBMS_OUTPUT.PUT_LINE (ncount || 'count');
BEGIN
v_sql :=' CREATE TABLE EMP_INFORMATION
(
emp_id VARCHAR2(3),
emp_name VARCHAR2(20),
emp_salary VARCHAR2(3),
emp_department VARCHAR2(3)
)';
EXECUTE IMMEDIATE v_sql;
BEGIN
FOR i IN c1
LOOP
EXECUTE IMMEDIATE 'INSERT
INTO EMP_INFORMATION
(
emp_id,
emp_name,
emp_salary,
emp_department
)
VALUES
(
:a,
:b,
:c,
:d
)' using i.bank_code, i.bank_name, i.center_code, i.logo;
END LOOP;
END;
END;
END IF;
end;
/

PL/SQL: Cursor ::Retrieve a list of employees for each department

How to retrieve list of employees for each department from table EMP into a comma-delimited new table
something like:
[column x:ie deptno] [column y:ie ename]
--------------------------
7 Jesus, María, José
5 Staz, Przemek, Tomek
6 John, Jane, Bob
below table is where I want to put my result from Function concatenate_list compilation
CREATE TABLE Z
(
x NUMBER(2) NOT NULL,
y VARCHAR2 (4000) NOT NULL
);
SET SERVEROUTPUT ON
CREATE OR REPLACE FUNCTION concatenate_list (xy_cursor IN SYS_REFCURSOR)
RETURN VARCHAR2
IS
lret VARCHAR2(30000);
ltemp VARCHAR2(30000);
BEGIN
LOOP
FETCH xy_cursor
INTO ltemp;
EXIT WHEN xy_cursor%notfound;
lret := lret || ',' || ltemp;
END LOOP;
RETURN LTRIM(lret, ',');
END;
/
SHOW ERRORS
how to insert the results from "Function concatenate_lit compile" and get a result as mentioned above.
Maybe using something like this:
INSERT INTO Z( x, y) SELECT e1.x,
concatenate_list(CURSOR(SELECT e2.y FROM EMP e2 WHERE e2.x= e1.x));
but how to set it up form inside the PL/SQL block
This may help you.
declare
type cur_name is ref cursor;
emp_name cur_name;
v_ename emp.ename%type;
v_all_ename varchar2(1000);
v_deptno emp.deptno%type;
cursor c is select deptno,cursor(select ename from emp e where e.deptno=f.deptno) from emp f group by deptno;
begin
open c;
loop
fetch c into v_deptno,emp_name;
exit when c%notfound;
loop
fetch emp_name into v_ename;
exit when emp_name%notfound;
v_all_ename:=v_all_ename||v_ename;
v_all_ename:=v_all_ename||',';
end loop;
dbms_output.put_line(v_deptno||' '||v_all_ename);
v_all_ename:='';
end loop;
close c;
end;

Mutating Table error in row level trigger

Write a database trigger to
Halt the transaction between the the time 6pm to 10am on table
Give the appropriate message if the record exceed more than 10
Delete data older than 2 months from Mon - Sat and date shouldn't be 1st of the month.
(i.e. leave Sunday & 1st OF THE MONTH DATA older THAN 2 months)
I tried this code,
CREATE OR REPLACE TRIGGER EMP_INFO_BFT BEFORE
INSERT OR DELETE OR UPDATE ON EMP_INFO
FOR EACH ROW
DECLARE l_TIME NUMBER(10);
l_RECORD NUMBER;
BEGIN
l_TIME:=TO_CHAR(SYSDATE,'HH24');
IF l_TIME NOT BETWEEN 18 AND 10 THEN
RAISE_APPLICATION_ERROR(-20003,'TIME ALREADY OVER.....TRANSACTION NOT ALLOWED NOW');
END IF;
DELETE
FROM EMP_INFO
WHERE TRUNC (HIRE_DATE ) < ADD_MONTHS (TRUNC (SYSDATE), -2)
AND TO_CHAR (TRUNC (HIRE_DATE ), 'DY') != 'SUN'
AND TO_CHAR (TRUNC (HIRE_DATE ), 'DD') != '01';
SELECT COUNT(*) INTO l_RECORD FROM EMP_INFO;
IF l_RECORD>=10 THEN
RAISE_APPLICATION_ERROR(-20005,'10 RECORD ALLOWED IN EMP_INFO TABLE');
END IF;
END;
I got mutating error while inserting.
Mutating error
Check this link which basically says:
"If a trigger does result in a mutating table error, the only real option is to rewrite the trigger as a statement-level trigger.
Mutating table errors only impact row level triggers."
Your code doesn't reference :NEW or :OLD, so changing it to a statement level trigger should be easy, just remove the FOR EACH ROW.
PS
I don't think your BETWEEN will work.
Changing
IF l_TIME NOT BETWEEN 18 AND 10 THEN
to
IF l_TIME BETWEEN 10 AND 18 THEN
NULL;
ELSE
would fix it.
Make this trigger as autonomous trigger, check the following code:
CREATE OR REPLACE TRIGGER EMP_INFO_BFT BEFORE
INSERT OR DELETE OR UPDATE ON EMP_INFO
FOR EACH ROW
DECLARE l_TIME NUMBER(10);
l_RECORD NUMBER;
pragma autonomous_transaction;
BEGIN
l_TIME:=TO_CHAR(SYSDATE,'HH24');
IF l_TIME NOT BETWEEN 18 AND 10 THEN
RAISE_APPLICATION_ERROR(-20003,'TIME ALREADY OVER.....TRANSACTION NOT ALLOWED NOW');
END IF;
DELETE
FROM EMP_INFO
WHERE TRUNC (HIRE_DATE ) < ADD_MONTHS (TRUNC (SYSDATE), -2)
AND TO_CHAR (TRUNC (HIRE_DATE ), 'DY') != 'SUN'
AND TO_CHAR (TRUNC (HIRE_DATE ), 'DD') != '01';
commit;
SELECT COUNT(*) INTO l_RECORD FROM EMP_INFO;
IF l_RECORD>=10 THEN
RAISE_APPLICATION_ERROR(-20005,'10 RECORD ALLOWED IN EMP_INFO TABLE');
END IF;
END;

Does SQLite have Cursors?

i wonder if i could run the following procedure in SQLite:
set nocount on
select T.ID, max(T.SerialNo) as SerialNo
into #Tmp_Ticket_ID
from Ticket as T, Ticket as inserted
where t.ID = inserted.ID
group by T.id having count(*) > 1
declare zeiger cursor for
select SerialNo
from #Tmp_Ticket_ID
declare #SerialNo int
OPEN Zeiger
FETCH NEXT FROM zeiger INTO #SerialNo
WHILE (##fetch_status <> -1)
BEGIN
IF (##fetch_status <> -2)
BEGIN
update T
set ID = (select max(id) + 1 from Ticket)
from ticket AS T, #Tmp_Ticket_ID as I
where t.serialNo = i.serialno
and I.Serialno = #SerialNo
END
FETCH NEXT FROM zeiger INTO #SerialNo
END
CLOSE Zeiger
DEALLOCATE Zeiger
DROP TABLE #Tmp_Ticket_ID
This is a little procedure from a ms-sql2000 which cleans doubles of Ticket_id's in a given table Ticket of the following structur:
create table Ticket (serialNo int identity(1,1) not null
, ID as int not null
, Ticket_issue as varchar(50)
, some_more_field varchar(500))
Due to a simple merger from different databases, the ticket_id's becomes not unique. To fix by renumbering this i developed this procedure but now we have a similar issue on a SQLite-db.
delete from Ticket
where exists
(select rowid from Ticket t2
where t2.ID = Ticket.ID and t2.rowid < Ticket.rowid)
rowid is the always-present SQLite btree index column.
Thanks to Martin Engelschalk on the SQLite mailing list on 2009-08-17.

Resources