You are on page 1of 43

Database Management Systems

Chapter 7
Database Integrity and
Transactions

Jerry Post
Copyright © 2003
1
D Programming Environment
A  Create code Tables DBMS
T (1) Within the query system
(2) In forms and reports
Queries
(1)
A (3) Hosted in external programs
If ( . . ) Then

Else . . .
SELECT . . .

B External
Program (3)
Forms &
Reports
End If
UPDATE . . .

A C++
if (. . .) {

S // embed SQL
SELECT …
(2)
If (Click) Then
} MsgBox . . .
E End If

2
D User-Defined Function
A CREATE FUNCTION EstimateCosts
(ListPrice Currency, ItemCategory VarChar)

T RETURNS Currency
BEGIN
IF (ItemCategory = ‘Clothing’) THEN
A ELSE
RETURN ListPrice * 0.5

B END IF
RETURN ListPrice * 0.75

A END

S
E
3
D Function to Perform Conditional Update
A CREATE FUNCTION IncreaseSalary

T (EmpID INTEGER, Amt CURRENCY)


RETURNS CURRENCY
BEGIN
A IF (Amt > 50000) THEN
RETURN -1 -- error flag

B END
UPDATE Employee SET Salary = Salary + Amt
WHERE EmployeeID = EmpID;
A END
RETURN Amt

S
E
4
D Looking Up Data
A CREATE FUNCTION IncreaseSalary
(EmpID INTEGER, Amt CURRENCY)

T RETURNS CURRENCY
DECLARE
CURRENCY MaxAmount;
A BEGIN
SELECT MaxRaise INTO MaxAmount
FROM CompanyLimits
B WHERE LimitName = ‘Raise’;

A IF (Amt > 50000) THEN

END
RETURN -1 -- error flag

S UPDATE Employee SET Salary = Salary + Amt


WHERE EmployeeID = EmpID;
RETURN Amt;
E END

5
D Data Trigger Events
A INSERT
T BEFORE DELETE AFTER

A UPDATE

B
 Oracle additions:
A  Tables ALTER, CREATE, DROP
 User LOGOFF, LOGON
S  Database SERVERERROR, SHUTDOWN, STARTUP

E
6
D Statement v. Row Triggers
A UPDATE Employee
T SQL SET Salary = Salary + 10000
WHERE EmployeeID=442

A OR EmployeeID=558

B Before Update
On table
Triggers for overall table After Update
On table

A Update After Update … other rows


Before Update time
S Row 442 Row 442

Triggers for each row


Row 442

E
7
D Data Trigger Example
A CREATE TRIGGER LogSalaryChanges
T AFTER UPDATE OF Salary ON Employee
REFERENCING OLD ROW as oldrow

A FOR EACH ROW


NEW ROW AS newrow

INSERT INTO SalaryChanges


B (EmpID, ChangeDate, User, OldValue, NewValue)
VALUES
A (newrow.EmployeeID, CURRENT_TIMESTAMP,
CURRENT_USER, oldrow.Salary, newrow.Salary);

S
E
8
D Canceling Data Changes in Triggers
A CREATE TRIGGER TestDeletePresident
T BEFORE DELETE ON Employee
REFERENCING OLD ROW AS oldrow

A FOR EACH ROW


WHEN (oldrow.Title = ‘President’)
SIGNAL _CANNOT_DELETE_PRES;
B
A
S
E
9
D Cascading Triggers
A Sale(SaleID, SaleDate, …)
SaleItem(SaleID, ItemID, Quantity, …)
T AFTER INSERT
UPDATE Inventory

A Inventory(ItemID, QOH, …)
SET QOH = QOH – newrow.Quantity

B AFTER UPDATE
WHEN newrow.QOH < newrow.Reorder

A INSERT {new order}


INSERT {new OrderItem}

S Order(OrderID, OrderDate, …)

OrderItem(OrderID, ItemID, Quantity, …)

E
10
D Trigger Loop
A Employee(EID, Salary) AFTER UPDATE
IF newrow.Salary > 100000 THEN

T END
Add Bonus

A BonusPaid(EID, BonusDate, Amount)


AFTER UPDATE Or INSERT
IF newrow.Bonus > 50000 THEN
B Reduce Bonus
Add Options
END
A StockOptions(EID, OptionDate, Amount, SalaryAdj)

S AFTER UPDATE Or INSERT


IF newrow.Amount > 100000 THEN
Reduce Salary
E END

11
D Transactions
 Some transactions result in multiple
A changes.
 These changes must all be Savings Accounts

T completed successfully, or the


group must fail. Inez: 5340.92
4340.92
 Protection for hardware and
A communication failures.
 example: bank customer
$1000
Checking Accounts

B transfers money from savings


account to checking account.
 Decrease savings balance
Inez: 1424.27

A  Increase checking balance


 Problem if one transaction and
Transaction

S
machine crashes.
1. Subtract $1000 from savings.
 Possibly: give users a chance to
(machine crashes)
reverse/undo a transaction. 2. Add $1000 to Checking.
E  Performance gain by executing
transactions as a block.
(money disappears)

12
D Defining Transactions
A  The computer needs to be told which
changes must be grouped into a
T transaction.
 Turn on transaction processing.
A  Signify a transaction start.
 Signify the end.
B  Success: save all changes
 Failure: cancel all changes

A  Must be set in module code


 Commit
S  Rollback

E
13
D SQL Transaction Code

A
CREATE FUNCTION TransferMoney(Amount Currency, AccountFrom Number,
AccountTo Number) RETURNS NUMBER
curBalance Currency;

T
BEGIN
DECLARE HANDLER FOR SQLEXCEPTION
BEGIN

A
ROLLBACK;
Return -2; -- flag for completion error
END;

B
START TRANSACTION; -- optional
SELECT CurrentBalance INTO curBalance
FROM Accounts WHERE (AccountID = AccountFrom);

A
IF (curBalance < Amount) THEN
RETURN -1; -- flag for insufficient funds
END IF

S
UPDATE Accounts
SET CurrentBalance = CurrentBalance – Amount
WHERE AccountID = AccountFrom;

E
UPDATE Accounts
SET CurrentBalance = CurrentBalance + Amount
WHERE AccountID = AccountTo;
COMMIT;
RETURN 0; -- flag for success 14
END;
D SAVEPOINT
A start
SAVEPOINT
StartOptional commit

T Required elements Risky steps


time
Partial
A rollback

B
START TRANSACTION;
SELECT …
UPDATE …

A SAVEPOINT StartOptional;
UPDATE …
UPDATE …
S If error THEN
ROLLBACK TO SAVEPOINT StartOptional;

E
END IF
COMMIT;

15
D Concurrent Access
 Concurrent Access  Two processes
A  Multiple users or  Receive payment ($200)
processes changing the
T same data at the same
time.
 Place new order ($150)
 Initial balance $800
A  Final data will be wrong!  Result should be $800
-200 + 150 = $750
 Force sequential
B  Locking
 Interference result is
either $600 or $950
 Delayed, batch updates
A Receive Payment
Customers
Place New Order
ID Balance
S 1) Read balance
2) Subtract pmt
800
-200
Jones $800
$600
3) Read balance
5) Add order
800
150

E 4) Save new bal. 600 $950 6) Write balance 950

16
D Pessimistic Locks: Serialization
A  One answer to concurrent access is to prevent it.
T  When a transaction needs to alter data, it places a
SERIALIZABLE lock on the data used, so no other transactions
A can even read the data until the first transaction is completed.

B SET TRANSACTION SERIALIZABLE, READ WRITE


A Receive Payment
Customers
Place New Order
ID Balance
S 1) Read balance
2) Subtract pmt
800
-200
Jones $800
$600
3) Read balance
Receive error

E
message that it is
4) Save new bal. 600
locked.

17
D SQL Pessimistic Lock

A CREATE FUNCTION ReceivePayment (

BEGIN
AccountID NUMBER, Amount Currency) RETURNS NUMBER

T DECLARE HANDLER FOR SQLEXCEPTION


BEGIN
ROLLBACK;
A END
RETURN -2;

B SET TRANSACTION SERIALIZABLE, READ WRITE;


UPDATE Accounts
SET AccountBalance = AccountBalance - Amount
A WHERE AccountNumber = AccountID;
COMMIT;
RETURN 0;
S END

E
18
D Deadlock
A 1) Lock Data A
 Deadlock
T  Two (or more) processes have
placed locks on data and are
3) Wait for Data B

A waiting for the other’s data.


 Many solutions
B  Random wait time
 Global lock manager
Data A Data B

A  Two-phase commit - messages

S 2) Lock Data B
4) Wait for Data A
E
19
D Lock Manager
A Resource Resource Resource Resource Resource

T Process1
A B
Lock
C D
Wait
E

A Process2 Wait Lock

B
Process3 Lock

Process4 Lock Wait

A Process5 Wait

S Process6 Wait Lock

Process7 Wait Wait


E
20
D Optimistic Locks
A  Assume that collisions are rare
 Improved performance, fewer resources
T  Allow all code to read any data (no locks)

A  When code tries to write a new value


 Check to see if the existing value is different from the one

B you were given earlier


 If it is different, someone changed the database before

A you finished, so it is a collision--raise an error


 Reread the value and try again

S
E
21
D Optimistic Locks for Simple Update
A
(1) Read the balance
T (2) Add the new order value
A (3) Write the new balance

B (4) Check for errors


(5) If there are errors, go back to step (1).
A
S
E
22
D Optimistic Locks with SQL
A CREATE FUNCTION ReceivePayment (
AccountID NUMBER, Amount Currency) RETURNS NUMBER
oldAmount Currency;

T testEnd Boolean = FALSE;


BEGIN
DO UNTIL testEnd = TRUE

A BEGIN
SELECT Amount INTO oldAmount
WHERE AccountNumber = AccountID;

B …
UPDATE Accounts
SET AccountBalance = AccountBalance - Amount

A WHERE AccountNumber = AccountID


AND Amount = oldAmount;
COMMIT;

S IF SQLCODE = 0 and nrows > 0 THEN


testEnd = TRUE;
RETURN 0;

E
END IF
-- keep a counter to avoid infinite loops
END
END
23
D ACID Transactions
A
 Atomicity: all changes succeed or fail together.
T  Consistency: all data remain internally consistent
(when committed) and can be validated by
A application checks.

B  Isolation: The system gives each transaction the


perception that it is running in isolation. There are no
A concurrent access issues.
 Durability: When a transaction is committed, all
S changes are permanently saved even if there is a
hardware or system failure.
E
24
D SQL 99/200x Isolation Levels
A  READ UNCOMMITTED
 Problem: might read dirty data that is rolled back

T
 Restriction: not allowed to save any data
 READ COMMITTED
 Problem: Second transaction might change or delete data

A  Restriction: Need optimistic concurrency handling


 REPEATABLE READ
 Problem: Phantom rows
B  SERIALIZABLE
 Provides same level of control as if all transactions were run

A
sequentially.
 But, still might encounter locks and deadlocks

S
E
25
D Phantom Rows
A SELECT SUM(QOH)
FROM Inventory
WHERE Price BETWEEN 10 and 20
T Included ItemID QOH Price
UPDATE Inventory
A in first
query
111
113
5
6
15
7
SET Price = Price/2
WHERE …

B 117
118
12
4
30
12
A 119 7 22 Additional rows
will be included in
120 8 17
S
the second query

SELECT SUM(QOH)

E FROM Inventory
WHERE Price BETWEEN 10 and 20

26
D Generated Keys
A Customer Table

T Create an order for a new customer: CustomerID, Name, …

(1) Create new key for CustomerID


A (2) INSERT row into Customer
(3) Create key for new OrderID

B (4) INSERT row into Order Order Table


OrderID, CustomerID, …
A
S
E
27
D Methods to Generate Keys
A 1. The DBMS generates key values automatically whenever a
row is inserted into a table.
T Drawback: it is tricky to get the generated value to use it in

A
a second table.

2. A separate key generator is called by a programmer to create

B a new key for a specified table.

Drawback: programmers have to write code to generate a


A key for every table and each row insertion.

S
Overall drawbacks: neither method is likely to be
transportable. If you change the DBMS, you will have to
rewrite the procedures to generate keys.

E
28
D Auto-Generated Keys
A
T Create an order for a new customer:

(1) INSERT row into Customer


A (2)
(3)
Get the key value that was generated
Verify the key value is correct. How?

B (4) INSERT row into Order

A Major problem:
Step 2 requires that the DBMS return the key value that was
most recently generated. How do you know it is the right
S value? What happens if two transactions generate keys at
almost the same time on the same table?
E
29
D Key-Generation Routine
A
T Create an order for a new customer:

(1) Generate a key for CustomerID


A (2)
(3)
INSERT row into Customer
Generate a key for OrderID

B (4) INSERT row into Order

A This method ensures that unique keys are generated, and that
you can use the keys in multiple tables because you know the
value. But, none of it is automatic. It always requires
S procedures and sometimes data triggers.

E
30
D Database Cursors
A
 Purpose Year Sales

T  Track through table or


query one row at a time.
1998
1999
104,321
145,998
2000 276,004
A  Data cursor is a pointer to
active row.
2001 362,736

B  Why?
 Performance.
A  SQL cannot do everything.
 Complex calculations.

S  Compare multiple rows.

E
31
D Database Cursor Program Structure
A DECLARE cursor1 CURSOR FOR
SELECT AccountBalance

T FROM Customer;
sumAccount, balance Currency;
SQLSTATE Char(5);

A BEGIN
sumAccount = 0;
OPEN cursor1;
B WHILE (SQLSTATE = ‘00000’)
BEGIN

A FETCH cursor1 INTO balance;


IF (SQLSTATE = ‘00000’) THEN
sumAccount = sumAccount + balance;

S END
END IF

CLOSE cursor1;
E END
-- display the sumAccount or do a calculation

32
D Cursor Positioning with FETCH
A DECLARE cursor2 SCROLL CURSOR FOR
SELECT …

T OPEN cursor2;
FETCH LAST FROM cursor2 INTO …
Loop…
A FETCH PRIOR FROM cursor2 INTO …
End loop

B
CLOSE cursor2;

FETCH positioning options:


A FETCH NEXT
FETCH PRIOR
next row
prior row
FETCH FIRST first row
S FETCH LAST
FETCH ABSOLUTE 5
last row
fifth row

E FETCH RELATIVE -3 back 3 rows

33
D Problems with Multiple Users

A Original Data Modified Data

T
Name Sales Name Sales
Alice 444,321 Alice 444,321
Carl 254,998 Bob 333,229
New row is
A Donna
Ed
652,004
411,736
added--while
code is running.
Carl
Donna
Ed
254,998
652,004
411,736
B The SQL standard can prevent this problem with the
A INSENSITIVE option:
DECLARE cursor3 INSENSITIVE CURSOR FOR …
S But, this is an expensive approach, because
E the DBMS usually makes a copy of the data.
Instead, avoid moving backwards.

34
D Changing Data with Cursors
A DECLARE cursor1 CURSOR FOR
SELECT Year, Sales, Gain
FROM SalesTotal
Year
2000
Sales
151,039
Gain

T ORDER BY Year
FOR UPDATE OF Gain;
2001
2002
179,332
195,453
priorSales, curYear, curSales, curGain
A BEGIN
priorSales = 0;
2003
2004
221,883
223,748

B OPEN cursor1;
Loop:
FETCH cursor1 INTO curYear, curSales, curGain
A UPDATE SalesTotal
SET Gain = Sales – priorSales
WHERE CURRENT OF cursor1;
S priorSales = curSales;
Until end of rows

E END
CLOSE cursor1;
COMMIT;

35
D Dynamic Parameterized Cursor Queries
A DECLARE cursor2 CURSOR FOR
SELECT ItemID, Description, Price
T FROM Inventory
WHERE Price < :maxPrice;

A
maxPrice Currency;
BEGIN
maxPrice = … -- from user or other query

B OPEN cursor2;
Loop:
-- runs query with current value

-- Do something with the rows retrieved


A Until end of rows
CLOSE cursor2;

S
END

Parameters enable you to control the rows retrieved dynamically

E from within the procedure code. The value is applied when the
cursor is opened.

36
D Sally’s Pet Store Inventory
A
 Inventory method 1: calculate the current quantity on
T hand by totaling all purchases and sales every time
the total is needed.
A  Drawback: performance
 Inventory method 2: keep a running balance in the
B inventory table and update it when an item is
purchased or sold.
A  Drawback: tricky code

S  Also, you need an adjustment process for “inventory


shrink”
E
37
D Inventory QuantityOnHand
A Merchandise

T
ItemID
Description Add items purchased
QuantityOnHand Subtract items sold
A ListPrice
Category Adjust for shrink

B SaleItem

A SaleID
ItemID

S
Quantity
SalePrice

E
38
D Inventory Events
A SaleItem  For a new sale, a row is added to
the SaleItem table.
SaleID
T ItemID
Quantity
 A sale or an item could be
removed because of a clerical

A SalePrice error or the customer changes his


or her mind. A SaleItem row will
be deleted.
B (1) Add a row.  An item could be returned, or the
quantity could be adjusted
(2) Delete a row.
A (3) Update Quantity.
because of a counting error. The
Quantity is updated in the

S (4) Update ItemID.


SaleItem table.
 An item is entered incorrectly.
ItemID is updated in the SaleItem
E table.

39
D New Sale: Insert SaleItem Row
A CREATE TRIGGER NewSaleItem
AFTER INSERT ON SaleItem
T REFERENCING NEW ROW AS newrow
FOR EACH ROW

A
UPDATE Merchandise
SET QuantityOnHand = QuantityOnHand – newrow.Quantity
WHERE ItemID = newrow.ItemID;

B
A
S
E
40
D Delete SaleItem Row
A CREATE TRIGGER DeleteSaleItem
AFTER DELETE ON SaleItem
T REFERENCING OLD ROW AS oldrow
FOR EACH ROW

A
UPDATE Merchandise
SET QuantityOnHand = QuantityOnHand + oldrow.Quantity
WHERE ItemID = oldrow.ItemID;

B
A
S
E
41
D Quantity Changed Event
A CREATE TRIGGER UpdateSaleItem
AFTER UPDATE ON SaleItem
T REFERENCING OLD ROW AS oldrow
NEW ROW AS newrow

A
FOR EACH ROW
UPDATE Merchandise
SET QuantityOnHand = QuantityOnHand

B + oldrow.Quantity – newrow.Quantity
WHERE ItemID = oldrow.ItemID;

A
S
E
42
D ItemID or Quantity Changed Event
A CREATE TRIGGER UpdateSaleItem
AFTER UPDATE ON SaleItem
T REFERENCING OLD ROW AS oldrow
NEW ROW AS newrow

A
FOR EACH ROW
BEGIN
UPDATE Merchandise

B SET QuantityOnHand = QuantityOnHand + oldRow.Quantity


WHERE ItemID = oldrow.ItemID;

A UPDATE Merchandise
SET QuantityOnHand = QuantityOnHand – newRow.Quantity

S
WHERE ItemID = newrow.ItemID;
COMMIT;
END

E
43

You might also like