update of multiple columns - plsql

I flipped through the official doc. and the existing threads but couldn't figure out when would the following trigger execute :
CREATE OR REPLACE TRIGGER TRIG_TS_TRANSPORT_AFTER
AFTER INSERT OR
UPDATE OF iud, addressid, idd, rld, pickupaddressid, vessel
ON chassitransports
REFERENCING NEW AS new OLD AS old
FOR EACH ROW
.
.
.
Any one of the columns is updated
ALL the columns are updated
Since the updates occur from an external db, I cannot test the above scenarios :|

It should fire after INSERT of rows or after UPDATE of any of the mentioned column. See below example :
---- Create sample Tables
CREATE TABLE temptable1 (regNo VARCHAR2(20), timec TIMESTAMP(6));
create table TEMPTABLE2
(
idx NUMBER,
regno VARCHAR2(20),
eventb VARCHAR2(20),
timec DATE,
rfid NUMBER
);
----- Trigger definition
CREATE OR REPLACE TRIGGER after_update_tr
AFTER UPDATE OF timec, regNo ON temptable2
FOR EACH ROW
BEGIN
INSERT INTO temptable1
VALUES(:NEW.regNo,
:NEW.timec);
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line(sqlerrm);
END;
------ Fire update statement ----
UPDATE temptable2
SET regNo = 'VISIT0000011'
WHERE timec IS NULL;
and it executed successfully.

Related

How to solve this issue in pl/sql

How to create a trigger which interdicts insertion of symbols and space in a certain column and after insertion just to have only the upper letters
for example:
insert into tale xxx values '"&$))(/-$:&##¥*|^]asjdj';
and the result should be the following:
ASJDJ
thank you
a lot of functions procedures trigger and nothing was right
Add a new column to the table and update that column extracting only the letters from the column with special characters.
Using your eg.
Add new column value in tale table. Right after inserting the xxx column do the updates like:
update tale set value = upper(regexp_substr(xxx,'[[:alpha:]]+'));
That would be a row-level trigger which fires both before insert or update on table so that value is modified in any case. There are various options which let you remove everything but letters; regular expression is simple enough.
Sample table:
SQL> create table test (col varchar2(40));
Table created.
Trigger:
SQL> create or replace trigger trg_biu_test
2 before insert or update on test
3 for each row
4 begin
5 :new.col := upper(regexp_replace(:new.col, '[^[:alpha:]]'));
6 end;
7 /
Trigger created.
Testing:
SQL> insert into test (col) values ('"&$))(/-$:&##¥*|^]asjdj');
1 row created.
SQL> select * from test;
COL
----------------------------------------
YASJDJ
SQL> update test set col = '25xyz';
1 row updated.
SQL> select * from test;
COL
----------------------------------------
XYZ
SQL>

How to write trigger on the source table

I have a table data_package_code with schema as follows:
Name Null? Type
----------------- ----- ------------
mult qty VARCHAR2(2)
CHARGE NUMBER(19,4)
Credit Charge NUMBER(19,4)
Stop Date VARCHAR2(7)
Table_id NUMBER
SYS_CREATION_DATE DATE
I want to implement a trigger which will run an insert statement on the same table to add sysdate in sys_creation_date column.
It is done to store the date on which a new entry is inserted in the table.
My implementation is as follows:
create or replace trigger package_insert_date
before insert on data_package_code for each row
begin
insert into data_package_code(sys_creation_date)
values(sysdate);
end;
But it is giving me an error on line 2.
I am using oracle sql developer for this project.
It is just
create or replace trigger package_insert_date
before insert on data_package_code
for each row
begin
:new.sys_creation_date := sysdate;
end;
Although, you could have created table that way:
create table ...
(...
sys_creation_date date default sysdate --> this
);

PL/SQL not functioning

Im currently trying to implement a row trigger that fires when the new Employee number inserted into the table is not continuous.
"Continuous" in a relationship to the Employee number means the first record inserted will have the Employee number 1, the second record will have the employee number 2, and each next position must have a number greater by one that a number of the previous position.
I have successfully created the trigger, however when I inserted a new record that have an Employee number that is not continuous, my trigger is not fired.
Im unsure where I went wrong and hope I can get some explanation and corrections on my code.
CREATE OR REPLACE TRIGGER CONTENUM
AFTER INSERT ON TRKEMPLOYEE
FOR EACH ROW
DECLARE
continuous_value EXCEPTION;
PRAGMA exception_init(continuous_value, -20111);
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
IF (:NEW.E# > :OLD.E# + 1) THEN
RAISE_APPLICATION_ERROR (-20111,'The value of Employee number must be continuous');
END IF;
END CONTENUM;
/
Here is the format of my sample TRKEMPLOYEE table
CREATE TABLE TRKEMPLOYEE(
E# NUMBER(12) NOT NULL,
NAME VARCHAR(50) NOT NULL,
DOB DATE ,
ADDRESS VARCHAR(300) NOT NULL,
HIREDATE DATE NOT NULL,
CONSTRAINT TRKEMPLOYEE_PKEY PRIMARY KEY(E#) );
Here is my insert statement.
Currently in my table TRKEMPLOYEE there is only 15 rows thus with my insert statement, the trigger should fire but it is not happening.
INSERT INTO TRKEMPLOYEE VALUES( 17, 'David', NULL, 'GB',sysdate );
Thank you.
First of all you are checking AFTER INSERT ON TRKEMPLOYEE which will be executed after the row is inserted.
Secondly, you cannot check :OLD.E# since you are not updating and you are not using a old value.
Also you should drop the trigger at all and use SEQUENCES and let Oracle take care of the auto-increment values every time you add a new employee.
If you want to continue with your current logic, fixes that can be applied:
Change AFTER INSERT ON TRKEMPLOYEE to BEFORE INSERT ON TRKEMPLOYEE
Logic should be changed as below:
CREATE OR REPLACE TRIGGER contenum BEFORE
INSERT ON trkemployee
FOR EACH ROW
DECLARE
continuous_value EXCEPTION;
PRAGMA exception_init ( continuous_value, -20111 );
PRAGMA autonomous_transaction;
max_e# INTEGER;
BEGIN
SELECT
nvl(MAX(e#), 0)
INTO max_e#
FROM
trkemployee;
IF ( :new.e# > max_e# + 1 ) THEN
raise_application_error(-20111, 'The value of Employee number must be continuous');
END IF;
END contenum;
/
I do not recommend this solution because it will start to become slower as your table starts to grow.

How to use a bind variable in trigger body?

I'm new to PL/SQL. I'm using oracle 11g XE along with sql developer. I'm trying to create to create an after insert trigger as follows
create or replace trigger tr1
after
insert ON
employee
for each row
begin
print :new.emp_id;
end;
The employee table is as follows
create table employee
( emp_id varchar2(5) primary key,
emp_name varchar2(10),
salary number,
company varchar2(10) foreign key references companies(comp_name)
);
When I run the statement I got a 'enter binds' window for the bind variable :new. But I was confused that why do I need to enter the value for :new since it is pseudorecord. Then I entered 'employee' as the values for :new. Now I'm getting the following error.
Error(2,8): PLS-00103: Encountered the symbol "" when expecting one of the following: := . ( # % ; The symbol ":=" was substituted for "" to continue.
Your problem is not in the :new pseudorecord. The error is coming from the usage of print, which is used to print the bind variable used in successful PL/SQL block or used in an EXECUTE command. For example, you can use it this way:
VARIABLE n NUMBER
BEGIN
:n := 1;
END;
/
Then
PRINT n;
But if you want to test the value being inserted, you can use DBMS_OUTPUT.PUT_LINE like this:
create or replace trigger tr1
after
insert ON
employee
for each row
BEGIN
dbms_output.put_line(:new.emp_id);
END;
/
Enable DBMS_OUTPUT window in your SQL Developer, then run
insert into employee values(1, 'empName', 1000, 'ABC');
You'll see 1 printed out.
However, you can always test the value from the table. Because the value should be already inserted into table. You can just query.

How to skip a transaction in replicate(Target system) in Goldengate oracle

Requirement:
Source table contains 5 columns. We are replicating 3 columns on target out of 5.
SEQ_ID is additional column on target.
When update operation is performed on columns which are not in target table,SEQ_ID is increased.
SEQ_ID should increase only when update performed on columns which are present on target.
Enabling unconditional supplemental table level logging on selected columns(ID,AGE,COL1) to be replicated:
Source:
Table name: Test1(ID,AGE,COL1,COL2,COL3)
Target:
Table name: Test1(ID,AGE,COL1,SEQ_ID)
We created a sequence to increse the SEQ_ID when a insert or update happens.
Scenario :
If insert or update happens on source table on these columns (ID,AGE,COL1) SEQ_ID is incresed,
and if update happens on others columns(COL2,COL3) SEQ_ID is also getting incremented.
Our Requirement is when update happens on others columns(COL2,COL3) ,SEQ_ID should not get incrementd.
I want to skip the transaction of updates happening on columns(COL2,COL3) .
Source:
Primary extract test_e1
EXTRACT TEST_e1
USERID DBTUAT_GG,PASSWORD dbt_1234
EXTTRAIL /DB_TRACK_GG/GGS/dirdat/dd
GETUPDATEBEFORES
--IGNOREUPDATES
--IGNOREDELETES
NOCOMPRESSUPDATES
TABLE HARI.TEST1,COLS(ID,AGE,COL1),FILTER (ON UPDATE,IGNORE UPDATE, #STREQ(before.AGE, AGE) = 0);
Datapump test_p1:
EXTRACT TEST_P1
USERID DBTUAT_GG,PASSWORD dbt_1234
RMTHOST 10.24.187.235, MGRPORT 7809,
RMTTRAIL /Trail_files/tt
--PASSTHRU
TABLE DBTUAT_GG.TEST1;
Target:
Target Repicat file:
Edit param test_r
REPLICAT TEST_R
USERID GGPROD,PASSWORD GGPROD_123
SOURCEDEFS ./dirsql/def32.sql
HANDLECOLLISIONS
IGNOREDELETES
INSERTMISSINGUPDATES
MAP HARI.TEST1, TARGET HARI.TEST1, &
SQLEXEC (ID test_num,QUERY "select GGPROD.test_seq.NEXTVAL test_val from dual", NOPARAMS), &
COLMAP(USEDEFAULTS,SEQ_ID=test_num.test_val);
Kindly suggest any possible solutions .
First note: you don't need USERID and PASSWORD in the Pump PRM. The Pump process does not connect to any database.
Actually you have already achieved your goal. You are only replicating the data when AGE is modified. There is a FILTER clause in the Extract PRM file. The ID column should not get changed since this is the PK. The only problem is that your are increasing the SEQ_ID if a delete gets replicated.
Something like that should work:
ALLOWDUPTARGETMAP
IGNOREDELETES
-- just inserts and updates that change COL1
MAP HARI.TEST1, TARGET HARI.TEST1, &
SQLEXEC (ID test_num,QUERY "select GGPROD.test_seq.NEXTVAL test_val from dual", NOPARAMS), &
COLMAP(USEDEFAULTS, SEQ_ID = test_num.test_val);
-- just replicate the delete operations
GETDELETES
IGNOREINSERTS
IGNOREUPDATES
MAP HARI.TEST1, TARGET HARI.TEST1;
GETINSERTS
GETUPDATES

Resources