2. inhoud
• benaderingen voor gegevensbankprogrammeren
• ingebedde SQL
– Embedded SQL in C
– SQLJ in Java
• gegevensbanken via APIs
– Java en JDBC
– Python en pyodbc
• webtoegang tot gegevensbanken
– PHP
2
3. gebruik van SQL
• interactief
– opdracht wordt aangeboden en onmiddellijk uitgevoerd
– command line client, maar ook bijv. PhpMyAdmin
• vanuit applicatie
– SQL wordt gebruikt in een programma
3
5. benaderingen
1. inbedden SQL opdrachten in programmacode
• SQL opdrachten worden door een precompiler opgezocht
• en omgevormd tot functie-aanroepen van de programmeertaal
2. gebruik van een bibliotheek met functies
• die toegang verschaffen tot de gegevensbank
• en resultaten beschikbaar stellen aan een programma in een API
3. een (nieuwe) programmeertaal ontwikkelen
• die compatibel is met het gegevensmodel en query taal
• vb: PL/SQL van Oracle
6. twee aanpakken
Host language
1. +
Embedded SQL
Preprocessor
2.
Host language
+
Function calls
Host‐language
SQL library Object-code
compiler
program
7. SQL/Host Language Interface
SQL stmt
Function call SQL
Table Library
While(…){
Cursor DBMS
}
Fetch rows Impedance
host program from the cursor mismatch
problem
[Kazuhiro Minami]
8. impedance mismatch
• verschillen tussen gegevensmodel en model van de programmeertaal
– CHAR, VARCHAR -- String
– INTEGER -- int
• `bindings’ voor verschillende programmeertalen
– definieert overeenkomsten van de attribuuttypes met de types in de programmeertaal
– bindt resultaat van query (=verzameling van tuples) aan datastructuur van het
programma
• representatie in een tabelstructuur vaak onmogelijk
– daarom meestal tupel voor tupel
8
9. typische interactie client/server model
1. het client programma opent een verbinding met de gegevensbankserver
– vereist meestal adres van machine met de server,
– en login-naam en paswoord voor gegevensbank
2. interactie tussen het programma en de gegevensbank:
– programma biedt queries, updates, … aan
– server levert resultaten van de queries,…
3. programma sluit de verbinding met de gegevensbank
9
10. twee aanpakken
Host language
1. +
Embedded SQL
Preprocessor
2.
Host language
+
Function calls
Host‐language
SQL library Object-code
compiler
program
12. ingebedde SQL
• embedded SQL
• SQL opdracht kan in programmacode ingebed worden
• een pre-compiler verwerkt de SQL opdrachten vóór de compilatie van
het programma:
– SQL opdrachten worden vervangen door declaraties en functie-
aanroepen in de programmeertaal
• syntax verschilt wat naargelang van de programmeertaal
EXEC SQL < embedded SQL statement > END‐EXEC
EXEC SQL < embedded SQL statement > ;
#SQL { < embedded SQL statement > } ; 12
13. ingebedde SQL
– connecteren met de gegevensbank:
CONNECT TO < server name > AS < connection name >
AUTHORIZATION < user account name and password > ;
• slechts één connectie kan actief zijn;
• wijzigen van de actieve connectie:
SET CONNECT < connection name > ;
– verbinding beëindigen:
DISCONNECT < connection name > ; 13
14. ingebed gebruik van SQL
• gemeenschappelijke variabelen
– SQL opdrachten kunnen verwijzen naar programmavariabelen
– dubbele punt (:) als prefix
• de gemeenschappelijke variabelen moeten
gedeclareerd worden in een SQL declaratiesectie
• via variabelen kan informatie worden uitgewisseld
14
15. ingebedde SQL: voorbeeld
• Eén tupel ophalen uit een gegevensbank
• Voorbeeld:
– declaratie van variabelen, in C
EXEC SQL BEGIN DECLARE SECTION;
varchar dname[16], fname[16], lname[16];
char ssn[10], bdate[11], sex[2], minit[2];
float salary, raise;
int dno, dnumer;
int SQLCODE ; char SQLSTATE[6];
EXEC SQL END DECLARE SECTION;
16. ingebedde SQL: voorbeeld
Herhaal een aantal maal: vraag om ssn van een werknemer en
geef gegevens van die werknemer
loop = 1;
while (loop) {
prompt(“Enter a social security number: “, ssn);
EXEC SQL
select Fname, Minit, Lname, Address, Salary
into :fname, :minit, :lname, :address, :salary
from EMPLOYEE
where SSN = :ssn;
if (SQLCODE == 0)
printf(fname, minit, lname, address, salary)
else printf(“social sec. numb. does not exist: “, ssn);
prompt(“More s.s.numbers (enter 1 for Yes, 0 for No): “,
loop) ;
}
17. SQLJ
• SQL commando’s ingebed in Java
– SQLJ vertaler zet SQL commando’s om in Java,
– commando’s worden uitgevoerd d.m.v. de JDBC interface
– JDBC driver moet dus geïnstalleerd worden
• vereist:
– importeren van verscheidene klassen
• JDBC en IO klassen
• extra klassen
– connecteren met de gewenste gegevensbank
• getConnection
17
18. SQLJ
– importeren van de nodige klassen (vb. met Oracle)
import java.sql.*;
import java.io.*;
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
import oracle.sqlj.runtime.*;
…
– connectie maken
DefaultContext cntxt =
oracle.getConnection(“<url name>”,
“<user name>”, “<pasword>”, true);
DefaultContext.setDefaultContext(cntxt);
…
19. SQLJ
– Voorbeeld 1:
• lees het ssn van een werknemer en schrijf (op de uitvoer) gegevens van
die werknemer
ssn = readEntry(“Enter a social security number: “);
try {
#sql{select Fname, Minit, Lname, Address, Salary
into :fname, :minit, :lname, :address, :salary
from EMPLOYEE where Ssn = :ssn};
} catch (SQLException se) {
System.out.println(“s.s.number does not exist: “+ ssn);
return ;
}
System.out.println(fname + “ “ + minit + “ “ + lname + “ “
+ “ “ + salary)
19
20. dname = readEntry(“Enter the department name: “);
try {
#sql{select Dnumber into :dnumber
from DEPARTMENT where Dname = :dname};
}
catch (SQLException se) {
System.out.println(“department does not exist:“ + dname);
return;
}
System.out.println(“ information for department: “ + dname);
#sql iterator Emp(String ssn, String fname, String minit,
String lname, double salary);
Emp e = null;
#sql e = {select ssn, fname, minit, lname, salary
from EMPLOYEE where Dno = :dnumber};
while (e.next()) {
System,out.println(e.ssn + “ “ “ e.fname + “ “ +
e.minit + “ “ + e.lname + “ “ + e.salary);
} ;
e.close();
21. twee aanpakken
Host language
+
Embedded SQL
Preprocessor
2.
DB API Host language
+
Function calls
Host‐language
SQL library Object-code
compiler
program
23. JDBC
• Call function interface voor toegang vanuit Java
• SQL statements worden dynamisch aangemaakt en
doorgegeven als string
• Gebruikt API voor toegang tot DBMS
23
24. JDBC
• gestandaardiseerde API (Application Programming Interface)
– geregistreerde naam door Sun Microsystems
– zou niet staan voor ‘Java DataBase Connectivity’
• JDBC driver = een implementatie van de functie-aanroepen die
gespecificeerd zijn in de JDBC API
• DBMS leveranciers bieden JDBC drivers aan zodat het mogelijk wordt
om gegevensbanken vanuit een Java programma aan te spreken
24
26. stappen in JDBC gebruik
1. importeer het java.sql pakket
2. laad en registreer de driver
3. zorg voor passende variabelen in Java
4. maak een connectie met de gegevensbank
5. creëer een opdracht
6. voer de opdracht uit
7. haal het resultaat (of de resultaten) op
8. sluit de opdracht en de connectie
27. 1. importeer het java.sql pakket
import java.sql.*;
of
of
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.DriverManager;
import java.sql.Driver;
import java.sql.Statement;
import java.sql.ResultSet;
…
27
28. 2. laad en registreer de driver
• dit gebeurt d.m.v. de klasse DriverManager
• laden van een specifieke driver gebeurt door de
statische methode registerDriver() op te roepen
DriverManager.registerDriver
(new oracle.jdbc.driver.OracleDriver());
DriverManager.registerDriver
(new org.postgresql.Driver());
28
29.
30. JDBC gebruik
3. zorg voor de passende variabelen in Java
public class Department {
private String dname;
private String dnumber;
private String mgrssn;
private String mgrstartdate;
public Department(String dname, String dnumber,
String mgrssn, String mgrstartdate) {
setDname(dname);
setDnumber(dnumber);
setMgrssn(mgrssn);
setMgrstartdate(mgrstartdate);
}
public String getDname() {
return dname;
}
}
31. 3. maak een connectie met de gegevensbank
• gebruik de statische methode getConnection() uit de
klasse DriverManager om een connection object te maken
• twee schrijfwijzen
– drie door komma’s gescheiden argumenten
– een string als argument
Connection con = DriverManager.getConnection
(url,”userName”,”password”);
Connection con = DriverManager.getConnection
("jdbc:postgresql:employee", "postgres", ”pwd");
31
32. 4. creëer een opdracht
• Statement object
Statement stmt = con.createStatement();
vb: een tabel Department maken:
Statement stmt = con.createStatement();
String creeer= “CREATE TABLE Department (“ +
“ Dname Varchar(15) Not Null,”+
“ Dnumber Integer Not Null,”+
“ MgrSsn Char(9),”+
“ MgrStartDate DATE,”+
“ PRIMARY KEY (Dnumber),”+
“ UNIQUE (Dname)”+
“)”;
32
33. 5. voer de opdracht uit
• executeQuery
• executeUpdate
try{
stmt.executeUpdate ("INSERT INTO DEPARTMENT VALUES ("
+quotes(d.getDname())+", "+d.getDnumber()+", "
+quotes(d.getMgrssn())+", "
+getDate(d.getMgrstartdate())+") ");
stmt.executeUpdate("COMMIT");
}
catch(SQLException sqle){
stmt.executeUpdate("ROLLBACK");
throw new FailureNoticeException(sqle.getMessage());
}
stmt.close();
33
34. opdrachten
• ResultSet executeQuery(String sql_query)
– Voert de query sql_query uit en geeft een ResultSet object
dat het resultaat van de query bevat.
• int executeUpdate(String sql_query)
– Voert de query sql_query uit en geeft als resultaat het aantal
rijen dat werd toegevoegd/verwijderd/gewijzigd.
34
35. 6. haal het resultaat (of de resultaten) op
• het resultaat wordt teruggegeven in een object van het
type ResultSet
ResultSet rs = stmt.executeQuery
("SELECT dname, dnumber, mgrssn, mgrstartdate " +
" FROM Department" +
" WHERE dnumber = " + number );
if (!rs.next()) throw new FailureNoticeException
("Geen departement voldoet aan het zoekcriterium.");
Department d = new Department(rs.getString("dname"),
rs.getString("dnumber"), rs.getString("mgrssn"),
rs.getString("mgrstartdate"));
rs.close();
35
36. 7. afsluiten
sluit de opdracht en de connectie
• ook eventuele resultset(s) moeten worden afgesloten
stmt.close();
con.close ();
36
38. java.sql.Statement
• meest gebruikt type opdracht
– v.b. Connection con = …;
Statement stmt = con.createStatement();
• hoe worden SQL statements uitgevoerd?
– de gebruiker voert een SQL opdracht in
– het gevensbanksysteem ontleedt de opdracht
– het gegevensbanksysteem controleert de syntax
– het gegevensbanksysteem compileert de opdracht
– het gegevensbanksysteem voert de opdracht uit
38
39. java.sql.PreparedStatement
– gebruikt voor de (herhaalde) uitvoering van dynamische SQL
opdrachten
• parameters kunnen later worden ingesteld
Res PreparedStatement p = con.prepareStatement(
"SELECT dname, dnumber, mgrssn, mgrstartdate " +
" FROM Department" +
" WHERE dnumber = ?" );
p.clearParameters();
p.setInt(1, 1);
ResultSet rs=p.executeQuery();
39
41. SQLJ versus JDBC
SQLJ JDBC
SQL statements static dynamic
Strong typing yes no
Checking static runtime only
Syntax concise API
Standard ANSI Sun
Portable yes yes
Object support yes* yes*
Source: www.cs.manchester.ac.uk/~horrocks/cs2312/Lectures/PPT/jdbc.ppt
43. Python Database API 2.0
• gestandaardiseerde API
– aanmoediging tot gelijkaardige DB modules voor Python
• vele verschillende implementaties beschikbaar
– DBMS-specifiek
– Generiek: ODBC-gebaseerd, ADO (Windows)
– Maar ook: SQLite, flat files, XML, …
43
44. pyodbc
• voor veel platformen (besturingssystemen) beschikbaar
– open source
• kan met veel DMBSen communiceren
– want gebruikt ODBC drivers
44
45. pyodbc – verbinden
• maak een verbinding
• creëer een cursor
cnxn = pyodbc.connect('DRIVER={SQL Server};
SERVER=localhost;DATABASE=testdb;UID=me;PWD=pass')
cursor = cnxn.cursor()
46. pyodbc – gegevens opvragen
cursor.execute("select user_id, user_name from users")
row = cursor.fetchone()
if row:
print row.user_name
cursor.execute("select user_id, user_name from users")
rows = cursor.fetchall()
for row in rows:
print row.user_id, user_name
47. pyodbc – data toevoegen
• execute() ipv query()
• met ODBC kun je een ? als parameter gebruiken en de
waarde daarna los meegeven
• commit() is noodzakelijk om wijzigingen op te slaan
cursor.execute("insert into products(id, name) values
(?, ?)", 'pyodbc', 'awesome library')
cnxn.commit()
51. webtechnologie …
• met dit onderwerp kun je gemakkelijk een heel vak
vullen, of twee
• we komen hier niet verder dan een heel globaal
overzicht van de mogelijkheden van de combinatie van
– HTML,
– PHP,
– MySQL
52. Hypertext Markup Language (HTML)
• gebruikt voor webpagina’s
• statische pagina’s
• tekst met tags tussen scherpe haakjes specificeren het
formaat waarin de tekst getoond moet worden
<html>
<head>
<title>Welkom</title>
</head>
<body>
<h1>Ga zitten</h1>
<p>Hartelijk <b>welkom</b> in de cursus.</p>
</body>
</html>
53. Cascading Style Sheets (CSS)
• groot nadeel HTML: mengt vorm en inhoud
• met CSS kunnen vorm en inhoud beter worden
gescheiden
• HTML bepaalt structuur en inhoud, CSS de vorm
div#main {
background: #fff;
color: #000;
}
h2 {
color: #fff;
font-weight: bold;
text-align: center;
}
54. dynamische pagina’s
• moderne webpagina’s zijn zelden statisch!
• server-side applicaties genereren dynamische HTML pagina’s
– vaak scripttalen: PHP, ASP, Python, Perl, …
– maar ook Java, C++, etc. kunnen worden gebruikt
• gebruik scripttalen:
– in een document kan afwisselend code en HTML worden geplaatst
– wanneer de pagina wordt opgevraagd, wordt op de server de PHP code
uitgevoerd (geïnterpreteerd); het resultaat wordt doorgestuurd
<html>
<body>
<?php
echo "Welkom!";
?>
</body>
</html>
55. PHP: een inleiding
• scripttaal
– een programmeertaal geschikt voor het schrijven van kleine
programma’s (=scripts)
– om veel voorkomende taken te automatiseren
• ontworpen in 1994 door Rasmus Lerdorf
• naam
– oorspronkelijk: PHP = Personal Home Page
– nu: PHP = PHP: Hypertext Preprocessor
• PHP processor is geschreven in C, dus erg draagbaar
• erg geschikt voor het manipuleren van dynamische
webpagina’s op een webserver
• heeft verscheidene functiebibliotheken voor toegang tot
verschillende types van relationele gegevensbanken
56. variabelen
• namen
– beginnen met $
– mogen verder letters, cijfers en het onderstrepingsteken
bevatten (maar geen cijfers onmiddellijk na $-teken)
• type: variant – kan wijzigen in functie van de
uitgevoerde bewerking
– moet dus niet vooraf gedeclareerd worden
– een variable krijgt haar type bij de eerste toekenning
(maar dat type kan later wijzigen!)
• data types
– getallen; strings (tussen ‘ ‘ of “ “); booleaanse waarden
57. PHP
• Begin- en eindtag:
– <?php ?>
– <? ?>
– Alleen code binnen tags wordt geïnterpreteerd en
uitgevoerd, al het overige wordt direct naar client
gestuurd
• Commentaar:
– // tot einde regel
– # tot einde regel
– /* over verscheidene regels */
58. tabellen (arrays)
• zijn dynamisch: geen vast aantal elementen
• kan elementen van verschillende typen bevatten
• posities kunnen genummerd zijn (beginnend bij 0)
• posities kunnen ook door een string aangegeven
worden; dan spreekt men van associatieve tabellen.
60. tabellen (arrays)
• Sequentieel doorlopen van tabellen kan met foreach
• foreach($Fruitlijst as $fruit)
print(“$fruit <br />”);
• foreach($Fruitlijst as $index => $fruit)
print(“$index: $fruit <br />”);
61. PHP
• rekenkundige operatoren:
– * / % + - ++ --
• vergelijkingsoperatoren:
– == === < > <= >= != <> !==
• echo() en print()
– weergeven van strings binnen PHP
– met echo() kan de tekst meerdere regels omvatten, met
print() niet
– Voorbeelden
echo `dit is tekst`;
echo (`dit is tekst`);
62. PHP
• Logische operatoren
– ! and && or ||
• String operatoren
– . .= (bijv. $s = ‘G’; $s .= ‘B’;)
• Controlestructuren
– if – else
– verkorte if-else
– switch
– for
– while
– do – while
– foreach
63. if .. then .. else ; include
<?php
if($user == `Matthijs`) {
include(`secretpage.inc.php`);
} else {
include(`publicpage.inc.php`);
}
?>
• nadeel HTTP protocol: stateless
• voor iedere request wordt applicatie (PHP script)
opnieuw opgestart
• status moet server-side worden bijgehouden
• oplossing: sessies en cookies
65. globale variabelen
• gebruik van variabelen die buiten de functie aangemaakt zijn
• voorbeeld
<?php
$som = 0;
function maakSom ($g1, $g2){
global $som;
$som = $g1 + $g2;
echo $som;
}
?>
...
<?php echo $som ?> // geeft: 0
<?php maakSom(5,6) ?> // geeft: 11
<?php echo $som ?> // geeft: 11
66. globale variabelen #2
• gebruik van variabelen die buiten de functie aangemaakt zijn
• voorbeeld
<?php
$som = 0;
function maakSom ($g1, $g2){
$GLOBALS[‘som‘] = $g1 + $g2;
echo $GLOBALS[‘som‘];
}
?>
...
<?php echo $som ?> // geeft: 0
<?php maakSom(5,6) ?> // geeft: 11
<?php echo $som ?> // geeft: 11
67. superglobal variabelen
• variabelen die automatisch door PHP aangemaakt worden
en altijd globaal zijn
• een aantal arrays van superglobals zijn beschikbaar, o.a.:
– $GLOBALS:
• array van alle variabelen die je zelf als global definieert
– $_GET en $_POST:
• array van alle formuliervelden die via GET of POST verzonden worden
– $_SESSION:
• array met sessievariabelen
– $_SERVER:
• array met servergegevens (servernaam, protocol,…)
– $_ENV:
• array met omgevingsvariabelen (OS, computernaam,…)
– …
68. formulieren
• geschikt voor invoer van gebruiker
• gepreciseerd tussen tags <form> en </form>
• belangrijke attributen van <form> tag:
– action: verwijzing naar de pagina die de verwerking van het
formulier doet
– method: manier waarop de gegevens verstuurd worden (keuze
tussen GET en POST)
• GET: plakt alle gegevens achter de URL
• POST: de verzonden gegevens zijn niet zichtbaar in de URL, maar komen
in de HTTP-headers
• de velden van het formulier zijn beschikbaar in php-
script d.m.v. de superglobals $_POST en $_GET
69. formulieren
<html>
<body>
<form action="formHandler.php" method="post">
Voornaam: <input type="text" name="voornaam" />
Familienaam: <input type="text" name="naam" />
<input type="submit" />
</form>
</body>
</html>
• bij versturen van dit formulier gaan de gegevens naar het
formHandler.php script, dat er b.v. als volgt kan uitzien:
<html>
<body>
Hallo <?php echo $_POST["voornaam"]." ".
$_POST["naam"]."!"; ?>
</body>
</html>
70.
71. verbinding maken met een
gegevensbank in PHP
Twee manieren
1. Database-specifieke API, bijv. voor MySQL
2. Algemene bibliotheek, bijv. MDB2
72. verbinding maken met een
gegevensbank
• Gebruik mysql_connect en mysql_select_db
– mysql_connect ([<server> [,<gebruikersnaam> [,<paswoord>]]]) ;
– mysql_select_db ( <gegevensbank> [,<connectie>]) ;
$host = ‘barbary.cs.kuleuven.be’ ;
$user = ‘phpdb’ ;
$pass = ‘frietjes’ ;
$database = ‘muziek’ ;
$conn = mysql_connect ( $host, $user, $pass )
or die(“cannot connect to database”);
mysql_select_db ( $database ) ;
73. queries
• gebruik mysql_query
– mysql_query ( <query> [, <connectie>] ) ;
– dit geeft een tabel als resultaat
$query = “SELECT user_id AS id, login_name AS naam, ”
.”birthdate AS datum “
.”FROM user ” ;
$result = mysql_query ($query) or
or die (“database fout: “ .
mysql_error() ) ;
74. rijen uit het resultaat halen
• gebruik een herhaling zoals while, foreach,…
while ( $entry = mysql_fetch_array($result,
MYSQL_ASSOC) ) {
?>
<tr>
<td><?php echo $entry[‘naam’]; ?> </td>
<td><?php echo $entry[‘datum’]; ?> </td>
</tr>
<?php
}
75. afsluiten van de connectie
• Gebruik mysql_close
mysql_close (<connectie>) ;
• Voorbeeld
mysql_close($conn);
76. PEAR MDB2
• PEAR is een collectie PHP extensies
• MDB2 is een abstractielaag voor gegevensbanken
• kan met vele DMBSen verbinding maken
• niet altijd beschikbaar
require ‘MDB2.php‘;
$d = MDB2::connect(‘oci8://acct1:pwd@sql.kul.be/db‘);
if(PEAR::isError($d)) { die(‘Cannot connect: ‘.
$d->GetMessage()); }
77. PEAR – tupel toevoegen
• voor tabellen met een oplopend integer als primaire
sleutel kunnen we `volgende ID’ opvragen
// Get next id
$eid = $d->nextID(`EMPLOYEE`);
// Insert tuple into Employee table
$q = $d->query(“INSERT INTO EMPLOYEE VALUES
($eid, `$_POST[`name`]`, $_POST[`dno`])“);
78. SQL injectie
• opgelet: vertrouw nooit je gebruiker!
• onderstaande query kan tot grote problemen leiden
// Get next id
$eid = $d->nextID(`EMPLOYEE`);
// Insert tuple into Employee table
$q = $d->query(“INSERT INTO EMPLOYEE VALUES
($eid, `$_POST[`name`]`, $_POST[`dno`])“);
79. SQL injectie
• name = Matthijs
• dno = 2); DELETE FROM EMPLOYEE;
// Get next id
$eid = $d->nextID(`EMPLOYEE`);
INSERT INTO EMPLOYEE VALUES
(81, `Matthijs`,into DELETE FROM EMPLOYEE; );
// Insert tuple 2); Employee table
$q = $d->query(“INSERT INTO EMPLOYEE VALUES
($eid, `$_POST[`name`]`, $_POST[`dno`])“);
80. SQL injectie
• oplossing 1: valideer altijd alle invoer van de gebruiker,
voordat je deze gebruikt (!)
• oplossing 2: gebruik het ? (mits ondersteund)
// Get next id
$eid = $d->nextID(`EMPLOYEE`);
// Insert tuple into Employee table
$q = $d->query(“INSERT INTO EMPLOYEE VALUES
(?, ?, ?)“,
array($eid,$_POST[`name`],$_POST[`dno`]));
81. documentatie
• PHP Manual
http://www.php.net/manual/en/index.php
• MySQL documentation
http://dev.mysql.com/doc/