Modifikation der Datenbank Löschen Einfügen Änderungen Änderungen von Sichten 71
Löschen Wir haben bereits gesehen, dass wir den gesamten Inhalt einer Tabelle r löschen können durch das Kommando: delete from r Wir können aber auch selektiv Tupel (Zeilen) löschen, die eine bestimmte Bedingung P erfüllen: delete from r where P 72
Beispiele Löschen 73 Löschen aller Konten bei der Perryridge Filiale: delete from account where branch_name= Perryridge Löschen aller Kredite zwischen $1300 und $1500: delete from loan where amount between 1300 and 1500 Löschen aller Konten von Filialen in Brooklyn: delete from account where branch_name in (select branch_name from branch where branch_city= Brooklyn )
Bemerkung zu delete Beim Löschen von Tupeln ist es wichtig, dass zuerst alle Tupel ermittelt werden welche die Bedingung erfüllen und dann erst alle Tupel gelöscht werden. 74
Einfügen Wir können mit SQL Tupel direkt einfügen durch das insert into Kommando: insert into account values( A-9732, Perryridge,1200) Hierbei müssen wir allerdings die Reihenfolge der Attribute kennen! 75
Einfügen Man kann allerdings auch die Attributsnamen explizit angeben, dann kann die Reihenfolge variiert werden: insert into account (branch_name,account_number,balance) values( Perryridge, A-9732,1200) 76
Einfügen durch Select-Ausdrücke Wir können auch Tupel einfügen, die wir aus anderen Tabellen selektiert haben. Bsp: Wir erzeugen ein Konto mit 200$ Startguthaben für jeden Besitzer eines Kredites an der Perryridge Filiale. insert into account select loan_number, branch_name, 200 from loan where branch_name= Perryridge 77
Einfügen durch Select-Statements Auch hier ist es wichtig, dass der select - Teil vollkommen ausgewertet wird bevor die Tupel eingefügt werden. Bsp: insert into account select * from account 78
Änderung bestimmter Werte In manchen Fällen wollen wir den Wert eines Attributs ändern ohne die anderen Werte zu modifizieren. Das geht mit dem update-kommando: update account set balance = balance*1.05 79
Änderungen mit update Änderungen mit update können wir auch selektiv für bestimmte Tupel machen: update account set balance = balance*1.05 where balance >= 1000 80
Änderungen in Sichten Sichten stellen ein sehr wichtiges und praktisches Werkzeug dar; allerdings ist es problematisch, Sichten zu ändern. Betrachten wir z.b. folgende Sicht: create view loan_info as select customer_id, amount from borrower, loan where borrower.loan_number=loan.loan_number 81
Änderungen in Sichten Was passiert nun wenn wir versuchen, in die Sicht Zeilen einzufügen? insert into loan_info values ( Johnson,1900). Loan_info 82
Änderungen in Sichten Problem: diese Änderung hat nicht den erwünschten Effekt (warum?) 83
Änderbare Sichten (updatable) 84 Auf Grund der Probleme, die mit der Modifikation von Sichten einhergehen, verbieten einige Datenbanksysteme schlicht und einfach die Modifikation von Sichten. Im Allgemeinen können wir aber festlegen, dass eine Sicht änderbar (updatable) ist wenn folgende Bedingungen erfüllt sind: -Der from-teil bezieht sich auf nur eine Tabelle -Der select-teil beinhaltet nur Attribute der Tabelle aber keine komplexen Ausdrücke oder Aggregate -Jedes Attribut welches nicht im select-teil vorkommt kann auf null gesetzt werden. -Die Query verwendet nicht die Konstrukte group by oder having.
Änderbare Sichten 85 Auch änderbare Sichten garantieren nicht, dass die eingefügte Zeile dann auch wirklich in der Sicht enthalten ist. Man kann in SQL dann eine Sicht definieren als with check option. Dann wird ein Tupel nur eingefügt wenn auch sichergestellt ist, dass das Tupel in der Sicht auch enthalten ist. create view loan_info as select customer_id, amount from borrower, loan where borrower.loan_number=loan.loan_number with check option
Weitere Datentypen in SQL Zusätzlich zu den Datentypen, die wir bisher kennengelernt haben, unterstützt SQL auch folgende Datentypen: -Date: stellt einen Kalendertag dar, beschrieben durch ein Jahr (4 Ziffern), einen Monat (2 Ziffern) und einen Tag (2 Ziffern). -Time: repräsentiert eine Tageszeit mit Angabe der Stunde, Minute und Sekunde. -Timestamp: eine Kombination aus Date und Time, um einen Zeitpunkt eindeutig zu charakterisieren. 86
Datentypen in SQL SQL stellt uns auch Vergleichsoperatoren sowie arithmetische Operatoren für diese Datentypen bereit: 2009-10-22 > 2009-10-15 = true 2009-10-22 2009-10-15 = Intervall von sieben Tagen 2009-10-22 + Intervall von 7 Tagen = 2009-10-29 87
User-definierte Datentypen In SQL können eigene Datentypen definiert werden, z.b. create type Euros as numeric(12,2) final Diese Typen können wir dann bei der Definition eines Schemas natürlich verwenden: 88 create table account (account_number char(10), branch_name balance char(15), Euros)
Integritätsbedingungen Integritätsbedingungen auf einer einzelnen Relation -Not Null -Eindeutigkeitsbedingung -Der Check-Konstrukt Referentielle Integrität 89
Integritätsbedingungen Beispiele für Integritätsbedingungen sind folgende: -Ein Kontostand kann nicht null sein. -Konten müssen unterschiedliche Kontonummern haben. -Jedes Konto in der depositor-relation muss auch einen entsprechenden Eintrag in der account-relation haben. 90
Integritätsbedingungen Integritätsbedingungen werden meistens bei der Erzeugung des Schemas einer Tabelle spezifiziert. Wir haben bisher dadurch Primärschlüssel von Relationen angegeben: create table customer (customer_name char(20), customer_street char(20), customer_city char(30), primary key (customer_name)) 91
Not null -Bedingung In manchen Fällen macht es keinen Sinn, null -values zuzulassen (z.b. beim Stand eines Kontos). Mit dem not null Ausdruck können wir null -values explizit verbieten: create table account ( account_number char(15) not null, branch_name char(3), balance numeric(16,2) not null, primary key (account_number)) 92
Eindeutigkeitsbedingung Man kann in SQL nicht nur den Primärschlüssel spezifizieren, sondern auch festlegen, dass keine zwei Tupel in der Datenbank die selben Werte für zwei Attribute haben sollen. Das geht mit dem unique-konstrukt: create table account ( account_number char(15) not null unique, branch_name char(3), balance numeric(16,2) not null ) 93
Weitere Bedingungen Es können weitere Bedingungen an eine Relation geknüpft werden. Das erfolgt durch das Keyword check. Bsp: Der Kontostand muss immer positiv sein: create table account (account_number char(10) not null, branch_name char(15), balance numeric(12,2) not null, primary key (account_number), check (balance >=0)) 94
Weitere Bedingungen Bsp: Die Branche eines Kontos muss in der branch-tabelle enthalten sein: create table account (account_number char(10) not null, branch_name char(15), balance numeric(12,2) not null, primary key (account_number), check (balance >=0), check branch_name in (select branch_name from branch)) 95
Referentielle Integrität Wir können auch mit Hilfe der DDL von SQL foreign keys definieren. Formale Definition eines foreign keys: -Gegeben zwei Relationen r 1 und r 2 mit Schemas R 1 (r 1 ) und R 2 (r 2 ) und Primärschlüsseln K 1 und K 2 jeweils. -Eine Teilmenge r der Attribute in R 1 nennen wir Fremdschlüssel (oder foreign key) mit Referenz auf R 2 wenn für jedes Tupel t 1 in r 1 ein Tupel t 2 in r 2 existiert so dass t 1 [r ]=t 2 [K 2 ]. -Wir können diese Bedingung auch äquivalent schreiben als: 96
Spezifikation von Fremdschlüssel-Verweisen Wir können Fremdschlüssel durch das Schlüsselwort references einführen: create table account (account_number char(10) not null, branch_name char(15) references branch, balance numeric(12,2) not null, primary key (account_number), check (balance >=0)) 97
Spezifikation von Fremdschlüssel-Verweisen Oder alternativ: create table account (account_number char(10) not null, branch_name char(15) balance numeric(12,2) not null, primary key (account_number), foreign key (branch_name) references branch check (balance >=0)) Damit müssen wir in der account-tabelle einen Filialennamen (branch_name) angeben, der in der branch-tabelle auch existiert. 98
Änderungen in der referenzierten Tabelle Frage: Was passiert wenn Branchen gelöscht werden? SQL stellt uns verschiedene Strategien zur Verfügung, wie bei der Löschung von referenzierten Tupeln verfahren werden soll. Verhalten im Löschen-Fall: - on delete cascade : wenn Tupel in der referenzierten Tabelle gelöscht werden, dann lösche alle Tupel in der referenzierenden Tabelle, die das gelöschte Tupel referenzieren. - on delete set null : wenn Tupel in der referenzierten Tabelle gelöscht werden dann setze die entsprechende Fremdschlüssel- Referenz in der referenzierenden Tabelle auf null. 99
Änderungen in der referenzierten Tabelle Frage: Was passiert wenn der Name einer Branche sich ändert? SQL stellt uns verschiedene Strategien zur Verfügung, wie bei einer Änderung der referenzierten Tupel verfahren werden soll. Verhalten im Fall einer Änderung - on update cascade : wenn Tupel in der referenzierten Tabelle geändert werden, dann ändere entsprechend alle Tupel in der referenzierenden Tabelle, die das Tupel referenzieren. - on update set null : wenn Tupel in der referenzierten Tabelle geändert werden (Primärschlüssel), dann setze die Referenzen in den Tupeln der referenzierenden Tabelle auf null. 100
Probleme mit referentieller Integrität Nehmen wir an, wir haben eine Tabelle person, die wie folgt aussieht: create table person (firstname char(10) not null, secondname char(15) not null, middlename char(10), birthday date, address char(50), marriedtopersonwithfirstname char(10), marriedtopersonwithsecondname char(15), marriedtopersonwithbirthday date primary key (firstname,secondname,birthday), foreign key(marriedtopersonwithfirstname, marriedtopersonwithsecondname,marriedtopersonwithbirthday) references person (firstname,secondname,birthday) ) 101
Aufschiebbar oder nicht aufschiebbar? 102 Was ist nun wenn wir zwei Personen hinzufügen wollen, die verheiratet sind (z.b. Mia und Vincent)? Unabhängig davon welche Person zuerst angelegt wird, werden wir die referentielle Integrität verletzen! In SQL kann man angeben, dass die Überprüfung bestimmter Integritätsbedingungen aufgeschoben werden kann (deferred) bis zum Ende einer Transaktion. In einigen Datenbanken (PostgreSQL, ORACLE) sagt initially deferred deferrable, dass der Fremdschlüsselcheck erst nach der Transaktion durchgeführt werden soll.
An unserem Beispiel create table person (firstname 103 secondname middlename birthday address marriedtopersonwithfirstname marriedtopersonwithsecondname marriedtopersonwithbirthday char(10) not null, char (15) not null, char(10), date not null, char(50), char(10), char(15), date primary key (firstname,secondname,birthday), foreign key(marriedtopersonwithfirstname, marriedtopersonwithsecondname, marriedtopersonwithbirthday) references people (firstname,secondname,birthday) on delete set null on update cascade initially deferred deferrable (PostgreSQL, ORACLE, aber nicht MySQL)
Zugriffsrechte In SQL kann man für jede Tabelle folgende Rechte vergeben: -Leserecht -das Recht, Daten einzufügen -das Recht, Daten zu ändern -das Recht, Daten zu löschen Diese Rechte werden in SQL privileges genannt. SQL unterscheidet folgende privileges : -select -insert -update -delete 104
Vergabe von Rechten (Authorisierung) Die Vergabe von Rechten auf einer Tabelle erfolgt durch den Befehl (DDL): grant <Privilege_List> on <Table> to <User> Bsp: grant select on account to John, Mary grant select, update(amount) on loan to John, Mary 105
Vergabe von Rechten Es können auch alle Rechte auf einer Tabelle mit dem keyword all vergeben werden: grant all on account to Philipp Rechte können natürlich auch wieder entzogen werden: revoke insert on account from Philipp 106
Embedded SQL und JDBC Oft will man auf eine Datenbank von der Programmiersprache aus zugreifen, in der man eine Anwendung entwickelt. Wenn SQL-Ausdrücke in eine Programmiersprache eingebettet sind, so spricht man von Embedded SQL. Für die Einbettung von SQL in eine Programmiersprache (z.b. Java) benötigt man Software (einen Connector) der zwischen dem Programm und der Datenbank vermittelt. Für Java gibt es z.b. die JDBC API (Java Database Connectivity). Für C gibt es die Open Database Connectivity (ODBC) API. Alle unsere Beispiele werden sich auf die JDBC API beziehen. 107
Wichtige Schritte um SQL in Java einzubetten 1. Eine Library importieren, die JDBC implementiert (z.b. von MySQL), siehe http://dev.mysql.com/downloads/ connector/j/3.1.html 2. Den richtigen Treiber laden. 3. Eine Verbindung zur Datenbank herstellen. 4. Los geht s! (Anfragen, Löschen, Änderungen etc.) 108
Imports in Java (siehe Example1.java) import java.sql.connection; import java.sql.drivermanager; import java.sql.sqlexception; import java.sql.statement; import java.sql.resultset; 109
Treiber laden (siehe Example1.java) public class Example1 { public static void main(string[] args) { Connection conn=null; Statement stmt; ResultSet rs; // load the driver 110 System.out.println("Loading driver..."); try{ Class.forName("com.mysql.jdbc.Driver").newInstance(); } catch(exception e) { System.out.println("Class strife. " + e); } System.out.println("Driver loaded!");... }
Verbindung zur Datenbank herstellen (siehe Example1.java) try{ conn = DriverManager.getConnection ("jdbc:mysql://localhost/banking?user=cimiano"); } catch (SQLException ex) {} 111
Syntax für URL in DriverManager.getConnection() jdbc:mysql://[hostname][:port]/dbname[? param1=value1][¶m2=value2]... String url = jdbc:mysql://localhost/banking"; Connection con = DriverManager.getConnection(url, cimiano", "password"); 112
localhost Der Port wird per Default auf 3306 gesetzt (wenn nichts anderes angegeben wird!). Dementsprechend sind folgende Statements äquivalent: conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ Banking?user=cimiano&password=pass"); conn = DriverManager.getConnection("jdbc:mysql://localhost/ Banking?user=cimiano&password=pass"); conn = DriverManager.getConnection("jdbc:mysql://localhost/ Banking, cimiano, pass ); 113
Anfragen (siehe Example1.java) try { } stmt = conn.createstatement(); rs = stmt.executequery("select * from account"); int count=0; while (rs.next ()) { String account_no = rs.getstring ("account_number"); String balance = rs.getstring ("balance"); System.out.println ("account number = " + account_no+ ", balance = " + balance); count++; } rs.close (); System.out.println (count + " rows were retrieved"); 114
Updates (siehe Example2.java) stmt.executeupdate("insert into customer values ('447-77-0000','John','5th Av.','New York')"); Siehe Example2.java auf http://philipp.cimiano.org/ teaching/datenbanken_ws09/ 115
Anfragen von Metadaten mit JDBC (siehe Example3.java) Metadaten sind Daten über Daten. Man kann z.b. zu den Ergebnissen einer Anfrage die Namen der Spalten (als Metadaten) besorgen (siehe Example3.java): 116 stmt = conn.createstatement(); rs = stmt.executequery("select * from account"); String column; int count=0; rsmd = (ResultSetMetaData) rs.getmetadata(); for (int i=1; i <= rsmd.getcolumncount(); i++) { } column = rsmd.getcolumnname(i); System.out.print(column+"\t");