15
Oracle Advanced DML Oracle Advanced DML Alan Beaulieu Alan Beaulieu Beaulieu Consulting Beaulieu Consulting July 2008 July 2008

Oracle Advanced Dml

Embed Size (px)

Citation preview

Page 1: Oracle Advanced Dml

Oracle Advanced DMLOracle Advanced DML

Alan BeaulieuAlan BeaulieuBeaulieu ConsultingBeaulieu Consulting

July 2008July 2008

Page 2: Oracle Advanced Dml

AgendaAgenda

What is Advanced DML?What is Advanced DML? Conditional InsertsConditional Inserts Multi-table InsertsMulti-table Inserts Upserts (Update/Insert)Upserts (Update/Insert) Updating via JoinsUpdating via Joins

Page 3: Oracle Advanced Dml

What is Advanced DML?What is Advanced DML?

Non-standard ways to insert, update, deleteNon-standard ways to insert, update, delete Includes variations on existing statements along Includes variations on existing statements along

with new statementswith new statements Reduces need for procedural code (i.e. PL/SQL)Reduces need for procedural code (i.e. PL/SQL) Especially pertinent to data-warehouse Especially pertinent to data-warehouse

environmentsenvironments

Page 4: Oracle Advanced Dml

InsertsInserts

New (since 9i) variations allow you to: New (since 9i) variations allow you to: Insert rows into one of several tablesInsert rows into one of several tables Insert rows into multiple tablesInsert rows into multiple tables Insert different flavors of the same row multiple Insert different flavors of the same row multiple

timestimes

Page 5: Oracle Advanced Dml

Insert FirstInsert FirstAllows each row to be placed into one of several Allows each row to be placed into one of several

tables using conditional logic.tables using conditional logic.

Example: Insert into either current or history table depending on dateExample: Insert into either current or history table depending on date

INSERT FIRSTINSERT FIRST WHEN cal_dt = trunc(sysdate) THEN INTO pos_sum_dlyWHEN cal_dt = trunc(sysdate) THEN INTO pos_sum_dly VALUES (fund_id, cal_dt, security_id, …)VALUES (fund_id, cal_dt, security_id, …) WHEN cal_dt < trunc(sysdate) THEN INTO pos_sum_dly_histWHEN cal_dt < trunc(sysdate) THEN INTO pos_sum_dly_hist VALUES (fund_id, cal_dt, security_id, …)VALUES (fund_id, cal_dt, security_id, …)SELECT fund_id, cal_dt, asset_id security_id, …SELECT fund_id, cal_dt, asset_id security_id, …FROM cus_pos_extrnlFROM cus_pos_extrnl

Insert today’s data into pos_sum_dly

Insert old data into pos_sum_dly_hist

Page 6: Oracle Advanced Dml

Insert AllInsert AllAllows each row to be placed into 0, 1, …N tables Allows each row to be placed into 0, 1, …N tables

using conditional logic. using conditional logic.

Example: Insert data into pos_sum_dly, along with optional warningsExample: Insert data into pos_sum_dly, along with optional warnings

INSERT ALLINSERT ALL

WHEN mtrty_dt IS NULL THEN INTO WHEN mtrty_dt IS NULL THEN INTO di_exception_rpt

VALUES (VALUES ('INFO:INVALID RSM_MATURITY_DATE in CUSPOS', …), …)

WHEN 1 = 1 THEN INTO pos_sum_dlyWHEN 1 = 1 THEN INTO pos_sum_dly

VALUES (fund_id, cal_dt, security_id, …)VALUES (fund_id, cal_dt, security_id, …)

SELECT fund_id, cal_dt, asset_id security_id, …SELECT fund_id, cal_dt, asset_id security_id, …

FROM cus_pos_extrnlFROM cus_pos_extrnl

Insert warning record if maturity date is NULL

Always insert into pos_sum_dly

Page 7: Oracle Advanced Dml

Insert All (cntd)Insert All (cntd)Allows different flavors of each row to be inserted into the Allows different flavors of each row to be inserted into the

same table.same table.

Example: Add pricing data going out 7 daysExample: Add pricing data going out 7 days

INSERT ALLINSERT ALL

INTO pricing_master INTO pricing_master

VALUES (sec_id, src_cd, prc_typ_cd, crncy_cd, effect_dt, …)VALUES (sec_id, src_cd, prc_typ_cd, crncy_cd, effect_dt, …)

INTO pricing_master INTO pricing_master

VALUES (sec_id, src_cd, prc_typ_cd, crncy_cd, effect_dt + 1, …)VALUES (sec_id, src_cd, prc_typ_cd, crncy_cd, effect_dt + 1, …)

… …

INTO pricing_master INTO pricing_master

VALUES (sec_id, src_cd, prc_typ_cd, crncy_cd, effect_dt + 6, …)VALUES (sec_id, src_cd, prc_typ_cd, crncy_cd, effect_dt + 6, …)

SELECT sec_id, src_cd, prc_typ_cd, crncy_cd, effect_dt, …SELECT sec_id, src_cd, prc_typ_cd, crncy_cd, effect_dt, …

FROM pricing_extrnlFROM pricing_extrnl

Page 8: Oracle Advanced Dml

INSERT/UPDATEINSERT/UPDATE

Pre-9i implementation of INSERT/UPDATE logic…Pre-9i implementation of INSERT/UPDATE logic…

BEGINBEGIN INSERT INTO table_x (a, b, c, …)INSERT INTO table_x (a, b, c, …) VALUES (v_1, v_2, v_3, …);VALUES (v_1, v_2, v_3, …);EXCEPTIONEXCEPTION WHEN DUP_VAL_ON_INDEX WHEN DUP_VAL_ON_INDEX UPDATE table_xUPDATE table_x SET b = v_2, c = v_3SET b = v_2, c = v_3 WHERE a = v_1;WHERE a = v_1;END;END;

Page 9: Oracle Advanced Dml

INSERT/UPDATE (cntd)INSERT/UPDATE (cntd)

New (9i) SQL command : MERGENew (9i) SQL command : MERGE Allows you to both update and insert with a Allows you to both update and insert with a

single statementsingle statement If a row already exists, data is updated; If a row already exists, data is updated;

otherwise, data is insertedotherwise, data is inserted Also includes the ability to do conditional Also includes the ability to do conditional

DELETE’sDELETE’s

Page 10: Oracle Advanced Dml

MergeMergeAllows data to be either updated or inserted using Allows data to be either updated or inserted using

a single SQL statement.a single SQL statement.

Example:Example:

MERGE INTO pos_sum_dly trg USING MERGE INTO pos_sum_dly trg USING

(SELECT fund_id, cal_dt, asset_id security_id, …(SELECT fund_id, cal_dt, asset_id security_id, …

FROM cus_pos_extrnl) srcFROM cus_pos_extrnl) src

ON (trg.fund_id = src.fund_id, trg.cal_dt = src.cal_dt, …)ON (trg.fund_id = src.fund_id, trg.cal_dt = src.cal_dt, …)

WHEN MATCHED THEN UPDATEWHEN MATCHED THEN UPDATE

SET trg.mtrty_dt = src.pos_mtrty_dt, …SET trg.mtrty_dt = src.pos_mtrty_dt, …

WHEN NOT MATCHED THEN INSERTWHEN NOT MATCHED THEN INSERT

VALUES (src.fund_id, src.cal_dt, src.security_id, …)VALUES (src.fund_id, src.cal_dt, src.security_id, …)

Row exists - Update

No row exists - Insert

Page 11: Oracle Advanced Dml

Merge (cntd)Merge (cntd)Don’t need to specify both WHEN MATCHED and WHEN NOT MATCHEDDon’t need to specify both WHEN MATCHED and WHEN NOT MATCHED

Example: Fill in values for denormalized columnExample: Fill in values for denormalized column

MERGE /*+ PARALLEL(trg, 8) */ INTO income_recv_asof trgUSING (SELECT /*+ FULL(ira) PARALLEL(ira, 8) USE_NL_WITH_INDEX(iraf, income_recv_asof_fin_key) */ ira.ssb_fund, ira.period_indicator, ira.income_instance, ira.asof_date, iraf.fin_currency FROM income_recv_asof ira, income_recv_asof_fin iraf WHERE ira.ssb_fund = iraf.ssb_fund AND ira.period_indicator = iraf.period_indicator AND ira.income_instance = iraf.income_instance AND ira.asof_date = iraf.asof_date AND ira.income_currency <> iraf.fin_currency ) srcON (src.ssb_fund = trg.ssb_fund AND src.period_indicator = trg.period_indicator AND src.income_instance = trg.income_instance AND src.asof_date = trg.asof_date)WHEN MATCHED THEN UPDATE SET trg.income_currency = src.fin_currency;

Same table being updated…

Page 12: Oracle Advanced Dml

Updating Using JoinsUpdating Using Joins

SQL Server lets you do the following:SQL Server lets you do the following:

UPDATE Sales.SalesPerson UPDATE Sales.SalesPerson SET SalesYTD = SalesYTD + SubTotal SET SalesYTD = SalesYTD + SubTotal FROM Sales.SalesPerson AS sp FROM Sales.SalesPerson AS sp JOINJOIN Sales.SalesOrderHeader AS so Sales.SalesOrderHeader AS so ON sp.SalesPersonID = so.SalesPersonID ON sp.SalesPersonID = so.SalesPersonID AND so.OrderDate = AND so.OrderDate = (SELECT MAX(OrderDate) FROM Sales.SalesOrderHeader (SELECT MAX(OrderDate) FROM Sales.SalesOrderHeader

WHERE SalesPersonID = sp.SalesPersonID);WHERE SalesPersonID = sp.SalesPersonID);

Page 13: Oracle Advanced Dml

Updating Using Joins (cntd)Updating Using Joins (cntd)

Doesn’t work with Oracle unless you update Doesn’t work with Oracle unless you update through an inline view:through an inline view:

UPDATE (SELECT hdr.fund_type, dhr.fund_type new_typ FROM fund_header hdr INNER JOIN dhr_t dhr ON dhr.ssb_fund = hdr.ssb_fund ) SET fund_type = new_typ;

Page 14: Oracle Advanced Dml

Updating Using Joins (cntd)Updating Using Joins (cntd)

However, opposite statement doesn’t work:However, opposite statement doesn’t work:

UPDATE (SELECT dhr.fund_type, hdr.fund_type new_typ FROM dhr_t dhr INNER JOIN fund_header hdr ON dhr.ssb_fund = hdr.ssb_fund AND hdr.eval_ind = '0' ) SET fund_type = new_typ;Error at line 1ORA-01779: cannot modify a column which maps to a non key-

preserved table

Page 15: Oracle Advanced Dml

Deleting Using JoinsDeleting Using Joins

Again, only through an inline view:Again, only through an inline view:

DELETE (SELECT hdr.ssb_fund FROM fund_header hdr INNER JOIN dhr_t dhr ON dhr.ssb_fund = hdr.ssb_fund WHERE hdr.tot_mkt_value < 1 AND dhr.max_bal < 100 );

Does it matter which columns are selected?