Oracle insert into returning - oracle

I'm trying return id after insert:
CREATE SEQUENCE seq_osobne_udaje
INCREMENT BY 1 START WITH 1;
CREATE OR REPLACE TRIGGER trig_osobne_udaje_seq
BEFORE INSERT ON osobne_udaje
FOR EACH ROW
BEGIN
SELECT seq_osobne_udaje.nextval INTO :new.id FROM dual;
END;
/
and then:
var tmp number;
insert into osobne_udaje(name,sur,born,is_man)
values('Jacob','Wulp',to_date('28.07.1992','DD.MM.YYYY'),'Y')
returning id into tmp;
but it write exception in insert row: SQL Error: ORA-00905: missing keyword

This script works in SQL Developer:
DROP TRIGGER trig_osobne_udaje_seq;
DROP SEQUENCE seq_osobne_udaje;
DROP table osobne_udaje;
create table osobne_udaje(
id NUMBER,
name VARCHAR2(20),
sur VARCHAR2(20),
born DATE,
is_man CHAR(1)
)
/
CREATE SEQUENCE seq_osobne_udaje
INCREMENT BY 1 START WITH 1;
/
CREATE OR REPLACE TRIGGER trig_osobne_udaje_seq
BEFORE INSERT ON osobne_udaje
FOR EACH ROW
BEGIN
:new.id := seq_osobne_udaje.nextval;
END;
/
var tmp number;
/
BEGIN
insert into osobne_udaje(name,sur,born,is_man)
values('Jacob','Wulp',to_date('28.07.1992','DD.MM.YYYY'),'Y')
returning id into :tmp;
END;
/
print tmp;

Related

Create backup table concatenated with sysdate before deleting the rows in oracle procedure

I have created a package and defined a procedure to delete specific rows retrieved by the cursor.
Before the rows were deleted from the table, I want to take a backup of those records every time the package is compiled and I need the backup table to be created as tablename concatenated with sysdate.
ex: if table name is emp, backup table should be created as emp_2020_10_16
Below is the sample code I have created:
PROCEDURE DELETE_REC(
P_retcode NUMBER,
P_errorbuff VARCHAR2,
P_unit_id NUMBER,
P_join_date VARCHAR2
)
IS
CURSOR cur1
IS
SELECT unit_ID,dept_ID,join_DATE
FROM EMP MMT
WHERE MMT.dep_TYPE_ID IN (44,35)
AND MMT.unit_id = P_unit_id
AND MMT.join_date < to_date(P_join_date,'RRRR/MM/DD HH24:MI:SS');
BEGIN
--begin
-- EXECUTE IMMEDIATE 'Create table EMP_' || to_char(sysdate,'yyyy_mm_dd') || ' as select * from EMP MMT WHERE MMT.dep_TYPE_ID IN (44,35)
AND MMT.unit_id = P_unit_id
AND MMT.join_date < to_date(P_join_date,'RRRR/MM/DD HH24:MI:SS');
--
-- end;
/*Here i would like to create backup table like above before executing the below delete statement but i am not sure about the correct standards that i should be using for above dynamic statement*/
FOR val IN cur1
LOOP
DELETE
FROM EMP MMT
WHERE MMT.dept_ID= val.dept_id;
How can I backup the table using above dynamic statement in best possible way? I am still learning PL&SQL.
Maybe sth like this would help:
create table employees as select * from hr.employees;
--drop table emp_2020_10_18;
--drop table employees;
----------------
declare
vTabName varchar2(50);
nDept_id number := 10;
nCnt number := 0;
vSQL varchar2(1000);
begin
vTabName := 'emp_'||to_char(sysdate, 'yyyy_mm_dd');
-- check if table exists
begin
execute immediate 'select count(*) from emp_tmp' into nCnt;
exception when others then
nCnt := -1;
end;
-- if not exists create one
if nCnt = -1 then
execute immediate 'create table '|| vTabName||' as select * from employees where 1=2' ;
end if;
execute immediate 'insert into '|| vTabName ||' select * from employees where department_id = :nDept_id' using nDept_id;
delete from employees where department_id = nDept_id;
exception when others then
dbms_output.put_line(sqlerrm);
end;
/

Difficulty compiling an AFTER INSERT OR UPDATE trigger

I have an EMPLOYEE table with SALARY field. I'm using Oracle SQL developer. I want to write a trigger so that when someone update salary in EMPLOYEE table, it will update Salary field in EMPLOYEE_SALARIES table as low, medium, high. Here's the second table.
CREATE TABLE Employee_Salaries(
Ssn CHAR(9) NOT NULL,
Salary VARCHAR(10),
Log_Date DATE
);
Here's the trigger and procedure to update the Salary field to low, middle or high.
CREATE OR REPLACE PROCEDURE salaryType(x IN NUMBER, y OUT VARCHAR) IS
BEGIN
IF x >= 60000 THEN y := 'HIGH';
ELSIF (x >= 40000 AND x <= 60000) THEN y := 'MEDIUM';
ELSE y := 'LOW';
END IF;
END salaryType;
/
I get compiler error on this trigger. Please tell me what I did wrong or am I missing something.
CREATE OR REPLACE TRIGGER salary1
AFTER INSERT OR UPDATE ON Employee
FOR EACH ROW
BEGIN
DECLARE
salaryRank VARCHAR(10) := ' ';
salaryType(:new.Salary, salaryRank);
INSERT INTO Employee_Salaries(Ssn, Salary, Log_Date) VALUES (:new.Ssn, salaryRank, SYSDATE);
END;
/
Declaration Part is at wrong place(should be before BEGIN and just after FOR EACH ROW statement of TRIGGER's header), Make it as the following :
CREATE OR REPLACE TRIGGER salary1
AFTER INSERT OR UPDATE ON Employee
FOR EACH ROW
DECLARE
salaryRank VARCHAR(10) := ' ';
BEGIN
salaryType(:new.Salary, salaryRank);
INSERT INTO Employee_Salaries(Ssn, Salary, Log_Date) VALUES (:new.Ssn, salaryRank, SYSDATE);
END;
The keyword BEGIN in the trigger is in the wrong place. It should come after the DEFINE block; that is, after you declare salaryrank and before you invoke the procedure.

Warning: Trigger created with compilation errors

I am trying to create a trigger in oracle like blow:
CREATE OR REPLACE TRIGGER TRIGGER_VC_PART_LIST
BEFORE INSERT ON VC_PART_LIST FOR EACH ROW
BEGIN
SELECT VC_PART_LIST_SEQ.NEWTVAL INTO :new.SEQ_ID FROM dual;
END;
/
anyone can help me?Thx.
In sequence to fetch the next value use NEXTVAL . Below is the correct syntax
CREATE OR REPLACE TRIGGER TRIGGER_VC_PART_LIST
BEFORE INSERT
ON VC_PART_LIST
FOR EACH ROW
BEGIN
SELECT VC_PART_LIST_SEQ.NEXTVAL INTO :new.SEQ_ID FROM DUAL;
END;
There are few issues in your code.
1) VC_PART_LIST_SEQ.NEWTVAL there is nothing called NEWTVAL in Oracle. It should be Nextval.
2) There is no need for a SQL statement.
See demo:
Trigger:
CREATE OR REPLACE TRIGGER TRIGGER_VC_PART_LIST
BEFORE INSERT
ON VC_PART_LIST
FOR EACH ROW
BEGIN
:new.SEQ_ID := VC_PART_LIST_SEQ.NEXTVAL;
END;
/
Table:
create table VC_PART_LIST (SEQ_ID number,
VC_VTC varchar2(20), PART_NO varchar2(20), CONSUME_QTY varchar2(20));
Sequence
create sequence VC_PART_LIST_SEQ start with 1 increment by 1;
Insertion:
INSERT INTO VC_PART_LIST (VC_VTC, PART_NO, CONSUME_QTY)
VALUES ('6175SMFGD132000D', 'SC25R136', '11');
Commit;
Selection:
SQL> select * from VC_PART_LIST;
SEQ_ID VC_VTC PART_NO CONSUME_QTY
---------- -------------------- -------------------- --------------------
1 6175SMFGD132000D SC25R136 11

Mutating table error thrown from stored procedure fired by an after insert trigger

I have a requirement to call a stored procedure via 'after insert' trigger whenever data is inserted into table but I run into "error ORA-04091: table TEST.EMP is mutating, trigger/function may not see it". I understand the reason behind this error but how can I overcome this through Compound Triggers without disturbing the procedure?
create TABLE emp(
id NUMBER(4),
emp_name VARCHAR2(30),
dept_name VARCHAR2(10));
create or replace PROCEDURE emp_count(dept_name_v emp.dept_name%TYPE) as
DECLARE
dept_emp_count NUMBER(4) := 0;
BEGIN
SELECT count(*) INTO dept_emp_count FROM emp WHERE dept_name = dept_name_v;
UPDATE dept_stat SET d_emp_count = dept_emp_count WHERE dept_name = dept_name_v;
END;
create or replace TRIGGER dept
AFTER INSERT ON emp
FOR EACH ROW
BEGIN
emp_count(:NEW.dept_name);
END;
There is an example in documentation how to create a compound trigger: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#CHDFEBFJ
Just change a few identifiers and declarations in this example, and you will get a trigger for your case:
CREATE OR REPLACE TRIGGER some_trigger
FOR INSERT ON emp
COMPOUND TRIGGER
TYPE dept_names_t IS TABLE OF emp.dept_name%TYPE INDEX BY SIMPLE_INTEGER;
dept_names dept_names_t;
idx SIMPLE_INTEGER := 0;
-- AFTER EACH ROW Section:
AFTER EACH ROW IS
BEGIN
idx := idx + 1;
dept_names(idx) := :NEW.dept_name;
END AFTER EACH ROW;
AFTER STATEMENT IS
BEGIN
FOR j IN 1..idx
LOOP
emp_count(dept_names(j));
END LOOP;
END AFTER STATEMENT;
END;
/

can any solve what is wrong with this please?

create table account_type
(
acct_type number(3) primary key,
acct_desc Varchar2(30) not null CHECK (acct_desc IN('savings','salary','current','credit')),
acct_wd_limit number(10)
);
create sequence acct_seq;
CREATE OR REPLACE TRIGGER acct_pk
BEFORE INSERT ON account_type
FOR EACH ROW
WHEN (new.acct_type IS NULL)
BEGIN
SELECT acct_seq.NEXTVAL
INTO :new.acct_type
FROM account_type;
END;
i am getting an error on the line before insert on account_type. no idea why
I also tried doing
CREATE OR REPLACE TRIGGER acct_pk
BEFORE INSERT ON account_type
FOR EACH ROW
WHEN (new.id IS NULL)
BEGIN
SELECT acct_seq.NEXTVAL
INTO :new.id
FROM account_type;
END;
Even doing this is giving me an error
create sequence acct_pk
start with 1
increment by 1
max value 999
min value 1
no cycle;
Thanks
Since the author tagged the question with oracle10g, she can't use sequence_name.nextVal in PL/SQL. Solution:
CREATE OR REPLACE TRIGGER acct_pk
BEFORE INSERT ON account_type
FOR EACH ROW
DECLARE
v_acct_type NUMBER;
BEGIN
IF :new.acct_type IS NULL THEN
SELECT acct_seq.NEXTVAL
INTO v_acct_type
FROM dual;
:new.acct_type := v_acct_type;
END IF;
END;

Resources