34
1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

Embed Size (px)

Citation preview

Page 1: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

1

All Powder Board and Ski

Oracle 9i WorkbookChapter 7: Integrity and TransactionsJerry PostCopyright © 2003

Page 2: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

2

Compute Sales Tax

Sales Tax

From Figure 6.29

Page 3: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

3

Create Oracle Package and Function

The slash is required to separate the commands

Package definition

Package body

Function definition

Page 4: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

4

Test the Function in SQL

Dual is a tiny system table used for testing because it has one column and one row

Package name

Function name

Correct result: 7 percent of 500

Page 5: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

5

Add Event Code to the Sales Form

Choose the PRE-TEXT-ITEM event

Call the new function

Page 6: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

6

Debugging

Double click to set breakpoint

Debug/Debug ModuleDebug/Step Into

See form and variable values with Debug/Debug Windows

Page 7: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

7

Inventory Database Triggers

Sale(SaleID, CustomerID, EmployeeID, SaleDate, …)

SaleItem(SaleID, SKU, QuantitySold, SalePrice)

Inventory(SKU, QuantityOnHand, …)

If a new item is sold, subtract QuantitySold from QuantityOnHandComplications: changes to the data

A SaleItem is revoked, the SaleItem row deletedThe QuantitySold is changedThe SKU is changed

Sample values:SaleID=3000 SKU=500000 or 500010CustomerID=582 EmployeeID=5

Page 8: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

8

Database Event Triggers

DELETE

BEFORE INSERT AFTER

UPDATE

CREATE OR REPLACE TRIGGER NewSaleQOHAFTER INSERT ON SaleItemFOR EACH ROW

BEGINUPDATE INVENTORY SET QuantityOnHand = QuantityOnHand - :NEW.QuantitySold WHERE SKU = :NEW.SKU;

END;

New/inserted value

Page 9: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

9

Setup Example

INSERT INTO Sale (SaleID, CustomerID, EmployeeID)VALUES (3000, 582, 5);

SELECT SKU, QuantityOnHandFROM InventoryWHERE SKU=500000;

INSERT INTO SaleItem (SaleID, SKU, QuantitySold, SalePrice)VALUES (3000, 500000, 1, 100);

Check the QuantityOnHand before and after the INSERT

Page 10: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

10

Potential Problem: Delete Row

DELETE FROM SaleItemWHERE SaleID=3000 And SKU=500000;

Check the QuantityOnHand before and after the DELETEThe value does not change!

CREATE OR REPLACE TRIGGER DelSaleQOHAFTER DELETE ON SaleItemFOR EACH ROW

BEGINUPDATE INVENTORY SET QuantityOnHand = QuantityOnHand + :OLD.QuantitySold WHERE SKU = :OLD.SKU;

END;

Restore the deleted quantity

Page 11: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

11

Problems

What if the clerk entered the wrong value and should have entered 1 instead of 2 units?

Test it, and the code subtracts 1 from the QOH, leaving 7.

You need to add the original 2 units back.

QuantityOnHand = QuantityOnHand – QuantitySold + OldQuantity

Page 12: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

12

Problem: Change the Quantity

CREATE or REPLACE TRIGGER ChangeSaleQOHAFTER UPDATE ON SaleItemFOR EACH ROW

BEGINUPDATE Inventory SET QuantityOnHand = QuantityOnHand

+ :OLD.QuantitySold - :NEW.QuantitySoldWHERE SKU = :OLD.SKU;

END;

UPDATE SaleITemSET QuantitySold = 2WHERE SaleID=3000 And SKU=500000;

Test it

Test it again

Add back the old quantity (1) and subtract the new value (2)

Page 13: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

13

Problem: Change the SKU

UPDATE SaleITemSET QuantitySold = 3, SKU = 500010WHERE SaleID=3000 And SKU=500000;

Test it by changing both QuantitySold and SKU

SELECT SKU, QuantityOnHandFROM InventoryWHERE SKU=500000 Or SKU=500010;

SELECT SKU, QuantityOnHandFROM InventoryWHERE SKU=500000 Or SKU=500010;

Page 14: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

14

Trigger to Handle SKU Changes

CREATE or REPLACE TRIGGER ChangeSaleQOHAFTER UPDATE ON SaleItemFOR EACH ROW

BEGINIF (:OLD.SKU = :NEW.SKU) THEN

UPDATE Inventory SET QuantityOnHand = QuantityOnHand

+ :OLD.QuantitySold - :NEW.QuantitySoldWHERE SKU = :OLD.SKU;

ELSEUPDATE InventorySET QuantityOnHand = QuantityOnHand + :OLD.QuantitySoldWHERE SKU = :OLD.SKU;UPDATE InventorySET QuantityOnHand = QuantityOnHand - :NEW.QuantitySoldWHERE SKU = :NEW.SKU;

END IF;END; Test it again

Page 15: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

15

Transactions for Discounts

New table

Page 16: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

16

Rental Form

Button to open discount form

Page 17: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

17

Rental Discount Form

RentID and Amount are determined by the Rental form

Date default value is set to $$DATETIME$$ This is an unbound form built from

design view with no Data Block source

Page 18: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

18

Rental Form Code: Discount Button

:global.RentID := :Rental.RentID;:global.Amount := :Rental.SubCharges;Call_Form('D:\Students\AllPowder\GiveRentDiscount');

Save the RentID and total repair charges into global variables that can be retrieved by the discount form when it starts.

Rental Form, Button to open Discount form

Trigger event: WHEN-BUTTON-PRESS

Page 19: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

19

Discount Form Triggers

:RentalID := :global.RentID;:Amount := :global.Amount;

Form: WHEN-NEW-FORM-INSTANCE

UPDATE RentItem SET RepairCharges=0 WHERE RentID = :RentalID;

INSERT INTO RentalDiscount(RentID, DiscountDate, DiscountAmount, Reason)VALUES (:RentalID, :TransDate, :Amount, :Reason);Commit;:txtMessage := 'Changes recorded.';

Button: WHEN-BUTTON-PRESSED

Page 20: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

20

Transaction Code

BEGINUPDATE RentItem SET RepairCharges=0 WHERE RentID = :RentalID;

INSERT INTO RentalDiscount(RentID, DiscountDate, DiscountAmount, Reason)

VALUES (:RentalID, :TransDate, :Amount, :Reason);Commit;:txtMessage := 'Changes recorded.';

EXCEPTIONWHEN OTHERS THENRollback;

END;

WHEN-BUTTON-PRESSED

If something goes wrong, cancel the first update

Page 21: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

21

Query for Cursor: Weekly Sales

CREATE VIEW WeeklySales ASSELECT TO_CHAR(SaleDate, 'ww') AS SalesWeek,

Sum(SalePrice*QuantitySold) AS ValueFROM Sale INNER JOIN SaleItem ON Sale.SaleID=SaleItem.SaleIDWHERE SaleDate Is Not NullGROUP BY TO_CHAR(SaleDate, 'ww');

Page 22: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

22

Set up Package to Compute Average

CREATE OR REPLACE PACKAGE SalesAnalysis ASFUNCTION AvgPercentWeeklyChange return REAL;

END SalesAnalysis;/CREATE or REPLACE PACKAGE BODY SalesAnalysis AS

FUNCTION AvgPercentWeeklyChange return REAL ISCURSOR c1 IS

SELECT SalesWeek, Value FROM WeeklySales;Avg1 REAL;N Integer;PriorValue WeeklySales.Value%TYPE;

Define the SELECT statement for the cursor to trace throughCreate variable to hold the

value from the previous row with the same data type as the column in the table

Page 23: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

23

Code to Compute Average Change

BEGINAvg1 := 0;N := 0;PriorValue := -1;FOR recSales in c1 LOOP

IF PriorValue > 0 THENAvg1 := Avg1 + (recSales.Value - PriorValue)/PriorValue;N := N + 1;

END IF;PriorValue := recSales.Value;

END LOOP;RETURN (Avg1/N);

END AvgPercentWeeklyChange;END SalesAnalysis;/

Skip the first week because there is no prior value

Compute the percent change and keep a running total

Save the current row value and move to the next row

Page 24: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

24

A Sequence for the Sale Table

CREATE SEQUENCE seq_SaleINCREMENT BY 1START WITH 10000NOMAXVALUENOCYCLECACHE 10;

Start at a high number to avoid collisions with existing data

Page 25: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

25

Trigger to Generate Key

CREATE OR REPLACE TRIGGER GenKeyForSaleBEFORE INSERT ON SaleFOR EACH ROW

BEGINSELECT seq_Sale.NEXTVAL INTO :NEW.SaleID FROM dual;

END;/

Automatically generate and use a new key value for SaleID whenever a row is added to the Sale table

Generate next value Use it as the new SaleID

Page 26: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

26

Test the Key Generator

INSERT INTO Sale (CustomerID, EmployeeID) VALUES (582, 5);

SELECT seq_Sale.CURRVAL FROM dual;

SELECT * FROM Sale WHERE SaleID=10000;

Insert a row into Sale without specifying a SaleID

See what key value was generated

Retrieve the sales data to ensure the row was created

Page 27: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

27

Keys: Create Sales and Items (barcode)

Customer ID card is scanned

Create new sale

Scan an item

Save sale item, update QOH and totals

Repeat until done (payment key)

Get SaleID

Save SaleID, SKU, Quantity

Page 28: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

28

Generate Sale Form

IDs and SKU would be scanned, but to test code, set default values

Page 29: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

29

Concurrency and Lock Test Form

Page 30: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

30

PL/SQL to Change ZIP Code

BEGINUPDATE CustomerSET ZIP = :ZIPCodeWHERE CustomerID = :CustomerID;Commit;

END;

Page 31: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

31

Customer List Form

Page 32: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

32

Read Consistent Lock on the Form

Open both forms and use the testing form to change the ZIP code for CustomerID=1

Error message that value was changed

Return here and try to change the ZIP code

Page 33: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

33

Stronger Lock on the Test Form

DECLAREconcurrency_hit EXCEPTION;PRAGMA EXCEPTION_INIT(concurrency_hit, -8177);

BEGINSET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

UPDATE CustomerSET ZIP = :ZIPCodeWHERE CustomerID = :CustomerID;Commit;

EXCEPTIONWHEN concurrency_hit THEN

message ('Data has been changed by another process.');WHEN OTHERS THEN

message ('Unknown error.');END;

Name the concurrency error

Set strongest isolation level

Catch error raised by this update interrupting another one

Notify user who can decide to try again or exit

Page 34: 1 All Powder Board and Ski Oracle 9i Workbook Chapter 7: Integrity and Transactions Jerry Post Copyright © 2003

34

Serializable Isolation Level

The change is not made and the error is trapped because the row is locked