ORA-04079: invalid trigger specification --- Error occered - oracle

My trigger is :
CREATE OR REPLACE trigger TA_C_WARRANTY_AUDIT_TRG
BEFORE INSERT OR DELETE OR UPDATE ON TA_WARRANTY
FOR EACH ROW`enter code here`
ENABLE
DECLARE
v_user VARCHAR2(30);
v_date VARCHAR2(30);
BEGIN
SELECT user, TO_CHAR(sysdate,'DD/MON/YYYY HH24:MI:SS') INTO v_user,v_date FROM dual;
IF INSERTING THEN
INSERT INTO TA_C_WARRANTY_AUDIT(new_name,old_name,user_name,entry_date,operation)
VALUES (:NEW.LAST_UPDATE_ID, NULL,v_user,v_date,'Insert');
ELSIF DELETING THEN
INSERT INTO TA_C_WARRANTY_AUDIT(new_name,old_name,user_name,entry_date,operation)
VALUES (NULL, :OLD.LAST_UPDATE_ID,v_user,v_date,'Delete');
ELSIF UPDATING THEN
INSERT INTO TA_C_WARRANTY_AUDIT(new_name,old_name,user_name,entry_date,operation)
VALUES (:NEW.LAST_UPDATE_ID, :OLD.LAST_UPDATE_ID,v_user,v_date,'Update');
END IF;
END;
/
Looks my code is okay but I got below error message:
ORA-04079: invalid trigger specification
Any suggession or idea will be highly appreciated.
EDIT:
CREATE TABLE TA_C_WARRANTY_AUDIT
(
new_name VARCHAR2(30),
OLD_name VARCHAR2(30),
user_name VARCHAR2(30),
entry_date VARCHAR2(30),
operation VARCHAR2(30)
);

Try to remove ENABLE from your code

Related

SQL Developer will not insert data

create or replace PROCEDURE ADD_TO_BLACKLIST(
P_EMPLOYEE_USERNAME IN VARCHAR2,
T_CURSOR OUT SYS_REFCURSOR
)
AS
BEGIN
DECLARE
E_COUNT PLS_INTEGER := 0;
BEGIN
SELECT COUNT(*) INTO E_COUNT FROM EXAMPLE_TABLE
WHERE UPPER(EMPLOYEE_USERNAME) LIKE UPPER(P_EMPLOYEE_USERNAME)||'%';
IF E_COUNT = 0 THEN
INSERT INTO EXAMPLE_TABLE
(employee_number, employee_username)
SELECT EMPLOYEE_NUMBER, EMAIL FROM EXAMPLE_VIEW
WHERE UPPER(EMAIL)=CONCAT(UPPER(P_EMPLOYEE_USERNAME), '#microsoft.com');
ELSE
UPDATE EXAMPLE_TABLE
SET (EMPLOYEE_NUMBER, EMPLOYEE_USERNAME) =
(SELECT EMPLOYEE_NUMBER, EMAIL FROM EXAMPLE_VIEW
WHERE UPPER(EMAIL) = CONCAT(UPPER(P_EMPLOYEE_USERNAME), '#microsoft.com'));
COMMIT;
END IF;
OPEN T_CURSOR For
SELECT * FROM EXAMPLE_VIEW
WHERE EMAIL LIKE CONCAT(UPPER(P_EMPLOYEE_USERNAME), '%');
END;
END ADD_TO_BLACKLIST;
This compiles, but when I try to test it with a valid P_EMPLOYEE_USERNAME (which I've confirmed to be in the EXAMPLE_VIEW), I do not see any data being inserted.
I am new to PLSQL and not sure how to figure out the value of E_COUNT
The Example_Table DDL is
CREATE TABLE "Example_Table"
( "EMPLOYEE_NUMBER" NUMBER NOT NULL ENABLE,
"EMPLOYEE_USERNAME" VARCHAR2(250 BYTE) NOT NULL ENABLE,
"ACCOUNT_STATUS" NUMBER DEFAULT 0,
"ACCOUNT_STATUS_LAST_UPDATE" TIMESTAMP (6) DEFAULT SYSDATE NOT NULL ENABLE,
CONSTRAINT "BOE_SAFEGAURD_PK" PRIMARY KEY ("EMPLOYEE_USERNAME"))
The issue is in below line,you are not converting the case after concatenation.please modify and try below,
WHERE UPPER(EMAIL) = UPPER(CONCAT(UPPER(P_EMPLOYEE_USERNAME), '#microsoft.com'));
EDIT : To prove the theory please find below the details.
I have tested this and it works,
DDL to create the tables:
CREATE TABLE Example_Table
( EMPLOYEE_NUMBER NUMBER NOT NULL ENABLE,
EMPLOYEE_USERNAME VARCHAR2(250 BYTE) NOT NULL ENABLE,
ACCOUNT_STATUS NUMBER DEFAULT 0,
ACCOUNT_STATUS_LAST_UPDATE TIMESTAMP (6) DEFAULT SYSDATE NOT NULL ENABLE,
CONSTRAINT BOE_SAFEGAURD_PK PRIMARY KEY (EMPLOYEE_USERNAME));
CREATE TABLE Example_view
( EMPLOYEE_NUMBER NUMBER NOT NULL ENABLE,
EMAIL VARCHAR2(250 BYTE) NOT NULL ENABLE,
ACCOUNT_STATUS NUMBER DEFAULT 0,
ACCOUNT_STATUS_LAST_UPDATE TIMESTAMP (6) DEFAULT SYSDATE NOT NULL ENABLE
);
DML to populate data to example_view that will be used for the test.
insert into example_view values(1,'Test#microsoft.com',1,sysdate);
Modified the procedure to add UPPER on the rightside of the join for both insert and update conditions and place the commit after end if.A good code should have only one commit and that should be at the end of execution before the exception block of main begin..end block.
create or replace PROCEDURE ADD_TO_BLACKLIST(
P_EMPLOYEE_USERNAME IN VARCHAR2,
T_CURSOR OUT SYS_REFCURSOR
)
AS
BEGIN
DECLARE E_COUNT PLS_INTEGER := 0;
BEGIN
SELECT COUNT(*) INTO E_COUNT FROM EXAMPLE_TABLE WHERE UPPER(EMPLOYEE_USERNAME) LIKE UPPER(P_EMPLOYEE_USERNAME)||'%';
IF E_COUNT = 0 THEN
INSERT INTO EXAMPLE_TABLE
(employee_number, employee_username)
SELECT EMPLOYEE_NUMBER, EMAIL FROM EXAMPLE_VIEW WHERE UPPER(EMAIL)=UPPER(CONCAT(UPPER(P_EMPLOYEE_USERNAME), '#microsoft.com'));
ELSE
UPDATE EXAMPLE_TABLE SET (EMPLOYEE_NUMBER, EMPLOYEE_USERNAME) = (SELECT EMPLOYEE_NUMBER, EMAIL FROM EXAMPLE_VIEW WHERE UPPER(EMAIL)=UPPER(CONCAT(UPPER(P_EMPLOYEE_USERNAME), '#microsoft.com')));
END IF;
COMMIT;
OPEN T_CURSOR For
SELECT * FROM EXAMPLE_VIEW WHERE EMAIL LIKE CONCAT(UPPER(P_EMPLOYEE_USERNAME), '%');
END;
END ADD_TO_BLACKLIST;
In an anonymous block invoked the procedure,
DECLARE
T_CURSOR SYS_REFCURSOR;
BEGIN
ADD_TO_BLACKLIST('test',T_CURSOR);
end;
Ran a query to check if records are inserted,
select * from example_table;
Output is below,
You just need a commit after IF-ELSE condition rather than inside it. I have updated your code along with some other minor updates -
create or replace PROCEDURE ADD_TO_BLACKLIST( P_EMPLOYEE_USERNAME IN VARCHAR2,
T_CURSOR OUT SYS_REFCURSOR
)
AS
E_COUNT PLS_INTEGER := 0;
BEGIN
SELECT COUNT(*)
INTO E_COUNT
FROM EXAMPLE_TABLE
WHERE UPPER(EMPLOYEE_USERNAME) LIKE UPPER(P_EMPLOYEE_USERNAME)||'%';
IF E_COUNT = 0 THEN
INSERT INTO EXAMPLE_TABLE
(employee_number, employee_username)
SELECT EMPLOYEE_NUMBER, EMAIL
FROM EXAMPLE_VIEW
WHERE UPPER(EMAIL) = CONCAT(UPPER(P_EMPLOYEE_USERNAME), '#microsoft.com');
ELSE
UPDATE EXAMPLE_TABLE
SET (EMPLOYEE_NUMBER, EMPLOYEE_USERNAME) = (SELECT EMPLOYEE_NUMBER, EMAIL
FROM EXAMPLE_VIEW
WHERE UPPER(EMAIL)=CONCAT(UPPER(P_EMPLOYEE_USERNAME), '#microsoft.com'));
END IF;
COMMIT;
OPEN T_CURSOR For
SELECT *
FROM EXAMPLE_VIEW
WHERE EMAIL LIKE CONCAT(UPPER(P_EMPLOYEE_USERNAME), '%');
END ADD_TO_BLACKLIST;

How define AUTONOMOUS_TRANSACTION in oracle?

How to define the autonomous pragma for error logging in oracle with the help of procedure.My table structure is like below.
CREATE TABLE error_logs (
id NUMBER(10) NOT NULL,
log_timestamp TIMESTAMP NOT NULL,
error_message VARCHAR2(4000),
CONSTRAINT error_logs_pk PRIMARY KEY (id)
);
CREATE SEQUENCE error_logs_seq
start with 1
nocycle
nocache;
i tried below code for my requirement.
CREATE OR REPLACE PROCEDURE log_errors (p_error_message IN VARCHAR2) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO error_logs (id, log_timestamp, error_message)
VALUES (error_logs_seq.NEXTVAL, SYSTIMESTAMP, p_error_message);
COMMIT;
END;
/

Trying to assign a value in a variable and used it in proc in Oracle

i am trying to assign a value in a variable "slno" use it to insert value in table "Par_conn" . but it is giving error while executing the Procedure with parameter.Any help would be appreciated.
Table
create table PAR_CONN
(
CUSTOMER_ID NUMBER(10) not null,
CUSTOMER_NAME VARCHAR2(50) not null,
CITY VARCHAR2(50)
)
Store Procedure
CREATE OR REPLACE PROCEDURE sp_insert(CUSTOMER_NAME IN VARCHAR2,CITY IN VARCHAR2)
IS
Declare slno number;
BEGIN
select count(*) into slno from Par_conn;
insert into Par_conn values(slno,CUSTOMER_NAME,CITY);
commit;
END;
Executing SP:
Begin
sp_insert('ramesh','dispur');
end;
The syntax is wrong. See below comments inline. Not sure what you wanted to achieve but at the first place you need to make all syntatic corrections before implementing any logic.
CREATE OR REPLACE PROCEDURE sp_insert (CUSTOMER_NAME IN VARCHAR2,
CITY IN VARCHAR2)
IS
---Declare slno number; --<this is wrong way of declaration
slno NUMBER;
BEGIN
SELECT COUNT (*) INTO slno FROM Par_conn;
INSERT INTO Par_conn
VALUES (slno, CUSTOMER_NAME, CITY);
COMMIT;
END;
Refer here how to create a procedure .
Procedure
Please do not reinvent wheel.
You probably aimed for:
CREATE OR REPLACE PROCEDURE sp_insert(CUSTOMER_NAME IN VARCHAR2,CITY IN VARCHAR2)
IS
slno number;
BEGIN
select max(id_col_name)+1 into slno from Par_conn;
insert into Par_conn values(slno,CUSTOMER_NAME,CITY);
commit;
END;
to set id value. I would strongly recommend to use SEQUENCE or IDENTITY.
Also you should always specify column list:
insert into Par_conn(col1_name, col2_name, col3_name)
values(slno,CUSTOMER_NAME,CITY);

Is possible use a not updated column in trigger body?

I'm coding a DML Trigger for insert update rows in a new table. Trigger will fired only when one single column be updated but... Is possible use into trigger body other column outside UPDATE OF one_single_column clause?
AUDIT TABLE:
CREATE TABLE employees_salary_history(
user_name VARCHAR2(45) NOT NULL,
time_stamp date DEFAULT (sysdate),
employee_id NUMBER(6),
old_salary NUMBER(8, 2),
new_salary NUMBER(8, 2),
percente_raise_salary NUMBER(8, 2));
DML TRIGGER:
CREATE OR REPLACE TRIGGER update_salary_trg
AFTER
UPDATE
OF salary
ON employees23
FOR EACH ROW
DECLARE
v_user VARCHAR2(25);
BEGIN
SELECT user
INTO v_user
FROM dual;
INSERT INTO employees_salary_history
VALUES(
v_user,
sysdate,
employee_id, -- I would like add employee_id about employee that was updated,
:OLD.salary,
:NEW.salary,
TRUNC((:NEW.salary - :OLD.salary) / :OLD.salary * 100, 3)
);
END update_salary_trg;
Trigger works right when I omite "employee_id" column but I would like add employee_id as a reference about the salary updated. When I add employee_id column I receive the following error:
Errors: check compiler log
Errores para TRIGGER HR.UPDATE_SALARY_TRG:
LINE/COL ERROR
-------- ----------------------------------
8/3 PL/SQL: SQL Statement ignored
8/15 PL/SQL: ORA-00913: too many values
This is because the trigger cant reference the employee_id field. In your case New and OLD will be same . So just replace employee_id with either :OLD.employee_id or :NEW. employee_id as shown below. Hope it helps.
CREATE OR REPLACE TRIGGER update_salary_trg
AFTER
UPDATE
OF salary
ON employees23
FOR EACH ROW
DECLARE
v_user VARCHAR2(25);
BEGIN
SELECT user
INTO v_user
FROM dual;
INSERT INTO employees_salary_history --employees_salary_history
VALUES(
v_user,
sysdate,
:NEW.employee_id, -- I would like add employee_id about employee that was updated,
:OLD.salary,
:NEW.salary,
TRUNC((:NEW.salary - :OLD.salary) / :OLD.salary * 100, 3)
);
END update_salary_trg;
Yes it is possible to use any column of employees23-table in the trigger.
If the column was not changed then the values of :old and :new pseudorecords are the same.
So in your case just use :new.employee_id.
Next I recommend you to RTFM: PL/SQL Triggers. It also explains in the details when the pseudorecords are available and what values they hold.

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