I'm trying to make an auto_increment trigger for the IDs of an Oracle database.
After some research, I found a way to write one using a sequence and a before insert trigger.
Problem is, when I execute the trigger, I have the following error :
Parsing failed for:
CREATE OR REPLACE TRIGGER AUTO_INC_PDE_ITINERAIRE
BEFORE INSERT
ON PDE_ITINERAIRE
FOR EACH ROW
BEGIN
SELECT PDE_ITINERAIRE_ID_SEQUENCE.NEXTVAL
INTO
If I use the following command :
select * from SYS.USER_ERRORS where name = 'AUTO_INC_PDE_ITINERAIRE';
It returns the following output :
Line 3 | Pos 10 | PLS-00201: identifier 'NEW.PDE_ITINERAIRE' must be declared
Line 2 | Pos 03 | PL/SQL: SQL statement ignored
Line 4 | Pos 03 | PL/SQL: ORA-00904 invalid identifier
Here is the full query for the trigger :
CREATE OR REPLACE TRIGGER AUTO_INC_PDE_ITINERAIRE
BEFORE INSERT
ON PDE_ITINERAIRE
FOR EACH ROW
BEGIN
SELECT PDE_ITINERAIRE_ID_SEQUENCE.NEXTVAL
INTO :NEW.PDE_ITINERAIRE.ID_PDE_ITINERAIRE
FROM dual;
END;
/
I'm not really used to Oracle's triggers, so could someone help me finding out what is wrong in my trigger ?
Thanks for your time
EDIT
I changed the trigger from your advice
CREATE OR REPLACE TRIGGER AUTO_INC_PDE_ITINERAIRE
BEFORE INSERT
ON PDE_ITINERAIRE
FOR EACH ROW
BEGIN
:NEW.ID_PDE_ITINERAIRE := PDE_ITINERAIRE_ID_SEQUENCE.NEXTVAL;
END;
/
I still have the same error output though.
More informations :
--Oracle is v11.
--TOra 3 is used as IDE.
EDIT 2
Here is the DDL as asked :
CREATE TABLE "GEOMAP"."PDE_ITINERAIRE"
( "ID_PDE_ITINERAIRE" NUMBER(11,0) NOT NULL ENABLE,
"NOM_ITINERAIRE" VARCHAR2(255) NOT NULL ENABLE,
"LONGUEUR" NUMBER(15,4),
"INSEE_DEPART" VARCHAR2(5),
"INSEE_ARRIVEE" VARCHAR2(5),
"TYPE_ITINERAIRE" VARCHAR2(30),
"TYPE_BALISAGE" VARCHAR2(30),
"COULEUR_BALISAGE" VARCHAR2(55),
"NOM_TOPO_GUIDE" VARCHAR2(255),
"ANNEE_TOPO_GUIDE" VARCHAR2(4),
"DATE_DERNIER_ENTRETIEN" DATE,
"PERIODICITE_PREVUE" VARCHAR2(30),
"DATE_PROCHAIN_ENTRETIEN" DATE,
"ORGANISME_ENTRETIEN" VARCHAR2(60),
"OBSERVATIONS_ENTRETIEN" VARCHAR2(30),
"CREATEUR" VARCHAR2(55),
"COUT_TOTAL" VARCHAR2(50),
"DATE_DECISION_CP" DATE,
"SUBVENTION_ITINERAIRE" NUMBER(8,2),
"SUBVENTION_TOPO" NUMBER(8,2),
"OBSERVATIONS_ADMIN" VARCHAR2(255),
"HEBERGEMENT" VARCHAR2(30),
"MONUMENTS" VARCHAR2(30),
"OBSERVATIONS_TOURISTIQUES" VARCHAR2(30),
"GEOMETRIE" "MDSYS"."SDO_GEOMETRY" ,
"COMMUNE_DEPART" VARCHAR2(55),
"COMMUNE_ARRIVEE" VARCHAR2(55),
"FICHIER_TOPO_GUIDE" VARCHAR2(255)
)
:new is a record containing all columns of the trigger's table, so you can't include the table name when referencing it:
:NEW.PDE_ITINERAIRE.ID_PDE_ITINERAIRE should be :NEW.ID_PDE_ITINERAIRE
Additionally, you don't need the select, you can simply assign the value (at least with any supported version of Oracle):
CREATE OR REPLACE TRIGGER AUTO_INC_PDE_ITINERAIRE
BEFORE INSERT
ON PDE_ITINERAIRE
FOR EACH ROW
BEGIN
:NEW.ID_PDE_ITINERAIRE := PDE_ITINERAIRE_ID_SEQUENCE.NEXTVAL;
END;
/
It is fixed !
I finally downloaded Oracle SQL Developer to check my trigger in another IDE, and it proposed me to link a value (NEW) when i executed it.
This last trick did the job.
I assume either Tora does not execute pl/sql properly, or maybe I missed a declaration for :NEW and SQL Developer fixed it.
Thank you for your help.
Related
I have created a Trigger on table Customers so that every time a record is deleted from table customers this same record is inserted in table Customer_Archives with the current date as Deletion_Date.
I am have to insert a new customer into table Customers and then delete it. The record must be inserted correctly into table Customers_Archive.
Here's script I have so far:
CREATE TABLE Customer_Archives
(
customer_id NUMBER NOT NULL,
customer_first_name VARCHAR2(50),
customer_last_name VARCHAR2(50) NOT NULL,
customer_address VARCHAR2(255) NOT NULL,
customer_city VARCHAR2(50) NOT NULL,
customer_state CHAR(2) NOT NULL,
customer_zip VARCHAR2(20) NOT NULL,
customer_phone VARCHAR2(30) NOT NULL,
customer_fax VARCHAR2(30),
deletion_date DATE,
CONSTRAINT customer_archives_pk
PRIMARY KEY (customer_id)
);
CREATE OR REPLACE TRIGGER Customers_before_insert
BEFORE DELETE ON Customers
FOR EACH ROW
DECLARE
ar_row Customers%rowtype;
BEGIN
INSERT INTO Customer_Archives
VALUES(ar_row.Customer_id,
ar_row.Customer_First_Name,
ar_row.Customer_Last_Name,
ar_row.Customer_Address,
ar_row.Customer_City,
ar_row.Customer_State,
ar_row.Customer_Zip,
ar_row.Customer_Phone,
ar_row.Customer_Fax,
sysdate());
dbms_output.put_line('New row is added to Customers_Archive
Table with Customer_ID:' ||ar_row.Customer_id ||'on date:' || sysdate());
END;
/
SELECT trigger_name, status FROM user_triggers;
INSERT INTO CUSTOMERS
(customer_id, customer_first_name, customer_last_name, customer_address,
customer_city, customer_state, customer_zip, customer_phone, customer_fax)
VALUES (27,'Sofia','Chen','8888 Cowden St.','Philadelphia','PA',
'19149',7654321234',NULL);
DELETE FROM CUSTOMERS
WHERE customer_id = 27;
When I try to delete the customer that I just inserted I get an error:
Error starting at line : 47 in command -
DELETE FROM CUSTOMERS
WHERE customer_id = 27
Error report -
ORA-01400: cannot insert NULL into ("TUG81959"."CUSTOMER_ARCHIVES"."CUSTOMER_ID")
ORA-06512: at "TUG81959.CUSTOMERS_BEFORE_INSERT", line 4
ORA-04088: error during execution of trigger 'TUG81959.CUSTOMERS_BEFORE_INSERT'
In your DELETE trigger you should be using the :OLD values when creating your archive record:
CREATE OR REPLACE TRIGGER CUSTOMERS_BEFORE_INSERT
BEFORE DELETE ON CUSTOMERS
FOR EACH ROW
BEGIN
INSERT INTO CUSTOMER_ARCHIVES
(CUSTOMER_ID,
CUSTOMER_FIRST_NAME,
CUSTOMER_LAST_NAME,
CUSTOMER_ADDRESS,
CUSTOMER_CITY,
CUSTOMER_STATE,
CUSTOMER_ZIP,
CUSTOMER_PHONE,
CUSTOMER_FAX,
DELETION_DATE)
VALUES
(:OLD.CUSTOMER_ID,
:OLD.CUSTOMER_FIRST_NAME,
:OLD.CUSTOMER_LAST_NAME,
:OLD.CUSTOMER_ADDRESS,
:OLD.CUSTOMER_CITY,
:OLD.CUSTOMER_STATE,
:OLD.CUSTOMER_ZIP,
:OLD.CUSTOMER_PHONE,
:OLD.CUSTOMER_FAX,
SYSDATE());
DBMS_OUTPUT.PUT_LINE('New row is added to Customers_Archive
Table with Customer_ID:' ||:OLD.Customer_id ||'on date:' || SYSDATE());
END;
In your original trigger you'd declared a row variable named ar_row but hadn't assigned anything to any of the fields - therefore they were all NULL. When a BEFORE trigger is invoked during a DELETE, the :OLD values have the values prior to the deletion, and the :NEW values are all NULL.
Best of luck.
I'm creating a trigger that will insert a record into another table based on an after update and certain text being referenced in the update..
CREATE OR REPLACE TRIGGER NCATSPROD_PM.DEACTIVATE_USERS
AFTER UPDATE OF "CHANGEBY_CHAR" ON NCATSPROD_PM.PM_USER_DATA
REFERENCING NEW AS "BICSUPP"
BEGIN
INSERT INTO NCATSPROD_PM.DEACTIVATED_USERS (USERNAME, EMAIL, DEACTIVATED_DATE)
VALUES (SELECT USER_ID, EMAIL, CHANGE_DATE FROM ncatsprod_pm.pm_user_data);
END;
When i try to compile this i'm getting an error
Error(1,3): PL/SQL: SQL Statement ignored
Error(1,90): PL/SQL: ORA-00936: missing expression
A little unsure where i'm going wrong with this? Go to source on the error takes me to the AFTER UPDATE line but looking at examples i don't see what's up. I tried using SQL Developer's trigger wizard and that gave me the same result
The REFERENCING clause is just used to change the names of the built-in OLD and NEW records. OLD contains the values of the row before it was updated, and NEW holds the values after it was updated. Here's an example of how you might use them.
create table PM_USER_DATA (user_id varchar2(20), email varchar2(20), change_date date, changeby_char varchar2(20));
create table DEACTIVATED_USERS (username varchar2(20), email varchar2(20), deactivated_date date);
insert into pm_user_data values ('test', 'test#test.com', sysdate, 'SOMEUSER');
create or replace trigger deactivate_users
after update of changeby_char on pm_user_data
referencing old as o1 new as n1
for each row
begin
if :n1.changeby_char = 'BICSUPP' then
insert into deactivated_users (username, email, deactivated_date)
values (:n1.user_id, :n1.email, :n1.change_date);
end if;
end;
/
update pm_user_data set changeby_char = 'BICSUPP';
select * from deactivated_users;
/* output:
USERNAME EMAIL DEACTIVATED_DATE
-------------------- -------------------- ----------------
test test#test.com 10-OCT-17
1 row selected.
*/
Here is a code snippet of a sql script which is giving me error,I have to generate a sequence on the primary_key of the table without using triggers in oracle:
CREATE SEQUENCE t1_seq START WITH 1 INCREMENT BY 1;
DROP TABLE CPR_SOURCE_SYSTEM_METADATA;
CREATE TABLE CPR_SOURCE_SYSTEM_METADATA
(
SYSTEM_ID NUMBER(4) NOT NULL t1_seq.nextval,
SYSTEM_NAME VARCHAR2(200),
DATE_FORMAT VARCHAR2(200),
CREATED_BY VARCHAR2(200),
MODIFIED_BY VARCHAR2(200),
CREATED_ON NUMBER(20),
MODIFIED_ON NUMBER(20),
IS_DELETED VARCHAR2(1),
CONSTRAINT "CPR_SOURCE_SYSTEM_PK" PRIMARY KEY ("SYSTEM_ID")
);
It is giving me the below error :
DROP TABLE CPR_SOURCE_SYSTEM_METADATA
* ERROR at line 1: ORA-00942: table or view does not exist
SYSTEM_ID NUMBER(4) NOT NULL t1_seq.nextval,
* ERROR at line 3: ORA-00907: missing right parenthesis
Not able to figure out the error,can anyone help??
SYSTEM_ID NUMBER(4) NOT NULL t1_seq.nextval,
The t1_seq.nextval segment is not valid - you cannot specify an auto-incrementing column like that.
The SQL parser is expecting to see:
SYSTEM_ID NUMBER(4) NOT NULL,
and throws the exception as the comma is not where it expects.
In Oracle 12c you can use an identity column but in earlier versions you will either need to:
Use the sequence in the SQL insert statement;
Use a trigger to insert the correct sequence value; or
Create a stored procedure to handle inserts and manage the sequence through that (disallowing direct inserts that could bypass this).
I am facing following problem. I created a table with following sql in Oracle 11g release 2:
create table loc_aud
(
username varchar2(20),
audittime date,
IP VARCHAR2(30),
locno number(4),
old_city number(4),
new_city number(4)
);
This table is in sys schema. Then I created a trigger for value base auditing using following command in sys schema
CREATE OR REPLACE TRIGGER location_audit
AFTER UPDATE OF city
ON hr.locations
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
IF :old.city != :new.city THEN
INSERT INTO loc_aud
VALUES (user, sysdate, UTL_INADDR.get_host_address,
:new.location_id,:old.city,:new.city);
END IF;
END;
After that I connected with hr schema and tried to update the city column with following command:
update locations set city = 'Dhaka' where location_id = 2100;
But it is giving me following errors
update locations set city = 'Dubai' where location_id = 2100
*
ERROR at line 1:
ORA-01722: invalid number
ORA-06512: at "SYS.LOCATION_AUDIT", line 3
ORA-04088: error during execution of trigger 'SYS.LOCATION_AUDIT'
What am I doing wrong?
The table I created named loc_aud had a wrong datatype. The column city was varchar2 and what I tried to save in it was a number datatype. I altered the table and it worked.
Is there anyway that we can set a constraint in database table level to have upper or lower case values for certain columns? When we create a table, we can set NOT NULL to avoid having null values on a column. Same way, can we do that for either uppercase or lower case?
You can do that using a check constraint:
create table foo
(
only_lower varchar(20) not null check (lower(only_lower) = only_lower),
only_upper varchar(20) not null check (upper(only_upper) = only_upper)
);
I had almost same case, tried with check constraint, but if the user is not mentioning it as UPPER() or LOWER() it gives error so I took TRIGGER route as below code.
--creating table
create table user_name (
first_name varchar2(50),
last_name varchar2(50));
--creating trigger
CREATE OR REPLACE TRIGGER TRG_USER_NAME_IU
BEFORE INSERT OR UPDATE ON USER_NAME
FOR EACH ROW
BEGIN
:NEW.FIRST_NAME := UPPER(:NEW.FIRST_NAME);
:NEW.LAST_NAME := UPPER(:NEW.LAST_NAME);
END;
/
Can test and share feedback or comments