//*************************************************************************** // (c) Copyright IBM Corp. 2007 All rights reserved. // // The following sample of source code ("Sample") is owned by International // Business Machines Corporation or one of its subsidiaries ("IBM") and is // copyrighted and licensed, not sold. You may use, copy, modify, and // distribute the Sample in any form without payment to IBM, for the purpose of // assisting you in the development of your applications. // // The Sample code is provided to you on an "AS IS" basis, without warranty of // any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR // IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions do // not allow for the exclusion or limitation of implied warranties, so the above // limitations or exclusions may not apply to you. IBM shall not be liable for // any damages you suffer as a result of using, copying, modifying or // distributing the Sample, even if IBM has been advised of the possibility of // such damages. //*************************************************************************** // // SOURCE FILE NAME: TbTrig.sqlj // // SAMPLE: How to use triggers // // SQL Statements USED: // CREATE TABLE // CREATE TRIGGER // DROP TABLE // DROP TRIGGER // SELECT // INSERT // UPDATE // DELETE // COMMIT // ROLLBACK // // JAVA 2 CLASSES USED: // Statement // // Classes used from Util.sqlj are: // Db // Data // SqljException // // // Output will vary depending on the JDBC driver connectivity used. //*************************************************************************** // // For more information on the sample programs, see the README file. // // For information on developing Java applications see the Developing Java Applications book. // // For information on using SQL statements, see the SQL Reference. // // For the latest information on programming, compiling, and running DB2 // applications, visit the DB2 Information Center at // http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp //**************************************************************************/ import java.lang.*; import java.sql.*; import sqlj.runtime.*; import sqlj.runtime.ref.*; #sql iterator TbTrig_Cursor1(int, String, int, String, Integer, double, Double); class TbTrig { public static void main(String argv[]) { DefaultContext ctx = null; try { Db db = new Db(argv); System.out.println(); System.out.println("THIS SAMPLE SHOWS HOW TO USE TRIGGERS."); // connect to the 'sample' database ctx = db.getDefaultContext(); beforeInsertTriggerUse(); afterInsertTriggerUse( ctx.getConnection() ); beforeDeleteTriggerUse(); beforeUpdateTriggerUse( ctx.getConnection() ); afterUpdateTriggerUse( ctx.getConnection() ); // disconnect from the 'sample' database db.disconnect(); } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // main // helping function static void staffTbContentDisplay() { try { int id = 0; int dept = 0; double salary = 0.0; String name = null; String job = null; Integer years = new Integer(0); Double comm = new Double(0.0); TbTrig_Cursor1 c1; System.out.println(); System.out.println(" SELECT * FROM staff WHERE id <= 50"); System.out.println( " ID NAME DEPT JOB YEARS SALARY COMM\n" + " --- ------- ---- ----- ----- -------- --------"); #sql c1 = {SELECT * FROM staff WHERE id <= 50}; #sql {FETCH :c1 INTO :id, :name, :dept, :job, :years, :salary, :comm}; while (!c1.endFetch()) { System.out.print(" " + Data.format(id,3) + " " + Data.format(name,7) + " " + Data.format(dept,4)); if (job != null) { System.out.print(" " + Data.format(job,5)); } else { System.out.print(" -"); } if (years != null) { System.out.print(" " + Data.format(years,5)); } else { System.out.print(" -"); } System.out.print(" " + Data.format(salary,7,2)); if (comm != null) { System.out.print(" " + Data.format(comm,7,2)); } else { System.out.print(" -"); } System.out.println(); #sql {FETCH :c1 INTO :id, :name, :dept, :job, :years, :salary, :comm}; } c1.close(); } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // staffTbContentDisplay // helping function static void staffStatsTbCreate(Connection con) { try { System.out.println(); System.out.println(" CREATE TABLE staff_stats(nbemp SMALLINT)"); #sql {CREATE TABLE staff_stats(nbemp SMALLINT)}; System.out.println(); System.out.println( " INSERT INTO staff_stats VALUES(SELECT COUNT(*) FROM staff)"); Statement stmt = con.createStatement(); stmt.executeUpdate( "INSERT INTO staff_stats VALUES(SELECT COUNT(*) FROM staff)"); stmt.close(); System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // staffStatsTbCreate // helping function static void staffStatsTbContentDisplay(Connection con) { try { System.out.println(); System.out.println(" SELECT nbemp FROM staff_stats"); System.out.println(" NBEMP\n" + " -----"); Statement stmt = con.createStatement(); ResultSet rs2 = stmt.executeQuery("SELECT * FROM staff_stats"); rs2.next(); System.out.println(" " + Data.format(rs2.getShort("nbemp"),5)); rs2.close(); stmt.close(); } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // staffStatsTbContentDisplay // helping function static void staffStatsTbDrop() { try { System.out.println(); System.out.println(" DROP TABLE staff_stats"); #sql {DROP TABLE staff_stats}; System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // staffStatsTbDrop // helping function static void salaryStatusTbCreate(Connection con) { try { System.out.println(); System.out.println( " CREATE TABLE salary_status(emp_name VARCHAR(9),\n" + " sal DECIMAL(7, 2),\n" + " status CHAR(15))"); #sql {CREATE TABLE salary_status(emp_name VARCHAR(9), sal DECIMAL(7, 2), status CHAR(15))}; System.out.println(); System.out.println(" INSERT INTO salary_status\n" + " SELECT name, salary, 'Not Defined'\n" + " FROM staff\n" + " WHERE id <= 50"); Statement stmt = con.createStatement(); stmt.executeUpdate("INSERT INTO salary_status " + " SELECT name, salary, 'Not Defined' " + " FROM staff " + " WHERE id <= 50"); System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // salaryStatusTbCreate // helping function static void salaryStatusTbContentDisplay(Connection con) { try { System.out.println(); System.out.println(" SELECT * FROM salary_status"); System.out.println(" EMP_NAME SALARY STATUS\n" + " ---------- -------- ----------------"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM salary_status"); while (rs.next()) { System.out.println( " " + Data.format(rs.getString("emp_name"), 10) + " " + Data.format(rs.getDouble("sal"), 7, 2) + " " + Data.format(rs.getString("status"), 15)); } rs.close(); stmt.close(); } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // salaryStatusTbContentDisplay // helping function static void salaryStatusTbDrop() { try { System.out.println(); System.out.println(" DROP TABLE salary_status"); #sql {DROP TABLE salary_status}; System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // salaryStatusTbDrop // helping function static void salaryHistoryTbCreate() { try { System.out.println(); System.out.println( " CREATE TABLE salary_history(employee_name VARCHAR(9),\n" + " salary_record DECIMAL(7, 2),\n" + " change_date DATE)"); #sql {CREATE TABLE salary_history(employee_name VARCHAR(9), salary_record DECIMAL(7, 2), change_date DATE)}; System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // salaryHistoryTbCreate // helping function static void salaryHistoryTbContentDisplay(Connection con) { try { System.out.println(); System.out.println(" SELECT * FROM salary_history"); System.out.println(" EMPLOYEE_NAME SALARY_RECORD CHANGE_DATE\n" + " -------------- -------------- -----------"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM salary_history"); while (rs.next()) { System.out.println( " " + Data.format(rs.getString("employee_name"),14) + " " + Data.format(rs.getDouble("salary_record"),13,2) + " " + rs.getDate("change_date")); } rs.close(); stmt.close(); } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // salaryHistoryTbContentDisplay // helping function static void salaryHistoryTbDrop() { try { System.out.println(); System.out.println(" DROP TABLE salary_history"); #sql {DROP TABLE salary_history}; System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // salaryHistoryTbDrop static void beforeInsertTriggerUse() { System.out.println(); System.out.println( "----------------------------------------------------------\n" + "USE THE SQL STATEMENTS:\n" + " CREATE TRIGGER\n" + " COMMIT\n" + " INSERT\n" + " ROLLBACK\n" + " DROP TRIGGER\n" + "TO SHOW A 'BEFORE INSERT' TRIGGER."); // display the initial content of the 'staff' table staffTbContentDisplay(); // create a 'BEFORE INSERT' trigger try { System.out.println(); System.out.println( " CREATE TRIGGER min_sal\n" + " NO CASCADE BEFORE INSERT\n" + " ON staff\n" + " REFERENCING NEW AS newstaff\n" + " FOR EACH ROW \n" + " BEGIN ATOMIC\n" + " SET newstaff.salary =\n" + " CASE\n" + " WHEN newstaff.job = 'Mgr' AND\n" + " newstaff.salary < 17000.00\n" + " THEN 17000.00\n" + " WHEN newstaff.job = 'Sales' AND\n" + " newstaff.salary < 14000.00\n" + " THEN 14000.00\n" + " WHEN newstaff.job = 'Clerk' AND\n" + " newstaff.salary < 10000.00\n" + " THEN 10000.00\n" + " ELSE newstaff.salary\n" + " END;\n" + " END"); #sql {CREATE TRIGGER min_sal NO CASCADE BEFORE INSERT ON staff REFERENCING NEW AS newstaff FOR EACH ROW BEGIN ATOMIC SET newstaff.salary = CASE WHEN newstaff.job = 'Mgr' AND newstaff.salary < 17000.00 THEN 17000.00 WHEN newstaff.job = 'Sales' AND newstaff.salary < 14000.00 THEN 14000.00 WHEN newstaff.job = 'Clerk' AND newstaff.salary < 10000.00 THEN 10000.00 ELSE newstaff.salary END; END}; System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // insert table data using values try { System.out.println(); System.out.println( " Invoke the statement:\n" + " INSERT INTO staff(id, name, dept, job, salary)\n" + " VALUES(25, 'Pearce', 38, 'Clerk', 7217.50),\n" + " (35, 'Hachey', 38, 'Mgr', 21270.00),\n" + " (45, 'Wagland', 38, 'Sales', 11575.00)"); #sql {INSERT INTO staff(id, name, dept, job, salary) VALUES(25, 'Pearce', 38, 'Clerk', 7217.50), (35, 'Hachey', 38, 'Mgr', 21270.00), (45, 'Wagland', 38, 'Sales', 11575.00)}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // display the final content of the 'staff' table staffTbContentDisplay(); // roll back the transaction and then drop the trigger try { System.out.println(); System.out.println(" Roll back the transaction."); #sql {ROLLBACK}; System.out.println(); System.out.println(" DROP TRIGGER min_sal"); #sql {DROP TRIGGER min_sal}; System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // beforeInsertTriggerUse static void afterInsertTriggerUse(Connection con) { System.out.println(); System.out.println( "----------------------------------------------------------\n" + "USE THE SQL STATEMENTS:\n" + " CREATE TRIGGER\n" + " COMMIT\n" + " INSERT\n" + " ROLLBACK\n" + " DROP TRIGGER\n" + "TO SHOW AN 'AFTER INSERT' TRIGGER."); // create a table called 'staff_stats' staffStatsTbCreate(con); // display the content of the 'staff_stats' table staffStatsTbContentDisplay(con); // create an 'AFTER INSERT' trigger try { System.out.println(); System.out.println(" CREATE TRIGGER new_hire\n" + " AFTER INSERT\n" + " ON staff\n" + " FOR EACH ROW \n" + " BEGIN ATOMIC\n" + " UPDATE staff_stats\n" + " SET nbemp = nbemp + 1;\n" + " END"); Statement stmt = con.createStatement(); stmt.executeUpdate("CREATE TRIGGER new_hire " + " AFTER INSERT " + " ON staff " + " FOR EACH ROW " + " BEGIN ATOMIC " + " UPDATE staff_stats " + " SET nbemp = nbemp + 1; " + " END"); System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // insert table data using values try { System.out.println(); System.out.println( " Invoke the statement:\n" + " INSERT INTO staff(id, name, dept, job, salary)\n" + " VALUES(25, 'Pearce', 38, 'Clerk', 7217.50),\n" + " (35, 'Hachey', 38, 'Mgr', 21270.00),\n" + " (45, 'Wagland', 38, 'Sales', 11575.00)"); #sql {INSERT INTO staff(id, name, dept, job, salary) VALUES(25, 'Pearce', 38, 'Clerk', 7217.50), (35, 'Hachey', 38, 'Mgr', 21270.00), (45, 'Wagland', 38, 'Sales', 11575.00)}; // display the content of the 'staff_stats' table staffStatsTbContentDisplay(con); // roll back the transaction System.out.println(); System.out.println(" Roll back the transaction."); #sql {ROLLBACK}; // drop the trigger System.out.println(); System.out.println(" DROP TRIGGER new_hire"); Statement stmt = con.createStatement(); stmt.executeUpdate("DROP TRIGGER new_hire"); stmt.close(); System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // drop the 'staff_stats' table staffStatsTbDrop(); } // afterInsertTriggerUse static void beforeDeleteTriggerUse() { String sqlstate; String sqlerrmsg; System.out.println(); System.out.println( "----------------------------------------------------------\n" + "USE THE SQL STATEMENTS:\n" + " CREATE TRIGGER\n" + " COMMIT\n" + " DELETE\n" + " ROLLBACK\n" + " DROP TRIGGER\n" + "TO SHOW A 'BEFORE DELETE' TRIGGER."); // display the initial content of the 'staff' table staffTbContentDisplay(); // create a 'BEFORE DELETE' trigger try { System.out.println(); System.out.println(" CREATE TRIGGER do_not_delete_sales\n" + " NO CASCADE BEFORE DELETE\n" + " ON staff\n" + " REFERENCING OLD AS oldstaff\n" + " FOR EACH ROW \n" + " WHEN (oldstaff.job = 'Sales')\n" + " BEGIN ATOMIC\n" + " SIGNAL SQLSTATE '75000' " + "('Sales cannot be deleted now.');\n" + " END"); #sql {CREATE TRIGGER do_not_delete_sales NO CASCADE BEFORE DELETE ON staff REFERENCING OLD AS oldstaff FOR EACH ROW WHEN(oldstaff.job = 'Sales') BEGIN ATOMIC SIGNAL SQLSTATE '75000' ('Sales cannot be deleted now.'); END}; System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // delete data from the 'staff' table try { System.out.println(); System.out.println(" Invoke the statement:\n" + " DELETE FROM staff WHERE id <= 50"); #sql {DELETE FROM staff WHERE id <= 50}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handleExpectedErr(); } // display the final content of the 'staff' table staffTbContentDisplay(); // roll back the transaction and then drop the trigger try { System.out.println(); System.out.println(" Roll back the transaction."); #sql {ROLLBACK}; System.out.println(); System.out.println(" DROP TRIGGER do_not_delete_sales"); #sql {DROP TRIGGER do_not_delete_sales}; System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } } // beforeDeleteTriggerUse static void beforeUpdateTriggerUse(Connection con) { System.out.println(); System.out.println( "----------------------------------------------------------\n" + "USE THE SQL STATEMENTS:\n" + " CREATE TRIGGER\n" + " COMMIT\n" + " UPDATE\n" + " ROLLBACK\n" + " DROP TRIGGER\n" + "TO SHOW A 'BEFORE UPDATE' TRIGGER."); // create a table called salary_status salaryStatusTbCreate(con); // display the content of the 'salary_status' table salaryStatusTbContentDisplay(con); // create a 'BEFORE UPDATE' trigger try { System.out.println(); System.out.println( " CREATE TRIGGER salary_status\n" + " NO CASCADE BEFORE UPDATE OF sal\n" + " ON salary_status\n" + " REFERENCING NEW AS new OLD AS old\n" + " FOR EACH ROW \n" + " BEGIN ATOMIC\n" + " SET new.status =\n" + " CASE\n" + " WHEN new.sal < old.sal\n" + " THEN 'Decreasing'\n" + " WHEN new.sal > old.sal\n" + " THEN 'Increasing'\n" + " END;\n" + " END"); Statement stmt = con.createStatement(); stmt.executeUpdate("CREATE TRIGGER sal_status " + " NO CASCADE BEFORE UPDATE OF sal " + " ON salary_status " + " REFERENCING NEW AS new OLD AS old " + " FOR EACH ROW " + " BEGIN ATOMIC " + " SET new.status = " + " CASE " + " WHEN new.sal < old.sal " + " THEN 'Decreasing' " + " WHEN new.sal > old.sal " + " THEN 'Increasing' " + " END; " + " END"); System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // update data in table 'salary_status' try { System.out.println(); System.out.println(" Invoke the statement:\n" + " UPDATE salary_status SET sal = 18000.00"); Statement stmt = con.createStatement(); stmt.executeUpdate("UPDATE salary_status SET sal = 18000.00"); stmt.close(); } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // display the content of the 'salary_status' table salaryStatusTbContentDisplay(con); // roll back the transaction try { System.out.println(); System.out.println(" Roll back the transaction."); #sql {ROLLBACK}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // drop the trigger try { System.out.println(); System.out.println(" DROP TRIGGER sal_status"); Statement stmt = con.createStatement(); stmt.executeUpdate("DROP TRIGGER sal_status"); System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // drop salary_status table salaryStatusTbDrop(); } // beforeUpdateTriggerUse static void afterUpdateTriggerUse(Connection con) { System.out.println(); System.out.println( "----------------------------------------------------------\n" + "USE THE SQL STATEMENTS:\n" + " CREATE TRIGGER\n" + " COMMIT\n" + " UPDATE\n" + " DROP TRIGGER\n" + "TO SHOW AN 'AFTER UPDATE' TRIGGER."); // create a table called 'salary_history' salaryHistoryTbCreate(); // display the content of the 'salary_history' table salaryHistoryTbContentDisplay(con); try { System.out.println(); System.out.println(" CREATE TRIGGER sal_history\n" + " AFTER UPDATE OF salary\n" + " ON staff\n" + " REFERENCING NEW AS newstaff\n" + " FOR EACH ROW \n" + " BEGIN ATOMIC\n" + " INSERT INTO salary_history\n" + " VALUES(newstaff.name,\n" + " newstaff.salary,\n" + " CURRENT DATE);\n" + " END"); Statement stmt = con.createStatement(); stmt.executeUpdate("CREATE TRIGGER sal_history " + " AFTER UPDATE OF salary " + " ON staff " + " REFERENCING NEW AS newstaff " + " FOR EACH ROW " + " BEGIN ATOMIC " + " INSERT INTO salary_history " + " VALUES(newstaff.name, " + " newstaff.salary, " + " CURRENT DATE); " + " END"); System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // update table data try { System.out.println(); System.out.println( " Invoke the statement:\n" + " UPDATE staff SET salary = 20000.00 WHERE name = 'Sanders'"); #sql {UPDATE staff SET salary = 20000.00 WHERE name = 'Sanders'}; System.out.println(); System.out.println( " Invoke the statement:\n" + " UPDATE staff SET salary = 21000.00 WHERE name = 'Sanders'"); #sql {UPDATE staff SET salary = 21000.00 WHERE name = 'Sanders'}; System.out.println(); System.out.println( " Invoke the statement:\n" + " UPDATE staff SET salary = 23000.00 WHERE name = 'Sanders'"); #sql {UPDATE staff SET salary = 23000.00 WHERE name = 'Sanders'}; System.out.println(); System.out.println( " Invoke the statement:\n" + " UPDATE staff SET salary = 20000.00 WHERE name = 'Hanes'"); #sql {UPDATE staff SET salary = 20000.00 WHERE name = 'Hanes'}; System.out.println(); System.out.println( " Invoke the statement:\n" + " UPDATE staff SET salary = 21000.00 WHERE name = 'Hanes'"); #sql {UPDATE staff SET salary = 21000.00 WHERE name = 'Hanes'}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // display the content of the 'salary_history' table salaryHistoryTbContentDisplay(con); // roll back the transaction try { System.out.println(); System.out.println(" Roll back the transaction."); #sql {ROLLBACK}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // drop the trigger try { System.out.println(); System.out.println(" DROP TRIGGER sal_history"); Statement stmt = con.createStatement(); stmt.execute("DROP TRIGGER sal_history"); System.out.println(); System.out.println(" COMMIT"); #sql {COMMIT}; } catch (Exception e) { SqljException sqljExc = new SqljException(e); sqljExc.handle(); } // drop the 'salary_history' table salaryHistoryTbDrop(); } // afterUpdateTriggerUse } // TbTrig