Bazy Danych i Systemy informacyjne Wykład 9 Piotr Syga 30.11.2018
API Przykłady API ODBC JDBC OLEDB ADO.NET data provider
API Funkcjonalności Komponenty Główne komponenty odpowiadające za komunikację API/data provider baza danych: Connector Command Executor Data Reader Data Adapter Typy zapytań Ze względu na przechowywanie i wymagany preprocessing wyróżniamy 3 typy zapytań: Statement PreparedStatement CallableStatement
JDBC Sterowniki Do połączenia z każdą bazą, JDBC wymaga osobnego sterownika, który odpowiada za połączenie oraz komunikację pomiędzy Javą a bazą danych. Dostępne sterowniki należą do jednego z czterech typów:
JDBC Sterowniki Do połączenia z każdą bazą, JDBC wymaga osobnego sterownika, który odpowiada za połączenie oraz komunikację pomiędzy Javą a bazą danych. Dostępne sterowniki należą do jednego z czterech typów: Typ 1 łącznik JDBC ODBC, konwertujący metody JDBC na funkcję uniwersalnego API Przykład: sun.jdbc.odbc.jdbcodbcdriver +: uniwersalność -: konieczność translacji (czas działania), wymagany dostęp do ODBC, wycofywane wsparcie Typ 2 natywne API (wykorzystuje pakiety po stonie klienta) Przykład: Oracle Call Interface +: szybszy niż Typ 1 -: wymóg bibliotek po stronie klienta (dopasowanych do bazdy danych), zależny od platformy, nie obsługuje apletów
JDBC Sterowniki Do połączenia z każdą bazą, JDBC wymaga osobnego sterownika, który odpowiada za połączenie oraz komunikację pomiędzy Javą a bazą danych. Dostępne sterowniki należą do jednego z czterech typów: Typ 3 wykorzystanie pośrednika Przykład: com.jw.client, com.jw.server, com.jw.client.jwdriver +: niezależność od platformy, niezależność od typu bazy danych (komunikacja z pośrednikiem wyłacznie Java) -: obecność pośrednika, opóźnienia komunikacyjne, obsługa konkretnej bazy danych na pośredniku Typ 4 bezpośrednia komunikacja w Javie Przykład: oracle.jdbc.driver.oracledriver (:thin:) +: szybkość, niezależność od platformy, brak pośrednika, debugowanie -: osobne sterowniki do każdej bazy, prawa autorskie Lista sterowników Oracle, MySQL Connector/J
JDBC Przykład Select import java.sql.connection; import java.sql.statement; import java.sql.resultset; public class JdbcExample { public static void main(string[] args) { try ( Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/bazatestowa", "user", "pass"); Statement stmt = conn.createstatement(); ) { String testquery = "Select name, lastname, score From Tests"; ResultSet res = stmt.executequery(testquery); int rowcount = 0; while(res.next()) { String n = res.getstring("name"); String l = res.getstring("lastname"); int score = res.getint("score"); /*... */ ++rowcount; catch(sqlexception ex) { ex.printstacktrace();
JDBC Przykład Update, Insert, Delete import java.sql.*; public class JdbcExampleB { public static void main(string[] args) { try ( Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/bazatestowa", "user", "pass"); Statement stmt = conn.createstatement(); ) { String upquery = "Update Tests Set mark = Ok Where score>10"; int upcounter = stmt.executeupdate(upquery); System.out.println(upcounter + " passed"); String delquery = "Delete From Tests Where score is NULL"; int delcounter = stmt.executeupdate(delquery); inquery = "Insert Into Tests (name, lastname, score) " + "values ( Jan, Kowalski, 7)" + "( Jan, Nowak,20)"; stmt.executeupdate(inquery); catch(sqlexception ex) { ex.printstacktrace();
JDBC Przykład Tworzenie tabel import java.sql.*; public class JdbcExampleC { public static void main(string[] args) { try ( Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/bazatestowa", "user", "pass"); Statement stmt = conn.createstatement(); ) { String cdb = "Create Database tmp"; stmt.executeupdate(cdb); String ctab = "Create Table tmp.albums " + "(name varchar(50) NOT NULL, " + "band int NOT NULL, " + "release date, " + "PRIMARY KEY (name,band), " + "FOREIGN KEY (band) REFERENCES " + "tmp.bands(id))"; stmt.executeupdate(ctab); catch(sqlexception ex) { ex.printstacktrace();
JDBC PreparedStatement przypomnienie Możemy stworzyć uniwersalne kwerendy do Update ów, Insertów,... String AlmostUniversalUpdateStatement = "Update?" + "Set kol1 =? " + "Where ID =?"; try { con.setautocommit(false); upstmt = con.preparestatement(almostuniversalupdatestatement); upstmt.setstring(1, Tab1 ); upstmt.setint(2, 100); upstmt.setint(3, 1); upstmt.executeupdate(); upstmt.setstring(1, Tab1 ); upstmt.setint(2, 73); upstmt.setint(3, 2); upstmt.executeupdate(); con.commit(); catch (SQLException e ) { /*... */ Jak zrobić całkowicie uniwersalny Update? Co z bezpieczeństwem?
JDBC Obsługa błędów Oracle docs public static void printsqlexception(sqlexception ex) { for (Throwable e : ex) { if (e instanceof SQLException) { if (ignoresqlexception( ((SQLException)e). getsqlstate()) == false) { e.printstacktrace(system.err); System.err.println("SQL State: " + ((SQLException)e).getSQLState()); System.err.println("Error Code: " + ((SQLException)e).getErrorCode()); System.err.println("Message: " + e.getmessage()); Throwable t = ex.getcause(); while(t!= null) { System.out.println("Cause: " + t); t = t.getcause();
JDBC Warto przejrzeć typy danych, tablice, struktury, mapy procedury składowane transakcje Process, Runtime wywołanie msqldump SQLXML
PHP PDO PHP Data Objects Rozszerzenie PHP umożliwiające połączenie z szeregiem różnych baz danych za pomocą stałego interfejsu lista sterowników.
PHP PDO połączenie <?php try { $dbh = new PDO( mysql:host=localhost;dbname=test,\ $user, $pass); foreach($dbh->query( SELECT * from FOO ) as $row) { print_r($row); $dbh = null; catch (PDOException $e) { print "Error!: ". $e->getmessage(). "<br/>"; die();?>
PHP PDO Prepared Statement <?php try { $dbh = new PDO( mysql:host=localhost;dbname=test,\ $user, $pass); $stmt = $dbh->prepare( SELECT * FROM FOO ); $stmt->execute(); $dbh = null; //... catch (PDOException $e) { print "Error!: ". $e->getmessage(). "<br/>"; die();?> Uwaga: Mimo $dbh = null; połączenie nie zostanie zerwane do czasu $stmt = null; lub końca poleceń
PHP PDO transakcje <?php try { $dbh = new PDO( odbc:sample, db2inst1, ibmdb2, array(pdo::attr_persistent => true)); catch (Exception $e) { die("connection error: ". $e->getmessage()); try { $dbh->setattribute(pdo::attr_errmode, PDO::ERRMODE_EXCEPTION); $dbh->begintransaction(); $dbh->exec("insert Into people (PESEL, imię, nazwisko, data) Values ( 66010100000, Jan, Kowalski, 1966-01-01 )"); $stmt = $dbh->prepare("insert Into staff (PESEL, occupation, salary) Values (:p, :o, :s)"); $stmt->bindparam( :p, $pes); $stmt->bindparam( :o, $occ); $stmt->bindparam( :s, $sal); $pes = 66010100000 ; $occ = sprzedawca ; $sal = 3000; $stmt->execute(); $dbh->commit(); catch (Exception $e) { $dbh->rollback(); echo "Failed: ". $e->getmessage();?> Czy transakcja rzeczywiście zadziała dopiero przy $dbh->commit();?
PHP PDO organizacja danych <?php function readdata($dbh) { $sql = SELECT imie, nazwisko, wzrost FROM ludzie ; try { $stmt = $dbh->prepare($sql); $stmt->execute(); $stmt->bindcolumn(1, $name); $stmt->bindcolumn(2, $lname); $stmt->bindcolumn( wzrost, $h); while ($row = $stmt->fetch(pdo::fetch_bound)) { $data = $name. "\t". $lname. "\t". $h. "\n"; print $data; catch (PDOException $e) { print $e->getmessage(); readdata($dbh);?> Uwaga: W analogiczny sposób możemy wiązać wartości bindvalue.
PHP Warto przejrzeć kursory, fetch atrybuty quote(), rowcount() obsługa błędów, klasy wyjątków
Python Pakiety Poza interpreterem i silnikiem bazy danych potrzebne są: python-mysqldb python-mysqldb-dbg Konektory i interfejsy są dostępne również na stronach dialektu i języka.
Python Łączenie z bazą #!/usr/bin/python import _mysql import sys try: con = _mysql.connect( localhost, user, pass, bazatestowa ) con.query("select VERSION()") result = con.use_result() print "MySQL version: %s" % \ result.fetch_row()[0] except _mysql.error, e: print "Error %d: %s" % (e.args[0], e.args[1]) sys.exit(1) finally: if con: con.close()
Python Kursory #!/usr/bin/python import MySQLdb as mdb import sys try: con = mdb.connect( localhost, user, pass, bazatestowa ) kursor = con.cursor() kursor.execute("select PESEL, salary From staff") person, sal = kursor.fetchone() while person is not None: print "Pracownicy: %s %d" % (person, sal) person, sal = kursor.fetchone() except mdb.error, e: print "Error %d: %s" % (e.args[0], e.args[1]) sys.exit(1) finally: if con: con.close()
Python Kursory #!/usr/bin/python import MySQLdb as mdb import sys try: con = mdb.connect( localhost, user, pass, bazatestowa ) kursor = con.cursor() kursor.execute("select PESEL, salary From staff") person, sal = kursor.fetchone() while person is not None: print "Pracownicy: %s %d" % (person, sal) person, sal = kursor.fetchone() except mdb.error, e: print "Error %d: %s" % (e.args[0], e.args[1]) sys.exit(1) finally: if con: con.close() Co dzieje się z kursor po ostatnim wierszu? kursor.close()
Python Kursory przydatne metody cursor.description cursor.rowcount cursor.statement cursor.column_names cursor.callproc
Python cursor.execute stmt = "SELECT * FROM staff WHERE pesel = %(p)s" cursor.execute(stmt, { p : 66010100000 ) stmt = "INSERT INTO staff (pesel, salary) VALUES (%s, %s)" data = [ ( 77010100000, 4000), ( 88010100000, 3000), ( 99010100000, 2000), ] cursor.executemany(stmt, data)
Inne języki C++ Haskell NodeJS Julia Go
Wprowadzenie Zastosowanie aplikacje webowe Android wsparcie Hibernate Możliwe serwery konsola (Webserver) klient PostgreSQL architektura klient server via TCP
Server TCP import org.h2.tools.server; /* importy */ Server svr = Server.createTcpServer(args).start();/* start serwe /* operacje */ svr.stop(); /* zatrzymanie */
Połączenie Korzystamy ze sterownika org.h2.driver import java.sql.*; public class Test { public static void main(string[] a) throws Exception { Connection conn = \ DriverManager.getConnection("jdbc:h2:~/baza", "user", "pass"); /* operacje analogicznie do przykładów JDBC z początku wykładu */ conn.close();
Backup & Restore konsola: java -cp h2*.jar org.h2.tools.backup (Więcej informacji o narzędziach konsolowych po wywołaniu z opcją -?) script tool: java org.h2.tools.script -url jdbc:h2: /test -user <user_name> -script test.zip -options compression zip (Uwaga: można wywołać z poziomu SQL za pomocą SCRIPT) Backup On-line: BACKUP TO backup.zip
Backup & Restore konsola: java -cp h2*.jar org.h2.tools.restore (Uwaga: Jeśli baza jest uszkodzona, próba odtworzenia: org.h2.tools.recover) script tool: java org.h2.tools.runscript -url jdbc:h2: /test -user <user_name> -script test.zip -options compression zip