How to create a new row for the same record after modifying one of the records and updating a new date? - oracle

I am trying to make it so that when I change a description from my records, the table will automatically add a new record with a new PRODUCTKEY value which contains the same data as the previous records but with the new description. This new record will also update the dates so that the new start date will become the previous end date, and the new end date will become the SYSDATE which is the date in which the record was last modified.
I have merged my tables together but MERGING only changes all the dates and doesn't add a new record. I do not know what to do anymore.
Here's an example:
Here's my code:
CREATE TABLE PRODUCT_DIM
(
PRODUCTKEY integer NOT NULL,
PRODUCTID integer,
PRODUCTDESCRIPTION VARCHAR2(50 BYTE),
PRODUCTLINEID integer,
PRODUCTLINENAME VARCHAR2(50 BYTE),
CONSTRAINT PRODUCT_DIM_PK PRIMARY KEY (PRODUCTKEY)
);
ALTER TABLE PRODUCT_DIM
ADD EFF_START_DATE DATE DEFAULT '27-NOV-17';
ALTER TABLE PRODUCT_DIM
ADD EFF_END_DATE DATE DEFAULT '27-NOV-17';
CREATE SEQUENCE PRODUCT_KEY_SEQ
MINVALUE 1001
START WITH 1001
INCREMENT BY 1
CACHE 25;
INSERT INTO PRODUCT_DIM
(PRODUCTKEY, PRODUCTID, PRODUCTDESCRIPTION, PRODUCTLINEID, PRODUCTLINENAME)
SELECT PRODUCT_KEY_SEQ.NEXTVAL, nvl(to_char(p.PRODUCTID), 'Undefined'), nvl(to_char(p.PRODUCTDESCRIPTION), 'Undefined'),
nvl(to_char(p.PRODUCTLINEID), 'Undefined'), nvl(to_char(pl.PRODUCTLINENAME), 'Undefined')
FROM PRODUCTLINE_T pl, PRODUCT_T p
WHERE p.PRODUCTLINEID = pl.PRODUCTLINEID;
INSERT INTO PRODUCT_DIM
(PRODUCTKEY, PRODUCTID, PRODUCTDESCRIPTION, PRODUCTLINEID, PRODUCTLINENAME)
VALUES (PRODUCT_KEY_SEQ.NEXTVAL, -99, 'Undefined', -99, 'Undefined');
CREATE TABLE PRODUCT_DIM_HIS
(
PRODUCTKEY integer NOT NULL,
PRODUCTID integer,
PRODUCTDESCRIPTION VARCHAR2(50 BYTE),
PRODUCTLINEID integer,
PRODUCTLINENAME VARCHAR2(50 BYTE),
EFF_START_DATE DATE,
EFF_END_DATE DATE,
CONSTRAINT PRODUCT_DIM_HIS_PK PRIMARY KEY (PRODUCTKEY)
);
INSERT INTO PRODUCT_DIM_HIS
(PRODUCTKEY, PRODUCTID, PRODUCTDESCRIPTION, PRODUCTLINEID, PRODUCTLINENAME, EFF_START_DATE, EFF_END_DATE)
SELECT PRODUCT_KEY_SEQ.NEXTVAL, nvl(to_char(p.PRODUCTID), 'Undefined'), nvl(to_char(p.PRODUCTDESCRIPTION), 'Undefined'),
nvl(to_char(p.PRODUCTLINEID), 'Undefined'), nvl(to_char(pl.PRODUCTLINENAME), 'Undefined'),
to_date(o.ORDERDATE), to_date(o.FULFILLMENTDATE)
FROM PRODUCTLINE_T pl, PRODUCT_T p, ORDER_T o, ORDERLINE_T ol
WHERE p.PRODUCTLINEID = pl.PRODUCTLINEID
AND o.ORDERID = ol.ORDERID
AND ol.PRODUCTID = p.PRODUCTID;
MERGE INTO PRODUCT_DIM_HIS pdh
USING PRODUCT_DIM pd
ON (pdh.PRODUCTID = pd.PRODUCTID)
WHEN MATCHED THEN
UPDATE SET
EFF_START_DATE = pd.EFF_START_DATE,
EFF_END_DATE = SYSDATE;

You need to write procedural code to manage this. There are various options.
One would be to have a stored procedure to wrap the update and insert implementation. This is probably the cleanest approach; it is definitely the approach to take if you need to do this operation in bulk.
Alternatively write a trigger which populates the history table when the source table is changed.
If you have Enterprise Edition 11.2.0.4 or later you could use the built-in Flashback Data Archive feature which maintains history tables transparently. Find out more.
Which approach is best depends on how you want to use the history table.

Related

How to optional update data on oracle?

i have this table:
CREATE TABLE "ALMAT"."PRODUCT"
( "ID" NUMBER(*,0) NOT NULL ENABLE,
"NAME" VARCHAR2(50 BYTE),
"PRICE" NUMBER(*,0),
"DESCRIPTION" VARCHAR2(180 BYTE),
"CREATE_DATE" DATE,
"UPDATE_DATE" DATE,
CONSTRAINT "PRODUCT_PK" PRIMARY KEY ("ID"))
i want to update data in this table, this is my stored procedure:
CREATE OR REPLACE PROCEDURE UPDATEPRODUCT(prod_id int, prod_name varchar2 default null, prod_price int default null) AS
BEGIN
update product
set
name = prod_name,
price = prod_price,
update_date = sysdate
where id = prod_id;
commit;
END UPDATEPRODUCT;
im using optional parameters, how can i update only 1 column? for example: only "NAME" or "PRICE".
Use COALESCE (or NVL) to keep the current value when a NULL value is passed in (or the default is used):
CREATE OR REPLACE PROCEDURE UPDATEPRODUCT(
prod_id PRODUCT.ID%TYPE,
prod_name PRODUCT.NAME%TYPE DEFAULT NULL,
prod_price PRODUCT.PRICE%TYPE DEFAULT NULL
)
AS
BEGIN
UPDATE product
SET name = COALESCE(prod_name, name),
price = COALESCE(prod_price, price),
update_date = SYSDATE
WHERE id = prod_id;
END UPDATEPRODUCT;
Also, do not COMMIT in a stored procedure as it prevents you from chaining multiple procedures together in a single transaction and rolling them all back as a block. Instead, COMMIT from the PL/SQL block that calls the procedure.
You can use NVL function here. So your updated procedure would look alike -
CREATE OR REPLACE PROCEDURE UPDATEPRODUCT(prod_id int,
prod_name varchar2 default null,
prod_price int default null) AS
BEGIN
UPDATE product
SET name = NVL(prod_name, name),
price = NVL(prod_price, price),
update_date = sysdate
WHERE id = prod_id;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END UPDATEPRODUCT;

how to automatic add word in values after insert table in oracle

I have this table:
create table a(
id_a number(5) not null,
name varchar2(15) not null,
address varchar2(30),
phone varchar2(12),
constraint pk_a primary key (id_a)
);
after i insert into table,
i want to add the word automatic behind the values in field "name".
1, Grace, Aussie, 0111111
then, i want to after insert this. the value Grace automatic add S, Comp behind the word.
1, Grace S.Comp, Aussie, 0111111
thanks
You can use a trigger (before insert - for each row):
create trigger your_trigger_name before insert on a for each row
when (new.name is not null)
begin
:new.name := :new.name || ' S.Comp';
end;
This trigger will change "name" column automatically (only when "name" is not null).

Getting wrong results from fultext search in postgres

This is my table structure:
CREATE TABLE semantified_content_key_word
(
id bigint NOT NULL,
semantified_content_id bigint,
key_word_text text,
content_date timestamp without time zone NOT NULL,
context_id bigint NOT NULL,
CONSTRAINT pk_sckw_id PRIMARY KEY (id )
)
WITH (
OIDS=FALSE
);
ALTER TABLE semantified_content_key_word
OWNER TO postgres;
-- Index: idx_sckw_kwt
-- DROP INDEX idx_sckw_kwt;
CREATE INDEX idx_sckw_kwt
ON semantified_content_key_word
USING gin
(to_tsvector('english'::regconfig, key_word_text) );
-- Index: idx_sckw_sc_id
-- DROP INDEX idx_sckw_sc_id;
CREATE INDEX idx_sckw_sc_id
ON semantified_content_key_word
USING btree
(semantified_content_id );
Following is the data :
INSERT INTO semantified_content_key_word (id, semantified_content_id, key_word_text, content_date, context_id)
VALUES (7347, 7347, ', agreementnumber customer servicecreditdate the guarantor taken exhausted prior being pursuant avoidance doubt shall remain liable case non incomplete', '2014-11-21 00:00:00', 111);
INSERT INTO semantified_content_key_word (id, semantified_content_id, key_word_text, content_date, context_id)
VALUES (7356, 7356, ', ; agreementnumber agreementperiod aircraftmodel commencementdate customer enginemodel enginequantity enginetype foddeductibleamount llpminimumbuild servicecreditdate steppedpopularrate takeoffderate termdate turnaroundtime ion ls initiated manager otherwise) inform whether proposed qualified view lnltlated confirm satisfies criteria out article instruct programme accordingly determined meet pursuant paragraph a) treated subject only g) below b)', '2014-11-21 00:00:00', 111);
INSERT INTO semantified_content_key_word (id, semantified_content_id, key_word_text, content_date, context_id)
VALUES (7441, 7441, ', activationdate agreementnumber enginemodel enginetype llpminimumbuild servicecreditdate steppedpopularrate turnaroundtime leap-1a as united continental customer 1/ neutral qec configuration engines shop maintenance: each engine ', '2014-11-17 00:00:00', 111);
-------------------------------------------------------------
select sckw.*
FROM semantified_content_key_word sckw
where TO_TSVECTOR(sckw.key_word_text) ## TO_TSQUERY('exhausted');
This is the query which i am running. And the keyword "exhausted" is present only in one of the rows but i am getting all the 3 rows.
How to avoid the rows where the keyword is not present
Thanks
Prasanna

updating create view - error ORA-01779:

I've used the CREATE VIEW command to create a view (obviously), and join multiple tables. The CREATE VIEW command works perfectly, but when I try to update the VIEW RentalInfoOct, I receive error "ORA-01779: cannot modify a column which maps to a non key-preserved table"
CREATE VIEW RentalInfoOct
(branch_no, branch_name, customer_no, customer_name, item_no, rental_date)
AS
SELECT i.branchNo, b.branchName, r.customerNo, c.customerName, i.itemNo, r.dateFrom
FROM item i
INNER JOIN rental r
ON i.itemNo = r.itemNo
INNER JOIN branch b
ON i.branchNo = b.branchNo
INNER JOIN customer c
ON r.customerNo = c.customerNo
WHERE r.dateFrom
BETWEEN to_date('10-01-2009','MM-DD-YYYY')
AND to_date('10-31-2009','MM-DD-YYYY')
My update command.
UPDATE RentalInfoOct
SET item_no = '3'
WHERE customer_name = 'April Alister'
AND branch_name = 'Kingsway'
AND rental_date = '10/28/2009'
I'm not sure if this will help in solving the problem, but here are my CREATE TABLE commands
CREATE TABLE Branch
(
branchNo SMALLINT NOT NULL,
branchName VARCHAR(20) NOT NULL,
branchAddress VARCHAR(40) NOT NULL,
PRIMARY KEY (BranchNo)
);
--Item Table Definition
CREATE TABLE Item
(
branchNo SMALLINT NOT NULL,
itemNo SMALLINT NOT NULL,
itemSize VARCHAR(8) NOT NULL,
price DECIMAL(6,2) NOT NULL,
PRIMARY KEY (ItemNo, BranchNo),
FOREIGN KEY (BranchNo) REFERENCES Branch ON DELETE CASCADE,
CONSTRAINT VALIDAMT
CHECK (price > 0)
);
-- Customer Table Definition
CREATE TABLE Customer
(
customerNo SMALLINT NOT NULL,
customerName VARCHAR(15) NOT NULL,
customerAddress VARCHAR(40) NOT NULL,
customerTel VARCHAR(10),
PRIMARY KEY (CustomerNo)
);
-- Rental Table Definition
CREATE TABLE Rental
(
branchNo SMALLINT NOT NULL,
customerNo SMALLINT NOT NULL,
dateFrom DATE NOT NULL,
dateTo DATE,
itemNo SMALLINT NOT NULL,
PRIMARY KEY (BranchNo, CustomerNo, dateFrom),
FOREIGN KEY (BranchNo) REFERENCES Branch(BranchNo) ON DELETE CASCADE,
FOREIGN KEY (CustomerNo) REFERENCES Customer(CustomerNo) ON DELETE CASCADE,
CONSTRAINT CORRECTDATES CHECK (dateTo > dateFrom OR dateTo IS NULL)
);
See: Oracle: multiple table updates => ORA-01779: cannot modify a column which maps to a non key-preserved table
You're attempting to update a view with joins, but the join conditions are not based on a uniqueness constraint, which creates the possibility of multiple rows that are created from a single row in one table.
It seems like you need a Unique Key - Foreign Key relationship between the columns your join condition is based on.
EDIT: I just saw your edit. Changing r.branchNo = b.branchNo to i.branchNo = b.branchNo should go a long way. Not sure how well r.customerNo = c.customerNo will work out.

Oracle trigger to update an entity in different table

So this is from a uni coursework and is my first time working with Oracle (and using triggers). We are supposed to be creating a database for an airlines.
Part of the database is
CREATE TABLE FLIGHT_BOOKING (
BOOKING_ID NUMBER(11) PRIMARY KEY,
BOOKING_TIME DATE NOT NULL,
EMPLOYEE_ID NUMBER(11) NOT NULL,
FLIGHT_ID NUMBER(11) NOT NULL,
TOTAL_COST NUMBER(4,2) NOT NULL
);
CREATE TABLE FLIGHT (
FLIGHT_ID NUMBER(11) PRIMARY KEY,
PLANE_ID NUMBER(11) NOT NULL,
START_ID NUMBER(11) NOT NULL,
DESTINATION_ID NUMBER(11) NOT NULL,
TRANSIT_ID NUMBER(11),
DEPARTURE_TIME DATE NOT NULL,
ARRIVAL_TIME DATE NOT NULL,
NUM_BOOKED NUMBER (4) NOT NULL
);
CREATE TABLE PASSENGER (
PASSENGER_ID NUMBER(11) PRIMARY KEY,
FIRST_NAME VARCHAR2(20) NOT NULL,
MIDDLE_NAME VARCHAR2(20) NULL,
LAST_NAME VARCHAR2(20) NOT NULL,
TELEPHONE NUMBER(11) NOT NULL,
BOOKING_ID NUMBER(11) NOT NULL
);
So what I want to do is create a trigger such that every time a new passenger is added to the PASSENGER table, the trigger finds the corresponding FLIGHT_ID from the FLIGHT_BOOKING table and increments NUM_BOOKED for the corresponding flight in the FLIGHT table.
I have tried going through the oracle documentation, but i could not find anything that describes a situation where two or more tables are concerned.
Any help would be really appreciated!
you can do it like this:
CREATE OR REPLACE TRIGGER update_flight_booking_info
AFTER INSERT ON PASSENGER
FOR EACH ROW
DECLARE
v_flight_id number;
v_booking_id number;
BEGIN
v_booking_id := :new.booking_id ;
select flight_id into v_flight_id
from flight_booking
where booking_id = v_booking_id;
update flight
set NUM_BOOKED = NUM_BOOKED + 1
where flight_id = v_flight_id;
END;
HTH.
I'd rather not store that number, and calculate it as needed, but okay, it is just course material. :)
When you create a trigger, inside it you can put all kinds of code, including update statements.
So you can write a trigger like this:
create or replace trigger TIDB_BOOKING
before insert or delete
for each row
declare
V_Increment int;
begin
-- Inc or dec, depending on insert or update.
-- Hasn't a booking got a number of seats?
-- Also, can bookings be updated/moved to other flights?
-- These problems aren't yet taken into account in this code.
V_Increment := 1;
if deleting then
V_Increment := -1;
update FLIGHT f
set f.NUM_BOOKED = f.NUM_BOOKED + V_Increment
where f.FLIGHT_ID = nvl(:new.FLIGHT_ID, :old.FLIGHT_ID);
end;

Resources