DB2 Basics: Creating Your First Trigger in DB2 Universal Database

Creating DB2 triggers doesn't have to be complicated. Join Kulvir Singh Bhogal as he walks you through the process of creating a trigger used in a mock banking scenario.

Share:

Kulvir Bhogal, Consultant, IBM

Kulvir Singh Bhogal works as an IBM consultant, devising and implementing Java-centric solutions at customer sites across the nation. You can reach Kulvir at kbhogal@us.ibm.com.



14 August 2003

© 2003 International Business Machines Corporation. All rights reserved.

Introduction

IBM DB2 e-kit for Database Professionals

Learn how easy it is to get trained and certified for DB2 for Linux, UNIX, and Windows with the IBM DB2 e-kit for Database Professionals. Register now, and expand your skills portfolio, or extend your DBMS vendor support to include DB2.

When certain events take place in an IBM® DB2® Universal DatabaseTM database, you can fire triggers that can perform other actions. In this article, you'll explore the world of triggers and see how they can be used to enforce business rules in your database. You'll also learn how the DB2 UDB Version 8.1 Control Center can help you build a simple trigger that can be applied to a simple business scenario.

What are triggers

When a specified SQL operation -- a DELETE, INSERT, or UPDATE -- occurs on a table, a trigger can be activated that defines a set of actions. Triggers, unlike referential and check constraints, can even be used to update other tables.

Our business scenario

It always helps to apply a technology to a real-world scenario. For educational purposes, let's study triggers in the context of a bank that has a simple setup of just one table. Again, I did say this was simplified! What we will be doing with triggers is facilitating the overdraft protection that some banks offer. For example, a bank customer has a checking account and a savings account. When an amount is withdrawn from their checking account that exceeds the balance of the checking account, an automated transfer of funds (coined overdraft protection) can take place that transfers money from the customer's savings account. Of course, conditions must be checked to ensure that the savings account in question has enough money in it to make up for the overage.


Setting up shop

As mentioned above, our bank will consist of only one table. In it, we'll house information about a customer's checking account and savings account balances. Each customer is identified by their social security number. Here is a description of the table:

Table 1. Description of ACCTTABLE

Column NameColumn TypeNullable?
SSN*Varchar(11)NO
LastNameVarchar(30)NO
FirstNameVarchar(30)NO
SavingBalanceDecimal (Precision: 7, Scale: 2)NO
CheckingBalanceDecimal (Precision: 7, Scale: 2)NO

* denotes primary key

Go ahead and use the DB2 Command Line Processor to create a database for the table above. Call the database bnkdb.

db2 => create database bnkdb

Next, connect to the database. I am going to assume you have a user on your machine of the name db2admin with a password of db2admin.

db2 => connect to bnkdb user db2admin using db2admin

Now, create the accttable table:

db2 => create table accttable(ssn varchar(30) not null primary key,  
lastname varchar(30) not null, firstname varchar(30) not null,  
savingbalance decimal(7,2) not null, checkingbalance decimal(7,2) not null)

Now go ahead and add a couple of entries to the table:

db2 => insert into accttable values 
('111-11-1111','Bhogal','Kulvir',1500.00,1000)
db2 => insert into accttable values 
('222-22-2222','Guy','Someother',2000.00,4000)

Triggers can be fired before or after an INSERT, DELETE, or UPDATE of a table. In our example, you'll be creating a trigger that fires before the UPDATE of the ACCTTABLE. In trigger terminology, the INSERT, DELETE, or UPDATE that causes a trigger to be fired is known as the triggering event. Whether a trigger fires before or after the triggering event is known as the activation time of the trigger.


Creating the trigger using the Control Center

Start creating the trigger by opening up the DB2 Control Center, expanding the database you created (that is, bnkdb) and right clicking on the Triggers option and choosing Create.....

Figure 1. Create trigger
Figure 1.

On the Create Trigger screen, you'll be able to specify the schema your trigger resides in. Go ahead and choose the DB2ADMIN schema. Remember, triggers are associated with tables, so we need to choose the schema of the associated table. Again go ahead and choose the DB2ADMIN schema:

Figure 2. Choose a schema
Figure 2.

In the same screen, you will need to specify a trigger name. Specify a trigger name of OVERDRAFT. Also, specify the table name that is associated with the trigger. Pick the table you created called ACCTTABLE.

Figure 3. Pick the table you created
Figure 3.

In the Time to trigger action area, choose Before.

Figure 4. Choose Before
Figure 4.

In the section called Operation that causes the trigger to be executed choose the Update of columns function and specify the column of CHECKINGBALANCE:

Figure 5.
Figure 5. Specify the column name

Click the Triggered action tab to further build the trigger:

Figure 6. Build the trigger
Figure 6.

Specifying transition variables

DB2 UDB can keep track of state of a row before and after the statement that fired the trigger. In the Correlation name for the old rows area, specify OLDROW and in the Correlation name for the new rows area, specify NEWROW:

Figure 7. Specify NEWROW
Figure 7.

Note that you might not be able to specify a correlation name for an option depending on the combination of activation time and the particular operation that causes the trigger to fire. For example, let's say you chose a Time to trigger action of Before for an trigger that is fired by a DELETE statement. In such a scenario, we won't be able to specify a "Correlation name for the new rows" Why? Because after a delete, a new row will not exist.

Because you are formulating a before trigger invoked by an UPDATE, you cannot populate the Temporary table for the old rows and Temporary table for the new rows options.

You'll notice that in this case (a before trigger invoked by an update), you can only specify that the trigger fire on each row, not each statement.

Figure 8. Trigger fires on Row
Figure 8.

The statement that causes a triggering event might affect multiple rows in the database. The "For each Row" option means that the trigger will be activated once for each row that is modified. On the other hand, the "For each statement" (not allowed for "before" triggers) would mean that the actions defined by a trigger would only be performed once for the invoking SQL statement.

You can click the Show SQL button to see what the underlying SQL statement looks like so far:

Figure 9. Show SQL box
Figure 9.

Building the triggered action

Now it's time to build the triggered action. Our business rule states that a checking balance must fall below zero for the trigger to be invoked. Namely, we want to specify the search-condition of NEWROW.CHECKINGBALANCE<0. We specify NEWROW.CHECKINGBALANCE because we want to analyze the checking balance as it would be after the update occurred.

Creating the trigger body

We are now going to replace the triggered-SQL-statement (see below).

Figure 10. Create the trigger statement
Figure 10.

in the Triggered Action text area with:

declare overage decimal (7,2);  
set overage = (NEWROW.CHECKINGBALANCE*-1);  
if overage&gt;OLDROW.SAVINGBALANCE then SIGNAL SQLSTATE '70001'  
('Overdraft Protection Unsuccessful');  
  else set newrow.savingbalance =  
  oldrow.savingbalance-overage, newrow.checkingbalance = 0;  
end if;

Let's dissect this logic piece by piece. In a trigger body, you can declare variables that you want to use in the body of the trigger. We do this with the line: decimal(7,2)declare overage decimal (7,2); where we declared a variable named overage of the type decimal(7,2).

Next we set the value of our overage variable to the value of (NEWROW.CHECKINGBALANCE*-1);

We'll use this calculation to figure out how much extra (the overage) we are trying to pull out from checking account. NEWROW.CHECKINGBALANCE is specified because we want to analyze the checking balance as it would be if the update were carried out.

set overage = (NEWROW.CHECKINGBALANCE*-1);

Signalling an error condition

You can use a SIGNAL statement to raise an error condition if the business rule defined in your trigger is violated. In our case, we do not allow someone to have a negative checking account balance. If someone tries to update the checking account balance column to a negative amount, we try and see if we have enough in the savings account to make up for the negative amount. If not, we signal the SQL state of '70001' with the message of "'Overdraft Protection Unsuccessful".

It is important to realize the impact of the inclusion of our SIGNAL statement. The SIGNAL statement rolls back the changes that were attempted by the triggering statement (that is, our update statement). SIGNAL statements will also roll back changes caused within the trigger. Furthermore, let us say that we are using something like a JavaTM application that interacts with our database and tries to perform an update operation that fires our trigger and violates our business rule. The Java application will receive the SQLSTATE we specified and the SQLCODE of -438. We use the SIGNAL SQLSTATE feature in this line:

if overage>OLDROW.SAVINGBALANCE then SIGNAL SQLSTATE '70001'  
('Overdraft Protection Unsuccessful');

which states that if our overage is greater than the amount in our savings balance, then we need to go ahead and raise a red flag.

Transferring money

Transferring money occurs if the savings account balance is large enough to make up for the overage. If this condition is met, we perform two modifications to the new row:

  1. Modify the savingbalance column of the "new row" and subtract the overage to facilitate the overdraft transfer.
  2. Set the new row's checking balance to zero. We do this with our code of:
    else set newrow.savingbalance = oldrow.savingbalance-overage, 
    newrow.checkingbalance = 0; end if;

The final product

You can see the final product of your efforts by using the Show SQL button again:

Figure 11. Show SQL
Figure 11.

When you click Close, you should see that the OVERDRAFT trigger has been created:

Figure 12. Create OVERDRAFT trigger
Figure 12.

Testing things out

Test things out by issuing an update statement. Go ahead and issue the following statement:

db2=> update accttable set checkingbalance = -500 where ssn='111-11-1111'

Following the business logic we created, this update should fire our trigger which will take 500.00 from the savingbalance column to account for the overdraft of the checking account. Consequently, our checkingbalance will be 0.00 and our savingbalance will be 1000.00 (the original balance of 1500 - 500 of overdraft) for the account with SSN 111-11-1111. The query shown below verifies this:

Figure 13. Query
Figure 13.

Wrap-up

You've created a DB2 trigger in the context of a mock business scenario. Triggers are a powerful DB2 database feature that can be used to polarize business logic to the relational database. Such a polarization is quite powerful considering the fact that you might have multiple applications trying to interact with the same database. Many times, in a large enterprise, you might even be unaware of what applications are being built that will interact with your database. Rather than just hope that these applications follow business rules that are considered the commandments of your organization (that is, they are deemed always true) , you can use triggers as one of the tools in your toolbox to make sure such business rules are enforced by all applications that interact with your database now and in the future.


Capabilities, restrictions, and further reading

A trigger can only be associated with a table and not a view. You might consider using INSTEAD OF triggers for interaction with views. These were added DB2 UDB in version 8.1. You can learn more about these INSTEAD OF triggers in Serge Rielaus's DB2 Developer Domain article

Triggers can also be used to invoke UDFs. Such a setup is quite powerful when you would like to perform an operation such as send an e-mail to a person as a result of a certain change in your database. I actually cover this in an earlier DB2 Developer Domain article.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Information management on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Information Management
ArticleID=14411
ArticleTitle=DB2 Basics: Creating Your First Trigger in DB2 Universal Database
publish-date=08142003