Databases 2011 Embedded SQL Christian S. Jensen Computer Science, Aarhus University Embedded SQL SQL is rarely written as ad-hoc queries using the generic SQL interface The typical scenario: client server database SQL is embedded in the server application code Embedded SQL 2 Static vs. Dynamic SQL Static SQL • • • • syntactic extension of host language predefined and stored in the database typical use: monthly accounting statements checked in advance, efficient Dynamic SQL • • • • • API in host language dynamically interpreted by the database typical use: web applications highly flexible JDBC for Java, works well with Hibernate Embedded SQL 3 JDBC – Java Database Connectivity A common Java framework for SQL databases • java.sql.* Each vendor provides a driver class • • • • com.ibm.db2.jcc.DB2driver oracle.jdc.driver.OracleDriver com.microsoft.sqlserver.jdbc.SQLServerDriver com.mysql.jdbc.Driver SQL statements are built as string expressions Results are accessed through a cursor Embedded SQL 4 Running a JDBC Application Initialization load driver create connection java.sql.DriverManager java.sql.Connection Processing generate SQL process results java.sql.Statement java.sql.ResultSet Termination end connection release data structures java.sql.Connection java.sql.Statement Embedded SQL 5 A Simple Example import java.sql.*; public class Test { public static void main(String args[]) { Connection con; try { String server = "localhost"; String port = "50000"; String url = "jdbc:mysql://"+server+":"+port+"/sample"; String userid = ”userid"; String password = ”password"; Class.forName("com.mysql.jdbc.Driver").newInstance(); con = DriverManager.getConnection(url, userid, password); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM Rooms"); while (rs.next()) System.out.println(rs.getString(1)+" "+rs.getString(2)); stmt.close(); con.close(); } catch(Exception e) { e.printStackTrace(); } } } Embedded SQL Dreyer-201 12 Zuse-127 10 Shannon-164 30 Shannon-157 40 Shannon-159 38 Wiener-026 30 Hopper-334A 4 Ada-333 26 Turing-029 8 Turing-129 8 Turing-230 12 Turing-130 12 Turing-030 12 Stibitz-123 12 Hopper-334 4 Shannon-156 24 Stibitz-113 12 Undervisning 36 Store-Aud 152 Lille-Aud 70 Turing-014 26 Turing-229 8 D-01 25 D-02 18 D-03 18 Aud-D1 100 Aud-D2 100 Aud-D4 62 Aud-G1 85 Aud-G2 85 Kol-G3 22 Kol-G4 22 G-32 20 G-33 20 Aud-E 286 Aud-F 165 ... 6 Creating A Connection Load the appropriate driver class: Class.forName("com.mysql.jdbc.Driver"); Create a connection object: DriverManager.getConnection(url, userid, password); URL structure (for MySQL) • • • • jdbc:mysql://server:port/database the name of your own machine is localhost the standard port number is 50000 the name of the database is, e.g., SAMPLE Embedded SQL 7 Simple SQL Statements Create a statement object: Statement stmt = con.createStatement(); The statement object is used many times • stmt.executeQuery("…"); • stmt.executeUpdate("…"); And is finally closed • stmt.close(); Embedded SQL 8 Transactions Default auto-commits after every statement, change with • con.setAutoCommit(false); • con.commit(); • con.rollback(); Transaction isolation levels • con.setTransactionIsolation(level); • • • • Connection.TRANSACTION_READ_COMMITTED Connection.TRANSACTION_READ_UNCOMMITTED Connection.TRANSACTION_READ_REPEATABLE_READ Connection.TRANSACTION_SERIALIZABLE • con.setReadOnly(true); Embedded SQL 9 Impedance Mismatch Java uses native types • int, char[], String, ... • collection classes SQL uses tables • CHAR(7), VARCHAR(20), FLOAT, DATE, ... • possibly huge amounts of data Not obvious how to translate tables into Java objects Results are instead accessed using cursors Embedded SQL 10 Using Result Sets A ResultSet object manages a cursor on rows ResultSet rs = stmt.executeQuery("..."); while (rs.next()) { ... } rs.close(); room capacity Turing-216 4 rs Ada-333 Aud-E Embedded SQL 26 286 11 Navigating With Cursors A cursor can by default only move forward • rs.next(); A Boolean result tells if the move was possible • looks like an iterator object An ORDER BY clause determines the order Embedded SQL 12 Reading With Cursors Column index or column name • String room = rs.getString(1); • int capacity = rs.getInt("capacity"); Different result types • getString(...) • getInt(...) • java.sql.Time time = getTime(...) Check for NULL • wasNull() room capacity Turing-216 4 rs Ada-333 Aud-E Embedded SQL 26 286 13 Better Cursors A result set can be made scrollable and updatable • stmt = createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); • • • • rs.previous(); rs.first(); rs.last(); rs.absolute(42); Embedded SQL 14 Modifications with Cursors A result set can then be updated • rs.updateString("room","ADA-333"); Updates can be pushed to the database • rs.updateRow(); Rows can be deleted both places • rs.deleteRow(); Embedded SQL room capacity Turing-216 4 rs ADA-333 Ada-333 26 26 Aud-E 286 15 Insertions With Cursors A special virtual insert row exists rs.moveToInsertRow(); rs.updateString("room”,"Turing-310"); rs.updateInt("capacity",4); rs.insertRow(); rs.moveToCurrentRow(); room capacity Turing-216 4 rs Ada-333 Embedded SQL 26 Aud-E 286 Turing-310 4 16 Prepared Statements SQL statements may be prepared • checked and compiled once • executed multiple times PreparedStatement pstmt = con.prepareStatement( "SELECT * FROM Rooms" ); ResultSet rs = pstmt.executeQuery(); Embedded SQL 17 Arguments to Prepared Statements Use ? symbols for variables Insert values using absolute position PreparedStatement pstmt = con.prepareStatement( "INSERT INTO Meetings VALUES(?,?,?,'dDB',?)" ); pstmt.setInt(1,34716); pstmt.setDate(2,new java.sql.Date(2010,8,23)); pstmt.setInt(3,14); pstmt.setString(4,"csj"); pstmt.executeUpdate(); Embedded SQL 18 Metadata java.sql.ResultSetMetaData • reflectively describes the structure of a result • names and types of columns • allows generic queries java.sql.DatabaseMetaData • reflectively describes the structure of a database • name, version, tables, supported SQL types • allows generic connections Embedded SQL 19 Result Set Metadata rs = stmt.executeQuery("SELECT * FROM Rooms"); ResultSetMetaData rsm = rs.getMetaData(); int columns = rsm.getColumnCount(); for (int i=1; i<=columns; i++) { System.out.println( "Column "+i+" "+ "has name "+rsm.getColumnName(i)+", " "SQL type "+rsm.getColumnType(i)+" and " "JDBC type "+rsm.getColumnTypeName(i) ); } Column 1 has name ROOM, SQL type 12 and JDBC type VARCHAR Column 2 has name CAPACITY, SQL type 4 and JDBC type INTEGER Embedded SQL 20 SQL Injection Attacks Be careful with dynamic SQL: "SELECT * FROM Users WHERE userid ='" + userid + "'" Fine if userid is "mis" Bad if userid is "x' OR 'y'='y" • all data is revealed Worse if userid is ”x';DROP TABLE Users;--" • all data is deleted Prepared statements avoid this problem Embedded SQL 21 SQL Injection Cartoon Embedded SQL 22