Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Triggers 1 PL/SQL reminder • We presented PL/SQL- a Procedural extension to the SQL language. • We reviewed the structure of an anonymous PL/SQL block: DECLARE (optional) /* Variable declaration */ BEGIN (mandatory) /* Block action*/ EXCEPTION (optional) /* Exception handling */ END; (optional) / 2 Example from last week DECLARE e_number1 EXCEPTION; cnt NUMBER; BEGIN select count(*) into cnt from number_table; IF cnt = 1 THEN RAISE e_number1; ELSE dbms_output.put_line(cnt); END IF; EXCEPTION WHEN e_number1 THEN dbms_output.put_line('Count = 1'); end; 3 PL/SQL reminder-cont. • We also showed the structures of procedures and functions: create or replace procedure num_logged (person IN mylog.who%TYPE, num OUT mylog.logon_num%TYPE) IS BEGIN select logon_num into num from mylog where who = person; END; / 4 Triggers- introduction • A trigger is an action which the Database should perform when some DB event has occurred. • For example (in pseudocode): TriggerA: For any row that is inserted into table Sailors: if age>30 -> insert this row into oldSailors; else-> insert this row into youngSailors; 5 Trigger introduction cont. • The code within the trigger, called the trigger body, is made up of PL/SQL blocks • The “firing” of a trigger is transparent to the user. • There are many optional triggering events, but we will focus on update, delete, and insert. • Triggers can be used to check for data integrity, but should be used so only if it is not possible through other means. 6 Types of triggers 1. Row level triggers: The code in the trigger is executed once for every row updated. 2. Statement level triggers (Default): The code in the trigger is performed once per statement. • For example: if the triggering event was an update which updates 100 rows, a row-level trigger will execute 100 times, and a statement level trigger will execute once. 7 Types of triggers-cont. 1.BEFORE triggers: The trigger fires immediately BEFORE the triggering event executes. 2.AFTER triggers: The trigger fires immediately AFTER the triggering event executes. 3.INSTEAD OF triggers: The trigger fires INSTEAD of the triggering event. • We can reference the “old” and “new” values. • If we want to change rows which will be inserted, we have to use a BEFORE trigger and change the ‘new’ values. Using an AFTER trigger will not allow the change. 8 Example (pseudocode) Create Before-Trigger: – For every string inserted into sailorName, turn it into upper case before insertion 9 Trigger syntax CREATE [or REPLACE] TRIGGER trig_name {BEFORE | AFTER | INSTEAD OF} Trigger timing {DELETE | INSERT | UPDATE} [of column1, column2,…] Triggering event [or {DELETE | INSERT | UPDATE] [of columnA, columnB,…] on table_name [FOR EACH ROW] [WHEN (condition)] PL/SQL block Further restricts when trigger is fired 10 Backing Up Data create table sailors( sid number, sname VARCHAR2(30), rating number check(rating <= 10), age number ); create table sailors_backup( who varchar2(30), when_chngd date, sid number, old_rating number, new_rating number ); 11 sailors(sid,sname,rating,age); sailors_backup(who,when_chngd,sid, old_rating,new_rating); CREATE or REPLACE TRIGGER backup_trig AFTER UPDATE of Rating on Sailors FOR EACH ROW WHEN (old.rating < new.rating) BEGIN INSERT INTO sailors_backup VALUES (USER, SYSDATE, :old.sid, :old.rating, :new.rating); END; / • Q: Why AFTER Trigger? • A: Because in that case, the firing of the trigger occurs only when the inserted data complies with the table integrity (check..) 12 Ensuring Upper Case CREATE or REPLACE TRIGGER sname_trig BEFORE INSERT or UPDATE of sname on Sailors FOR EACH ROW BEGIN :new.sname := UPPER(:new.sname); END; / • Q: Why BEFORE Trigger? • A: You cannot update inserted values after insertion 13 Instead Of Trigger create view sailors_reserves as select sailors.sname, reserves.bid from sailors, reserves where sailors.sid = reserves.sid; CREATE or REPLACE TRIGGER view_trig INSTEAD OF INSERT on sailors_reserves FOR EACH ROW BEGIN INSERT INTO sailors values(:new.sname); INSERT INTO reserves values(:new.bid); END; / 14 Statement Trigger CREATE or REPLACE TRIGGER no_work_on_shabbat_trig BEFORE INSERT or DELETE or UPDATE on reserves DECLARE shabbat_exception EXCEPTION; BEGIN if (TO_CHAR(sysdate,'DY')='SAT') then raise shabbat_exception; end if; END; / 15 Another example create or replace trigger trig2 after update of rating on sailors for each row DECLARE diff number:=abs((:old.rating)-(:new.rating)); BEGIN If ((:old.rating)>(:new.rating)) then dbms_output.put_line('The rating of '||:old.sname||' has dropped by '||diff); elsif ((:old.rating)<(:new.rating)) then dbms_output.put_line('The rating of '||:old.sname||' has been raised by '||diff); else dbms_output.put_line('The rating of '||:old.sname||' has remained the same'); end if; END; / 16 Trigger Compilation Errors • As with procedures and functions, when creating a Trigger with errors, you will get the message: “Warning: Trigger created with compilation errors.” To view the errors, type: SHOW ERRORS TRIGGER myTrigger • To drop a trigger write drop trigger myTrig • To disable/enable a trigger write alter trigger myTrig disable/enable 17 Additional Types of Triggers • Can also define triggers for – logging in and off – create/drop table events – system errors – etc. 18 JDBCTM "Java Database Connectivity" 19 Useful JDBC Links • Getting Started Guide: http://java.sun.com/j2se/1.5.0/docs/guide/jdbc/g etstart/GettingStartedTOC.fm.html • java.sql Package API: http://java.sun.com/j2se/1.5.0/docs/api/java/sql/ package-summary.html 20 Introduction to JDBC • JDBC allows for convenient database access from Java applications • Data is transferred from relations to objects and vice-versa – databases optimized for searching/indexing – objects optimized for engineering/flexibility 21 Why Access a Database from within a Program? • As we saw last week, some queries can’t be computed in SQL. • PL/SQL includes more programming tools than SQL • However, sometimes using PL/SQL will not be suitable: – If we require object-oriented programming – If accessing the database is a small part of a large Java application – If we would like to access other DBMSes than Oracle – Etc. • Why not keep all the data in Java objects? • “Separation of concerns”: DBMSes concentrate on data storage and access; programs concentrate on algorithms, networking, etc. 22 Six Steps • Load the driver • Establish the Connection • Create a Statement object • Execute a query • Process the result • Close the connection 23 Packages to Import • In order to connect to the Oracle database from java, import the following packages: – java.sql.*; (usually enough) – javax.sql.* (for advanced features, such as scrollable result sets) 24 JDBC Architecture (1) Driver Manager Application Driver DBMS • DriverManager is provided by Java Software as part of the Java 2 Platform. • Drivers are provided by DBMS vendors. JDBC Architecture (2) • The application creates a driver instance and registers it with the DriverManager. • The DriverManager tells the driver to connect to the DB • The DriverManager keeps track of registered driver instances and their connections to DB’s. • The Driver “talks” to a particular DB through the connection Connecting 1. Initializing a driver: new oracle.jdbc.driver.OracleDriver() 2. Registering it with the DriverManager: DriverManager.registerDriver(…) 3. Getting a connection: DriverManager.getConnection(URL) Note: • Stages 1+2 may be combined with Class.forName(“oracle.jdbc.driver.OracleDriver"); • In Stage 3, the Manager tries all drivers and assigns a connection to the first driver that succeeds. 27 Connecting to the Database String String String String String String String path = "jdbc:oracle:thin:"; host = "sol4"; port = "1521"; db = "stud"; login = “sqlUser"; password = “passwd”; url = path + login + "/" + password + "@" + host +":" + port + ":" + db; Class.forName("oracle.jdbc.driver.OracleDriver"); Connection con = DriverManager.getConnection(url); 28 Statements 1. Statement createStatement() – returns a new Statement object “prepared” because it already includes the query string 2. PreparedStatement prepareStatement(String) – returns a new PreparedStatement object • Both are used to send SQL commands to the DB • Both are created via the connection object Statement query methods 1. executeQuery(String query): for queries that return a single ResultSet object (typically select) 2. executeUpdate(String query): for INSERT, UPDATE, DELETE, and SQL DDL directives 30 Compilation • When executing an SQL statement via JDBC, it is not checked for errors until it is run (Not checked during compilation) 31 executeQuery String queryStr = "SELECT * FROM Sailors " + "WHERE Name = 'joe smith'"; No semicolon(;) Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(queryStr); • The executeQuery method returns a ResultSet object representing the query result. 32 executeUpdate String deleteStr = “DELETE FROM Sailors " + "WHERE sid = 15"; No semicolon(;) Statement stmt = con.createStatement(); int delnum = stmt.executeUpdate(deleteStr); • executeUpdate returns the number of rows modified 33 PreparedStatement motivation • Suppose we would like to run the query SELECT * FROM Emp where name=‘moshe’; • But we would like to run this for all employees (separately), not only ‘moshe’… • Could we create a variable instead of ‘moshe’ which would get a different name every time??.. 34 Prepared Statements • Prepared Statements are used for queries that are executed many times with possibly different contents. • A PreparedStatement object includes the query and is prepared for execution (precompiled). • Question marks can be inserted as variables. -setString(i, value) The i-th question -setInt(i, value) mark is set to the given value. 35 PreparedStatement.executeQuery() String queryStr = "SELECT * FROM Sailors " + "WHERE Name = ? and Rating < ?”; PreparedStatement pstmt = con.prepareStatement(queryStr); Value to insert pstmt.setString(1, “Joe”); pstmt.setInt(2, 8); 1st question mark ResultSet rs = pstmt.executeQuery(); 36 PreparedStatement.executeUpdate() String deleteStr = “DELETE FROM Boats " + "WHERE Name = ? and Color = ?”; PreparedStatement pstmt = con.prepareStatement(deleteStr); pstmt.setString(1, “Fluffy”); pstmt.setString(2, "red"); int delnum = pstmt.executeUpdate(); 37 • Will this work? PreparedStatement pstmt = con.prepareStatement(“select * from ?”); pstmt.setString(1, "Sailors"); No! We may put ? only instead of values 38 ResultSet (1) • A ResultSet is an object which contains the result of a query - a “table”. • At most one ResultSet per Statement can be open at the same time(!!). • A ResultSet maintains a cursor pointing to its current row of data. • The 'next' method moves the cursor to the next row • As of JDBC 2.0, scrollable ResultSets are available, which also include ‘previous’, ’first’, ‘last’, etc.. ResultSet (2) • resultSet methods work on the current row. • The cursor is positioned before the first row upon creation. ResultSet (3) Statement stmt= con.createStatement(); ResultSet rs = stmt.executeQuery ( "SELECT * FROM Table1"); while (rs.next()) { //something… } ResultSet methods • Getting the value in some column (for the String s = current row): – getString(int columnNum); rs.getString(“column1"); – getString(String columnName); – getInt(int columnNum); – getInt(String columnName); – Etc… • To check if NULL was returned, you have to use wasNull() on the ResultSet after getting the value. 42 Example revisited Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1"); // retrieve and print the values for the current row while (rs.next()) { int i = rs.getInt("a"); String s = rs.getString("b"); float f = rs.getFloat("c"); System.out.println("ROW = " + i + " " + s + " " + f); } 43 ResultSetMetaData An object created by the ResultSet which holds information about its columns ResultSetMetaData rsmd = rs.getMetaData(); int numcols = rsmd.getColumnCount(); for (int i = 1 ; i <= numcols; i++) { if (i > 1) System.out.print(","); System.out.print(rsmd.getColumnLabel(i)); } 44 Mapping SQL and Java Types • SQL and Java data types are not identical • There are significant variations between the SQL types supported by different database products • JDBC defines a set of generic SQL type identifiers in the class java.sql.Types • The driver is responsible for mapping between the DB SQL types and JDBC SQL types 45 Some JDBC SQL Types • CHAR • DOUBLE • DATE • BIGINT • BOOLEAN • BINARY • INTEGER • CLOB • TINYINT • BLOB • VARCHAR • ARRAY • FLOAT • OTHER 46 JDBC to Java Type Mapping • Each getXXX() and setXXX() method is allowed to get/set columns of certain JDBC types • For example getDate() is allowed to access columns of types CHAR, VARCHAR, LONGVARCHAR, DATE, and TIMESTAMP • getDate() is the recommended method to access DATE columns 47 Printing Query Output: Result Set (2) while (rs.next()) { for (int i = 1 ; i <= numcols; i++) { if (i > 1) System.out.print(","); System.out.print(rs.getString(i)); } System.out.println(""); } • getString() is allowed to access all simple JDBC types 48 Cleaning Up After Yourself • Remember to close the Connections, Statements, PreparedStatements and ResultSets con.close(); stmt.close(); pstmt.close(); rs.close(); 49 Dealing With Exceptions catch (SQLException e) { //human readable message about the exception System.out.println(e.getMessage()); //String describing the reason of the exception System.out.println(e.getSQLState()); //driver-dependent code for the exception System.out.println(e.getErrorCode()); } 50 Transactions in JDBC 51 Transactions • Transaction = 2 or more statements which must all succeed (or all fail) together • If one fails, the system must reverse all previous actions • Aim: don’t leave DB in inconsistent state halfway through a transaction • COMMIT = complete transaction • ROLLBACK = abort 52 Example • Suppose we want to transfer money from bank account 13 to account 72: PreparedStatement pstmt = con.prepareStatement(“UPDATE BankAccount SET amount = amount + ? WHERE accountId = ?”); pstmt.setInt(1,-100); pstmt.setInt(2, 13); pstmt.executeUpdate(); What happens if this pstmt.setInt(1, 100); update fails? pstmt.setInt(2, 72); pstmt.executeUpdate(); 53 Transaction Management • The connection has a state called AutoCommit mode • if AutoCommit is true, then every statement is automatically committed • if AutoCommit is false, then every statement is added to an ongoing transaction • Default: true 54 AutoCommit con.setAutoCommit(boolean val) • If you set AutoCommit to false, you must explicitly commit or rollback the transaction using Connection.commit() and Connection.rollback() 55 Example con.setAutoCommit(false); try { PreparedStatement pstmt = con.prepareStatement(“update BankAccount set amount = amount + ? where accountId = ?”); pstmt.setInt(1,-100); pstmt.setInt(2, 13); pstmt.executeUpdate(); pstmt.setInt(1, 100); pstmt.setInt(2, 72); pstmt.executeUpdate(); con.commit(); }catch (SQLException e) { con.rollback(); } 56