Download as pdf or txt
Download as pdf or txt
You are on page 1of 387

Ανοικτά Ακαδημαϊκά Μαθήματα

Τεχνολογικό Εκπαιδευτικό Ίδρυμα Αθήνας

Βάσεις Δεδομένων Ι (Εργαστηριο)


Ενότητα 1: Εργαστήριο προσανατολισμού (orientation): Δημιουργία και διαχείριση
σχεσιακής βάσης δεδομένων με πραγματικά Προϊόντα Διαχείρισης Βάσης
Δεδομένων (Data Base Management Systems)

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Εισαγωγή στη χρήση του προϊόντος της Oracle .................................................... 2
2. Εισαγωγή στη χρήση του προϊόντος mySQL ......................................................... 3
3. Συγκριτικός Πίνακας διαφορών............................................................................. 5
4. Εγκατάσταση (installation) των προϊόντων ........................................................... 5
5. Χρήση του προϊόντος της MySQL .......................................................................... 7

Στόχος του εργαστηρίου είναι η εξοικείωση με τη δημιουργία και τη διαχείριση μίας


απλής σχεσιακής βάσης δεδομένων με πραγματικά Προϊόντα Διαχείρισης Βάσης
Δεδομένων (Data Base Management Systems). Το εργαστήριο εστιάζει στην
επισήμανση των διαφορών στην περίπτωση υλοποίησης με χρήση των προϊόντων
mySQL και Oracle. Επιπλέον, δίδονται στοιχεία για την εγκατάσταση προϊόντων
διαχείρισης βάσης δεδομένων. Μετά την επεξεργασία του εργαστηρίου ο
ενδιαφερόμενος θα έχει εγκαταστήσει προϊόντα για την παραπέρα άσκηση του και
θα έχει κατανοήσει τα θέματα δημιουργίας βάσης δεδομένων στα δύο προϊόντα.

Λέξεις Κλειδιά: Σχεσιακή βάση δεδομένων (Relational database), Προϊόντα


Διαχείρισης Βάσης Δεδομένων (Data Base Management Systems), mySQL, Oracle,
Εγκατάσταση (installation) προϊόντων Διαχείρισης Βάσης Δεδομένων, DBTechNet
DebianDB virtual machine package

2
1. Εισαγωγή στη χρήση του προϊόντος της Oracle

Έστω η παρακάτω βάση δεδομένων προσωπικού εταιρείας.

emp (πίνακας υπαλλήλων)


Empno Ename Job Hiredate Mgr Sal Comm Deptno
10 CODD ANALYST 1/1/89 15 3000 10
15 ELMASRI ANALYST 2/5/95 15 1200 150 10
20 NAVATHE SALESMAN 7/7/77 20 2000 20
30 DATE PROGRAMMER 4/5/04 15 1800 200 10

dept (πίνακας τμημάτων)


Deptno Dname Loc
10 ACCOUNTING ATHENS
20 SALES LONDON
30 RESEARCH ATHENS
40 PAYROLL LONDON

Δημιουργήστε τη βάση και τους δύο πίνακες και εισάγετε στοιχεία.

CREATE TABLE DEPT(DEPTNO NUMBER(2) NOT NULL,

DNAME VARCHAR2(14), LOC VARCHAR2(14));

CREATE TABLE EMP(EMPNO NUMBER(4) NOT NULL, ENAME VARCHAR2(10), JOB VARCHAR2(25),

HIREDATE DATE, MGR NUMBER(4), SAL NUMBER(7,2), COMM NUMBER(7,2),

DEPTNO NUMBER(2));

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO EMP

VALUES (10, 'CODD', 'ANALYST', '01/01/1989', 15, 3000, NULL, 10);

Δείτε τα στοιχεία των πινάκων της βάσης.

SELECT * FROM EMP;

SELECT * FROM DEPT;

Πως θα διαγράψετε τους πίνακές σας

DROP TABLE EMP;

DROP TABLE DEPT;

3
2. Εισαγωγή στη χρήση του προϊόντος mySQL

Έστω η παρακάτω βάση δεδομένων προσωπικού εταιρείας.

emp (πίνακας υπαλλήλων)


Empno Ename Job Hiredate Mgr Sal Comm Deptno
10 CODD ANALYST 1/1/89 15 3000 10
15 ELMASRI ANALYST 2/5/95 15 1200 150 10
20 NAVATHE SALESMAN 7/7/77 20 2000 20
30 DATE PROGRAMMER 4/5/04 15 1800 200 10

dept (πίνακας τμημάτων)


Deptno Dname Loc
10 ACCOUNTING ATHENS
20 SALES LONDON
30 RESEARCH ATHENS
40 PAYROLL LONDON

Δημιουργήστε τη βάση και τους δύο πίνακες και εισάγετε στοιχεία.

DROP DATABASE NEW_PERSONNEL;

CREATE DATABASE new_personnel;

USE new_personnel;

CREATE TABLE DEPT(DEPTNO INT(2) NOT NULL,

DNAME VARCHAR(14), LOC VARCHAR(14));

CREATE TABLE EMP(EMPNO INT(4) NOT NULL,

ENAME VARCHAR(10), JOB VARCHAR(25),

HIREDATE DATE, MGR INT(4), SAL FLOAT(7,2), COMM FLOAT(7,2),

DEPTNO INT(2));

SHOW TABLES;

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO EMP

VALUES (10, 'CODD', 'ANALYST', '1989/01/01', 15, 3000, NULL, 10);

4
Δείτε τα στοιχεία των πινάκων της βάσης.

SELECT * FROM EMP;

SELECT * FROM DEPT;

Πως θα διαγράψετε τους πίνακές σας

DROP TABLE EMP;

DROP TABLE DEPT;

3. Συγκριτικός Πίνακας διαφορών

mySQL Oracle
CREATE DATABASE new_personnel;
USE new_personnel;
CREATE TABLE DEPT(DEPTNO INT(2) NOT NULL, CREATE TABLE DEPT(DEPTNO NUMBER(2) NOT NULL,
DNAME VARCHAR(14), LOC VARCHAR(14)); DNAME VARCHAR2(14), LOC VARCHAR2(14));
CREATE TABLE EMP(EMPNO INT(4) NOT NULL, CREATE TABLE EMP(EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR(10), JOB VARCHAR(25), ENAME VARCHAR2(10), JOB VARCHAR2(25),
HIREDATE DATE, MGR INT(4), HIREDATE DATE, MGR NUMBER(4),
SAL FLOAT(7,2), COMM FLOAT(7,2), SAL NUMBER(7,2), COMM NUMBER(7,2),
DEPTNO INT(2)); DEPTNO NUMBER(2));
INSERT INTO DEPT(DEPTNO, DNAME, LOC) INSERT INTO DEPT(DEPTNO, DNAME, LOC)
VALUES (10, 'ACCOUNTING', 'NEW YORK'); VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO EMP INSERT INTO EMP
VALUES (10, 'CODD', 'ANALYST', '1989/01/01', 15, 3000, VALUES (10, 'CODD', 'ANALYST', '01/01/1989', 15, 3000,
NULL, 10); NULL, 10);
SELECT * FROM EMP; SELECT * FROM EMP;
SELECT * FROM DEPT; SELECT * FROM DEPT;
DROP TABLE EMP; DROP TABLE EMP;
DROP TABLE DEPT; DROP TABLE DEPT;
DROP DATABASE NEW_PERSONNEL;
SHOW TABLES; SELECT * FROM Tab;
Πίνακας 1. Συγκριτικός πίνακας διαφορών MySQL και Oracle

Άσκηση
Να υλοποιήσετε τη βάση δεδομένων με χρήση του προϊόντος Oracle.

4. Εγκατάσταση (installation) των προϊόντων

Η εγκατάσταση των προϊόντων μπορεί να γίνει εύκολα από τον ενδιαφερόμενο που θέλει
να δοκιμάσει εντολές SQL για τη διαχείριση σχεσιακών βάσεων δεδομένων. Πιο
συγκεκριμένα, υπάρχουν δύο εναλλακτικές λύσεις:

5
1) Λύση για αρχάριους: Ο ενδιαφερόμενος μπορεί να εγκαταστήσει κάποιο προϊόν
που διατίθεται ελεύθερα. Για παράδειγμα, θα μπορούσε να εγκαταστήσει το
προϊόν MySQL ή το προϊόν Oracle XE ή το προϊόν PostgreSQL. Η εγκατάσταση είναι
μάλλον απλή υπόθεση. Ακολουθούν στοιχεία:

Μια πρώτη εγκατάσταση του προϊόντος mySQL


- Κατεβάζουμε (Download) την τελευταία version του προϊόντος, που διατίθεται
ελεύθερα, από διάφορους ιστότοπους πχ
MySQL Community Downloads (http://dev.mysql.com/downloads/)

- Ακολουθούμε τις οδηγίες

Σε περίπτωση προβλήματος!

Κατεβάζετε παλαιότερη version (πχ 5.5.χ) από κάποιο ιστότοπο π.χ.


http://www.filehippo.com/download_mysql/

- Επιλέξτε set up type: Typical


- Επιλέξτε Launch the mySQL Instance Configuration Wizard
- Επιλέξτε Standard Configuration
- Επιλέξτε Install Windows service, Include Bin directory in Windows Path
- (Αν πρώτη φορά κάνετε εγκατάσταση και έχετε πολλά προβλήματα) Επιλέξτε Create an
Anonymous Account (τότε όταν συνδέεστε με το προϊόν δε θα χρησιμοποιείτε password)
- Execute

Συστήνεται μαζί με την εγκατάσταση του προϊόντος mySQL να εγκαταστήσετε και


κάποιο εργαλείο όπως:
- MySQL workbench
http://dev.mysql.com/downloads/mirror.php?id=410031

2) Λύση για σπουδαστές πληροφορικής και επαγγελματίες: Ο ενδιαφερόμενος αν δε


θελήσει να εγκαταστήσει μεμονωμένα προϊόντα μπορεί να κατεβάσει και να
εγκαταστήσει το DBTechNet DebianDB virtual machine package με το οποίο μπορεί
να ασκηθεί σε διάφορα προϊόντα. Αντιγράφουμε από τη σχετική ιστοσελίδα: “The
free DBMS products in DBTechNet DebianDB include DB2 Express-C, Oracle XE,
MySQL/InnoDB, PostgreSQL, and Pyrrho”. Το προΊόν Pyrrho είναι ένα ενδιαφέρον
πειραματικό προϊόν. Στο πακέτο DebianDB δεν περιλαμβάνεται το προϊόν SQL
Server Express edition που επίσης διατίθεται δωρεάν. Μπορείτε να το κατεβάσετε
και να το εγκαταστήσετε εύκολα:
http://www.microsoft.com/en-us/server-cloud/products/sql-server-editions/sql-
server-express.aspx

6
Στοιχεία για την εγκατάσταση του προϊόντος DBTechNet DebianDB virtual
machine package
Αντιγράφουμε από την ιστοσελίδα:

http://dbtech.uom.gr/mod/resource/view.php?id=824

(προσβάσιμη μέσω του DBTech portal: http://dbtech.uom.gr/)

Educational and Training Content:

 SQL-Transactions-Theory and Hands-On Exercises View Download

 Quick Start to the DebianDB Database Laboratory View Download

 DBTechNet DebianDB virtual machine package (attention: 4.9 GBytes in its size!)
Download

 Oracle VirtualBox and DBTechNet DebianDB VM installation guide: Video

Quick Start to the DebianDB Database Laboratory (.pdf document written by Martii Laiho))

“DebianDB is a Debian Linux virtual machine providing a portable and free database
laboratory to be used either on classroom courses or as self study tool of students or
individual professionals. It is based on an earlier version developed at University of
Macedonia in Thessaloniki for DBTech EXT project of DBTechNet, and further developed by
Mr. Taito Halonen at Haaga Helia UAS in Helsinki for DBTechNet.

The purpose of this document is to help you in installing the lab and to start using the
database product (s) of your choice in this Linux based database laboratory of your own,
even if you are not too familiar to Linux before.”

5. Χρήση του προϊόντος της MySQL

- Εκκινούμε το προϊόν σε Command Line Client (ή μέσα από τον Workbench client ή
μέσα από άλλον client που εγκαταστήσατε).
- Πληκτρολογείτε το συνθηματικό σας (αν έχετε δηλώσει συνθηματικό κατά την
εγκατάσταση, βέβαια καλό είναι να δηλώνετε συνθηματικά)
- Είσαστε έτοιμοι να γράψετε τις εντολές σας.
- Αν έχετε γράψει τις εντολές σε κάποιο αρχείο (καλή πρακτική) μπορείτε με copy-
paste (σε “Command Line Client” χρησιμοποιήστε δεξιό click στο ποντίκι για τη
λειτουργία paste) άμεσα να τις εκτελέσετε.

7
- Επίσης, αν έχετε προετοιμάσει κάποιο script εντολών δηλαδή αρχείο κειμένου που
περιλαμβάνει τις εντολές σας και έχει επέκταση .SQL (txt file, extension .SQL),
δηλαδή file_name.SQL, μπορείτε να το εκτελέσετε με την εντολή SOURCE.

mysql> source file_name

mysql> \. file_name

Θέμα: Διαχείριση βάσης δεδομένων αμερικανικών εκλογών


Έστω απλουστευμένη βάση των αμερικανικών προεδρικών εκλογών.
Στο δείγμα παρατίθενται εκλογικά αποτελέσματα για τις αναμετρήσεις
από το 1952 έως το 1992. Στη συνέχεια παραθέτουμε τους τέσσερις (4)
πίνακες στους οποίους επιμερίζονται τα στοιχεία των εκλογών.

PRESIDENTS

WINNER W-PARTY W_STATE

EISENHOWER REP TEXAS

KENNEDY DEM MASS.

JOHNSON DEM TEXAS

NIXON REP CALIF.

CARTER DEM NULL

REAGAN REP NULL

BUSH REP NULL

CLINTON DEM NULL

8
LOSERS

LOSER L_PARTY

STEVENSON DEM

NIXON REP

GOLDWATER REP

HUMPHREY DEM

WALLACE IND

McGOVERN DEM

FORD DEM

CARTER DEM

ANDERSON IND

MONDALE DEM

DOUKAKIS DEM

BUSH REP

PERAULT IND

ELECTIONWINNER

YEAR WINNER W_VOTES

1952 EISENHOWER 442

1956 EISENHOWER 447

1960 KENNEDY 303

1964 JOHNSON 486

1968 NIXON 301

1972 NIXON 520

1976 CARTER 297

1980 REAGAN 489

1984 REAGAN 525

1988 BUSH 426

1992 CLINTON NULL

9
ELECTIONLOSER

YEAR LOSER L_VOTES

1952 STEVENSON 89

1956 STEVENSON 73

1960 NIXON 219

1964 GOLDWATER 52

1968 HUMPHREY 191

1968 WALLACE 46

1972 McGOVERN 17

1976 FORD 240

1980 CARTER 49

1980 ANDERSON 0

1984 MONDALE 13

1988 DOUKAKIS 41

1992 BUSH NULL

1992 PERAULT NULL

Ορισμός πινάκων σε Oracle


CREATE TABLE presidents(winner VARCHAR2(15) NOT NULL,

w_party VARCHAR2(15), w_state VARCHAR2(15) );

CREATE TABLE losers(loser VARCHAR2(15) NOT NULL,

l_party VARCHAR2(15));

CREATE TABLE electionwinner(election_year VARCHAR2(4) NOT NULL,

winner VARCHAR2(15),w_votes NUMBER);

CREATE TABLE electionloser(election_year VARCHAR2(4) NOT NULL,

loser VARCHAR2(15) NOT NULL, l_votes NUMBER);

 Υλοποίηση και διαχείριση βάσης δεδομένων


Να δημιουργήσετε τέσσερα (4) scripts που θα περιλαμβάνουν SQL εντολές:

1. Δημιουργίας των πινάκων της βάσης (script CREATE.SQL).


2. Διαγραφής των πινάκων της βάσης (script DROP.SQL).
3. Εισαγωγής στοιχείων στους πίνακες της βάσης (script INSERT.SQL).

10
4. Αναζήτησης στοιχείων από τους πίνακες βάσης (script SELECT.SQL).

Δημιουργία των πινάκων της βάσης

/* script δημιουργίας της βάσης. */

SQL> EDIT CREATE.SQL

Καλείται ο προκαθορισμένος screen editor του συστήματος και εκεί


πληκτρολογούμε τις τέσσερις SQL δηλώσεις δημιουργίας των πινάκων:

CREATE TABLE presidents(winner VARCHAR2(15) NOT NULL,

w_party VARCHAR2(15), w_state VARCHAR2(15) );

CREATE TABLE losers(loser VARCHAR2(15) NOT NULL,

l_party VARCHAR2(15));

CREATE TABLE electionwinner(election_year VARCHAR2(4) NOT NULL,

winner VARCHAR2(15),w_votes NUMBER);

CREATE TABLE electionloser(election_year VARCHAR2(4) NOT NULL,

loser VARCHAR2(15) NOT NULL, l_votes NUMBER);

Για να εκτελέσουμε το script πληκτρολογούμε την παρακάτω εντολή.

SQL> @CREATE.SQL

Εισαγωγή στοιχείων στους πίνακες


/* Δηλώσεις SQL εισαγωγής στοιχείων */

SQL> EDIT INSERT.SQL

INSERT INTO presidents VALUES


('EISENHOWER','REPUBLICAN','TEXAS');

INSERT INTO losers VALUES('STEVENSON','DEMOCRAT');

INSERT INTO electionwinner


VALUES('1952','EISENHOWER',442);

INSERT INTO electionwinner


VALUES('1956','EISENHOWER',447);

INSERT INTO electionloser VALUES('1952','STEVENSON',89);

INSERT INTO electionloser VALUES('1956','STEVENSON',73);

11
………

/* τέλος script */

Για να εκτελέσουμε το script πληκτρολογούμε την παρακάτω εντολή.

SQL> @INSERT.SQL

Αναζητήσεις (queries)

SQL> EDIT SELECT.SQL

SELECT winner,w_party,w_state

FROM presidents;

κ.λπ.

Για να εκτελέσουμε το script πληκτρολογούμε την παρακάτω εντολή.

SQL> @SELECT.SQL

Διαγραφή πινάκων
/* script διαγραφής πινάκων */

SQL> EDIT DROP.SQL

DROP TABLE presidents;

DROP TABLE losers;

DROP TABLE electionwinner;

DROP TABLE electionloser;

/* τέλος εντολών */

Για να εκτελέσουμε το script πληκτρολογούμε την παρακάτω εντολή.

SQL> @DROP.SQL

Άσκηση
Να υλοποιήσετε τη βάση δεδομένων με χρήση του προϊόντος mySQL.

12
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 2: Δημιουργία και διαχείριση βάσης προσωπικού με χρήση του προϊόντος
mySQL

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Case study: Διαχείριση βάσης προσωπικού με χρήση mySQL .......................... 3

Στόχος του εργαστηρίου είναι η εξοικείωση με τη δημιουργία και τη διαχείριση


σχεσιακής βάσης δεδομένων με το προϊόν Διαχείρισης Βάσης Δεδομένων (Data
Base Management Systems) mySQL. Μετά την επεξεργασία του εργαστηρίου ο
ενδιαφερόμενος θα έχει κατανοήσει τα θέματα δημιουργίας βάσης δεδομένων στο
προϊόν.

Λέξεις κλειδιά: Σχεσιακή βάση δεδομένων (Relational database), mySQL, Εντολές


SQL

Προαπαιτούμενο: Εγκατάσταση του προϊόντος mySQL


(http://dev.mysql.com/downloads/mysql/)

2
1. Case study: Διαχείριση βάσης προσωπικού με χρήση mySQL

Έστω η παρακάτω βάση δεδομένων προσωπικού εταιρείας.

Πίνακας τμημάτων εταιρείας


+--------+------------+----------+
| DEPTNO | DNAME | LOC |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+

Πίνακας υπαλλήλων εταιρείας

+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 2002-02-01 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-12-24 | 2975.00 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-10-28 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 2001-05-02 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-11-27 | 2450.00 | NULL | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-29 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1987-11-12 | 5000.00 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 2007-10-19 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 2003-05-07 | 1100.00 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 2003-12-12 | 950.00 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 2003-12-19 | 3000.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 2003-01-19 | 1300.00 | NULL | 10 |
| 7999 | BATES | ANALYST | 7566 | 2004-01-04 | 1300.00 | NULL | NULL |
+-------+--------+-----------+------+------------+---------+---------+--------+

Δημιουργήστε τους πίνακες και εισάγετε τα στοιχεία.

Δημιουργία βάσης δεδομένων. Χρήση βάσης. Δημιουργία πινάκων.

CREATE DATABASE personnel;

USE personnel;

CREATE TABLE DEPT(DEPTNO INT(2) NOT NULL,

DNAME VARCHAR(14), LOC VARCHAR(14),

PRIMARY KEY(DEPTNO));

CREATE TABLE EMP(EMPNO INT(4) NOT NULL,

3
ENAME VARCHAR(10), JOB VARCHAR(9),

MGR INT(4), HIREDATE DATE,

SAL FLOAT(7,2), COMM FLOAT(7,2),

DEPTNO INT(2),

PRIMARY KEY(EMPNO),

FOREIGN KEY(DEPTNO) REFERENCES DEPT(DEPTNO));

Πως βλέπουμε τη δομή των πινάκων

SHOW TABLES;

Εισαγωγή δεδομένων

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (20, 'RESEARCH', 'DALLAS');

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (30, 'SALES', 'CHICAGO');

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (40, 'OPERATIONS', 'BOSTON');

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7369, 'SMITH', 'CLERK', 7902, '1980/12/17', 800, NULL, 20);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '1981/02/20', 1600, 300, 30);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

4
VALUES (7521, 'WARD', 'SALESMAN', 7698, '2002/02/01', 1250, 500, 30);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7566, 'JONES', 'MANAGER', 7839, '1981/12/24', 2975, NULL, 20);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '1981/10/28', 1250, 1400, 30);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7698, 'BLAKE', 'MANAGER', 7839, '2001/05/02', 2850, NULL, 30);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7782, 'CLARK', 'MANAGER', 7839, '1981/11/27', 2450, NULL, 10);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7788, 'TT', 'ANALYST', 7566, '1987/04/29', 3000, NULL, 20);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7839, 'KING', 'PRESIDENT', NULL, '1987/11/12', 5000, NULL, 10);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7844, 'TURNER', 'SALESMAN', 7698, '2007/10/19', 1500, 0, 30);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7876, 'ADAMS', 'CLERK', 7788, '2003/05/07', 1100, NULL, 20);

INSERT INTO EMP

5
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7900, 'JAMES', 'CLERK', 7698, '2003/12/12', 950, NULL, 30);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7902, 'FORD', 'ANALYST', 7566, '2003/12/19', 3000, NULL, 20);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7934, 'MILLER', 'CLERK', 7782, '2003/01/19', 1300, NULL, 10);

INSERT INTO EMP

(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7999, 'BATES', 'ANALYST', 7566, '2004/01/04', 1300, NULL, NULL);

SELECT * FROM EMP;

SELECT * FROM DEPT;

Τι υπολογίζει κάθε μία από τις εντολές;

SELECT empno, ename, sal+comm

FROM Emp;

SELECT empno, ename, sal+IFNULL(comm,0)

FROM Emp;

Δείξτε στοιχεία για αναλυτές, προγραμματιστές

SELECT empno "code", ename "name", job "θέση", sal "αμοιβή",

sal+IFNULL(comm, 0) "σύνολο"

FROM EMP

WHERE job IN ('ANALYST', 'PROGRAMMER')

6
ORDER BY job, ename;

Υπολογίστε μέσο όρο μισθού, ελάχιστο μισθό, μέγιστο μισθό, άθροισμα μισθών,
πόσοι υπάλληλοι έχουν μισθό, πόσοι είναι οι υπάλληλοι.

SELECT AVG(sal), MIN(sal), MAX(sal), SUM(sal), COUNT(sal), COUNT(*)

FROM EMP;

Δείξτε τα ίδια στοιχεία μόνο για αναλυτές.

SELECT AVG(sal), MIN(sal), MAX(sal), SUM(sal), COUNT(sal),

SUM(sal), COUNT(sal), COUNT(*)

FROM EMP

WHERE job='ANALYST';

Δείξτε θέσεις υπαλλήλων

SELECT DISTINCT job

FROM EMP

ORDER BY job;

Δείξτε θέσεις σε κάθε τμήμα

SELECT DISTINCT deptno, job

FROM EMP

ORDER BY deptno, job;

Δείξτε αναλυτές, προγραμματιστές με μισθό μεταξύ 1000 και 7000 ευρώ

SELECT ename, job, sal

FROM EMP

7
WHERE job IN ('ANALYST', 'PROGRAMMER')

AND sal>= 1000 AND sal<=7000;

SELECT ename, job, sal

FROM EMP

WHERE job IN ('ANALYST', 'PROGRAMMER')

AND sal BETWEEN 1000 AND 7000;

Τι δείχνει η αναζήτηση:

SELECT ename, job, sal

FROM EMP

WHERE (job IN ('ANALYST', 'PROGRAMMER'))

AND (sal>= 1300 OR sal+IFNULL(comm,0)>= 1500)

ORDER BY job, ename, sal;

Παραδείγματα εντολών Υπογλώσσας Χειρισμού Δεδομενων (DML)

INSERT INTO Emp(empno, ename, job, deptno)

VALUES(1111, 'SMITH', 'ANALYST', 30);

INSERT INTO Emp VALUES(9999, 'CLARKE', 'ANALYST', 7800,

'2003-04-04 ', 1000, NULL, 30);

SELECT ename, job, sal, comm

FROM EMP

WHERE job= 'ANALYST' OR comm> 0.25*sal;

εντολή UPDATE

UPDATE Emp

SET job='ANALYST'

8
WHERE ename = 'ADAMS';

UPDATE Emp

SET sal = 1.1*sal

WHERE job = 'CLERK';

Εντολή DROP

DROP TABLE Emp;

DROP TABLE Dept;

DROP DATABASE personnel;

9
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 3: Δημιουργία μοντέλου για βάση δεδομένων – παράδειγμα μοντέλου για
βάση δεδομένων διαχείρισης προσωπικού

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Δημιουργία Μοντέλου Βάσης Δεδομένων ............................................................ 3
1.1 Δημιουργία Βάσης Δεδομένων .......................................................................... 3
1.2 Δημιουργία πινάκων και εισαγωγή των στοιχείων. ........................................... 3
1.3 Δημιουργία μοντέλου ......................................................................................... 5

Στόχος του εργαστηρίου είναι η εξοικείωση με τη δημιουργία εννοιολογικού


μοντέλου δεδομένων με χρήση του προϊόντος mySQL Workbench. Μετά την
επεξεργασία του εργαστηρίου ο ενδιαφερόμενος θα έχει κατανοήσει θέματα
δημιουργίας μοντέλων.

Λέξεις κλειδιά: Εννοιολογικό μοντέλο δεδομένων (conceptual model), mySQL


Workbench

2
1. Δημιουργία Μοντέλου Βάσης Δεδομένων

1.1 Δημιουργία Βάσης Δεδομένων

Έστω η παρακάτω βάση δεδομένων προσωπικού εταιρείας.

assign (πίνακας που καταχωρεί ποιοί υπάλληλοι απασχολούνται σε ποιά έργα)


Empno Proj_code A_Time
10 100 40
10 200 60
15 100 100
20 200 100
30 100 100

project (πίνακας έργων)


Proj_code Description
100 PAYROLL
200 PERSONNEL
300 SALES

emp (πίνακας υπαλλήλων)


Empno Ename Job Hiredate Mgr Sal Comm Deptno
10 Codd ANALYST 1/1/89 15 3000 10
15 Elmasri ANALYST 2/5/95 15 1200 150 10
20 Navathe SALESMAN 7/7/77 20 2000 20
30 Date PROGRAMMER 4/5/04 15 1800 200 10

dept (πίνακας τμημάτων)


Deptno Dname Loc
10 ACCOUNTING ATHENS
20 SALES LONDON
30 RESEARCH ATHENS
40 PAYROLL LONDON

1.2 Δημιουργία πινάκων και εισαγωγή των στοιχείων.


DROP DATABASE NEW_PERSONNEL;

CREATE DATABASE new_personnel;

USE new_personnel;

CREATE TABLE DEPT(DEPTNO INT(2) NOT NULL,

DNAME VARCHAR(14), LOC VARCHAR(14),

PRIMARY KEY(DEPTNO));

CREATE TABLE EMP(EMPNO INT(4) NOT NULL,

ENAME VARCHAR(10), JOB VARCHAR(25),

HIREDATE DATE, MGR INT(4), SAL FLOAT(7,2), COMM FLOAT(7,2),

DEPTNO INT(2), PRIMARY KEY(EMPNO),

3
FOREIGN KEY(DEPTNO) REFERENCES DEPT(DEPTNO));

SHOW TABLES;

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (20, 'RESEARCH', 'DALLAS');

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (30, 'SALES', 'CHICAGO');

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (40, 'OPERATIONS', 'BOSTON');

INSERT INTO EMP

VALUES (10, 'CODD', 'ANALYST', '1989/01/01', 15, 3000, NULL, 10);

INSERT INTO EMP

VALUES (15, 'ELMASRI', 'ANALYST', '1995/05/02', 15, 1200, 150, 10);

INSERT INTO EMP

VALUES (20, 'NAVATHE', 'SALESMAN', '1977/07/07', 20, 2000, NULL, 20);

INSERT INTO EMP

VALUES (30, 'DATE', 'PROGRAMMER', '2004/05/04', 15, 1800, 200, 10);

SELECT * FROM EMP;

SELECT * FROM DEPT;

4
1.3 Δημιουργία μοντέλου

Υπόδειξη

Έστω ότι χρησιμοποιείτε τη βάση δεδομένων που βλέπετε στη συνέχεια:

5
Χρησιμοποιήστε το προϊόν Workbench για να κατασκευάσετε αρχικά το παρακάτω μοντέλο:

6
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 4: Δημιουργία και διαχείριση βάσης προσωπικού με χρήση απλών και
σύνθετων δηλώσεων (statements) SQL στα προϊόντα mySQL και Oracle. Έμφαση σε
θέματα αναζήτησης (queries)

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Δημιουργία βάσης ............................................................................................................ 3
2. Πώς αναζητούμε στοιχεία με τη γλώσσα sql. Σύνταξη της δήλωσης select. Πρακτικοί
κανόνες ...................................................................................................................................... 6
2.1 Πως βλέπουμε όλα τα στοιχεία ενός πίνακα. ............................................................... 6
2.2 Πώς αλλάζουμε τη σειρά των στηλών των αποτελεσμάτων. ....................................... 6
2.3 Πώς αλλάζουμε τα ονόματα των στηλών των αποτελεσμάτων. .................................. 6
2.4 Αναζητήσεις που οδηγούν σε αποτελέσματα χωρίς επανάληψη τιμών - τελεστής
DISTINCT ................................................................................................................................ 7
2.5 Πως περιορίζεις τις στήλες των αποτελεσμάτων με απλές συνθήκες - Υποπρόταση
WHERE. ................................................................................................................................. 7
2.6 Αναζητήσεις που περιλαμβάνουν υπολογισμούς, πράξεις σε strings κλπ. .................. 8
2.7 Πως σχηματίζουμε σύνθετες συνθήκες σε υποπρόταση WHERE. Τελεστές σύγκρισης,
Aριθμητικοί, Boole, LIKE, NOT LIKE, BETWEEN ...AND, NOT BETWEEN ...AND, σύνολα (ΙΝ).
10
Παράδειγμα 1: Χρήση τελεστών σύγκρισης ................................................................... 10
Παράδειγμα 2: Χρήση BETWEEN … AND ........................................................................ 10
Παράδειγμα 3: Χρήση συνόλων (τελεστών IN) .............................................................. 10
Παράδειγμα 4: Χρήση συνάρτησης substr ..................................................................... 11
Παράδειγμα 5: Χρήση BETWEEN … AND με ημερομηνίες ............................................. 12

Στόχος του εργαστηρίου είναι η εκμάθηση απλών και σύνθετων δηλώσεων


(statements) SQL με χρήση του προϊόντος mySQL. Μετά την επεξεργασία του
εργαστηρίου ο ενδιαφερόμενος θα γνωρίζει σύνταξη και χρήση δηλώσεων της
γλώσσας SQL και θα εφαρμόζει σειρά πρακτικών κανόνων για τη διαχείριση βάσης
δεδομένων με έμφαση σε θέματα αναζήτησης (queries).

Λέξεις Κλειδιά: SQL, mySQL, Oracle, CREATE TABLE, INSERT INTO, SELECT

2
1. Δημιουργία βάσης

Βάση δεδομένων που θα χρησιμοποιηθεί στα παραδείγματα αναζήτησης.

(πίνακας στοιχείων υπαλλήλου) EMP

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

(πίνακας στοιχείων Τμημάτων στις οποίες ανήκουν οι υπάλληλοι) DEPT

DEPTNO DNAME LOC

(πίνακας στοιχείων έργων της εταιρείας) PROJ

PROJNO PNAME BUDGET

(πίνακας απασχόλησης υπαλλήλων σε έργα της εταιρείας) ASSIGN

EMPNO PROJNO PTIME

Όπου EMPNO=κωδικός υπαλλήλου, ENAME=ονοματεπώνυμο


υπαλλήλου, JOB = θέση στην εταιρεία, MGR = ο επικεφαλής του, SAL=
μισθός, COMM = προμήθεια, DEPTNO = κωδικός Τμήματος. Υποτίθεται
ότι κάθε υπάλληλος ανήκει σε ένα Τμήμα, DNAME = όνομα Τμήματος,
LOC = έδρα Τμήματος, PROJNO = κωδικός έργου, PNAME = περιγραφή
έργου, BUDGET = προϋπολογισμός έργου, PTIME = ποσοστό χρόνου
απασχόλησης υπαλλήλου σε έργο. Υποτίθεται ότι κάθε υπάλληλος
μπορεί να εργάζεται σε περισσότερα από ένα έργα.

Δημιουργία της βάσης με mySQL. Οι πίνακες δημιουργούνται με


κύρια και ξένα κλειδιά.

Αν θέλουμε να δούμε τις υπαρχουσες βάσεις γράφουμε εντολή SHOW.


SHOW DATABASES;

Δημιουργία της βάσης


CREATE DATABASE new_personnel;

Χρήση βάσης
USE new_personnel;

Δημιουργία πινάκων
CREATE TABLE DEPT(DEPTNO INT(2) NOT NULL,
DNAME VARCHAR(14), LOC VARCHAR(14),
PRIMARY KEY(DEPTNO));
CREATE TABLE EMP(EMPNO INT(4) NOT NULL,

3
ENAME VARCHAR(10), JOB VARCHAR(25),
HIREDATE DATE, MGR INT(4), SAL FLOAT(7,2), COMM FLOAT(7,2),
DEPTNO INT(2),
PRIMARY KEY(EMPNO),
FOREIGN KEY(DEPTNO) REFERENCES DEPT(DEPTNO));
CREATE TABLE PROJ (projno INT(3) NOT NULL,
pname VARCHAR(15),
budget FLOAT(12,2),
PRIMARY KEY(projno));
CREATE TABLE ASSIGN(
EMPNO INT(4) NOT NULL, PROJNO INT(3) NOT NULL,
PTIME INT(3),
PRIMARY KEY(EMPNO,PROJNO),
FOREIGN KEY(EMPNO) REFERENCES EMP(EMPNO),
FOREIGN KEY(PROJNO) REFERENCES PROJ(PROJNO));

SHOW TABLES;

Αν θέλουμε να δούμε τη δομή των πινάκων γράφουμε εντολή


describe.
describe emp;

Εισαγωγή στοιχείων στους πίνακες


INSERT INTO DEPT(DEPTNO, DNAME, LOC)
VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT(DEPTNO, DNAME, LOC)
VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT(DEPTNO, DNAME, LOC)
VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO DEPT(DEPTNO, DNAME, LOC)
VALUES (40, 'OPERATIONS', 'BOSTON');
INSERT INTO EMP
VALUES (10, 'CODD', 'ANALYST', '1989/01/01', 15, 3000, NULL, 10);
INSERT INTO EMP
VALUES (15, 'ELMASRI', 'ANALYST', '1995/05/02', 15, 1200, 150, 10);
INSERT INTO EMP
VALUES (20, 'NAVATHE', 'SALESMAN', '1977/07/07', 20, 2000, NULL, 20);
INSERT INTO EMP
VALUES (30, 'DATE', 'PROGRAMMER', '2004/05/04', 15, 1800, 200, 10);
INSERT INTO proj(projno, pname, budget)
VALUES(100, 'PAYROLL', 100000);
INSERT INTO proj(projno, pname, budget)
VALUES(200, 'PERSONNEL',200000 );
INSERT INTO proj(projno, pname, budget)
VALUES(300, 'SALES', 150000);
INSERT INTO assign(empno, projno, ptime)
VALUES(10,100, 40);
INSERT INTO assign(empno, projno, ptime)
VALUES(10, 200, 60);
INSERT INTO assign(empno, projno, ptime)
VALUES(15, 100, 100);
INSERT INTO assign(empno, projno, ptime)
VALUES(20, 200, 100);
INSERT INTO assign(empno, projno, ptime)
VALUES(30, 100, 100);

Πως βλέπουμε τα δεδομένα.


SELECT * FROM DEPT;
SELECT * FROM EMP;
SELECT * FROM PROJ;
SELECT * FROM ASSIGN;

4
Διαγραφή των πινάκων
DROP TABLE assign;
DROP TABLE emp;
DROP TABLE proj;
DROP TABLE dept;

Η διαγραφή της βάσης γίνεται με την εντολή:


DROP DATABASE NEW_PERSONNEL;

SELECT * FROM dept


DEPTNO DNAME LOC

10 ACCOUNTING NEW YORK


20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

SELECT * FROM emp

M CO DEPT
EMPNO ENAME JOB GR HIREDATE SAL MM NO

10 CODD ANALYST 15 01/01/1989 3000 - 10


15 ELMASRI ANALYST 15 02/05/1995 1200 150 10

20 NAVATHE SALESMAN 20 07/07/1977 2000 - 20

30 DATE PROGRAMMER 15 04/05/2004 1800 200 10

SELECT * FROM proj


PROJNO PNAME BUDGET

100 PAYROLL 100000


200 PERSONNEL 200000
300 SALES 150000

SELECT * FROM assign


EMPNO PROJNO PTIME

10 100 40
10 200 60
15 100 100
20 200 100
30 100 100

5
2. Πώς αναζητούμε στοιχεία με τη γλώσσα sql. Σύνταξη της
δήλωσης select. Πρακτικοί κανόνες

2.1 Πως βλέπουμε όλα τα στοιχεία ενός πίνακα.


Η σύνταξη της εντολής είναι:
SELECT * FROM όνομα-πίνακα;

Παράδειγμα
Η παρακάτω εντολή δείχνει τα στοιχεία του πίνακα DEPT.
SELECT * FROM dept;

2.2 Πώς αλλάζουμε τη σειρά των στηλών των αποτελεσμάτων.


Η συνηθισμένη σύνταξη της εντολής είναι:
SELECT όνομα-πίνακα.όνομα-στήλης, ...
FROM όνομα-πίνακα;

Παράδειγμα
Η παρακάτω εντολή δείχνει τις στήλες DNAME, LOC :

Προσοχή! Αν είναι σαφές σε ποιές στήλες αναφερόμαστε χωρίς να


χρειάζεται να εξετάζουμε το όνομα του πίνακα μπορούμε να το
παραλείψουμε.
Έτσι η παραπάνω αναζήτηση μπορεί να τροποποιηθεί:
SELECT DNAME, LOC FROM DEPT;

2.3 Πώς αλλάζουμε τα ονόματα των στηλών των αποτελεσμάτων.


Για να αλλάξουμε το όνομα μιας στήλης στα αποτελέσματα αρκεί να
γράψουμε σε εισαγωγικά το νέο όνομα δίπλα στο όνομα της στήλης.

Παράδειγμα
Η παρακάτω εντολή δείχνει τους υπαλλήλους της εταιρείας με το μισθό τους.
SELECT ENAME "ΟΝΟΜΑ ΥΠΑΛΛΗΛΟΥ", SAL "ΜΙΣΘΟΣ"
FROM EMP;

Σημείωση 1: Οπως θα δούμε στη συνέχεια η SQL επιτρέπει εντολές της


μορφής
SELECT ENAME , SAL/(25*8) "ΩΡΙΑΙΑ ΑΜΟΙΒΗ",
SAL+NVL(COMM,0) "ΣΥΝΟΛΟ ΑΠΟΔΟΧΩΝ"
FROM EMP;

Σε mySQL:
SELECT ENAME , SAL/(25*8) "ΩΡΙΑΙΑ ΑΜΟΙΒΗ",
SAL+IFNULL(COMM,0) "ΣΥΝΟΛΟ ΑΠΟΔΟΧΩΝ"
FROM EMP;

Σημείωση 2: Αν το όνομα που δίνουμε είναι μόνο μια λέξη δεν είναι
απαραίτητο να το γράφουμε σε εισαγωγικά.

6
SELECT ENAME "ΟΝΟΜΑ ΥΠΑΛΛΗΛΟΥ", SAL ΜΙΣΘΟΣ
FROM EMP;

Σε mySQL:
SELECT ENAME "ΟΝΟΜΑ ΥΠΑΛΛΗΛΟΥ", SAL "ΜΙΣΘΟΣ"
FROM EMP;
SELECT empno||ename FROM emp;

MySQL: select CONCAT(empno, ' ', ename) from emp;

Σημείωση 3: Ανάλογα με το προϊόν θα χρησιμοποιήσετε '…' ή “ ...”

2.4 Αναζητήσεις που οδηγούν σε αποτελέσματα χωρίς επανάληψη


τιμών - τελεστής DISTINCT
Η συνηθισμένη σύνταξη της εντολής είναι:
SELECT DISTINCT όνομα-πίνακα.όνομα-στήλης,
όνομα-πίνακα.όνομα-στήλης, ...
FROM όνομα-πίνακα κλπ.

Παράδειγμα
Η παρακάτω αναζήτηση προσδιορίζει τα επαγγέλματα των υπαλλήλων
επαναλαμβάνοντας τις τιμές στα αποτελέσματα:
SELECT JOB FROM EMP;

Αντίθετα η αναζήτηση
SELECT DISTINCT JOB FROM EMP;
δεν τις επαναλαμβάνει, δηλαδή, αναγράφει όλα τα επαγγέλματα που
υπάρχουν στο πίνακα EMP και μάλιστα μόνο μία φορά το καθένα.

Παράδειγμα
Παρατηρήστε τη διαφορά και στις επόμενες εντολές:
SELECT job, deptno
from emp;
SELECT DISTINCT job, deptno
from emp;

Προσοχή! Η εντολή SELECT DISTINCT job, deptno from emp; θα εμφανίσει 3


στήλες επειδή το ζεύγος (ANALYST, 10) εμφανίζεται 1 φορά.

Σημείωση: Ο τελεστής DISTINCT μπορεί να χρησιμοποιηθεί και με


συναρτήσεις και γενικά σε σύνθετες αναζητήσεις.

2.5 Πως περιορίζεις τις στήλες των αποτελεσμάτων με απλές


συνθήκες - Υποπρόταση WHERE.
Η συνηθισμένη σύνταξη της εντολής είναι:
SELECT ...
FROM ...
WHERE συνθήκη;

7
Παράδειγμα
Η παρακάτω αναζήτηση βρίσκει ποια τμήματα έχουν έδρα NEW YORK.
SELECT DNAME "ΟΝΟΜΑ ΤΜΗΜΑΤΟΣ", LOC ΕΔΡΑ
FROM DEPT
WHERE LOC = 'NEW YORK';

MySQL:
SELECT DNAME "ΟΝΟΜΑ ΤΜΗΜΑΤΟΣ", LOC "ΕΔΡΑ"
FROM DEPT
WHERE LOC = 'NEW YORK';

Παράδειγμα Διάλεξε μόνο τους υπάλληλους της Τμήματος 10.


SELECT *
FROM EMP
WHERE DEPTNO = 10;

Παράδειγμα Δείξε ονόματα,αριθμούς και Διευθύνσεις για τους αναλυτές.


SELECT ENAME,EMPNO,JOB, DEPTNO
FROM EMP
WHERE JOB = 'ANALYST';

Παράδειγμα Δείξε ονόματα και αριθμό Τμημάτων για τις Διευθύνσεις με


κωδικό (αριθμό) μεγαλύτερο του 20.
SELECT DNAME,DEPTNO
FROM DEPT
WHERE DEPTNO > 20;

Παράδειγμα Βρες ονόματα και αριθμούς Τμημάτων με κωδικό >= 20.


SELECT DNAME,DEPTNO
FROM DEPT
WHERE DEPTNO >= 20;

Παράδειγμα Βρες υπαλλήλους με προμήθεια μεγαλύτερη του δέκατου του μισθού τους.
SELECT ENAME,SAL,SAL/10, COMM
FROM EMP
WHERE COMM > SAL/10;

2.6 Αναζητήσεις που περιλαμβάνουν υπολογισμούς, πράξεις σε


strings κλπ.
Για να υπολογίσεις αθροίσματα, γινόμενα, μέσους όρους κλπ. μπορείς
να χρησιμοποιήσεις κατά την επιλογή στηλών:

1) αριθμητικούς τελεστές (+, -, *, /),


2) συναρτήσεις (όπως NVL-Null Value, POWER-ύψωση σε
δύναμη,ROUND-στρογγύλευση, TRUNC-αποκοπή, SUBSTR-
substring, UPPER-μεταγραφή σε κεφαλαία, AVG-μέσος όρος
κλπ),
3) παρενθέσεις,
4) τελεστή DISTINCT.

8
Βλέπουμε τη σημερινή ημερομηνία με τη συνάρτηση sysdate
χρησιμοποιώντας τον μονοθέσιο πίνακα dual του συστήματος.
SELECT sysdate FROM dual;

mySQL:
SELECT current_date;

Σε διάφορα προϊόντα, όπως για παράδειγμα στο προϊόν της ORACLE,


είναι δυνατές κάποιες αριθμητικές πράξεις σε ημερομηνίες. Για
παράδειγμα, η αναζήτηση
SELECT sysdate + 5 FROM dual;
προσθέτει πέντε ημέρες στην σημερινή ημερομηνία ενώ η αναζήτηση
mySQL: SELECT CURRENT_DATE + 5;
SELECT sysdate - 5 FROM dual αφαιρεί 5 ημέρες.
mySQL: SELECT CURRENT_DATE - 5;
Τέλος, η αναζήτηση
SELECT sysdate - hiredate, ename FROM emp;
εμφανίζει τον αριθμό των ετών, των μηνών, και των ημερών μεταξύ των
δύο ημερομηνιών.

MySQL: SELECT CURRENT_DATE - hiredate, ename FROM emp;

Παράδειγμα
Όπως είδαμε και στα προηγούμενα η παρακάτω αναζήτηση βρίσκει την
ωριαία και τη συνολική αμοιβή υπαλλήλων
SELECT ENAME ΟΝΟΜΑ, SAL/(25*8) "ΩΡΙΑΙΑ ΑΜΟΙΒΗ",
SAL+NVL (COMM,0) "ΣΥΝΟΛΙΚΗ ΑΜΟΙΒΗ"
FROM EMP;

Η συνάρτηση NVL εξασφαλίζει ότι το άθροισμα "Μισθός+Προμήθεια"


έχει τιμή στην περίπτωση υπαλλήλων που δεν έχουν προμήθεια.

MySQL:
SELECT ENAME "ΟΝΟΜΑ", SAL/(25*8) "ΩΡΙΑΙΑ ΑΜΟΙΒΗ",
SAL+IFNULL(COMM,0) "ΣΥΝΟΛΙΚΗ ΑΜΟΙΒΗ"
FROM EMP;

Δείτε τι θα συμβεί αν δεν χρησιμοποιήσουμε τη συνάρτηση.


SELECT ENAME ΟΝΟΜΑ,
SAL/(25*8) "ΩΡΙΑΙΑ ΑΜΟΙΒΗ",SAL+COMM,
SAL+NVL (COMM,0) "ΣΥΝΟΛΙΚΗ ΑΜΟΙΒΗ"
FROM EMP;

9
2.7 Πως σχηματίζουμε σύνθετες συνθήκες σε υποπρόταση WHERE.
Τελεστές σύγκρισης, Aριθμητικοί, Boole, LIKE, NOT LIKE,
BETWEEN ...AND, NOT BETWEEN ...AND, σύνολα (ΙΝ).

Για να σχηματίσουμε συνθήκες μπορούμε να χρησιμοποιήσουμε:

1) τελεστές σύγκρισης (>, <, >=, <=, != , <>,^ =), όπου οι τρεις
τελευταίοι (ή και άλλοι ανάλογα με το προϊόν) συμβολίζουν το
διάφορο.
2) αριθμητικούς (+, -, /, *),
3) τελεστές Boole (AND, OR, NOT),
4) τελεστή LIKE ή NOT LIKE (π.χ. ENAME NOT LIKE '%ΑΣ'),
5) τελεστές BETWEEN ...AND ή NOT BETWEEN ...AND
(π.χ. SAL BETWEEN 2500 AND 3000)
6) σύνολα τιμών (τελεστής ΙΝ),
(π.χ. JOB IN ('ΠΩΛΗΤΗΣ', 'ΑΝΑΛΥΤΗΣ ΣΥΣΤΗΜΑΤΩΝ')),
7) παρενθέσεις.

Παράδειγμα 1: Χρήση τελεστών σύγκρισης


Η παρακάτω αναζήτηση βρίσκει πωλητές με μισθό πάνω από 1,300 ή
προμήθεια μεγαλύτερη του ενός δεκάτου του μισθού τους
SELECT ENAME ΟΝΟΜΑ, SAL ΜΙΣΘΟΣ,COMM ΠΡΟΜΗΘΕΙΑ
FROM EMP
WHERE JOB = 'SALESMAN'
AND (SAL> 1300) OR (COMM > SAL/10);

mySQL:
SELECT ENAME "ΟΝΟΜΑ", SAL "ΜΙΣΘΟΣ", COMM "ΠΡΟΜΗΘΕΙΑ"
FROM EMP
WHERE JOB = 'SALESMAN'
AND (SAL> 1300) OR (COMM > SAL/10);

Παράδειγμα 2: Χρήση BETWEEN … AND


Η παρακάτω αναζήτηση βρίσκει πωλητές που έχουν μισθό μεταξύ 1800
και 2000.
SELECT ENAME, JOB, SAL
FROM EMP
WHERE JOB = 'SALESMAN'
AND SAL BETWEEN 1800 AND 2000;

Παράδειγμα 3: Χρήση συνόλων (τελεστών IN)


Η παρακάτω αναζήτηση βρίσκει πωλητές ή αναλυτές συστημάτων που
έχουν μισθό μεγαλύτερο από 1250
SELECT ENAME, JOB, SAL
FROM EMP
WHERE JOB IN ('SALESMAN', 'ANALYST')
AND SAL> 1250;

10
Παράδειγμα 4: Χρήση συνάρτησης substr
Η αναζήτηση βρίσκει αναλυτές με όνομα που αρχίζει από C, D, E.
SELECT ename, job FROM emp
WHERE (ename > = 'C' AND ename < 'F' )
AND job = 'ANALYST';

mySQL:
SELECT ename, job FROM emp
WHERE (ename >= 'C' AND ename < 'F' )
AND job = 'ANALYST';

Xρησιμοποιεί τη συνάρτηση substr για να απομονώσει το 1 γράμμα.


SELECT ename, job
FROM emp
WHERE (substr(ename,1,1) IN ('C', 'D', 'E'))
AND job = 'ANALYST';

Σημείωση
Η χρήση LIKE για την σύγκριση ορμαθών (ή συμβολοσειρών) (strings)
συνδέεται συνήθως με το σύμβολο % όπως φαίνεται στα
παραδείγματα:

1) Η παρακάτω εντολή ψάχνει την εργασία του CODD


SELECT ename, job
FROM emp
WHERE ename LIKE 'CODD';
2) ... like 'C%' ; ψάχνει την εργασία αυτών με επώνυμο που αρχίζει από
το γράμμα C
SELECT ename, job
FROM emp
WHERE ename LIKE 'C%';
3) ... like '%TE' ; ψάχνει την εργασία αυτών που το όνομα τους
τελειώνει σε TE
SELECT ename, job
FROM emp
WHERE ename LIKE'%TE';
4) ... like '%D%' ; ψάχνει την εργασία αυτών με ονοματεπώνυμο που
περιέχει το γράμμα D
SELECT ename, job
FROM emp
WHERE ename LIKE '%D%';
5) select distinct job
from emp
where job like 'A%';
ψάχνει τις εργασίες που αρχίζουν από Α .

mySQL:
select DISTINCT job
from emp
where job like 'A%';

11
Παράδειγμα 5: Χρήση BETWEEN … AND με ημερομηνίες
Η παρακάτω αναζήτηση βρίσκει αυτούς που το επώνυμο τους αρχίζει
από C ή D και προσλήφθηκαν από το 1989 έως και το 1995
SELECT ename, hiredate from emp
where ename between 'C' and 'F'
and hiredate Between '01/01/1989' and '12/31/1995';

mySQL:
SELECT ename, hiredate from emp
where ename between 'C' and 'F'
and hiredate Between '1989/01/01' and '1995/12/31';
Στο Παράδειγμα μπορείτε να χρησιμοποιήσετε και τη συνάρτηση substr.

Παράδειγμα Βρες όνομα,θέση και μισθό των υπαλλήλων του Τμήματος 20 που κερδίζουν
πάνω από 2,000.
SELECT ENAME,JOB,SAL, DEPTNO
FROM EMP
WHERE DEPTNO = 10
AND SAL > 2000;

Παράδειγμα Βρες τους πωλητές της Τμήματος 20 με μισθό μεγαλύτερο ή ισο


των 1,500.
SELECT ENAME, SAL, JOB, DEPTNO FROM EMP
WHERE JOB = 'ANALYST'
AND DEPTNO = 10
AND SAL >= 1500;

Παράδειγμα Βρες τους υπάλληλους που είναι πωλητές ή αναλυτές


SELECT ENAME, JOB, SAL, DEPTNO
FROM EMP
WHERE JOB = 'ANALYST'
OR JOB = 'SALESMAN';

Παράδειγμα Βρες τους πωλητές ή αναλυτές που δεν ανήκουν στο τμήμα 10.
SELECT ENAME, JOB, SAL, DEPTNO
FROM EMP
WHERE (JOB = 'ANALYST' OR JOB = 'SALESMAN')
AND DEPTNO <> 10;

Παράδειγμα Βρες τους πωλητές ή αναλυτές που ανήκουν στο τμήμα 10.
SELECT ENAME, JOB, SAL, DEPTNO
FROM EMP
WHERE (JOB = 'ANALYST' OR JOB = 'SALESMAN')
AND DEPTNO=10;

Παράδειγμα Βρες πωλητές οποιουδήποτε τμήματος και αναλυτές του Τμήματος 10.
SELECT *
FROM EMP
WHERE JOB = 'SALESMAN'
OR (JOB = 'ANALYST' AND DEPTNO = 10);

Ποιό είναι το αποτέλεσμα της επόμενης αναζήτησης;


SELECT *
FROM EMP
WHERE (JOB = 'SALESMAN' OR JOB = 'ANALYST')

12
AND DEPTNO = 20;

Παράδειγμα Βρες υπάλληλους της Τμήματος 10 που δεν είναι πωλητές ή αναλυτές.
SELECT *
FROM EMP
WHERE NOT (JOB = 'SALESMAN' OR JOB = 'ANALYST')
AND DEPTNO = 10;

Παράδειγμα Βρες ποιοί έχουν μισθό μεταξύ 1,500 και 1,800.


SELECT ENAME,JOB,SAL
FROM EMP
WHERE SAL BETWEEN 1500 AND 1800;

Παράδειγμα Χρησιμοποίησε το τελεστή BETWEEN με τον τελεστή NOT για να βρείς τους
υπόλοιπους υπάλληλους.
SELECT ENAME,JOB,SAL
FROM EMP
WHERE SAL NOT BETWEEN 1500 AND 1800;

Παράδειγμα Βρες υπάλληλους που είναι αναλυτές ή πωλητές.


SELECT ENAME,JOB,DEPTNO
FROM EMP
WHERE JOB IN ('ANALYST','SALESMAN');

Παράδειγμα Βρες τους υπόλοιπους υπάλληλους.


SELECT ENAME,JOB,DEPTNO
FROM EMP
WHERE JOB NOT IN ('ANALYST','SALESMAN');

Παράδειγμα Βρες υπάλληλους που το επώνυμο τους αρχίζει με γράμμα C ή


E.
SELECT ENAME,JOB,DEPTNO
FROM EMP
WHERE (ENAME LIKE 'C%' OR ENAME LIKE 'E%');

Παράδειγμα Βρες υπάλληλους που το όνομα τους τελειώνει σε THE και είναι Πωλητές.
SELECT ENAME,JOB,DEPTNO
FROM EMP
WHERE ENAME LIKE '%THE'
AND JOB = 'SALESMAN';

13
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 5: Υποαναζητήσεις στη γλώσσα SQL στα προϊόντα mySQL και Oracle

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Δημιουργία Βάσης Δεδομένων ........................................................................................ 3
2. Πως σχηματίζουμε συνθήκες που περιλαμβάνουν υποαναζήτηση (SELECT). ................ 4
Παράδειγμα 1: Χρήση SELECT … SELECT .......................................................................... 4
Παράδειγμα 2: Χρήση υποαναζήτησης με συνάρτηση MAX ........................................... 5
Παράδειγμα 3: Χρήση υποαναζήτησης με επιστροφή ζεύγους τιμών από το
φωλιασμένο SELECT ......................................................................................................... 5
Παράδειγμα 4: Χρήση υποαναζήτησης με IN .................................................................. 5
Παράδειγμα 5: Χρήση υποαναζήτησης με NOT IN .......................................................... 5
Παράδειγμα 6: Χρήση υποαναζήτησης με επιστροφή ζεύγους τιμών από το
φωλιασμένο SELECT και χρήση συνόλου ......................................................................... 6
Παράδειγμα 7: Χρήση SELECT που περιλαμβάνει δύο ανεξάρτητα SELECT .................... 6
Παράδειγμα 8: Χρήση τριών φωλιασμένων SELECT και συνόλου ................................... 6
Παράδειγμα 9: Χρήση υποαναζήτησης με παράλληλη χρήση self-join........................... 7
Άσκηση.............................................................................................................................. 8

Στόχος του εργαστηρίου είναι η εκμάθηση δηλώσεων (statements) SQL για


υποαναζητήσεις με πρακτική άσκηση στα προϊόντα mySQL και Oracle

Λέξεις Κλειδιά: Υποαναζητήσεις, SQL, mySQL, Oracle

2
1. Δημιουργία Βάσης Δεδομένων

Βάση δεδομένων που θα χρησιμοποιηθεί στα παραδείγματα αναζήτησης.

(πίνακας στοιχείων υπαλλήλου) EMP

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

(πίνακας στοιχείων Τμημάτων στις οποίες ανήκουν οι υπάλληλοι) DEPT

DEPTNO DNAME LOC

(πίνακας στοιχείων έργων της εταιρείας) PROJ

PROJNO PNAME BUDGET

(πίνακας απασχόλησης υπαλλήλων σε έργα της εταιρείας) ASSIGN

EMPNO PROJNO PTIME

Όπου EMPNO=κωδικός υπαλλήλου, ENAME=ονοματεπώνυμο


υπαλλήλου, JOB = θέση στην εταιρεία, MGR = ο επικεφαλής του, SAL=
μισθός, COMM = προμήθεια, DEPTNO = κωδικός Τμήματος. Υποτίθεται
ότι κάθε υπάλληλος ανήκει σε ένα Τμήμα, DNAME = όνομα Τμήματος,
LOC = έδρα Τμήματος, PROJNO = κωδικός έργου, PNAME = περιγραφή
έργου, BUDGET = προϋπολογισμός έργου, PTIME = ποσοστό χρόνου
απασχόλησης υπαλλήλου σε έργο. Υποτίθεται ότι κάθε υπάλληλος
μπορεί να εργάζεται σε περισσότερα από ένα έργα.

Η Δημιουργία της βάσης με mySQL έγινε στην Τρίτη άσκηση. Οι πίνακες


δημιουργούνται με κύρια και ξένα κλειδιά.

SELECT * FROM dept


DEPTNO DNAME LOC

10 ACCOUNTING NEW YORK


20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

SELECT * FROM emp

3
M
EMP G CO DEPT
NO ENAME JOB R HIREDATE SAL MM NO

10 CODD ANALYST 15 01/01/1989 3000 - 10

15 ELMASRI ANALYST 15 02/05/1995 1200 150 10

20 NAVATHE SALESMAN 20 07/07/1977 2000 - 20

30 DATE PROGRAMMER 15 04/05/2004 1800 200 10

SELECT * FROM proj


PROJNO PNAME BUDGET

100 PAYROLL 100000


200 PERSONNEL 200000
300 SALES 150000

SELECT * FROM assign


EMPNO PROJNO PTIME

10 100 40
10 200 60
15 100 100
20 200 100
30 100 100

2. Πως σχηματίζουμε συνθήκες που περιλαμβάνουν


υποαναζήτηση (SELECT).

Για το σχηματισμό συνθήκης με υποαναζήτηση


μπορείς να χρησιμοποιήσεις:

i. τελεστές σύγκρισης (>, <, >=, <=, =, !=, <> , ^ =)


ii. τελεστές Boole (AND, OR, NOT)
iii. παρενθέσεις
iv. τελεστή IN (και άλλους τελεστές όπως ANY, ALL, EXIST που
θα δούμε αργότερα)
v. συναρτήσεις.

Παράδειγμα 1: Χρήση SELECT … SELECT


Η παρακάτω αναζήτηση βρίσκει υπαλλήλους που κάνουν την ίδια
εργασία με τον υπάλληλο CODD ή τον υπάλληλο ELMASRI και έχουν
μισθό μεγαλύτερο των 1250.

SELECT ENAME, JOB, SAL

4
FROM EMP
WHERE JOB IN (SELECT JOB
FROM EMP
WHERE ENAME='CODD' OR ENAME='ELMASRI')
AND SAL > 1250;

Παράδειγμα 2: Χρήση υποαναζήτησης με συνάρτηση MAX


Η παρακάτω αναζήτηση βρίσκει ποιοί υπάλληλοι παίρνουν
περισσότερο μισθό από όλους τους πωλητές και ποιά η εργασία τους.

SELECT ENAME "ΟΝΟΜΑ", JOB "ΘΕΣΗ", SAL "ΜΙΣΘΟΣ"


FROM EMP
WHERE SAL > (SELECT MAX(SAL)
FROM EMP
WHERE JOB = 'SALESMAN');

Παράδειγμα 3: Χρήση υποαναζήτησης με επιστροφή ζεύγους τιμών από το


φωλιασμένο SELECT
Ποιοι υπάλληλοι ανήκουν στο ίδιο Τμήμα και έχουν την ίδια θέση με
τον CODD.

SELECT ename, deptno, sal


FROM emp
WHERE (deptno, job) IN (SELECT deptno, job
FROM emp
WHERE ename = 'CODD');

Παράδειγμα 4: Χρήση υποαναζήτησης με IN


Βρες τους αναλυτές που ανήκουν στο ίδιο τμήμα με προγραμματιστή.

SELECT ENAME,DEPTNO
FROM EMP
WHERE JOB = 'ANALYST'
AND DEPTNO IN
(SELECT DEPTNO
FROM EMP
WHERE JOB = 'PROGRAMMER');

Παράδειγμα 5: Χρήση υποαναζήτησης με NOT IN


Βρες τους αναλυτές που δεν ανήκουν στο ίδιο τμήμα με πωλητή.

SELECT * FROM EMP;

EMPNO EN AM E JOB M GR HIRED ATE S AL COMM DEPTNO

10 CODD ANALYST 15 01/01/1989 3000 - 10


15 ELMASRI ANALYST 15 02/05/1995 1200 150 10
20 NAVATHE SALESMAN 20 07/07/1977 2000 - 20
30 DATE PROGRAMMER 15 04/05/2004 1800 200 10

5
SELECT ENAME,DEPTNO
FROM EMP
WHERE JOB = 'ANALYST'
AND DEPTNO NOT IN
(SELECT DEPTNO
FROM EMP
WHERE JOB = 'SALESMAN');

ENAME DEPTNO

ELMASRI 10
CODD 10

Παράδειγμα 6: Χρήση υποαναζήτησης με επιστροφή ζεύγους τιμών από το


φωλιασμένο SELECT και χρήση συνόλου
Δείξε όνομα, θέση και μισθό υπαλλήλων που έχουν την ίδια θέση
και ανήκουν στο ίδιο τμήμα με τον CODD ή τον ELMASRI.

SELECT ENAME,JOB,SAL, DEPTNO


FROM EMP
WHERE (JOB,DEPTNO) =
(SELECT JOB,DEPTNO
FROM EMP
WHERE ENAME IN ('CODD', 'CODD'));

Παράδειγμα 7: Χρήση SELECT που περιλαμβάνει δύο ανεξάρτητα SELECT


Δείξε όνομα,θέση και Διεύθυνση υπαλλήλων που έχουν ίδια θέση με τον
CODD ή μισθό μεγαλύτερο ή ίσο του DATE.

SELECT ENAME,JOB,DEPTNO,SAL
FROM EMP
WHERE JOB IN
(SELECT JOB
FROM EMP
WHERE ENAME = 'CODD')
OR SAL >=
(SELECT SAL
FROM EMP
WHERE ENAME = 'DATE')
ORDER BY JOB,SAL;

Παράδειγμα 8: Χρήση τριών φωλιασμένων SELECT και συνόλου


Βρες τους υπάλληλους που έχουν θέση που συναντάται στα τμήματα SALES,
ACCOUNTING.

6
SELECT * FROM dept;
DEPTNO DNAME LOC

10 ACCOUNTING NEW YORK


20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

SELECT * FROM emp;


EMPNO EN AM E JOB M GR HIRED ATE S AL COMM DEPTNO

10 CODD ANALYST 15 01/01/1989 3000 - 10


15 ELMASRI ANALYST 15 02/05/1995 1200 150 10
20 NAVATHE SALESMAN 20 07/07/1977 2000 - 20
30 DATE PROGRAMMER 15 04/05/2004 1800 200 10

SELECT ENAME, JOB, DEPTNO


FROM EMP
WHERE JOB IN
(SELECT JOB
FROM EMP
WHERE DEPTNO IN (SELECT DEPTNO
FROM DEPT
WHERE DNAME IN ('SALES', 'ACCOUNTING')));

ENAME JOB DEPTNO

ELMASRI ANALYST 10
CODD ANALYST 10
DATE PROGRAMMER 10

Παράδειγμα 9: Χρήση υποαναζήτησης με παράλληλη χρήση self-join


Ποιοί υπάλληλοι κερδίζουν περισσότερα απο το μέσο μισθό
υπαλλήλων του τμήματος τους.
SELECT DEPTNO,ENAME,SAL
FROM EMP X
WHERE SAL >
(SELECT AVG(SAL)
FROM EMP
WHERE X.DEPTNO = DEPTNO)
ORDER BY DEPTNO;

Πως σχηματίζουμε συνθήκες που περιλαμβάνουν πολλά επίπεδα


υποαναζητήσεων

Για το σχηματισμό συνθήκης μπορείς να χρησιμοποιήσεις πολλά


επίπεδα υποαναζητήσεων.

7
Άσκηση
Γράψε αναζήτηση που βρίσκει ποιοί υπάλληλοι έχουν την ίδια θέση με
κάποιο υπάλληλο του τμήματος ACCOUNTING.

8
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 6: Ταξινόμηση

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Ταξινόμηση ....................................................................................................................... 3
1.1 Βάση δεδομένων που θα χρησιμοποιηθεί στα παραδείγματα αναζήτησης................ 3
1.2 Αναζήτηση στοιχείων με διάταξη των αποτελεσμάτων - υποπρόταση ORDER. .......... 5
1.3 Παράδειγμα: Ταξινόμηση κατά αύξουσα τάξη και κατά φθίνουσα τάξη..................... 6

Στόχος του εργαστηρίου είναι η εκμάθηση δηλώσεων (statements) SELECT που


περιλαμβάνουν υποπρόταση ORDER BY με πρακτική άσκηση στα προϊόντα mySQL
και Oracle

Λέξεις Κλειδιά: Ταξινόμηση, mySQL, Oracle

2
1. Ταξινόμηση

1.1 Βάση δεδομένων που θα χρησιμοποιηθεί στα παραδείγματα


αναζήτησης.

(πίνακας στοιχείων υπαλλήλου) EMP

COM
EMPNO ENAME JOB MGR HIREDATE SAL M DEPTNO

(πίνακας στοιχείων Τμημάτων στις οποίες ανήκουν οι υπάλληλοι) DEPT

DEPTNO DNAME LOC

(πίνακας στοιχείων έργων της εταιρείας) PROJ

PROJNO PNAME BUDGET

(πίνακας απασχόλησης υπαλλήλων σε έργα της εταιρείας) ASSIGN

EMPNO PROJNO PTIME

Όπου EMPNO=κωδικός υπαλλήλου, ENAME=ονοματεπώνυμο υπαλλήλου, JOB =


θέση στην εταιρεία, MGR = ο επικεφαλής του, SAL= μισθός, COMM = προμήθεια,
DEPTNO = κωδικός Τμήματος. Υποτίθεται ότι κάθε υπάλληλος ανήκει σε ένα
Τμήμα, DNAME = όνομα Τμήματος, LOC = έδρα Τμήματος, PROJNO = κωδικός
έργου, PNAME = περιγραφή έργου, BUDGET = προϋπολογισμός έργου, PTIME =
ποσοστό χρόνου απασχόλησης υπαλλήλου σε έργο. Υποτίθεται ότι κάθε υπάλληλος
μπορεί να εργάζεται σε περισσότερα από ένα έργα.

3
Η Δημιουργία της βάσης με mySQL έγινε στην Τρίτη άσκηση. Οι πίνακες
δημιουργούνται με κύρια και ξένα κλειδιά.

SELECT * FROM dept

DEPTNO DNAME LOC

NEW
10 ACCOUNTING
YORK

20 RESEARCH DALLAS

30 SALES CHICAGO

40 OPERATIONS BOSTON

SELECT * FROM emp

M CO
G M DEPT
EMPNO ENAME JOB R HIREDATE SAL M NO

01/01/198 300
10 CODD ANALYST 15 - 10
9 0

02/05/199 120
15 ELMASRI ANALYST 15 150 10
5 0

07/07/197 200
20 NAVATHE SALESMAN 20 - 20
7 0

PROGRAMM 04/05/200 180


30 DATE 15 200 10
ER 4 0

4
SELECT * FROM proj

PROJNO PNAME BUDGET

100 PAYROLL 100000

200 PERSONNEL 200000

300 SALES 150000

SELECT * FROM assign

EMPNO PROJNO PTIME

10 100 40

10 200 60

15 100 100

20 200 100

30 100 100

1.2 Αναζήτηση στοιχείων με διάταξη των αποτελεσμάτων -


υποπρόταση ORDER.

Η συνηθισμένη μορφή σύνταξης της εντολής SELECT που ταξινομεί τα


αποτελέσματα είναι:

SELECT ονόματα στηλών ή αριθμητικές εκφράσεις των στηλών ή ..

FROM όνομα πίνακα ή ονόματα πινάκων ή ....

WHERE συνθήκη

ORDER BY όνομα_πίνακα.όνομα_στήλης ASC ή DESC ή τίποτα,

όνομα_πίνακα.όνομα_στήλης κτλ.;

5
Δηλαδή, ο προγραμματιστής μπορεί να επιλέξει πολλά επίπεδα ταξινόμησης κατά
αύξουσα σειρά (όταν η αντίστοιχη στήλη συνοδεύεται με δήλωση ASC ή δεν
συνοδεύεται από δήλωση) ή φθίνουσα σειρά (όταν η αντίστοιχη στήλη συνοδεύεται
με δήλωση DESC).

Για χαρακτήρες η ταξινόμηση ακολουθεί την σειρά του πίνακα ASCII. Ετσι το 0
προηγείται του 9, το Α του Ζ κτλ.

Στην περίπτωση του προϊόντος της ORACLE οι τιμές NULL πάντοτε εμφανίζονται
πρώτες στα αποτελέσματα και απαιτείται τέχνασμα με χρήση συνάρτησης NVL-Null
Value για να ανατραπεί το γεγονός αυτό. Τι συμβαίνει στην περίπτωση του
προϊόντος της mySQL;

Στην υποπρόταση ORDER BY μπορούμε να χρησιμοποιήσουμε και εκφράσεις των


στηλών με πράξεις, παρενθέσεις κλπ ή και τον αύξοντα αριθμό ενός
χαρακτηριστικού (attribute) στον ορισμό του πίνακα.

π.χ. ... ORDER BY COMM/SAL

... ORDER BY 3 (αντί του ORDER BY JOB)

1.3 Παράδειγμα: Ταξινόμηση κατά αύξουσα τάξη και ταξινόμηση


κατά φθίνουσα τάξη

Η παρακάτω αναζήτηση ταξινομεί τους υπαλλήλους κατά Τμήμα και φθίνουσα τάξη
μισθού.

SELECT ENAME, DEPTNO, JOB, SAL

FROM EMP

ORDER BY DEPTNO, SAL DESC;

6
ENAME DEPTNO JOB SAL

CODD 10 ANALYST 3000

DATE 10 PROGRAMMER 1800

ELMASRI 10 ANALYST 1200

NAVATHE 20 SALESMAN 2000

Ασκήσεις
Άσκηση1 Βρες τους υπάλληλους της Τμήματος 10 και δείξε τους κατά μισθό.

Άσκηση 2 Το ίδιο κατά φθίνουσα τάξη μισθού.

Άσκηση 3 Να διατάξεις τους υπαλλήλους κατά θέση και για κάθε θέση κατά
φθίνουσα τάξη μισθού.

Άσκηση 4 Να διατάξεις τους υπαλλήλους της Τμήματος 10 ανάλογα με τη


προμήθεια τους.

Άσκηση 5 Το ίδιο αλλά κατά φθίνουσα τάξη.

Επαναλάβατε τις ασκήσεις 3 και 4 στο προϊόν της Oracle.

7
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 7: Υποπρόταση GROUP BY. Χρήση υποπρότασης HAVING σε συνδυασμό με
υποπρόταση GROUP BY

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Υποπρόταση GROUP BY. Χρήση υποπρότασης HAVING σε συνδυασμό με υποπρόταση
GROUP BY .................................................................................................................................. 3
1.1 Αναζήτηση στοιχείων με ομαδοποίηση αποτελεσμάτων ............................................. 5
1.2 Αναζήτηση στοιχείων με ομαδοποίηση αποτελεσμάτων και περιορισμό των στηλών -
Χρήση υποπρότασης HAVING σε συνδυασμό με υποπρόταση GROUP BY ......................... 6

Στόχος του εργαστηρίου είναι η εκμάθηση δηλώσεων (statements) SELECT που


περιλαμβάνουν Υποπρόταση GROUP BY ή χρήση υποπρότασης HAVING σε
συνδυασμό με υποπρόταση GROUP BY με πρακτική άσκηση στα προϊόντα mySQL
και Oracle

Λέξεις Κλειδιά: GROUP BY, GROUP BY HAVING, mySQL, Oracle

2
1. Υποπρόταση GROUP BY. Χρήση υποπρότασης HAVING σε
συνδυασμό με υποπρόταση GROUP BY

Βάση δεδομένων που θα χρησιμοποιηθεί στα παραδείγματα αναζήτησης.

(πίνακας στοιχείων υπαλλήλου) EMP

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

(πίνακας στοιχείων Τμημάτων στις οποίες ανήκουν οι υπάλληλοι) DEPT

DEPTNO DNAME LOC

(πίνακας στοιχείων έργων της εταιρείας) PROJ

PROJNO PNAME BUDGET

(πίνακας απασχόλησης υπαλλήλων σε έργα της εταιρείας) ASSIGN

EMPNO PROJNO PTIME

Όπου EMPNO=κωδικός υπαλλήλου, ENAME=ονοματεπώνυμο


υπαλλήλου, JOB = θέση στην εταιρεία, MGR = ο επικεφαλής του, SAL=
μισθός, COMM = προμήθεια, DEPTNO = κωδικός Τμήματος. Υποτίθεται
ότι κάθε υπάλληλος ανήκει σε ένα Τμήμα, DNAME = όνομα Τμήματος,
LOC = έδρα Τμήματος, PROJNO = κωδικός έργου, PNAME = περιγραφή
έργου, BUDGET = προϋπολογισμός έργου, PTIME = ποσοστό χρόνου
απασχόλησης υπαλλήλου σε έργο. Υποτίθεται ότι κάθε υπάλληλος μπορεί
να εργάζεται σε περισσότερα από ένα έργα.

Η Δημιουργία της βάσης με mySQL έγινε στην Τρίτη άσκηση. Οι πίνακες


δημιουργούνται με κύρια και ξένα κλειδιά.

3
SELECT * FROM dept

DEPTNO DNAME LOC

10 ACCOUNTING NEW YORK

20 RESEARCH DALLAS

30 SALES CHICAGO

40 OPERATIONS BOSTON

SELECT * FROM emp

M CO DEPT
EMPNO ENAME JOB GR HIREDATE SAL MM NO

10 CODD ANALYST 15 01/01/1989 3000 - 10

15 ELMASRI ANALYST 15 02/05/1995 1200 150 10

20 NAVATHE SALESMAN 20 07/07/1977 2000 - 20

30 DATE PROGRAMMER 15 04/05/2004 1800 200 10

SELECT * FROM proj

PROJNO PNAME BUDGET

100 PAYROLL 100000

200 PERSONNEL 200000

300 SALES 150000

4
SELECT * FROM assign

EMPNO PROJNO PTIME

10 100 40

10 200 60

15 100 100

20 200 100

30 100 100

1.1 Αναζήτηση στοιχείων με ομαδοποίηση αποτελεσμάτων

Υποπρόταση GROUP BY.


Η συνηθισμένη σύνταξη μίας εντολής SELECT που ομαδοποιεί τα
αποτελέσματα είναι:

SELECT στήλες ή .... (Προσοχή! Υπάρχουν σοβαροί περιορισμοί.)

FROM όνομα_πίνακα ή ονόματα πινάκων ή ....

GROUP BY όνομα_πίνακα.όνομα_στήλης;

Βέβαια υπάρχει δυνατότητα ομαδοποίησης με περισσότερα κριτήρια!

πχ. .... GROUP BY EMP.JOB , EMP.SAL ... ;

5
Παράδειγμα: Χρήση απλής στήλης ως κριτηρίου σε GROUP BY
Η παρακάτω αναζήτηση ομαδοποιεί τους υπαλλήλους ανά τμήμα και
βρίσκει το μέσο όρο μισθού.

SELECT DEPTNO, AVG(SAL)


FROM EMP

GROUP BY DEPTNO;

DEPTNO AVG(SAL)

20 2000

10 2000

1.2 Αναζήτηση στοιχείων με ομαδοποίηση αποτελεσμάτων και


περιορισμό των στηλών - Χρήση υποπρότασης HAVING σε
συνδυασμό με υποπρόταση GROUP BY

Η συνηθισμένη σύνταξη της εντολής SELECT που ομαδοποιεί τα


αποτελέσματα και περιορίζει τις στήλες των αποτελεσμάτων είναι:

SELECT ονόματα στηλών ή .... (Προσοχή! Υπάρχουν

σοβαροί περιορισμοί στην επιλογή στηλών)

FROM όνομα_πίνακα ή ονόματα πίνακων ή ....

GROUP BY ονόματα στηλών

HAVING συνθήκη;

6
Παράδειγμα 1: Χρήση GROUP BY … HAVING
Η παρακάτω αναζήτηση βρίσκει το μέσο όρο μισθού υπαλλήλων που
κάνουν την ίδια εργασία όταν ο μέσος μισθός ξεπερνά τις 1250.

SELECT JOB, AVG(SAL)


FROM EMP

GROUP BY JOB

HAVING AVG(SAL) > 1250;

JOB AVG(SAL)

SALESMAN 2000

ANALYST 2100

PROGRAMMER 1800

Παράδειγμα 2: Χρήση GROUP BY … HAVING και συνάρτησης


COUNT(*)
Η παρακάτω αναζήτηση βρίσκει το μέσο μισθό αυτών που κάνουν την
ίδια εργασία όταν είναι τουλάχιστον δύο.

SELECT JOB, AVG(SAL), COUNT(2)

FROM EMP

GROUP BY JOB

HAVING COUNT(*) >= 2;

JOB AVG(SAL) COUNT(2)

ANALYST 2100 2

Προσοχή! Η SELECT JOB, SAL ... δίνει συντακτικό λάθος επειδή


απαγορεύεται η χρήση χαρακτηριστικού στην υποπρόταση SELECT αν
δεν αναφέρεται στο GROUP BY ή αν δεν χρησιμοποιείται σαν όρισμα
συνάρτησης ομαδοποίησης.

Δοκιμάστε τις αναζητήσεις και στο προϊόν της ORACLE.

7
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 8: Συνδέσεις

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Συνδέσεις .......................................................................................................................... 3
1.1 Αναζήτηση στοιχείων που απαιτεί σύνδεση δύο πινάκων........................................... 5
Παράδειγμα Χρήση σύνδεσης και συνθήκης................................................................ 5
Άσκηση 1: Χρήση καρτεσιανού γινομένου ................................................................... 8
Άσκηση 2: Χρήση σύνδεσης INNER JOIN - JOIN ........................................................ 10
Άσκηση 3 Χρήση σύνδεσης LEFT JOIN, RIGHT JOIN. Σύνδεση FULL JOIN και mySQL.
Περίπτωση του προϊόντος της ORACLE....................................................................... 10
Άσκηση 4 Χρήση περισσότερων συνδέσεων ............................................................. 10

Στόχος του εργαστηρίου είναι η εκμάθηση δηλώσεων (statements) SELECT που


περιλαμβάνουν Συνδέσεις με πρακτική άσκηση στα προϊόντα mySQL και Oracle

Λέξεις Κλειδιά: Συνδέσεις (join), mySQL, Oracle

2
1. Συνδέσεις

Βάση δεδομένων που θα χρησιμοποιηθεί στα παραδείγματα αναζήτησης.

(πίνακας στοιχείων υπαλλήλου) EMP

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

(πίνακας στοιχείων Τμημάτων στις οποίες ανήκουν οι υπάλληλοι) DEPT

DEPTNO DNAME LOC

(πίνακας στοιχείων έργων της εταιρείας) PROJ

PROJNO PNAME BUDGET

(πίνακας απασχόλησης υπαλλήλων σε έργα της εταιρείας) ASSIGN

EMPNO PROJNO PTIME

Όπου EMPNO=κωδικός υπαλλήλου, ENAME=ονοματεπώνυμο


υπαλλήλου, JOB = θέση στην εταιρεία, MGR = ο επικεφαλής του, SAL=
μισθός, COMM = προμήθεια, DEPTNO = κωδικός Τμήματος. Υποτίθεται
ότι κάθε υπάλληλος ανήκει σε ένα Τμήμα, DNAME = όνομα Τμήματος,
LOC = έδρα Τμήματος, PROJNO = κωδικός έργου, PNAME = περιγραφή
έργου, BUDGET = προϋπολογισμός έργου, PTIME = ποσοστό χρόνου
απασχόλησης υπαλλήλου σε έργο. Υποτίθεται ότι κάθε υπάλληλος
μπορεί να εργάζεται σε περισσότερα από ένα έργα.

Η Δημιουργία της βάσης με mySQL έγινε στην Τρίτη άσκηση. Οι πίνακες


δημιουργούνται με κύρια και ξένα κλειδιά.

3
SELECT * FROM dept

DEPTNO DNAME LOC

10 ACCOUNTING NEW YORK

20 RESEARCH DALLAS

30 SALES CHICAGO

40 OPERATIONS BOSTON

SELECT * FROM emp

M
G CO DEPT
EMPNO ENAME JOB R HIREDATE SAL MM NO

10 CODD ANALYST 15 01/01/1989 3000 - 10

15 ELMASRI ANALYST 15 02/05/1995 1200 150 10

20 NAVATHE SALESMAN 20 07/07/1977 2000 - 20

30 DATE PROGRAMMER 15 04/05/2004 1800 200 10

SELECT * FROM proj

PROJNO PNAME BUDGET

100 PAYROLL 100000

200 PERSONNEL 200000

300 SALES 150000

4
SELECT * FROM assign

EMPNO PROJNO PTIME

10 100 40

10 200 60

15 100 100

20 200 100

30 100 100

1.1 Αναζήτηση στοιχείων που απαιτεί σύνδεση δύο πινάκων.

Η συνηθισμένη σύνταξη εντολής αναζήτησης που συνδέει δύο πίνακες


είναι:

SELECT όνομα_πίνακα1.όνομα_στήλης, ....

όνομα_πίνακα2.όνομα_στήλης, ....

FROM όνομα_πίνακα1 , όνομα_πίνακα2

WHERE όνομα_πίνακα1.όνομα_στήλης =

όνομα_πίνακα2.όνομα_στήλης κτλ.

Παράδειγμα: Χρήση σύνδεσης και συνθήκης


Η παρακάτω εντολή βρίσκει όνομα, μισθό και έδρα των πωλητών.

SELECT ENAME, JOB, SAL, LOC


FROM EMP,DEPT

WHERE JOB = 'SALESMAN'

AND EMP.DEPTNO = DEPT.DEPTNO;

5
ENAME JOB SAL LOC

NAVATHE SALESMAN 2000 DALLAS

Επεξήγηση

Η συνθήκη σύνδεσης (join)

EMP.DEPTNO = DEPT.DEPTNO

είναι σαν να μας εξασφαλίζει λογικά (conceptually) την "ενοποίηση"


των δύο πινάκων, όπως φαίνεται στην παρακάτω ανάλυση.

SELECT *

FROM EMP,DEPT

WHERE EMP.DEPTNO = DEPT.DEPTNO;

E
M
P DE
N EN AM MG HIRED A CO PT DEP
O E JOB R TE S AL MM NO TNO DN AM E LOC

NEW
3 PROGR ACCOUNTI
DATE 15 04/05/2004 1800 200 10 10 YOR
0 AMMER NG
K

NEW
1 ELMAS ANALYS ACCOUNTI
15 02/05/1995 1200 150 10 10 YOR
5 RI T NG
K

NEW
1 ANALYS ACCOUNTI
CODD 15 01/01/1989 3000 - 10 10 YOR
0 T NG
K

2 NAVAT SALESM RESEARC DALL


20 07/07/1977 2000 - 20 20
0 HE AN H AS

SELECT ENAME, JOB, SAL, LOC

FROM EMP,DEPT

WHERE JOB = 'SALESMAN'

AND EMP.DEPTNO = DEPT.DEPTNO;

6
ENAME JOB SAL LOC

NAVATHE SALESMAN 2000 DALLAS

Προσοχή!

Δεν είναι απαραίτητο οι πίνακες που θα συνδεθούν να έχουν κοινή


στήλη ή τις ίδιες τιμές (values) στις στήλες της σύνδεσης. Αρκεί να
έχουν στήλες με κοινό πεδίο ορισμού.

Για παράδειγμα, οι πίνακες:

CUSTOMER(cust_name, cust_city)

SUPPLIER(suppl_name, suppl_city)

CREATE TABLE customer(cust_name CHAR(15),


cust_city CHAR(15));
CREATE TABLE supplier(suppl_name CHAR(15),
suppl_city CHAR(15));

INSERT INTO customer VALUES('CODD', 'NEW YORK');


INSERT INTO customer VALUES('DATE', 'BERLIN');

INSERT INTO supplier VALUES('NAVATHE', 'NEW YORK');


INSERT INTO supplier VALUES('ELMASRI', 'ATHENS');

SELECT * FROM supplier;

SUPPL_NAME SUPPL_CITY

NAVATHE NEW YORK

ELMASRI ATHENS

7
SELECT * FROM customer;

CUST_NAME CUST_CITY

CODD NEW YORK

DATE BERLIN

Η παρακάτω αναζήτηση βρίσκει ποιοί πελάτες (customers) έχουν έδρα την ίδια
πόλη με κάποιο προμηθευτή (supplier):

SELECT *

FROM customer, supplier

WHERE customer.cust_city=supplier.suppl_city;

CUST_NAME CUST_CITY SUPPL_NAME SUPPL_CITY

CODD NEW YORK NAVATHE NEW YORK

Βλέπουμε ότι οι πίνακες μπορούν να συνδεθούν με συνθήκη

customer.cust_city=supplier.suppl_city

επειδή οι δύο στήλες έχουν το ίδιο πεδίο ορισμού.

Άσκηση 1: Χρήση καρτεσιανού γινομένου


Υλοποίησε το ίδιο παράδειγμα με χρήση MySQL

Καρτεσιανό Γινόμενο:

Προσοχή! Η εντολή

SELECT emp.ename, emp.sal, dept.loc

from emp, dept;

8
ENAME SAL LOC

CODD 3000 NEW YORK

CODD 3000 DALLAS

CODD 3000 CHICAGO

CODD 3000 BOSTON

ELMASRI 1200 NEW YORK

ELMASRI 1200 DALLAS

ELMASRI 1200 CHICAGO

ELMASRI 1200 BOSTON

NAVATHE 2000 NEW YORK

NAVATHE 2000 DALLAS

NAVATHE 2000 CHICAGO

NAVATHE 2000 BOSTON

DATE 1800 NEW YORK

DATE 1800 DALLAS

DATE 1800 CHICAGO

DATE 1800 BOSTON

δεν μπορεί να θεωρηθεί σαν εναλλακτική της αντίστοιχης αναζήτησης


που περιλαμβάνει join γιατί υπολογίζει το καρτεσιανό γινόμενο των
δύο πινάκων γεγονός που οδηγεί στην εμφάνιση στοιχείων που δεν
έχουν πραγματική σημασία.

9
Άσκηση 2: Χρήση σύνδεσης INNER JOIN - JOIN
Βρες όλους τους CODD από το πίνακα EMP και τη θέση της έδρας τους
από το πίνακα DEPT .

Άσκηση 3: Χρήση σύνδεσης LEFT JOIN, RIGHT JOIN. Σύνδεση FULL


JOIN και mySQL. Περίπτωση του προϊόντος της ORACLE.
Για κάθε τμήμα βρες αριθμό, όνομα, υπαλλήλους και θέση κάθε υπαλλήλου.
Διάταξε τα αποτελέσματα κατά αύξοντα αριθμό Τμήματος. Κάνε το ίδιο αλλά στα
αποτελέσματα να περιληφθούν τμήματα χωρίς υπαλλήλους. Στη συνέχεια κάνε το
ίδιο αλλά να περιληφθούν στα αποτελέσματα και υπάλληλοι που δεν έχουν
τοποθετηθεί σε τμήματα. Κάνε το ίδιο ώστε στα αποτελέσματα να περιληφθούν
τμήματα χωρίς υπαλλήλους και υπάλληλοι που δεν έχουν τοποθετηθεί σε τμήματα.
Εξέτασε τη σύνδεση FULL JOIN στην περίπτωση του προϊόντος mySQL. Υπολόγισε
το ζητούμενο με χρήση τελεστή UNION. Εξέτασε όλα τα παραπάνω στην περίπτωση
του προϊόντος της ORACLE.

Άσκηση 4: Χρήση περισσότερων συνδέσεων


Βρες τους υπάλληλους με έδρα NEW YORK ή BOSTON και θέση σαν του CODD. Δείξε
όλα τα στοιχεία των υπαλλήλων, πλήρη στοιχεία των έργων στα οποία εργάζονται
και πλήρη στοιχεία των τμημάτων στα οποία ανήκουν

10
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 9: Επανάληψη σε δηλώσεις SQL - Εμβάθυνση

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Επανάληψη σε δηλώσεις SQL - Εμβάθυνση ..................................................... 3

Στόχος του εργαστηρίου είναι η εκμάθηση των δηλώσεις SQL με επανάληψη και η
εμβάθυνση με πρακτική άσκηση στα προϊόντα mySQL και Oracle

Λέξεις Κλειδιά: Συνδέσεις (join), mySQL, Oracle

2
1. Επανάληψη σε δηλώσεις SQL - Εμβάθυνση

Δημιουργήστε τη βάση δεδομένων Personnel_db που περιλαμβάνει τους πίνακες:

SELECT * FROM Department

DEPTNO DNAM E

10 ACCOUNTING
20 SALES
30 PERSONNEL

SELECT * FROM Jobs

JOBNO JOB SAL

100 DBA 2500


200 ANALYST 2000

SELECT * FROM Employee

EM PNO ENAM E JOBCODE DEPTNO

1000 SMITH 100 10


2000 TOM 200 10
300 JIM 100 20
400 Smith 200 20

Να ορίσετε στους πίνακες σας κύρια και ξένα κλειδιά.

Εισάγετε τα δεδομένα στους πίνακες.

Δείτε τα δεδομένα των πινάκων

Γράψτε σύνδεση όλων των πινάκων με ταξινόμηση αποτελεσμάτων (job, ename)

EM PNO ENAM E DEPTNO DNAM E JOBCODE JOB SAL

2000 TOM 10 ACCOUNTING 200 ANALYST 2000


400 Smith 20 SALES 200 ANALYST 2000
300 JIM 20 SALES 100 DBA 2500
1000 SMITH 10 ACCOUNTING 100 DBA 2500

3
Αλλάξτε στην εντολή τη σειρά πινάκων, συνθηκών και διαπιστώστε ότι η εντολή
υπολογίζει τα ίδια αποτελέσματα.

Δείτε τα ίδια στοιχεία μόνο για υπαλλήλους των τμημάτων


'ACCOUNTING','SALES'

EM PNO ENAM E DEPTNO DNAM E JOBCODE JOB SAL

300 JIM 20 SALES 100 DBA 2500


1000 SMITH 10 ACCOUNTING 100 DBA 2500
400 Smith 20 SALES 200 ANALYST 2000
2000 TOM 10 ACCOUNTING 200 ANALYST 2000

Δώστε άλλα δικά σας παραδείγματα

Πόσοι υπάλληλοι ανήκουν σε κάθε τμήμα

DEPTNO COUNT(*)

20 2
10 2

Να υπολογίσετε το ίδιο αλλά η εντολή σας να περιλαμβάνει WHERE με συνδέσεις


όλων των πινάκων

Τώρα αλλάξτε το κριτήριο ώστε να βλέπετε και το όνομα του τμήματος

DEPTNO DNAM E COUNT(*)

10 ACCOUNTING 2
20 SALES 2

Με την ίδια τεχνική θα μπορούσατε να βλέπετε οποιαδήποτε στήλη οποιουδήποτε


πίνακα αρκεί να θυμάστε να προσθέτετε τη νέα στήλη και στο κριτήριο.

Να κάνετε «φιλτράρισμα» των αποτελεσμάτων με χρήση HAVING

JOBCODE COUNT(*)

100 2

Στο φιλτράρισμα μπορείτε να χρησιμοποιήσετε συνθήκη που περιλαμβάνει AND,


OR, NOT, το κριτήριο της group by και AVG, MAX, SUM, COUNT κ.λπ.

4
Προσοχή! Δείτε την παρακάτω εντολή στην Oracle. Δοκιμάστε την ίδια εντολή στη
mySQL. Τι παρατηρείτε;

SELECT dname,Employee.deptno, COUNT(*)


FROM Employee,Department,Jobs
WHERE Employee.deptno=Department.deptno
AND Employee.jobcode=Jobs.jobno
GROUP BY Employee.deptno
HAVING COUNT(*)>=1

ORA-00979: not a GROUP BY expression

Προσοχή! Δείτε την παρακάτω εντολή στην Oracle. Δοκιμάστε την ίδια εντολή στη
mySQL. Τι παρατηρείτε;
SELECT *
FROM Employee
WHERE ename='smith'

EM PNO ENAM E JOBCODE DEPTNO

400 smith 200 20

Statement processed. 0.01 seconds

Προσοχή! Δείτε την παρακάτω εντολή στην Oracle. Δοκιμάστε την ίδια εντολή στη
mySQL. Τι παρατηρείτε;
SELECT *
FROM Employee
WHERE ename='SMITH'

EM PNO ENAM E JOBCODE DEPTNO

1000 SMITH 100 10

Statement processed. 0.01 seconds

Δοκιμάστε εντολές UPDATE

UPDATE Employee

SET ename='NICK'

WHERE empno=300;

5
Προσθέστε στήλη hiredate στον πίνακα Employee
ALTER TABLE Employee ADD(hiredate date);

Εισάγετε δεδομένα για τη νέα στήλη

UPDATE Employee

SET hiredate='2010/1/1'

WHERE empno=300;

Κ.λπ

Δείτε στην Oracle προσθήκη στήλης που δείχνει αριθμό υπαλλήλων και πως
μπορούμε να υπολογίσουμε αυτόματα τις τιμές της στήλης αυτής.
Δεδομένου ότι οι εντολές UPDATE, DELETE παρουσιάζουν διαφορές από προϊόν σε
προϊόν δοκιμάστε αν η εντολή UPDATE εκτελείται και στη mySQL
ALTER TABLE Department ADD (no_of_employees NUMBER(3));

Table altered. 0.01 seconds

UPDATE Department
SET no_of_employees =
(SELECT COUNT(*)
FROM Employee
WHERE Employee.deptno = Department.deptno);

3 row(s) updated. 0.01 seconds

SELECT * FROM Department;

DEPTNO DNAM E NO_OF_EMPLOYEES

10 ACCOUNTING 2
20 SALES 2
30 PERSONNEL 0

3 rows selected. 0.01 seconds

Δημιουργήστε νέο πίνακα και μεταφέρετε με μία εντολή INSERT δεδομένα από
άλλον πίνακα
CREATE TABLE my_Employee(empno NUMBER(4) NOT NULL,
ename VARCHAR2(20),
jobcode NUMBER(3) NOT NULL,deptno NUMBER(2) NOT NULL);

Table created. 0.01 seconds

INSERT INTO my_Employee(empno,ename,jobcode,deptno)


SELECT empno,ename,jobcode,deptno
FROM Employee;

6
SELECT * FROM my_Employee;

EM PNO ENAM E JOBCODE DEPTNO

1000 SMITH 100 10


2000 TOM 200 10
300 NICK 100 20
400 smith 200 20

MySQL:

CREATE TABLE my_Employee(empno int(4) NOT NULL, ename varchar(20),

jobcode int(3) NOT NULL,deptno int(2) NOT NULL);

INSERT INTO my_Employee(empno,ename,jobcode,deptno)

SELECT empno,ename,jobcode,deptno

FROM Employee;

SELECT * FROM my_Employee;

Διαγράψτε τη βάση

DROP DATABASE Personnel_db;

7
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 10: Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information System) -
Μοντελοποίηση και Κανονικοποίηση - Επανάληψη εντολών SQL

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information System) -
Μοντελοποίηση και Κανονικοποίηση - Επανάληψη εντολών SQL .......................................... 3
1.1 Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information System) ..................... 3
1.2 Ανάλυση δεδομένων (data analysis) ............................................................................. 3
1.3 Υλοποίηση με χρήση SQL (Ασκήσεις - Ερωτήσεις – Υποδείξεις) ................................... 5

Στόχος του εργαστηρίου είναι η εκμάθηση και εμβάθυνση σε δηλώσεις SQL με


πρακτική άσκηση στα προϊόντα mySQL και Oracle και η εμβάθυνση σε θέματα
μοντελοποίησης και κανονικοποίησης.

Λέξεις Κλειδιά: Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information


System), Μοντελοποίηση, Κανονικοποίηση, SQL, mySQL

2
1. Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information
System) - Μοντελοποίηση και Κανονικοποίηση - Επανάληψη
εντολών SQL

1.1 Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information


System)

Έστω ότι η εταιρεία “Library Automation” στην οποία εργάζεστε αναλαμβάνει την
οργάνωση της νέας σπουδαστικής βιβλιοθήκης “La Galeria” που θα λειτουργεί
παράλληλα ως κέντρο πληροφόρησης σε μικρή επαρχιακή πόλη.

Δικό σας έργο είναι η δημιουργία και λειτουργία καταλόγου βιβλίων και η
οργάνωση της ταξινόμησης των βιβλίων στα ράφια.

Μετά από σχετικές συζητήσεις (interviews) με το προσωπικό μαθαίνετε ότι οι


βιβλιοθηκονόμοι καταλογογραφούν τα βιβλία, δηλαδή καταχωρούν τα στοιχεία των
βιβλίων (τίτλο, εκδότη, συγγραφείς κ.λπ.) σε βάση δεδομένων.

Επιπλέον, μαθαίνετε ότι χρησιμοποιούν το δεκαδικό σύστημα ταξινόμησης (“Dewey


Decimal Classification (DDC)” ή “Dewey Decimal System”) για να οργανώσουν τα
βιβλία της βιβλιοθήκης στα ράφια.

Τέλος, η βιβλιοθήκη ενημερώνει έναν πίνακα με θέματα (subjects) και κάθε βιβλίο
μπορεί να έχει ένα ή περισσότερα θέματα.

1.2 Ανάλυση δεδομένων (data analysis)

Μετά από τη σχετική ανάλυση δεδομένων καταλήγετε στους εξής επιχειρησιακούς


κανόνες - περιορισμούς:

1. Τα βιβλία στη βιβλιοθήκη θα είναι ταξινομημένα με το δεκαδικό σύστημα


Dewey. Σε κάθε βιβλίο θα δίνουμε ένα κωδικό Dewey.

2. Κάθε βιβλίο έχει πολλά θέματα και για ένα θέμα υπάρχουν πολλά βιβλία
στη βιβλιοθήκη.

3. Κάθε βιβλίο έχει ένα μοναδικό ISBN (Διεθνή Αριθμό Βιβλίου) και έναν
ακριβώς τίτλο.

3
4. Κάθε βιβλίο έχει τουλάχιστον ένα συγγραφέα και ένας συγγραφέας έχει
γράψει ένα ή περισσότερα βιβλία.

5. Κάθε βιβλίο έχει ένα μόνο εκδότη και κάθε εκδότης εκδίδει ένα ή
περισσότερα βιβλία..

6. Κάθε εκδότης έχει μία μόνο διεύθυνση και ένα μοναδικό όνομα.

7. Σε κάθε συγγραφέα εκχωρείται ένας μοναδικός αριθμός ώστε να μπορεί να


γίνει διάκριση σε περίπτωση συνωνυμίας.

8. Μπορούν να υπάρχουν πολλά αντίτυπα ενός βιβλίου στη βιβλιοθήκη.


Βεβαίως κάθε αντίτυπο έχει μοναδικό κωδικό αριθμό (unique accession
number).

Ακολουθεί μοντελοποίηση:

4
Η αντίστοιχη Τρίτη κανονική μορφή είναι η παρακάτω:

 BOOK (ISBN, Title, PubName, DeweyCode)

 COPY (AccessionNo, ISBN)

 AUTHOR (AuthorNo, Surname, Fname)

 SUBJECT (SubjectCode, Name)

 BOOK_SUBJECT (ISBN, SubjectCode)

 WRITER (ISBN, AuthorNo)

 PUBLISHER (PubName, Address)

1.3 Υλοποίηση με χρήση SQL (Ασκήσεις - Ερωτήσεις – Υποδείξεις)

Πληκτρολογήστε ορισμούς πινάκων χωρίς να δηλώσετε κύρια και ξένα κλειδιά.

/* SCRIPT */

CREATE DATABASE Library;

USE Library;

/* create authority tables */

CREATE TABLE AUTHORS (AuthorNo INT(5), Name VARCHAR(40));

CREATE TABLE SUBJECTS (SubjectCode VARCHAR(15),

Subject VARCHAR(40));

CREATE TABLE PUBLISHERS (PubName VARCHAR(15),

Address VARCHAR(40));

/* create main tables */

CREATE TABLE BOOKS (ISBN CHAR(13) , Title VARCHAR(70),

PubName VARCHAR(15), DeweyCode VARCHAR(15));

CREATE TABLE COPIES (AccessionNo INT(5), ISBN CHAR(13));

CREATE TABLE WRITERS (ISBN CHAR(13), AuthorNo INT(5));

CREATE BOOK_SUBJECT (ISBN CHAR(13), SubjectCode VARCHAR(15));

5
SHOW TABLES;

Δείξτε ότι είναι δυνατόν να εισαχθούν πολλές φορές οι ίδιες γραμμές. Για
παράδειγμα στον πίνακα του βιβλίου (BOOKS) μπορείτε να καταχωρήσετε δύο
φορές το ίδιο βιβλίο ή δύο γραμμές (βιβλία) με τον ίδιο αριθμό βιβλίου. Αυτό
επιτρέπεται επειδή ενώ θεωρείτε τη στήλη ISBN του πίνακα BOOKS σαν κύριο
κλειδί αν δεν το δηλώσετε στον ορισμό του πίνακα τότε δεν γίνεται έλεγχος κατά
την εισαγωγή στοιχείων.

/* Insert the same row two times */

INSERT INTO BOOKS (ISBN , Title , PubName , DeweyCode)

VALUES('0-672-30852-5', 'CLIENT/SERVER APPLICATIONS',

'SAMS', '005.74 DAT1');

INSERT INTO BOOKS (ISBN , Title , PubName , DeweyCode)

VALUES ('0-672-30852-5', 'CLIENT/SERVER APPLICATIONS',

'SAMS', '005.74 DAT1');

SELECT * FROM BOOKS;

Διαγράψτε τους πίνακες BOOKS και PUBLISHERS και δημιουργήστε τους πάλι
ορίζοντας κύρια και ξένα κλειδιά. Εξετάστε με ποιά σειρά πρέπει να
δημιουργηθούν οι πίνακες

/* drop tables */

DROP TABLE BOOKS;

DROP TABLE PUBLISHERS;

/* create tables books, publishers */

CREATE TABLE BOOKS (ISBN CHAR(13) , Title VARCHAR(70),

PubName VARCHAR(15), DeweyCode VARCHAR(15),

PRIMARY KEY(ISBN));

CREATE TABLE PUBLISHERS (PubName VARCHAR(15),

Address VARCHAR(40), PRIMARY KEY(PubName));

Παρατηρήστε ότι τώρα δεν μπορούμε να εισάγουμε την ίδια γραμμή σε πίνακα
όπου έχετε δηλώσει κύριο κλειδί. Εξετάστε αν μπορούμε να εισάγουμε γραμμή

6
στον πίνακα BOOKS που να περιλαμβάνει στοιχεία εκδότη που δεν υπάρχουν
στον πίνακα PUBLISHERS όταν οι δύο πίνακες είναι δεμένοι με σχέση κύριου -
ξένου κλειδιού.

/* It is not permitted to insert the same row two times */

INSERT INTO BOOKS (ISBN , Title , PubName , DeweyCode)

VALUES('0-672-30852-5', 'CLIENT/SERVER APPLICATIONS',

'SAMS', '005.74 DAT1');

INSERT INTO BOOKS (ISBN , Title , PubName , DeweyCode)

VALUES ('0-672-30852-5', 'CLIENT/SERVER APPLICATIONS',

'SAMS', '005.74 DAT1');

SELECT * FROM BOOKS;

/* drop tables */

DROP TABLE BOOKS;

DROP TABLE PUBLISHERS;

/* create tables books, publishers */

CREATE TABLE PUBLISHERS (PubName VARCHAR(15),

Address VARCHAR(40), PRIMARY KEY(PubName));

CREATE TABLE BOOKS (ISBN CHAR(13) , Title VARCHAR(70),

PubName VARCHAR(15), DeweyCode VARCHAR(15) ,

PRIMARY KEY(ISBN),

FOREIGN KEY(PubName)

REFERENCES PUBLISHERS(PubName));

INSERT INTO PUBLISHERS (PubName, Address)

VALUES ('SAMS', 'INDIANA');

INSERT INTO PUBLISHERS (PubName, Address)

VALUES ('ACADEMIC PRESS', 'NEW YORK');

SELECT * FROM PUBLISHERS;

INSERT INTO BOOKS (ISBN, Title, PubName, DeweyCode)

VALUES('0-672-30852-5',

7
'CLIENT/SERVER APPLICATIONS', 'SAMS', '005.74 DAT1');

INSERT INTO BOOKS (ISBN, Title, PubName, DeweyCode)

VALUES('0-632-20852-4', 'COMPUTER APPLICATIONS',

'ACADEMIC PRESS', '005.74 DAT1');

SELECT * FROM BOOKS;

Δώστε παράδειγμα που να δείχνει τη διαφορά αναζήτησης που βασίζεται σε


σύνδεση πινάκων και αναζήτησης που γίνεται σε καρτεσιανό γινόμενο.

/* Cartesian product, join */

SELECT ISBN , TITLE , BOOKS.PUBNAME , ADDRESS

FROM PUBLISHERS , BOOKS;

SELECT ISBN , TITLE , BOOKS.PUBNAME , ADDRESS

FROM PUBLISHERS , BOOKS

WHERE PUBLISHERS.PUBNAME = BOOKS.PUBNAME;

SELECT ISBN , TITLE , BOOKS.PUBNAME , ADDRESS

FROM PUBLISHERS , BOOKS

WHERE BOOKS.PUBNAME= PUBLISHERS.PUBNAME ;

SELECT ISBN , TITLE , BOOKS.PUBNAME , ADDRESS

FROM PUBLISHERS , BOOKS

WHERE PUBLISHERS.PUBNAME = BOOKS.PUBNAME

ORDER BY PUBNAME;

SELECT ISBN , TITLE , BOOKS.PUBNAME , ADDRESS

FROM PUBLISHERS , BOOKS

WHERE BOOKS.PUBNAME= PUBLISHERS.PUBNAME

ORDER BY PUBNAME;

8
Με ποιά σειρά πρέπει να διαγράψετε τους πίνακες BOOKS και PUBLISHERS όταν
οι δύο πίνακες είναι δεμένοι με σχέση κύριου - ξένου κλειδιού;

/* drop tables */

DROP TABLE BOOKS;

DROP TABLE PUBLISHERS;

Δημιουργήστε τους πίνακες BOOKS και PUBLISHERS χρησιμοποιώντας σαν


ονόματα στηλών τα παρακάτω.

BOOKS (ISBN, Title, PName, DeweyDode)

PUBLISHERS (PubName, Address)

/* create table books, publishers */

CREATE TABLE PUBLISHERS (PubName VARCHAR(15),

Address VARCHAR(40), PRIMARY KEY(PubName));

CREATE TABLE BOOKS (ISBN CHAR(13) , Title VARCHAR(70),

PName VARCHAR(15), DeweyCode VARCHAR(15) ,

PRIMARY KEY(ISBN),

FOREIGN KEY(PName) REFERENCES PUBLISHERS(PubName));

INSERT INTO PUBLISHERS (PubName, Address )

VALUES ('SAMS', 'INDIANA');

INSERT INTO PUBLISHERS (PubName , Address )

VALUES ('ACADEMIC PRESS', 'NEW YORK');

SELECT * FROM PUBLISHERS;

INSERT INTO BOOKS (ISBN, Title, PName, DeweyCode)

VALUES('0-672-30852-5' ,

'CLIENT/SERVER APPLICATIONS','SAMS', '005.74 DAT1');

INSERT INTO BOOKS (ISBN, Title, PName, DeweyCode)

VALUES('0-632-20852-4' , 'COMPUTER APPLICATIONS',

'ACADEMIC PRESS', '005.74 DAT2');

SELECT * FROM BOOKS;

9
Γράψτε αναζήτηση που να χρησιμοποιεί σύνδεση ανάμεσα στους πίνακες αυτούς.

SELECT ISBN, TITLE,

BOOKS.PNAME, publishers.pubname, ADDRESS

FROM PUBLISHERS, BOOKS

WHERE PUBLISHERS.PUBNAME = BOOKS.PNAME

ORDER BY PUBNAME;

Προσθέστε στους πίνακες PUBLISHERS, AUTHORS αντίστοιχα τις στήλες PCITY


(έδρα εκδότη), ACITY (γενέτειρα συγγραφέα) που έχουν τον ίδιο τύπο δεδομένων
και το ίδιο μήκος πχ. varchar(40).

ALTER TABLE PUBLISHERS ADD (PCITY VARCHAR(40));

ALTER TABLE AUTHORS ADD (ACITY VARCHAR(40));

DESCRIBE PUBLISHERS;

DESCRIBE AUTHORS;

Ενημερώστε τα στοιχεία των γραμμών σας ώστε να περιλαμβάνουν και στοιχεία


για τις νέες στήλες.

SELECT * FROM publishers;

UPDATE PUBLISHERS SET PCITY = 'ATHENS';

SELECT * FROM publishers;

INSERT INTO AUTHORS VALUES (100,'HIPSLEY','ATHENS');

SELECT * FROM authors;

Διαπιστώστε ότι μπορείτε να γράψετε αναζήτηση που να βασίζεται σε σύνδεση


των πινάκων ως προς αυτές τις στήλες (PCITY , ACITY).

SELECT PUBNAME ,PCITY , NAME , ACITY

FROM PUBLISHERS , AUTHORS

WHERE PUBLISHERS.PCITY = AUTHORS.ACITY;

10
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 11: Μελέτη Περιπτώσεως: Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης
(Library Information System) – Μοντελοποίηση και Κανονικοποίηση -
Μοντελοποίηση με χρήση mySQL workbench

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Μελέτη Περιπτώσεως: Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information
System) – Μοντελοποίηση και Κανονικοποίηση - Μοντελοποίηση με χρήση mySQL
workbench ................................................................................................................................. 3
1.1 Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information System) ..................... 3
Πως χρησιμοποιούμε το δεκαδικό σύστημα ταξινόμησης (“Dewey Decimal
Classification (DDC)” ή “Dewey Decimal System”) για να οργανώσουμε τα βιβλία της
βιβλιοθήκης στα ράφια .................................................................................................... 4
Παράδειγμα 1ο ................................................................................................................. 5
Παράδειγμα 2ο ................................................................................................................. 6
Ερώτηση............................................................................................................................ 7
Βιβλιογραφία .................................................................................................................... 7

Στόχος του εργαστηρίου είναι η εμβάθυνση σε θέματα μοντελοποίησης και


κανονικοποίησης. Έμφαση σε Μοντελοποίηση με χρήση mySQL workbench.

Λέξεις Κλειδιά: Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information


System), Μοντελοποίηση, Κανονικοποίηση, mySQL workbench

2
1. Μελέτη Περιπτώσεως: Σύστημα Διαχείρισης Βάσης
Βιβλιοθήκης (Library Information System) – Μοντελοποίηση
και Κανονικοποίηση - Μοντελοποίηση με χρήση mySQL
workbench

1.1 Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information


System)

Στην προηγούμενη άσκηση είδαμε τους πίνακες του συστήματος. Να ορίσετε εκ


νέου τους πίνακες αυτούς με κύρια και ξένα κλειδιά. Στη συνέχεια να
εγκαταστήσετε mySQL workbench και να γίνει Μοντελοποίηση. Να εισάγετε τα
στοιχεία των παρακάτω βιβλίων στους πίνακές σας και να γράψετε αναζήτηση που
να βασίζεται σε σύνδεση όλων των πινάκων. Να γράψετε και 10 αναζητήσεις της
επιλογής σας με χρήση του εργαλείου mySQL workbench. Τέλος, να κάνετε export
της βάσης.

Βιβλία που θα καταχωρήσετε.

1. Date, An Introduction to Database Systems, Addison-Wesley

2. Elmasri and Navathe, Fundamentals of Data-base Systems, Benjamin


Cummings

3. Ullman, Widom, A First Course in Database Systems, Prentice-Hall

4. Ramakrishnan, Gehrke, Database Management Systems, McGraw-Hill

5. Korth, Silberschatz, Sudarshan, Database System Concepts, McGraw Hill

6. Connolly, Begg, Database solutions. A step-by-step guide to building


databases, Addison-Wesley

Τους αριθμούς ISBN των βιβλίων θα τους βρείτε στο διαδίκτυο.

3
Ακολουθούν οδηγίες για το πως θα συμπληρώσετε και τα στοιχεία Dewey. Αν δεν
κατανοήσετε τις παρακάτω οδηγίες γράψτε τυχαία παραδείγματα κωδικών Dewey.
Θα ήταν καλό όμως να προσπαθήσετε να κατανοήσετε τα παρακάτω για να μάθετε
να χρησιμοποιείτε τη βιβλιοθήκη.

Πως χρησιμοποιούμε το δεκαδικό σύστημα ταξινόμησης (“Dewey Decimal


Classification (DDC)” ή “Dewey Decimal System”) για να οργανώσουμε τα
βιβλία της βιβλιοθήκης στα ράφια

Με το δεκαδικό σύστημα που ανέπτυξε ο Melvil Dewey το 1876 (το σύστημα έχει
τροποποιηθεί – επεκταθεί πάνω από είκοσι φορές από τότε) οι βιβλιοθηκονόμοι,
αλλά και οι έμπειροι χρήστες της βιβλιοθήκης, τοποθετούν τα βιβλία στα ράφια με
τέτοιο τρόπο ώστε να τα βρίσκουν εύκολα και επίσης να τα επιστρέφουν εύκολα
στη θέση τους. Το σύστημα Dewey χρησιμοποιείται σε περισσότερες από 200,000
βιβλιοθήκες σε περισσότερες από 130 χώρες!

Το σύστημα DDC προσπαθεί να οργανώσει την ανθρώπινη γνώση σε δέκα κύριες


κατηγορίες (classes):

000 – Computer science, information & general works

100 – Philosophy and psychology

200 – Religion

300 – Social sciences

400 – Language

500 – Science (including mathematics)

600 – Technology/Applied Science

700 – Arts and recreation

800 – Literature

900 – History, geography, and biography

Κάθε κύρια κατηγορία (main classes) υποδιαιρείται σε δέκα διευθύνσεις (divisions).


Κάθε διεύθυνση (division) υποδιαιρείται σε δέκα ενότητες (sections).

4
Επομένως έχουμε 10 κύριες κατηγορίες (main classes), 100 διευθύνσεις (divisions)
και 1000 ενότητες (sections). Να οι πρώτες από τις 1000 ενότητες:

000 Computer science, information & general works

001 Knowledge

002 The book

003 Systems

004 Data processing & computer science

005 Computer programming, programs & data

006 Special computer methods

007 [Unassigned]

008 [Unassigned]

009 [Unassigned]

Με άμεση (online) πρόσβαση στα στοιχεία του καταλόγου της βιβλιοθήκης, που
γίνεται μέσω διαδικτύου (δες Υπηρεσίες - - > βιβλιοθήκη κ.λπ. στον ιστότοπο του
ΤΕΙ), μπορούν οι σπουδαστές να βλέπουν στον υπολογιστή τους αν υπάρχει ένα
βιβλίο στη βιβλιοθήκη και επιπλέον τους παρέχονται στοιχεία ώστε να το βρουν
εύκολα όταν πάνε στη βιβλιοθήκη. Ακολουθούν παραδείγματα:

Παράδειγμα 1ο
Έστω ότι βλέπετε τα παρακάτω στοιχεία βιβλιου που σας ενδιαφέρει στον κατάλογο
της βιβλιοθήκης. Τα στοιχεία είναι προσβάσιμα από την ιστοσελίδα.

Database, a primer / υπό Date, C. J.

Reading, Mass: Addison-Wesley, 1983.

Θέματα: Database management

ISBN: 0201113589

Description: 265 p.; 24 cm.

5
Πληροφορίες Αντιτύπου

Location: TEI Αθήνας - Κεντρική Βιβλιοθήκη

Call number: Βιβλίο 005.74 DAT1 (Σχόλιο! Είναι ο κωδικός DEWEY)

Διαθέσιμο

Παράδειγμα 2ο
Στοιχεία καταλόγου

Information systems development : methodologies, techniques and tools /

υπό Avison, D. E., Fitzgerald, G.

London: McGraw-Hill, 1995.

Θέματα: Ανάλυση συστημάτων System analysis

Σχεδιασμός συστημάτων System design

ISBN: 0077092333

Description: 505 p.: ill.; 23 cm.

Edition: 2nd ed.

Πληροφορίες Αντιτύπου

Location: TEI Αθήνας - Κεντρική Βιβλιοθήκη

Call number: Βιβλίο 003 AVI 1 (κωδικός DEWEY)

Διαθέσιμο

6
Ερώτηση
Τι σημαίνουν τα γράμματα μετά τους αριθμούς στις δύο ταξινομήσεις;

 005.74 DAT1

 003 AVI 1

Υπόδειξη (αντιγράφουμε από τη Wikipedia)

“Books are placed on the shelf in increasing numerical order of the decimal number,
e.g. 050, 220, 330, 330.973, 331. When two books have the same classification
number the second line of the call number (usually the first letter or letters of the
author's last name, the title if there is no identifiable author) is placed in alphabetical
order”.

Υπόδειξη Βρείτε τα δύο παραπάνω βιβλία στα ράφια της βιβλιοθήκης του ΤΕΙ
Αθήνας

Βιβλιογραφία
http://en.wikipedia.org/wiki/Dewey_Decimal_Classification

http://en.wikipedia.org/wiki/List_of_Dewey_Decimal_classes

7
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 12: Μελέτη Περιπτώσεως: Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης
(Library Information System) - Ορισμός και χρήση View

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Μελέτη Περιπτώσεως: Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library
Information System) - Ορισμός και χρήση View ........................................................ 3

Στόχος του εργαστηρίου είναι η εκμάθηση και εμβάθυνση σε δηλώσεις SQL που
διαχειρίζονται views.

Λέξεις Κλειδιά: Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information


System), View

2
1. Μελέτη Περιπτώσεως: Σύστημα Διαχείρισης Βάσης
Βιβλιοθήκης (Library Information System) - Ορισμός και χρήση
View

Σύστημα Διαχείρισης Βάσης Βιβλιοθήκης (Library Information


System)

Έστω ότι η εταιρεία “Library Automation” στην οποία εργάζεστε αναλαμβάνει την
οργάνωση της νέας σπουδαστικής βιβλιοθήκης “La Galeria” που θα λειτουργεί
παράλληλα ως κέντρο πληροφόρησης σε μικρή επαρχιακή πόλη.
Δικό σας έργο είναι η δημιουργία και λειτουργία καταλόγου βιβλίων και η
οργάνωση της ταξινόμησης των βιβλίων στα ράφια.

Ανάλυση δεδομένων (data analysis)


Όπως εργασθήκατε στις δύο προηγούμενες ασκήσεις και μετά από τη σχετική
ανάλυση δεδομένων καταλήγετε στους εξής επιχειρησιακούς κανόνες -
περιορισμούς:

1. Τα βιβλία στη βιβλιοθήκη θα είναι ταξινομημένα με το δεκαδικό σύστημα


Dewey. Σε κάθε βιβλίο θα δίνουμε ένα κωδικό Dewey.
2. Κάθε βιβλίο έχει πολλά θέματα και για ένα θέμα υπάρχουν πολλά βιβλία
στη βιβλιοθήκη.
3. Κάθε βιβλίο έχει ένα μοναδικό ISBN (Διεθνή Αριθμό Βιβλίου) και έναν
ακριβώς τίτλο.
4. Κάθε βιβλίο έχει τουλάχιστον ένα συγγραφέα και ένας συγγραφέας έχει
γράψει ένα ή περισσότερα βιβλία.
5. Κάθε βιβλίο έχει ένα μόνο εκδότη και κάθε εκδότης εκδίδει ένα ή
περισσότερα βιβλία..
6. Κάθε εκδότης έχει μία μόνο διεύθυνση και ένα μοναδικό όνομα.
7. Σε κάθε συγγραφέα εκχωρείται ένας μοναδικός αριθμός ώστε να μπορεί να
γίνει διάκριση σε περίπτωση συνωνυμίας.
8. Μπορούν να υπάρχουν πολλά αντίτυπα ενός βιβλίου στη βιβλιοθήκη.
Βεβαίως κάθε αντίτυπο έχει μοναδικό κωδικό αριθμό (unique accession
number).

Ακολουθεί μοντελοποίηση:

Η αντίστοιχη Τρίτη κανονική μορφή είναι η παρακάτω:

 BOOK (ISBN, Title, PubName, DeweyCode)


 COPY (AccessionNo, ISBN)
 AUTHOR (AuthorNo, Surname, Fname)
 SUBJECT (SubjectCode, Name)
 BOOK_SUBJECT (ISBN, SubjectCode)

3
 WRITER (ISBN, AuthorNo)
 PUBLISHER (PubName, Address)

Υλοποίηση δύο πινάκων για πειραματισμό με τις view.

CREATE DATABASE Library;

USE Library;

/* create tables books, publishers */


CREATE TABLE PUBLISHERS (PubName VARCHAR(15),
Address VARCHAR(40), PRIMARY KEY(PubName));
CREATE TABLE BOOKS (ISBN CHAR(13) , Title VARCHAR(70),
PubName VARCHAR(15), DeweyCode VARCHAR(15) ,
PRIMARY KEY(ISBN),
FOREIGN KEY(PubName)
REFERENCES PUBLISHERS(PubName));

INSERT INTO PUBLISHERS (PubName, Address)


VALUES ('SAMS', 'INDIANA');
INSERT INTO PUBLISHERS (PubName, Address)
VALUES ('ACADEMIC PRESS', 'NEW YORK');

SELECT * FROM PUBLISHERS;

INSERT INTO BOOKS (ISBN, Title, PubName, DeweyCode)


VALUES('0-672-30852-5',
'CLIENT/SERVER APPLICATIONS', 'SAMS', '005.74 DAT1');
INSERT INTO BOOKS (ISBN, Title, PubName, DeweyCode)
VALUES('0-632-20852-4', 'COMPUTER APPLICATIONS',
'ACADEMIC PRESS', '005.74 DAT1');

SELECT * FROM BOOKS;

4
Ορίστε την παρακάτω όψη:

/* create view */
CREATE VIEW NEW_YORK_PUBL(PNAME, PADD)
AS SELECT PubName, Address
FROM PUBLISHERS
WHERE Address = 'NEW YORK';

SELECT * FROM publishers;


SELECT * FROM NEW_YORK_PUBL;

Διαπιστώστε ότι οι γραμμές που εισάγετε στον πίνακα PUBLISHERS φαίνονται και
στην όψη αν ικανοποιείται το κριτήριο Address = ‘NEW_YORK’.

Διαπιστώστε ότι οι γραμμές που εισάγετε στην όψη (και ικανοποιείται το κριτήριο
Address = ‘NEW_YORK’ ) φαίνονται και στον πίνακα PUBLISHERS .

Διαπιστώστε ότι μπορείτε να εισάγετε γραμμές στην όψη χωρίς να ικανοποιείται


το κριτήριο Address = ‘NEW_YORK’

Για να αποκλείσετε αυτή τη δυνατότητα διαγράψτε την όψη και δημιουργήστε


την πάλι προσθέτοντας στον ορισμό την υποπρόταση with check option

INSERT INTO PUBLISHERS (PubName, Address)


VALUES ('SAGE', 'NEW YORK');

SELECT * FROM PUBLISHERS;

SELECT * FROM NEW_YORK_PUBL;

INSERT INTO NEW_YORK_PUBL (PName, Padd)


VALUES ('BLACKWELL', 'INDIANA');

SELECT * FROM NEW_YORK_PUBL;


SELECT * FROM PUBLISHERS;

5
DROP VIEW NEW_YORK_PUBL;

CREATE VIEW NEW_YORK_PUBL (PNAME, PADD)


AS SELECT PubName, Address
FROM PUBLISHERS
WHERE Address = 'NEW YORK'
WITH CHECK OPTION;

SELECT * FROM PUBLISHERS;


SELECT * FROM NEW_YORK_PUBL;

INSERT INTO NEW_YORK_PUBL (PName, Padd)


VALUES ('BLACKWELL', 'INDIANA');

SELECT * FROM NEW_YORK_PUBL;

SELECT * FROM PUBLISHERS;

DROP VIEW NEW_YORK_PUBL;

6
Άσκηση

Να γίνει υλοποίηση όλων των πινάκων και εκτενέστερος πειραματισμός με τις


view

7
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 13: Μελέτη Περιπτώσεως: Αμερικανικές Προεδρικές εκλογές

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
Case Study: Αμερικανικές Προεδρικές εκλογές ........................................................................ 3
1.1 Υλοποίηση ..................................................................................................................... 5

Στόχος του εργαστηρίου είναι η εκμάθηση και εμβάθυνση σε δηλώσεις SQL και σε
θέματα σχεδιασμού και κανονικοποίησης.

Λέξεις Κλειδιά: Case Study, SQL, Oracle

2
Case Study: Αμερικανικές Προεδρικές εκλογές
Έστω απλουστευμένη βάση των αμερικανικών προεδρικών εκλογών.
Στο δείγμα (παγκόσμια σχέση) παρατίθενται εκλογικά αποτελέσματα
για τις αναμετρήσεις από το 1952 έως το 1992.

YEAR WINNER W_ W- W_ LOSER L_ L_


PARTY
VOTES STATE VOTES PARTY

1952 EISENHOWER 442 REP TEXAS STEVENSON 89 DEM

1956 EISENHOWER 447 REP TEXAS STEVENSON 73 DEM

1960 KENNEDY 303 DEM MASS. NIXON 219 REP

1964 JOHNSON 486 DEM TEXAS GOLDWATER 52 REP

1968 NIXON 301 REP CALIF HUMPHREY 191 DEM

1968 NIXON 301 REP CALIF WALLACE 46 IND

1972 NIXON 520 REP CALIF McGOVERN 17 DEM

1976 CARTER 297 DEM NULL FORD 240 DEM

1980 REAGAN 489 REP NULL CARTER 49 DEM

1980 REAGAN 489 REP NULL ANDERSON 0 IND

1984 REAGAN 525 REP NULL MONDALE 13 DEM

1988 BUSH 426 REP NULL DOUKAKIS 41 DEM

1992 CLINTON NULL DEM NULL BUSH NULL REP

1992 CLINTON NULL DEM NULL PERAULT NULL IND

REP=REPUBLICAN , DEM=DEMOCRAT , IND=INDEPENDENT

Ποιό είναι το πρωτεύον κλειδί;

Η αναγραφή NULL σε μια θέση του πίνακα σημαίνει ότι η αντίστοιχη θέση δεν έχει
τιμή.

Στη συνέχεια παραθέτουμε τέσσερις (4) πίνακες (3RD Normal Form - 3NF) στους
οποίους πρέπει να γράψετε τα στοιχεία των εκλογών.

Σημειώστε επίσης πρωτεύοντα και ξένα κλειδιά.

3
PRESIDENTS

WINNER W-PARTY W_STATE

EISENHOWER REPUBLICAN TEXAS

LOSERS

LOSER L_PARTY

STEVENSON DEMOCRAT
REPUBLICAN
NIXON

ELECTIONWINNER

YEAR WINNER W_VOTES

1952 EISENHOWER 442

1956 EISENHOWER 447

1960 KENNEDY 303

ELECTIONLOSER

YEAR LOSER L_VOTES

1952 STEVENSON 89

1956 STEVENSON 73

1960 NIXON 219

4
1.1 Υλοποίηση

Ακολουθούν εντολές δημιουργίας πινάκων στο προϊόν της Oracle. Στους ορισμούς
αυτούς παραλείπονται τα πρωτεύοντα και τα ξένα κλειδιά.

CREATE TABLE presidents(winner VARCHAR2(15) NOT NULL,

w_party VARCHAR2(15),w_state VARCHAR2(15));

PRESIDENTS

WINNER W-PARTY W_STATE

CREATE TABLE losers(loser VARCHAR2(15) NOT NULL,l_party VARCHAR2(15));

LOSERS

LOSER L_PARTY

CREATE TABLE electionwinner(election_year VARCHAR2(4) NOT NULL,

winner VARCHAR2(15), w_votes NUMBER);

ELECTIONWINNER

YEAR WINNER W_VOTES

CREATE TABLE electionloser(election_year VARCHAR2(4) NOT NULL,

loser VARCHAR2(15) NOT NULL, l_votes NUMBER);

ELECTIONLOSER

YEAR LOSER L_VOTES

5
Δημιουργήστε τη βάση ELECTIONS με τους παραπάνω πίνακες στο προϊόν της
mySQL. Στους ορισμούς σας να συμπεριλάβετε πρωτεύοντα και ξένα κλειδιά.

Θυμηθείτε να δημιουργήσετε πρώτα DATABASE και μετά να τη χρησιμοποιήσετε


(USE).

Ακολουθούν εντολές εισαγωγής στοιχείων στο προϊόν της Oracle.

INSERT INTO presidents VALUES ('EISENHOWER','REPUBLICAN','TEXAS');

INSERT INTO losers VALUES('STEVENSON','DEMOCRAT');

INSERT INTO electionwinner VALUES('1952','EISENHOWER',442);

INSERT INTO electionwinner VALUES('1956','EISENHOWER',447);

INSERT INTO electionloser VALUES('1952','STEVENSON',89);

INSERT INTO electionloser VALUES('1956','STEVENSON',73);

Γράψτε όλες τις εντολές εισαγωγής δεδομένων στο προϊόν της mySQL

Απαντήστε, επιπλέον στα παρακάτω ερωτήματα.

1. Δείξτε όλα τα στοιχεία προέδρων ταξινομημένα ανά όνομα


2. Δείξτε τα ονόματα των προέδρων από τον πίνακα electionwinner μία φορά
3. Δείξτε όλα τα στοιχεία προέδρων ανά κόμμα και αλφαβητικά
4. Δείξτε όλα τα στοιχεία προέδρων που ανήκουν στο κόμμα των
ρεπουμπλικάνων
5. τι θα δείξουν οι αναζητήσεις;

6
SELECT winner, w_party, w_state

FROM presidents

WHERE w_party = 'REP';

SELECT winner, w_party, w_state

FROM presidents

WHERE w_party = 'RepUBLICAN';

SELECT winner, w_party, w_state

FROM presidents

WHERE w_party = 'republican';

SELECT winner,w_party,w_state

FROM presidents

WHERE w_state = 'REPUBLICAN';

6. Δείξτε στοιχεία NIXON


7. Δείξτε υποψήφιους που έχασαν με ψήφους λιγότερους των 80
8. Δείξτε υποψήφιους που έχασαν στις εκλογές πάνω από μία (1) φορά (χρήση
GROUP BY)
9. Δείξτε όλα τα στοιχεία των εκλογών για κάθε έτος εκλογικής αναμέτρησης
10. Γράψτε εντολές διαγραφής των πινάκων και της βάσης δεδομένων.

7
Τέλος, γράψτε τις παρακάτω αναζητήσεις:

11. Δείξτε δημοκρατικούς προέδρους από την πολιτεία MASS


12. Δείξτε δημοκρατικούς προέδρους που εξελέγησαν νικητές πάνω από μία
φορά
13. Δείξτε όλα τα στοιχεία των υποψηφίων που ηττήθηκαν και νίκησαν σε
εκλογικές αναμετρήσεις πχ ο Nixon έχασε και κέρδισε εκλογές.
14. Πόσους ψήφους εκλεκτόρων έλαβαν οι δημοκρατικοί πρόεδροι από το 1952
έως το 1992.
15. Ποιος ο ελάχιστος αριθμός εκλεκτόρων που εξασφάλισε δημοκρατικός
πρόεδρος που εξελέγη από το 1952 έως και το 1984.
16. Ποιος ο μέσος όρος ψήφων εκλεκτόρων που έλαβαν οι υποψήφιοι που
εξελέγησαν πρόεδροι από το 1952 έως και το 1984.
17. Εκτυπώστε έτη εκλογικής αναμέτρησης, ονόματα νικητών και ψήφους
εκλεκτόρων. Ταξινομήστε τα αποτελέσματα ανά φθίνουσα σειρά ψήφων
εκλεκτόρων.
18. Δείξτε υποψήφιους που έχασαν πάνω από μία φορά με ψήφους εκλεκτόρων
λιγότερους από 100.
19. Πόσοι ανεξάρτητοι υποψήφιοι συμμετείχαν στις εκλογικές αναμετρήσεις
20. Δείξτε δημοκρατικούς υποψήφιους από το 1952 έως και το 1988.

8
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 14: Μελέτη Περιπτώσεως: Ακτινοθεραπευτικό Κέντρο Blue Sky

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
Case Study: Radiotherapy.............................................................................................. 3
1.1 Σχεδίαση μοντέλου με χρήση συμβολσμού Navathe-Elmasri και χρήση Mysql
Workbench ............................................................................................................................ 5

Στόχος του εργαστηρίου είναι η εκμάθηση αλλά και η εμβάθυνση σε δηλώσεις SQL
και σε θέματα σχεδιασμού και κανονικοποίησης.

Λέξεις Κλειδιά: Case Study, Μοντελοποίηση, Κανονικοποίηση, mySQL workbench,


SQL, mySQL, Oracle

2
Case study: Radiotherapy

Μελέτη Περίπτωσης (μικρό έργο - Άσκηση επανάληψης)


Το Ακτινοθεραπευτικό Κέντρο Blue Sky χρησιμοποιεί ένα Σύστημα Βάσης
Δεδομένων για να διαχειρίζεται τους ασθενείς και τους γιατρούς του κέντρου, τη
συνεργασία με ασφαλιστικές εταιρείες ή ασφαλιστικά ταμεία, τα στοιχεία εξέτασης
του ασθενή και τα στοιχεία διάγνωσης και θεραπείας.

Κάθε γιατρός έχει έναν μοναδικό κωδικό, επώνυμο και όνομα, μία ειδικότητα και
ένα τηλέφωνο. Υπάρχουν πολλοί γιατροί για μία συγκεκριμένη ειδικότητα.
Επομένως, για τους γιατρούς του κέντρου στη βάση δεδομένων καταχωρούνται τα
εξής στοιχεία:
d_code=κωδικός γιατρού, μοναδικός για κάθε γιατρό
d_Surname=επώνυμο, d_Name=όνομα
d_speciality=ειδικότητα, d_phone=τηλέφωνο

Ακολουθεί δείγμα δεδομένων:

Στο σύστημα καταχωρούνται στοιχεία διάγνωσης και στοιχεία θεραπείας.


Πιο συγκεκριμένα μία διάγνωση έχει ένα μοναδικό κωδικό και μία περιγραφή-
ονομασία. Mία προτεινόμενη θεραπεία έχει, επίσης, μοναδικό κωδικό και
περιγραφή-ονομασία.

Επομένως, διάγνωση και θεραπεία κωδικοποιούνται ως εξής:


diagnosis_code=κωδικός διάγνωσης
diagnosis=διάγνωση
therapy_code=κωδικός θεραπείας
therapy=θεραπεία

Ακολουθεί δείγμα δεδομένων για διάγνωση:

Και δείγμα δεδομένων για θεραπεία:

3
Το κέντρο συνεργάζεται με συγκεκριμένες ασφαλιστικές εταιρείες και ταμεία. Κάθε
εταιρεία ή ασφαλιστικό ταμείο έχει έναν μοναδικό κωδικό και μία επωνυμία. Στο
σύστημα καταχωρούνται:

Health_insurance_accno=κωδικός
Health_insurance=επωνυμία

Επιπλέον, στο σύστημα καταχωρείται η οικογενειακή κατάσταση η οποία και


κωδικοποιείται όπως φαίνεται στον παρακάτω πίνακα:

Code=κωδικός,
Status=οικογενειακή κατάσταση

Κάθε ασθενής έχει ένα μοναδικό κωδικό, επωνυμο, όνομα, ημερομηνία γέννησης,
τόπο γέννησης, εθνικότητα, φύλλο, διεύθυνση, τηλέφωνο. Επισης, για κάθε ασθενή
καταχωρείται η ασφαλιστική εταιρεία ή το ταμείο που τον καλύπτει και η
οικογενειακή του κατάσταση (έγγαμος, άγαμος).

4
Για τους ασθενείς της κλινικής στη βάση δεδομένων καταχωρούνται τα εξής
στοιχεία:

p_code=κωδικός,
p_surname=επωνυμο, p_name=όνομα
p_birthdate=ημερομηνία γέννησης, p_birthplace=τόπος γέννησης
p_nationality=εθνικότητα
p_sex=φύλλο, p_address=διεύθυνση, p_phone=τηλεφωνο
p_profession=επάγγελμα
Health_insurance_accno=κωδικός ασφαλιστικής ή ταμείου στο οποίο ανήκει ο
ασθενής
Marital_Status_code=κωδικός οικογενειακής κατάστασης

Ακολουθεί δείγμα δεδομένων.

SELECT p_code, p_surname, p_name, p_sex,


Health_insurance_accno "Insurance", Marital_Status_code "Marital"
FROM Patient;

Για την εξέταση του ασθενή καταχωρούνται ο κωδικός εξέτασης, ο μοναδικός


κωδικός ασθενή, η ημερομηνία εξέτασης, μία διάγνωση και μία προτεινόμενη
θεραπεία:
t_accno=κωδικός εξέτασης
p_code=κωδικός ασθενή
d_code=κωδικός γιατρού
t_date=ημερομηνία
diagnosis_code=κωδικός διάγνωσης
therapy_code=κωδικός θεραπείας

Ακολουθεί δείγμα δεδομένων.

5
Σχεδίαση μοντέλου με χρήση συμβολσμού Navathe-Elmasri και
χρήση Mysql Workbench

Υλοποίηση - Ζητούμενα

1. Δείξτε πίνακες διάγνωσης και θεραπείας ταξινομημένους αλφαβητικά


2. Δείξτε t_accno, p_code, d_code, t_date, diagnosis_code, therapy_code για
ασθενείς που εξετάσθηκαν μέσα στο 2012
3. Δείξτε p_code, t_date, diagnosis_code, therapy_code για ασθενείς που έχουν
διάγνωση καρκίνο του λάρυγγα (larynx)
4. Δείξτε p_code, t_date, diagnosis_code, therapy_code για άνδρες ασθενείς
που έχουν διάγνωση καρκίνο του προστάτη (prostate)
5. Δείξτε p_code, t_date, diagnosis_code, therapy_code για ασθενείς που έχουν
διάγνωση καρκίνο του λάρυγγα ή του προστάτη
6. Δείξτε τα στοιχεία γιατρών αλφαβητικά. Οι γιατροί που έχουν το ίδιο
επώνυμο να ταξινομούνται ως προς το μικρό τους όνομα.
7. Δείξτε p_code, t_date, diagnosis_code, therapy_code για ασθενείς που έχουν
διάγνωση καρκίνο του λάρυγγα πρίν από 1/1/2013
8. Δείξτε p_code, p_surname, p_name, p_sex, Health_insurance_accno,
Marital_Status_code για άνδρες ασθενείς
9. Δείξτε p_code, p_surname, p_name, p_sex για έγγαμους ασθενείς
10. Δείξτε p_code, p_surname, p_name, p_sex για έγγαμους άνδρες ασθενείς
11. Δείξτε τη σημερινή ημερομηνία, το τρέχον έτος και τον τρέχοντα μήνα
SELECT current_date,
YEAR(current_date) AS year, MONTH(current_date) AS month;
12. Πόσοι μήνες πέρασαν από την ημέρα που οι Ασθενείς εξετάσθηκαν
13. Ασθενείς που εξετάστηκαν τους τελευταίους 15 μήνες
14. Ποιοι ασθενείς εξετάστηκαν μετά το 2010, είχαν διάγνωση 10 (καρκίνο του
λάρυγγα) και προτεινόμενη θεραπεία 100 (χειρουργική επέμβαση). Δείξτε τα
εξής στοιχεία της εξέτασης: p_code, t_date, therapy_code, diagnosis_code
15. Ποιοι ασθενείς εξετάστηκαν μετά το 2010, είχαν διάγνωση 10 (καρκίνο του
λάρυγγα) και προτεινόμενη θεραπεία 100 (χειρουργική επέμβαση). Δείξτε τα
εξής στοιχεία της εξέτασης: Patient.p_code , Patient.p_surname,
Patient.p_name, t_date, therapy_code, diagnosis_code
16. Ποιοι ασθενείς εξετάστηκαν μετά το 2010, είχαν καρκίνο του λάρυγγα
(LARYNX) και προτάθηκε χειρουργική επέμβαση (OPERATION). Δείξτε τα
παρακάτω στοιχεία: Patient.p_code , Patient.p_surname, Patient.p_name,
t_date, therapy_code, diagnosis_code
17. Δείξτε τα στοιχεία ασθενούς και εξετάσεων του
18. Δείξτε όλους τους ασθενείς του HI_1
19. Ασθενείς που εξέτασε ο ιατρός Green C. μετά από '01/01/2011'
20. Πόσοι ασθενείς προτάθηκε να χειρουργηθούν το 2012
21. Πόσοι άγαμοι είχαν διάγνωση καρκίνου του λάρυγγα το 2012
22. Πόσοι ασθενείς προτάθηκε να χειρουργηθούν ανά ασφαλιστική εταιρεία
23. Η παρακάτω αναζήτηση είναι λανθασμένη. Γράψτε γιατί.

6
select count(*), Health_Insurance_Accno
from Patient
group by Health_Insurance_Accno
having Health_insurance_accno in(select Health_insurance_accno
from Patient,Test
where Patient.p_code = Test.P_code
and therapy_code = 100)
order by Health_Insurance_Accno;
24. Κατασκευάστε όψη που περιλαμβάνει άγαμους ασφαλισμένους του ΙΚΑ με
διάγνωση καρκίνου του λάρυγγα. Δείξτε τα στοιχεία της όψης.
25. Προσθέστε κύρια κλειδιά στους πίνακες.
26. Προσθέστε ξένα κλειδιά στους πίνακες.
27. Χρησιμοποιήστε mySQL Workbench για να κατασκευάσετε μοντέλο
οντοτήτων συσχετίσεων
28. Χρησιμοποιήστε mySQL Workbench για να εισάγετε στοιχεία στους πίνακες
της βάσης.
29. Διαγράψτε τους πίνακες της βάσης
30. Διαγράψτε τη βάση δεδομένων

7
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 15: Σύνδεση Excel-Mysql

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Σύνδεση Excel-Mysql ........................................................................................................ 3
1.1 Δημιουργία DSN ............................................................................................................ 3
1.2 Σύνδεση στο excel ......................................................................................................... 4

Στόχος του εργαστηρίου είναι η εκμάθηση της σύνδεσης Excel-Mysql.

Keywords: Excel, mySQL

2
1. Σύνδεση Excel-Mysql

Αρχικά θα πρέπει να εγκαταστήσετε τον Open Database Connectivity (ODBC) driver


για MySQL. http://dev.mysql.com/downloads/connector/odbc/ . (***Προσοχή στη
σωστή επιλογή***)

1.1 Δημιουργία DSN

Το DSN θα περιέχει όλες τις πληροφορίες προκειμένου να επιτύχετε σύνδεση με την


MySQL

Προκειμένου να δημιουργήσετε την σύνδεση ακολουθείτε τα παρακάτω βήματα.


Start > Control Panel >Administrative Tools>Data Sources (ODBC).

Στη συνέχεια επιλέξτε ADD:

3
Επιλέξτε MySQL ODBC 5.1 Driver και στη συνέχεια Finish . Εάν δεν εμφανίζεται ,
υπάρχει λάθος κατά την εγκατάσταση του driver.

Στην οθόνη που εμφανίζεται συμπληρώστε τα κατάλληλα στοιχεία προκειμένου να


δημιουργήσετε μια ODBC σύνδεση με την Mysql.
Αφού επιλέξετε OK, παρατηρήστε το όνομα της σύνδεσης στα ODBC Data Source.

1.2 Σύνδεση στο excel

Ανοίγετε το Excel και επιλέγετε Δεδομένα> Συνδέσεις

4
Εμφανίζεται η παρακάτω οθόνη:

Επιλέγετε ADD

Επιλέγετε Αναζήτηση για Περισσότερα > +Σύνδεση με το νέο αρχείο προέλευσης


δεδομένων.odc (διπλό κλίκ )

5
Στην συνέχεια επιλέγετε τον πίνακα π.χ. electionloser

6
Και επιλέγετε Τέλος

Στην συνέχεια εμφανίζονται 3 επιλογές


1. Πίνακας
2. Αναφορά Συγκεντρωτικού Πίνακα
3. Αναφορά Συγκεντρωτικού Γραφήματος και Συγκεντρωτικού Πίνακα

7
1. Πίνακας
Εμφανίζονται τα περιεχόμενα του πίνακα.

2. Αναφορά Συγκεντρωτικού Πίνακα


Σας εμφανίζει τα περιεχόμενα του πίνακα αλλά με περισσότερες δυνατότητες ως
προς την εμφάνιση - με την δυνατότητα υποστήριξης φίλτρων π.χ.(Συγκεντρωτικού
Πίνακα_1, Συγκεντρωτικού Πίνακα_2)

Συγκεντρωτικού Πίνακα_1

8
Συγκεντρωτικού Πίνακα_2

3. Αναφορά Συγκεντρωτικού Γραφήματος και Συγκεντρωτικού


Πίνακα
Σας εμφανίζει τα περιεχόμενα του πίνακα όπως και η λειτουργία «Αναφορά
Συγκεντρωτικού Πίνακα» αλλά επιπλέον σας παρέχει την δυνατότητα χρήσης
γραφημάτων

9
Τέλος, παρέχεται η δυνατότητα στη στήλη Τιμές να κάνετε δεξί κλικ και να
επιλέξετε Ρυθμίσεις πεδίου τιμής. Για παράδειγμα επιλέγετε Μ.Ο. l_votes

Και εμφανίζονται τα παρακάτω αποτελέσματα.

Επίσης κάθε φορά που θέλετε να συνδεθείτε με Mysql επιλέγετε τη σύνδεση την
οποία δημιουργήσατε (Δεδομένα> Υπάρχουσες Συνδέσεις)

10
11
Βάσεις Δεδομένων Ι (Ε)
Ενότητα 16: Εξετάσεις – Θέματα και κάποιες ενδεικτικές λύσεις

Χ. Σκουρλάς, Α. Τσολακίδης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
Θέμα 1................................................................................................................. 3
Θέμα 2................................................................................................................. 7

Στόχος του εργαστηρίου είναι η (αυτό)αξιολόγηση του φοιτητή σε θέματα


σχεδίασης, δημιουργίας και διαχείρισης μίας σχεσιακής βάσης δεδομένων με
πραγματικά Προϊόντα Διαχείρισης Βάσης Δεδομένων (Data Base Management
Systems).

Λέξεις Κλειδιά: Σύστημα Διαχείρισης Βάσης Δεδομένων, Μοντελοποίηση,


Κανονικοποίηση, SQL, mySQL, Oracle

2
Θέμα 1
Έστω η παρακάτω βάση δεδομένων Νοσοκομείων

Patient (πίνακας ασθενών)


P_i Pname Job
d
10 ΣΠΥΡΟΥ ΕΜΠΟΡΟΣ
20 ΙΩΑΝΝΟΥ ΠΩΛΗΤΗΣ
30 ΠΕΤΡΟΥ ΕΜΠΟΡΟΣ

Hospital (πίνακας νοσοκομείων)


H_id Hname
100 ΜΕΤΑΞΑ
200 ΑΡΕΤΑΙΕΙΟ

Ward (πίνακας κλινικών) κύριο κλειδί = (H_id, W_id)


W_id Wname H_id
1000 ΑΚΤΙΝΟΛΟΓΙΚΟ 100
2000 ΚΑΡΔΙΟΛΟΓΙΚΟ 100
2000 ΚΑΡΔΙΟΛΟΓΙΚΟ 200
1000 ΑΚΤΙΝΟΛΟΓΙΚΟ 200

Occupy (εισαγωγή ασθενούς σε κλινική)


H_id W_Id P_id Entry_Date
100 1000 10 1.1.2014
100 1000 20 1.1.2014
100 2000 10 5.1.2014
200 1000 10 29.1.2014
200 1000 30 2.1.2014

Υποτίθεται ότι το κύριο κλειδί είναι σύνθετο = (H_id, W_id, P_id, Entry_date)

1) Η βάση είναι στην Τρίτη κανονική μορφή; Αν όχι γράψτε την Τρίτη κανονική
μορφή.

Στην Τρίτη κανονική μορφή ο πίνακας


Ward (πίνακας κλινικών) κύριο κλειδί = (H_id, W_id)

W_id Wname H_id


1000 ΑΚΤΙΝΟΛΟΓΙΚΟ 100
2000 ΚΑΡΔΙΟΛΟΓΙΚΟ 100
2000 ΚΑΡΔΙΟΛΟΓΙΚΟ 200
1000 ΑΚΤΙΝΟΛΟΓΙΚΟ 200

3
Αντικαθίσταται από τους πίνακες:

Ward_list (πίνακας κωδικοποίησης κλινικών) κύριο κλειδί = (W_id)


W_id Wname
1000 ΑΚΤΙΝΟΛΟΓΙΚΟ
2000 ΚΑΡΔΙΟΛΟΓΙΚΟ

Hosp_Ward (πίνακας κλινικών νοσοκομείων) κύριο κλειδί = (H_id, W_id)


W_id H_id
1000 100
2000 100
2000 200
1000 200

Άλλες αλλαγές που προτάθηκαν από σπουδαστές και θα μπορούσαμε να δεχθούμε:


- Κωδικοποίηση της στήλης job. Άρα θα μπορούσαμε να έχουμε δύο πίνακες
job(jobno, job), patient(p_id, pname, jobno) αντί του πίνακα patient
- Εισαγωγή στήλης accno ως κύριου κλειδιού στον πίνακα occupy.

2) Δημιουργήστε την παραπάνω βάση με κύρια και ξένα κλειδιά και γράψτε τις
απαραίτητες εντολές INSERT INTO ώστε να καταχωρηθούν όλες οι
εισαγωγές του ΠΕΤΡΟΥ σε νοσοκομεία.

CREATE DATABASE test_hospital;


USE test_hospital;
CREATE TABLE Patient (P_id int(5) NOT NULL, Pname
varchar(20), Job varchar(15),
PRIMARY KEY(P_id));
INSERT INTO Patient (P_id, Pname, Job)
VALUES (10, 'ΣΠΥΡΟΥ', 'ΕΜΠΟΡΟΣ'),
(20, 'ΙΩΑΝΝΟΥ', 'ΠΩΛΗΤΗΣ'),
(30, 'ΠΕΤΡΟΥ', 'ΕΜΠΟΡΟΣ');
CREATE TABLE Hospital (H_id int(3) NOT NULL, Hname
varchar(20),
PRIMARY KEY (H_id));
INSERT INTO Hospital VALUES
(100, 'ΜΕΤΑΞΑ'), (200, 'ΑΡΕΤΑΙΕΙΟ');

CREATE TABLE Ward (W_id int(4) NOT NULL, Wname


varchar(20), H_id int(3) NOT NULL, PRIMARY
KEY(H_id, W_id), FOREIGN KEY(H_id) REFERENCES Hospital
(H_id));
INSERT INTO Ward VALUES
(1000, 'ΑΚΤΙΝΟΛΟΓΙΚΟ', 100),
(2000, 'ΚΑΡΔΙΟΛΟΓΙΚΟ', 100),
(2000, 'ΚΑΡΔΙΟΛΟΓΙΚΟ', 200),
(1000, 'ΑΚΤΙΝΟΛΟΓΙΚΟ', 200);
CREATE TABLE Occupy (H_id int(3) NOT NULL, W_id int(4)
NOT NULL,

4
P_id int(5) NOT NULL, Entry_Date DATE NOT NULL,
PRIMARY KEY(H_id, W_id, P_id, Entry_date),
FOREIGN KEY(H_id, W_id)REFERENCES ward(H_id, W_id),
FOREIGN KEY (P_id)REFERENCES patient(P_id));

INSERT INTO Occupy VALUES


(100, 1000, 10, '2014/01/01'),
(100, 1000, 20, '2014/01/01'),
(100, 2000, 10, '2014/01/05'),
(200, 1000, 10, '2014/01/29'),
(200, 1000, 30, '2014/01/02');

SELECT * FROM hospital;


SELECT * FROM patient;
SELECT * FROM ward;
SELECT * FROM occupy;

5
3) Αλλάξτε τον πίνακα Ward (δομή και περιεχόμενο)ώστε να έχει την
παρακάτω μορφή:

Ward (πίνακας κλινικών)


W_id Wname H_id Beds
1000 ΑΚΤΙΝΟΛΟΓΙΚΟ 100 10
2000 ΚΑΡΔΙΟΛΟΓΙΚΟ 100
2000 ΚΑΡΔΙΟΛΟΓΙΚΟ 200

ALTER TABLE ward ADD beds int(2);

UPDATE ward
SET beds=10
WHERE w_id=1000 AND h_id=100;

SELECT * FROM ward;

6
Θέμα 2
Έστω απλοποιημένη βάση δεδομένων Διεύθυνσης Προσωπικού. Οι στήλες των
πινάκων είναι: Empno=Κωδικός υπαλλήλου, Name=όνομα, JobCode/JobNo=κωδικός
θέσης, Job_descr= θέση, Deptno=κωδικός τμήματος, Dname=τμήμα Sal=μισθός,
Comm=προμήθεια. Υποτίθεται ότι κάθε υπάλληλος ανήκει σε ένα τμήμα και ότι ο
μισθός του εξαρτάται από τη θέση του.

Emp
Empno Name JobCode DeptNo Comm

10 ΣΠΥΡΟΥ 100 50 450


20 ΧΡΗΣΤΟΥ 100 50
30 ΝΙΚΟΥ 300 60

Job
JobNo Job_descr Sal

100 ΠΩΛΗΤΗΣ 2200


200 ΑΝΑΛΥΤΗΣ 2000
300 ΧΕΙΡΙΣΤΗΣ 1000

Dept
DeptNo Dname Loc
50 ΠΩΛΗΣΕΙΣ ΑΘΗΝΑ
60 ΛΟΓΙΣΤΗΡΙΟ ΑΘΗΝΑ
70 ΜΙΣΘΟΔΟΣΙΑ ΒΟΛΟΣ

CREATE DATABASE test_personnel;


USE test_personnel;
CREATE TABLE DEPT(DEPTNO INT(2) NOT NULL,
DNAME VARCHAR(14), LOC VARCHAR(14),
PRIMARY KEY(DEPTNO));
CREATE TABLE JOB (JOBNO INT(3) NOT NULL, JOB_DESCR
VARCHAR(15), SAL FLOAT(7,2),
PRIMARY KEY(JOBNO));
CREATE TABLE EMP(EMPNO INT(4) NOT NULL,
NAME VARCHAR(10), JOBCODE INT(3),
DEPTNO INT(2), COMM FLOAT(7,2),
PRIMARY KEY(EMPNO),
FOREIGN KEY(DEPTNO) REFERENCES DEPT(DEPTNO),
FOREIGN KEY(JOBCODE) REFERENCES JOB(JOBNO));
DESCRIBE DEPT;
DESCRIBE JOB;
DESCRIBE EMP;

INSERT INTO DEPT(DEPTNO, DNAME, LOC)


VALUES (50, 'ΠΩΛΗΣΕΙΣ', 'ΑΘΗΝΑ');

7
INSERT INTO DEPT(DEPTNO, DNAME, LOC)
VALUES (60, 'ΛΟΓΙΣΤΗΡΙΟ', 'ΑΘΗΝΑ');
INSERT INTO DEPT(DEPTNO, DNAME, LOC)
VALUES (70, 'ΜΙΣΘΟΔΟΣΙΑ', 'ΒΟΛΟΣ');

INSERT INTO JOB VALUES (100, 'ΠΩΛΗΤΗΣ', 2200);


INSERT INTO JOB VALUES (200, 'ΑΝΑΛΥΤΗΣ', 2000);
INSERT INTO JOB VALUES (300, 'ΧΕΙΡΙΣΤΗΣ', 1000);

INSERT INTO EMP


VALUES (10, 'ΣΠΥΡΟΥ', 100, 50, 450);
INSERT INTO EMP
VALUES (20, 'ΧΡΗΣΤΟΥ', 100, 50, NULL);
INSERT INTO EMP
VALUES (30, 'ΝΙΚΟΥ', 300, 60, NULL);

SELECT * FROM emp;


SELECT * FROM dept;
SELECT * FROM job;

8
1. Δείξτε (SELECT) name, empno, jobCode, job_descr, sal, deptno, dname των
υπαλλήλων που είναι αναλυτές ή πωλητές. Οι υπάλληλοι θα είναι
ταξινομημένοι ανά θέση (job_descr).

SELECT name, empno, jobCode, job_descr, sal, emp.deptno,


dname
FROM emp, dept, job
WHERE emp.jobcode=job.jobno
AND emp.deptno=dept.deptno
AND job_descr IN ('ΠΩΛΗΤΗΣ', 'ΑΝΑΛΥΤΗΣ')
ORDER BY job_descr;

2. Δείξτε (SELECT) name, empno, jobCode, job_descr, sal, deptno, dname των
υπαλλήλων που ανήκουν σε ένα από τα τμήματα: «ΠΩΛΗΣΕΙΣ» ή
«ΛΟΓΙΣΤΗΡΙΟ» (με 2 τρόπους) (select … select, χρήση join)

SELECT name, empno, jobCode, job_descr, sal, emp.deptno,


dname
FROM emp, dept, job
WHERE emp.jobcode=job.jobno
AND emp.deptno=dept.deptno
AND dname IN ('ΠΩΛΗΣΕΙΣ', 'ΛΟΓΙΣΤΗΡΙΟ')
ORDER BY job_descr;

SELECT name, empno, jobCode, job_descr, sal, emp.deptno,


dname
FROM emp, dept, job
WHERE emp.jobcode=job.jobno
AND emp.deptno=dept.deptno
AND EMP.deptno IN (SELECT deptno FROM dept
WHERE dname IN ('ΠΩΛΗΣΕΙΣ',
'ΛΟΓΙΣΤΗΡΙΟ'))
ORDER BY job_descr;

9
3. Δείξτε name, empno, job_descr, sal των υπαλλήλων με σύνολο αμοιβών
(άθροισμα μισθού και προμήθειας) μεγαλύτερο των 1000 ευρώ και
μικρότερο των 3000 ευρώ.

SELECT name, empno, job_descr, sal, SAL+IFNULL(COMM,0)


FROM emp, job
WHERE emp.jobcode=job.jobno
AND SAL+IFNULL(COMM,0)>1000
AND SAL+IFNULL(COMM,0)<3000
ORDER BY job_descr;

- Προσοχή! Η επόμενη εντολή δεν υπολογίζει το ζητούμενο.


-
SELECT name, empno, job_descr, sal, SAL+IFNULL(COMM,0)
FROM emp, job
WHERE emp.jobcode=job.jobno
AND SAL+IFNULL(COMM,0) BETWEEN 1000 AND 3000
ORDER BY job_descr;

- Επιπλέον θυμηθείτε ότι υποχρεωτικά γράφουμε SAL+IFNULL(COMM,0)


Και όχι SAL+COMM.

10
4. Διορθώστε και συμπληρώστε την παρακάτω εντολή SELECT ώστε να δείχνει
στοιχεία πωλητών και αναλυτών που έχουν μισθό μεγαλύτερο των 1500
ευρώ. Πρέπει να έχουμε δύο επίπεδα ταξινόμησης: Οι υπάλληλοι θα
τυπώνονται ανά θέση δηλαδή πρώτα οι αναλυτές, μετά οι πωλητές και οι
υπαλληλοι που έχουν την ίδια θέση θα εμφανίζονται αλφαβητικά.

SELECT empno, name, job, sal, comm, deptno, dname


FROM
WHERE
ORDER BY

SELECT name, empno, jobCode, job_descr, sal, emp.deptno,


dname
FROM emp, dept, job
WHERE emp.jobcode=job.jobno
AND emp.deptno=dept.deptno
AND job_descr IN ('ΠΩΛΗΤΗΣ', 'ΑΝΑΛΥΤΗΣ')
AND sal>1500
ORDER BY job_descr, name;

11
5. Γράψτε εντολή SELECT η οποία υπολογίζει πόσοι υπάλληλοι έχουν κωδικό
θέσης 100 (είναι πωλητές), πόσοι 300 (είναι χειριστές) κ.λπ. Να πως θα
φαίνονται τα αποτελέσματα.

JobCode No_of_employees.

100 2
300 1

SELECT jobcode, COUNT(*)


FROM emp
GROUP BY jobcode
ORDER BY jobcode;

Προσοχή! Αν χρησιμοποιώ GROUP BY έχω περιορισμούς στο τι επιλέγω στο


SELECT!

6. Τροποποιήστε την εντολή SELECT έτσι ώστε αν και υπολογίζει πόσοι


υπάλληλοι έχουν κωδικό θέσης 100 (είναι αναλυτές), πόσοι 300 (είναι
χειριστές) κ.λπ. να δείχνει μόνο θέσεις που απασχολούν περισσότερους από
έναν υπαλλήλους:

JobCode No_of_employees
100 2
SELECT jobcode, COUNT(*)
FROM emp
GROUP BY jobcode
HAVING COUNT(*)>1
ORDER BY jobcode;

12
7. Δείξτε τους υπάλληλους με έδρα 'ΑΘΗΝΑ' ή 'ΒΟΛΟΣ' και θέση σαν του
ΣΠΥΡΟΥ.

SELECT name, empno, jobCode, job_descr, sal, emp.deptno, dname, loc


FROM emp, dept, job
WHERE emp.jobcode=job.jobno
AND emp.deptno=dept.deptno
AND loc IN ('ΑΘΗΝΑ', 'ΒΟΛΟΣ')
AND jobcode=(SELECT jobcode FROM emp WHERE name='ΣΠΥΡΟΥ')
ORDER BY job_descr;

8. Διαφέρουν οι παρακάτω αριθμοί AVG(comm), SUM(comm)/COUNT(comm),


SUM(comm)/COUNT(*) για τους υπάλληλους του πίνακα emp;

SELECT AVG(comm), SUM(comm)/COUNT(comm), SUM(comm)/COUNT(*)


FROM EMP;

9. Εμφάνισε τον εργαζόμενο που έχει τον μεγαλύτερο μισθό στο τμήμα
'ΠΩΛΗΣΕΙΣ'

SELECT name, empno, jobCode, job_descr, sal, emp.deptno, dname, loc


FROM emp, dept, job
WHERE emp.jobcode=job.jobno
AND emp.deptno=dept.deptno
AND sal= (SELECT MAX(sal)
FROM emp, job
WHERE emp.jobcode=job.jobno
AND deptno IN (SELECT deptno FROM dept WHERE dname='ΠΩΛΗΣΕΙΣ'))
ORDER BY job_descr;

13
Λύνεται και χωρίς την υποπρόταση deptno IN (SELECT deptno FROM dept WHERE
dname='ΠΩΛΗΣΕΙΣ'). Απλά χρησιμοποιούμε τον κωδικό για dname='ΠΩΛΗΣΕΙΣ' ή
σύνδεση.

10. Δείξτε υπάλληλους που το όνομά τους αρχίζει με γράμμα Ν ή Σ.

SELECT *
FROM EMP
WHERE SUBSTR(name,1, 1) IN ('Ν','Σ');

14
Ανοικτά Ακαδημαϊκά Μαθήματα
Τεχνολογικό Εκπαιδευτικό Ίδρυμα Αθήνας

Βάσεις Δεδομένων ΙΙ (Εργαστηριο)


Ενότητα 1: Επισκόπηση θεμάτων σχεδιασμού Βάσεων Δεδομένων και υλοποίησης
με χρήση SQL

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1ο. ΘΕΜΑ (σχεδιασμός βάσης δεδομένων) .......................................................... 3
2ο. ΘΕΜΑ (υλοποίηση βάσης δεδομένων)) .......................................................... 5

Στόχος του πρώτου εργαστηρίου είναι μία περιεκτική εστίαση σε σημαντικά θέματα
σχεδιασμού Βάσεων Δεδομένων (μοντελοποίηση, κανονικοποίηση) και υλοποίησης
Βάσεων Δεδομένων με χρήση SQL.

Λέξεις Κλειδιά: Μοντελοποίηση, Κανονικοποίηση, Μοντέλο Οντοτήτων


Συσχετίσεων, SQL, Κανόνες ακεραιότητας

Τα θέματα αυτά αποτέλεσαν αντικείμενο μελέτης στο πλαίσιο του μαθημάτων


«Βάσεων Δεδομένων Ι». Το υλικό βασίζεται σε επεξεργασία των θεμάτων που
τέθηκαν στις Εξετάσεις Χειμερινού εξαμήνου στο μάθημα «Βάσεις Δεδομένων Ι –
Θεωρία» (Υπεύθυνος καθηγητής: Χ. Σκουρλάς, ημερομηνία εξέτασης: 17/2/2014).

2
1ο. ΘΕΜΑ (σχεδιασμός βάσης δεδομένων)

Η βάση δεδομένων των υπαλλήλων της εταιρείας e-ΚΟΣΜΟΣ περιλαμβάνει τα


παρακάτω στοιχεία:

Empno=Κωδικός υπαλλήλου, Name=όνομα, JobNo=κωδικός θέσης, Job=θέση,


Deptno=κωδικός τμήματος, Dname=τμήμα Sal=μισθός, C_No=αριθμός παιδιών
υπαλλήλου, C_Name=όνομα παιδιού, B_Date= ημερομηνία γέννησης παιδιού.

Περιορισμοί
Υποτίθεται ότι κάθε υπάλληλος έχει μία θέση, ανήκει σε ένα τμήμα, ο μισθός του
εξαρτάται από τη θέση και έχει ή δεν έχει παιδιά.
Employee
Empno Name JobNo Job DeptNo Dname Sal C_no C_Name B_date
10 ΣΠΥΡΟΥ 100 ΠΩΛΗΤΗΣ 50 ΠΩΛΗΣΕΙΣ 2200 2 ΜΑΡΙΑ 10/01/89
10 ΣΠΥΡΟΥ 100 ΠΩΛΗΤΗΣ 50 ΠΩΛΗΣΕΙΣ 2200 2 ΙΩΑΝΝΗΣ 20/03/90
20 ΧΡΗΣΤΟΥ 200 ΑΝΑΛΥΤΗΣ 60 ΛΟΓΙΣΤΗΡΙΟ 2000
30 ΝΙΚΟΥ 300 ΧΕΙΡΙΣΤΗΣ 70 ΜΙΣΘΟΔΟΣΙΑ 1000 1 ΘΩΜΑΣ 10/06/89

Γράψτε Πρώτη, Δεύτερη και Τρίτη Κανονική Μορφή και σχεδιάστε το Μοντέλο
Οντοτήτων–Συσχετίσεων με συμβολισμό Navathe-Elmasri.

Υπόδειξη επίλυσης

Ποιο είναι το κύριο κλειδί στην 1NF; Σίγουρα όχι το σύνθετο (empno, c_name)
(γιατί;)

3
Μοντέλο Οντοτήτων Συσχετίσεων (Entity Relationship model)

Τρίτη Κανονική Μορφή 3NF

Employee
Empno Name JobNo DeptNo C_no
10 ΣΠΥΡΟΥ 100 50 2
20 ΧΡΗΣΤΟΥ 200 60
30 ΝΙΚΟΥ 300 70 1
Κύριο κλειδί: empno
Jobs Dept
JobNo Job Sal DeptNo Dname
100 ΠΩΛΗΤΗΣ 2200 50 ΠΩΛΗΣΕΙΣ
200 ΑΝΑΛΥΤΗΣ 2000 60 ΛΟΓΙΣΤΗΡΙΟ
300 ΧΕΙΡΙΣΤΗΣ 1000 70 ΜΙΣΘΟΔΟΣΙΑ
Κύριο κλειδί: JobNo Κύριο κλειδί: deptno
Child
Empno C_Name B_date
10 ΜΑΡΙΑ 10-JAN-89
10 ΙΩΑΝΝΗΣ 20-MAR-90
30 ΘΩΜΑΣ 10-JUN-89
Κύριο κλειδί: (empno, c_name)
Names

C_Name
ΘΩΜΑΣ
ΙΩΑΝΝΗΣ
ΜΑΡΙΑ
Κύριο κλειδί: (c_name)

Παρατήρηση: Ο τελευταίος πίνακας θα μπορούσε να λείπει. Πότε μας είναι


απαραίτητος;

4
2ο. ΘΕΜΑ (υλοποίηση βάσης δεδομένων))

Υπόδειξη επίλυσης

Έστω απλοποιημένη βάση δεδομένων Διεύθυνσης Προσωπικού. Οι στήλες των


πινάκων είναι: Empno=Κωδικός υπαλλήλου, Name=όνομα, JobCode/JobNo=κωδικός
θέσης, Job_descr= θέση, Deptno=κωδικός τμήματος, Dname=τμήμα Sal=μισθός,
Comm=προμήθεια. Υποτίθεται ότι κάθε υπάλληλος ανήκει σε ένα τμήμα και ότι ο
μισθός του εξαρτάται από τη θέση του.

Emp
Empno Name JobΝο DeptNo Comm
10 ΣΠΥΡΟΥ 100 50 450
20 ΧΡΗΣΤΟΥ 200 50
30 ΝΙΚΟΥ 300 60
Job
JobCode Job_descr Sal
100 ΠΩΛΗΤΗΣ 2200
200 ΑΝΑΛΥΤΗΣ 2000
300 ΧΕΙΡΙΣΤΗΣ 1000
Dept
DeptNo Dname Loc
50 ΠΩΛΗΣΕΙΣ ΑΘΗΝΑ
60 ΛΟΓΙΣΤΗΡΙΟ ΑΘΗΝΑ
70 ΜΙΣΘΟΔΟΣΙΑ ΒΟΛΟΣ

Μετά από κάθε ερώτηση ακολουθούν απαντήσεις σπουδαστών. Σχολιάστε τις


απαντήσεις αυτές.

1. Δημιουργήστε τη βάση με κύρια και ξένα κλειδιά

/* Πρώτη εκδοχή */

CREATE DATABASE THEMA;


USE THEMA;

CREATE TABLE DEPT(DEPTNO INT(2) NOT NULL, DNAME VARCHAR(30),


LOC VARCHAR(30),
PRIMARY KEY(DEPTNO));

CREATE TABLE JOB(JOBCODE INT(3) NOT NULL, JOB_DESCR VARCHAR(30),


SAL INT(4),
PRIMARY KEY (JOBCODE));

CREATE TABLE EMP(EMPNO INT(2) NOT NULL, ENAME VARCHAR(30),


JOBNO INT(3), DEPTNO INT(2), COMM INT(4),
PRIMARY KEY (EMPNO),

5
FOREIGN KEY (JOBNO) REFERENCES JOB(JOBCODE),
FOREIGN KEY (DEPTNO) REFERENCES DEPT(DEPTNO));

/* Δεύτερη εκδοχή */

drop database if exists testing;

create database testing;

use testing;

create table Job (JobCode int(4) not null, Job_descr varchar(25),

Sal int (6), primary key (Jobcode));

create table Dept (Deptno int(3) not null, Dname varchar(25),

Loc varchar(25), primary key (Deptno));

create table Emp (Empno int(4) not null, Name varchar(20),

JobNo int(4), Deptno int(3), Comm int (6),

primary key (Empno),

foreign key (JobNo) references Job(JobCode),

foreign key (DeptNo) references Dept(DeptNo));

2. Γράψτε τις απαραίτητες εντολές INSERT INTO ώστε να καταχωρηθούν όλα τα


στοιχεία του ΣΠΥΡΟΥ.

/* Πρώτη εκδοχή */

INSERT INTO DEPT VALUES


(50,'ΠΩΛΗΣΕΙΣ','ATHINA');

INSERT INTO JOB VALUES


(100,'ΠΩΛΗΤΗΣ',2200);

INSERT INTO EMP VALUES

6
(10,'ΣΠΥΡΟΥ',100,50,450);

/* Δεύτερη εκδοχή */

insert into Job values (100,'PWLHTHS',2200);

insert into Dept values (50,'PWLHSEIS','ATHENS');

insert into Emp values (10,'SPYROU',100,50,450);

/* Εισαγωγή και των υπολοίπων στηλών των πινάκων */

insert into Job values (200,'ANALYTHS',2000), (300,'XEIRISTHS',1000);

insert into Dept values

(60,'LOGISTHRIO','ATHENS'),(70,'MISTHODOSIA','VOLOS');

insert into Emp values (20,'HRISTOU',200,50,NULL), (30,'NIKOY',300,60,NULL);

select * from Job;

select * from Dept;

select * from Emp;

3. Δείξτε (SELECT) name, empno, job_descr, sal, deptno, dname των υπαλλήλων
που είναι αναλυτές ή πωλητές ή χειριστές. Οι υπάλληλοι θα είναι
ταξινομημένοι ανά θέση (job_descr).

/* Πρώτη εκδοχή */

SELECT ENAME,EMPNO,JOB_DESCR,SAL,EMP.DEPTNO,DNAME
FROM EMP,DEPT,JOB
WHERE EMP.DEPTNO=DEPT.DEPTNO
AND JOBNO=JOBCODE
AND JOB_DESCR IN ('ΠΩΛΗΤΗΣ','ΑΝΑΛΥΤΗΣ','ΧΕΙΡΙΣΤΗΣ')
ORDER BY JOB_DESCR;

7
/* Δεύτερη εκδοχή */

select empno,job_descr,sal,emp.deptno,dname

from emp,job,dept

where emp.deptno=dept.deptno

and emp.jobNo=Job.JobCode

and job_descr in ('PWLHTHS','ANALYTHS','XEIRISTHS')

order by job_descr;

4. Δείξτε name, empno, job_descr, sal των υπαλλήλων με σύνολο αμοιβών


(άθροισμα μισθού και προμήθειας) μεγαλύτερο ή ίσο των 1000 ευρώ και
μικρότερο ή ίσο των 3000 ευρώ (τουλάχιστον με 2 τρόπους).

/* Πρώτη εκδοχή */

SELECT ENAME,EMPNO,JOB_DESCR,SAL
FROM EMP,JOB
WHERE JOBNO=JOBCODE
AND ( (SAL+IFNULL(COMM,0))>=1000 AND (SAL+IFNULL(COMM,0))<=3000 );

SELECT ENAME,EMPNO,JOB_DESCR,SAL
FROM EMP,JOB
WHERE JOBNO=JOBCODE
AND SAL+IFNULL(COMM,0) BETWEEN 1000 AND 3000;

/* Δεύτερη εκδοχή */

select name,empno,job_descr,sal

from emp,job

where Emp.jobNo=Job.jobCode

and (ifnull(emp.comm,0)+sal) >= 1000

and (ifnull(emp.comm,0)+sal) <=3000;

select name,empno,job_descr,sal

from emp,job

where Emp.jobNo=Job.jobCode

and (ifnull(emp.comm,0)+sal) between 1000 and 4000;

8
5. Διορθώστε και συμπληρώστε την παρακάτω εντολή SELECT ώστε να δείχνει
στοιχεία πωλητών, αναλυτών και χειριστών που έχουν μισθό μεγαλύτερο
των 1500 ευρώ και μικρότερο από 4000 ευρώ. Πρέπει να έχουμε δύο
επίπεδα ταξινόμησης: Οι υπάλληλοι θα τυπώνονται ανά θέση δηλαδή πρώτα
οι αναλυτές, μετά οι πωλητές και μετά οι χειριστές και οι υπάλληλοι που
έχουν την ίδια θέση θα εμφανίζονται αλφαβητικά.
SELECT empno, name, job, sal, comm, deptno, dname
FROM
WHERE
ORDER BY

/* Πρώτη εκδοχή */

SELECT EMPNO, ENAME, JOB_DESCR, SAL, COMM, EMP.DEPTNO, DNAME


FROM EMP,DEPT,JOB
WHERE EMP.DEPTNO=DEPT.DEPTNO
AND JOBNO=JOBCODE
AND JOB_DESCR IN ('ΠΩΛΗΤΗΣ','ΑΝΑΛΥΤΗΣ','ΧΕΙΡΙΣΤΗΣ')
AND SAL BETWEEN 1500 AND 4000
ORDER BY JOB_DESCR,ENAME;

/* Δεύτερη εκδοχή */

select empno,name,job_descr as job,sal,comm,emp.deptno,dname

from emp,job,dept

where emp.deptno=dept.deptno and emp.jobno=job.jobcode

and job_descr in ('PWLHTHS','ANALYTHS','XEIRISTHS')

and sal>1500 and sal<4000

order by job_descr,name;

6. Γράψτε εντολή SELECT η οποία υπολογίζει ανά κωδικό θέσης (100, 200, …)
πόσοι είναι οι υπάλληλοι που κατέχουν τη θέση. Να πως θα φαίνονται τα
αποτελέσματα στο συγκεκριμμένο παράδειγμα.

JobΝο No_of_employees
100 1
200 1
300 1

/* Πρώτη εκδοχή */

SELECT JOBNO, COUNT(*) AS NO_OF_EMPLOYEES


FROM EMP
GROUP BY JOBNO;

9
/* Δεύτερη εκδοχή */

select JobNo, count(*) as No_of_employees

from emp

group by jobno;

7. Τροποποιήστε την εντολή SELECT έτσι ώστε αν και υπολογίζει πόσοι είναι οι
υπάλληλοι ανά κωδικό θέσης (100, 200, 300, …) να δείχνει μόνο θέσεις που
απασχολούν τουλάχιστον έναν υπαλλήλο:

JobNo No_of_employees.
100 1
200 1
300 1

/* Πρώτη εκδοχή */

SELECT JOBNO, COUNT(*) AS NO_OF_EMPLOYEES


FROM EMP
GROUP BY JOBNO
HAVING COUNT(*)>=1;

/* Δεύτερη εκδοχή */

select JobNo,count(*) as No_of_employees

from emp

group by jobno

having count(*)>=1;

8. Εμφάνισε κάθε εργαζόμενο της εταιρείας που έχει μισθό ίσο με τον
μεγαλύτερο μισθό στο τμήμα 'ΠΩΛΗΣΕΙΣ'

/* Πρώτη εκδοχή */

SELECT ENAME,EMPNO,SAL
FROM EMP,JOB
WHERE JOBNO=JOBCODE
AND SAL=(SELECT MAX(SAL)
FROM EMP,DEPT,JOB
WHERE EMP.DEPTNO=DEPT.DEPTNO
AND JOBNO=JOBCODE
AND DNAME='ΠΩΛΗΣΕΙΣ');

/* Δεύτερη εκδοχή */

/*The join in the nested select is optional I guess..*/

10
select empno,name

from emp,dept,job

where emp.deptno=dept.deptno

and emp.jobno=job.jobcode

and sal = (select max(sal) from emp,job,dept where

/* emp.deptno=dept.deptno and emp.jobno=job.jobcode and */ dname='PWLHSEIS');

/* Τρίτη εκδοχή */

SELECT ename, sal, dname

FROM emp,job,dept

WHERE dept.deptno=emp.deptno

AND job.jobcode=emp.jobno

AND sal= ( SELECT MAX(sal)

FROM job,emp,dept

WHERE dept.deptno=emp.deptno

AND job.jobcode=emp.jobno

AND dname='pwlhseis');

9. Δείξτε όλα τα τμήματα με τριγράμματη συντομογραφία αποτελούμενη από


τα τρία πρώτα γράμματα του ονόματός τους

DeptNo Dname Abbr


50 ΠΩΛΗΣΕΙΣ ΠΩΛ
60 ΛΟΓΙΣΤΗΡΙΟ ΛΟΓ
70 ΜΙΣΘΟΔΟΣΙΑ ΜΙΣ

/* Πρώτη εκδοχή */

SELECT DEPTNO,DNAME,SUBSTR(DNAME,1,3) AS ADDR


FROM DEPT;

/* Δεύτερη εκδοχή */

11
select DeptNo,Dname,substring(Dname,1,3)

from dept;

Γράψτε Πρώτο και Δεύτερο Κανόνα ακεραιότητας.


10.
Σχολιάστε τις παρακάτω απαντήσεις και διατυπώστε με δικό σας τρόπο
/* Πρώτη εκδοχή */

Πρώτος κανόνας ακεραιότητας:


Καμιά συνιστώσα της τιμής ενός κύριου κλειδιού δεν μπορεί να μην έχει τιμή. Ο
κανόνας εξασφαλίζει ότι ανά δύο οι οντότητες (οι εγγραφές) είναι διακεκριμένες.
Δεύτερος κανόνας ακεραιότητας:
Έστω D ένα πρώτο πεδίο ορισμού δηλαδή ένα πεδίο ορισμού επάνω στο
οποίο ορίζεται ένα απλό κύριο κλειδί. Έστω σχέση R1 με ιδιότητα Α που ορίζεται
στο D και έστω σχέση R2 με κύριο κλειδί οριζόμενο στο D. Τότε η τιμή της ιδιότητας
Α στο R1 πρέπει να είναι είτε τίποτα (null) ή ίση με τιμή του κύριου κλειδιού
κάποιας πλειάδας της σχέσης R2 .
/* Δεύτερη εκδοχή */

Entity Integrity Rule:

- The entity integrity rule refers to rules the primary key must follow.

The primary key value cannot be null.

The primary key value must be unique.

Referential Integrity Rule:

- The referential integrity rule refers to the foreign key.

The foreign key may be null and may have the same value but:

The foreign key value must match a record in the table it is referring to.

/* Τρίτη εκδοχή */

Πρώτος κανόνας ακεραιότητας: Το κύριο κλειδί ή κάποιο μέρος του (αν έχουμε σύνθετο
κύριο κλειδί) απαγορεύεται να είναι NULL.

Δεύτερος κανόνας ακεραιότητας: Απαγορεύεται να γίνει INSERT μια τιμή σε μία στήλη που
είναι ξένο κλειδί αν αυτή η τιμή δεν υπάρχει εκεί που η αντίστοιχη στήλη της είναι κύριο
κλειδί. Αντίστοιχα ισχύουν για UPDATE, DELETE. Στο σχήμα ο πίνακας Alpha έχει μόνο μία
γραμμή.

Table Alpha Table B

A (Primary key) columns B(Primary key) C(Foreign key) columns


50 … … 40 …

12
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 2: Ανασκόπηση χρήσης της Γλώσσας SQL – θέματα υλοποίησης Βάσεων
Δεδομένων - Χρήση περιορισμών (constraints) – Χρήση Views

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Δημιουργία βάσης δεδομένων, δημιουργία πινάκων, ορισμός ευρετηρίων, αλλαγή
ορισμού (προσθήκη στηλών, τροποποίηση στηλών) κ.λπ. ...................................................... 4
2. Παραδείγματα σύνταξης και χρήσης εντολών Υπογλώσσας Ορισμού Δεδομένων (Data
Definition Language -DDL)......................................................................................................... 5
3. Δημιουργία ευρετηρίου - CREATE INDEX ......................................................................... 8
4. Διαχείριση Περιορισμών (Constraints) ............................................................................ 9
5. Ο περιορισμός Primary Key ............................................................................................ 12
6. Ο περιορισμός Foreign Key ............................................................................................ 14
7. Ο περιορισμός DEFAULT................................................................................................. 15
8. Ο περιορισμός AUTO_INCREMENT (στο προϊόν mySQL) ............................................... 16
9. Ο περιορισμός Check...................................................................................................... 17
10. Ανασκόπηση των όψεων (VIEW) ................................................................................. 19

Στόχος του δεύτερου εργαστηρίου είναι η ανασκόπηση των εντολών της γλώσσας
SQL έτσι ώστε στα επόμενα εργαστήρια ο ενδιαφερόμενος να εστιάσει απρόσκοπτα
σε θέματα υλοποίησης Βάσεων Δεδομένων με χρήση SQL και να προχωρήσει σε
θέματα αποθηκευμένων διαδικασιών (stored procedures), διαχείρισης cursors,
διαχείρισης δοσοληψιών (transactions processing) κ.λπ.

Μετά την επεξεργασία του εργαστηρίου ο ενδιαφερόμενος θα έχει επαναλάβει τα


εξής σημαντικά θέματα:
- Δημιουργία βάσης δεδομένων, δημιουργία πινάκων, ορισμός ευρετηρίων,
αλλαγή ορισμού (προσθήκη στηλών, τροποποίηση στηλών) κ.λπ.
- Οι τρεις Υπογλώσσες της γλώσσας SQL
- Δημιουργία πινάκων και Διαχείριση Περιορισμών (Constraints)
Επιπλέον, θα έχει εμπεδώσει θέματα χρήσης περιορισμών:
- Ο περιορισμός Not Null
- Ο περιορισμός Unique σε στήλη ή στήλες του πίνακα
- Ο περιορισμός Primary Key
- Ο περιορισμός Foreign Key
- Ο περιορισμός DEFAULT
- Ο περιορισμός AUTO_INCREMENT (mySQL)
- Ο περιορισμός Check
Τέλος, θα έχει κάνει ανασκόπηση των όψεων (VIEW)

Λέξεις κλειδιά: Δημιουργία βάσης δεδομένων, δημιουργία πινάκων, ορισμός


ευρετηρίων, αλλαγή ορισμού πινάκων, Υπογλώσσες της γλώσσας SQL, Δημιουργία
πινάκων και Διαχείριση Περιορισμών (Constraints), Views

2
1. Δημιουργία βάσης δεδομένων, δημιουργία πινάκων,
ορισμός ευρετηρίων, αλλαγή ορισμού (προσθήκη στηλών,
τροποποίηση στηλών) κ.λπ.

1.1 Οι τρεις Υπογλώσσες της γλώσσας SQL

Η γλώσσα SQL περιλαμβάνει τις παρακάτω υπογλώσσες:

1.1.1 Υπογλώσσα ορισμού δεδομένων - Data Definition Language (DDL).

Εντολές

1) CREATE DATABASE
2) ALTER DATABASE
3) CREATE TABLE
4) ALTER TABLE
5) DROP TABLE
6) CREATE INDEX
7) CREATE UNIQUE INDEX
8) DROP INDEX
9) CREATE TRIGGER
10) DROP TRIGGER
11) REPLACE TRIGGER
12) CREATE PROCEDURE
13) DROP PROCEDURE
14) CREATE FUNCTION
15) DROP FUNCTION

1.1.2 Υπογλώσσα Χειρισμού Δεδομένων - Data Manipulation Language


(DML)

Εντολές

1) SELECT
2) UPDATE
3) DELETE
4) INSERT INTO

1.1.3 Υπογλώσσα ελέγχου δεδομένων - Data Control Language (DCL)


Περιλαμβάνει εντολές που σχετίζονται με δικαιώματα

1) GRANT

2) REVOKE

3
1.2 Διαχείριση δοσοληψιών

Περιλαμβάνει εντολές που σχετίζονται με τη διαχείριση δοσοληψιών

1) COMMIT

2) ROLLBACK

2. Παραδείγματα σύνταξης και χρήσης εντολών Υπογλώσσας


Ορισμού Δεδομένων (Data Definition Language -DDL).

2.1 Δημιουργία βάσης δεδομένων: CREATE DATABASE

CREATE DATABASE database_name

2.2 Δημιουργία πινάκων της βάσης δεδομένων: CREATE TABLE

CREATE TABLE table_name


(
column_name1 data_type,
column_name2 data_type,
column_name3 data_type,

);

2.3 Ποιοί τύποι δεδομένων χρησιμοποιούνται.

Εξαρτάται από το προϊόν. Για παράδειγμα, στην περίπτωση του προϊόντος της
ORACLE χρησιμοποιούνται οι τύποι δεδομένων:

 CHAR (Width) - μέχρι 255 χαρακτήρες


 VARCHAR2(Width) - μέχρι 2000 χαρακτήρες
 NUMBER - προσημασμένοι δεκαδικοί μέχρι 38 ψηφία
 NUMBER (Width) - όπως παραπάνω για W ψηφία
 NUMBER (Width, Digits) - όπως παραπάνω για W ψηφία ,τα D δεκαδικά
 DATE - ημερομηνίες (‘2007-12-31’)

4
Στο προϊόν Mysql οι τύποι δεδομένων διαφέρουν λίγο πχ.
number -> numeric, int, float
varchar2->varchar

Βιβλιογραφία

http://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm
http://ss64.com/ora/syntax-datatypes.html
http://dev.mysql.com/doc/refman/5.7/en/data-types.html

2.4 Παραδείγματα δημιουργίας πινάκων σε MySql

CREATE TABLE DEPT (DEPTNO NUMERIC(2),


DNAME VARCHAR(24),
LOC CHAR(23));

CREATE TABLE EMP (EMPNO NUMERIC (4) NOT NULL,


ENAME VARCHAR (20),
JOB VARCHAR (19),
MGR NUMERIC (4),
HIREDATE DATE,
SAL NUMERIC (10,2),
COMM NUMERIC (10,2),
DEPTNO NUMERIC (2));

CREATE TABLE PROJ (PROJNO NUMERIC (3) NOT NULL,


PNAME VARCHAR (15),
BUDGET NUMERIC (12,2));

CREATE TABLE ASSIGN (EMPNO NUMERIC (4) NOT NULL ,


PROJNO NUMERIC (3) NOT NULL,
PTIME NUMERIC (2) ,BUDGET NUMERIC (12,2));

Θυμίζουμε ότι η εισαγωγή στοιχείων γίνεται με εντολές του τύπου:

INSERT INTO EMP


VALUES(7512,’ΑΝΔΡΕΟΥ’,’ΚΛΗΤΗΡΑΣ’,7890,’20/11/1988’,
1000,NULL,30);

Η εντολή INSERT ανήκει στην Υπογλώσσα Χειρισμού Δεδομένων ((DML)

5
2.5 Αλλαγή ορισμού πίνακα με εντολή ALTER TABLE – Εντολή
RENAME

Προσοχή! Η εντολή ALTER TABLE (όπως και άλλες εντολές στη συνέχεια)
διαφέρει από προϊόν σε προϊόν.

ALTER TABLE table_name


 ADD column_name datatype
 MODIFY column_name datatype
 DROP [COLUMN] col_name
 RENAME TABLE tbl_name TO new_tbl_name
[, tbl_name2 TO new_tbl_name2] ...
 CHANGE old_col_name new_col_name column_definition

RENAME TABLE old_table TO backup_table,

new_table TO old_table;

RENAME TABLE old_table TO tmp_table,

new_table TO old_table,

tmp_table TO new_table;

alter table
table_name
rename to
new_table_name;

2.6 Ορισμός πίνακα βασιζόμενος σε εντολή SELECT – Παραδείγματα

CREATE TABLE temporary

(employee_id, start_date, end_date, job_id, dept_id)

AS SELECT employee_id, start_date, end_date, job_id, department_id

FROM job_history;

DROP TABLE job_history;

RENAME temporary TO job_history;

6
ALTER TABLE customers
RENAME COLUMN credit TO credit_amount;

ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;

Βιβλιογραφία
http://dev.mysql.com/doc/refman/5.0/en/charset-conversion.html

http://docs.oracle.com/cd/E17952_01/refman-5.1-en/alter-table.html

2.7 Παραδείγματα προσθήκης στήλης σε πίνακα και τροποποίησης


στήλης

Για να προσθέσουμε στο πίνακα ΕΜΡ τη στήλη BIRTHDATE:


ALTER TABLE EMP ADD (BIRTHDATE DATE);

Για να αλλάξουμε στον πίνακα ΕΜΡ τη στήλη ΕΝΑΜΕ :


ALTER TABLE EMP MODIFY (ENAME TEXT);

2.8 Κατάργηση πίνακα DROP TABLE

DROP TABLE EMP;

3. Δημιουργία ευρετηρίου - CREATE INDEX

Tα ευρετήρια (indexes) δημιουργούνται για έναν ή περισσότερους πίνακες


προκειμένου να ανακτούμε τα δεδομένα γρηγορότερα. Τα ευρετήρια δεν είναι
διάφανα στον χρήστη και χρησιμοποιούνται από το ΣΔΒΔ για να επιταχύνουν τις
αναζητήσεις του χρήστη (users’ queries)

CREATE INDEX index_name ON table_name (column_name)

7
3.1 Ευρετήρια για απλές στήλες πίνακα

Για να ορίσουμε το ευρετήριο INAME που θα βασίζεται στη στήλη ENAME στον
πίνακα EMP:

CREATE INDEX INAME ON EMP (ENAME);

3.2 Ευρετήρια για συνδυασμό στηλών πίνακα

Για να ορίσουμε το ευρετήριο SALCOM που θα βασίζεται στο συνδυασμό στηλών


Μισθού (SAL) και προμήθειας (COMM):

CREATE INDEX SALCOM ON EMP (SAL,COMM);

Προσοχή! Τα παρακάτω ευρετήρια είναι διαφορετικά και χρησιμοποιούνται σε


διαφορετικές αναζητήσεις, δηλαδή βοηθούν στη γρηγορότερη εκτέλεση
διαφορετικών SELECT δηλώσεων:

CREATE INDEX SUR_NAM ON EMP (SURNAME, NAME);


CREATE INDEX NAM_SUR ON EMP (NAME, SURNAME);

3.3 Κατάργηση ευρετηρίου - Εντολή DROP INDEX

DROP INDEX SALCOM ON EMP;

4. Διαχείριση Περιορισμών (Constraints)

Που χρειαζόμαστε τους περιορισμούς - Παράδειγμα


Δημιουργήστε τον πίνακα Persons
CREATE TABLE Persons
(
P_Id int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
);

8
Παρατηρήστε ότι για τις στήλες του πίνακα δεν ορίσαμε περιορισμούς.

Κάνετε Εισαγωγή δεδομένων


insert into persons(p_id,lastname,firstname,address,city) values
(1,'Papadopoulos','Marios','Axarnwn 5','Athens'), (1,'Petrou','Nikos','Patisiwn
12','Athens');

Εμφάνιση των δεδομένων


select* from persons
p_id LastName FirstName Address City

1 Papadopoulos Marios Axarnwn 5 Athens

1 Petrou Nikos Patisiwn 12 Athens

Δηλαδή, εισάγουμε δύο διαφορετικά πρόσωπα με τον ίδιο κωδικό.

Διαγραφή των δεδομένων


delete from persons where p_id=1;

4.1 Ο περιορισμός Not Null

Όταν μια στήλη ενός πίνακα οριστεί ως NOT NULL δεν μπορεί να δεχτεί NULL
τιμές (values).

Παρατηρήστε ότι μπορούμε να προσθέσουμε εκ των υστέρων περιορισμούς NOT


NULL.

Προσθήκη περιορισμού:

alter table persons change p_id p_id INT(11) NOT NULL

Εισαγωγή δεδομένων
insert into persons(p_id,lastname,firstname,address,city) values
(1,'Papadopoulos','Marios','Axarnwn 5','Athens');
Τι θα δούμε;

Action Message
insert into 1 row(s) affected
persons(p_id,lastname,firstname,address,city)
values (1,'Papadopoulos','Marios','Axarnwn

9
5','Athens')

insert into persons(lastname,firstname,address,city) values


('Petrou','Nikos','Patisiwn 12','Athens');

Προσοχή! Με τη δήλωση insert into προσπαθήσαμε να εισάγουμε τιμή


NULL στη στήλη p_id.
Τι θα δούμε;

Action Message
insert into Error Code: 1364.
persons(lastname,firstname,address,city) Field 'p_id' doesn't
values ('Petrou','Nikos','Patisiwn 12','Athens') have a default value

Τι συμπέρασμα βγάζετε;

Διαγραφή δεδομένων
delete from persons where p_id=1;

4.2 Ο περιορισμός Unique σε στήλη του πίνακα

Ο περιορισμός Unique (UNIQUE constraint) εφαρμόζεται σε στήλη του πίνακα και


σημαίνει ότι κάθε τιμή στη στήλη πρέπει να υπάρχει μόνο μια φορά. Δηλαδή, κάθε
συγκεκριμένη τιμή αυτής της στήλης είναι μοναδική όπως θα συνέβαινε και αν
είχαμε ορίσει ένα κύριο κλειδί για αυτή τη στήλη. Οι περιορισμοί UNIQUE και
PRIMARY KEY (constraints) παρέχουν εγγύηση για τη μοναδικότητα μιας τιμής
για μια στήλη ή ένα σύνολο στηλών.

Προσοχή! Μπορεί να έχετε πολλούς περιορισμούς UNIQUE constraints για κάθε


πίνακα, αλλά μόνο ένα PRIMARY KEY constraint.

Ακολουθεί παράδειγμα

ALTER TABLE Persons


ADD UNIQUE (P_Id)

Δημιουργήστε περιορισμό δηλώνοντας και το όνομά του.

ALTER TABLE Persons


ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)

10
Εισαγωγή δεδομένων
insert into persons(p_id,lastname,firstname,address,city) values
(1,'Papadopoulos','Marios','Axarnwn 5','Athens');

OUTPUT

Action Message
insert into 1 row(s) affected
persons(p_id,lastname,firstname,address,city)
values (1,'Papadopoulos','Marios','Axarnwn
5','Athens')

insert into persons(lastname,firstname,address,city) values


('Petrou','Nikos','Patisiwn 12','Athens');
OUTPUT

Action Message
insert into Error Code: 1062.
persons(p_id,lastname,firstname,address,city) Duplicate entry '1' for
values (1,'Petrou','Nikos','Patisiwn key 'p_id_UNIQUE'
12','Athens');

Τι συμπέρασμα βγάζετε;

Διαγραφή δεδομένων
delete from persons where p_id=1;

5. Ο περιορισμός Primary Key

Παρατηρήστε ότι μπορούμε να προσθέσουμε εκ των υστέρων περιορισμούς για


κύρια και ξένα κλειδιά.

ALTER TABLE Persons


ADD PRIMARY KEY (P_Id);

Δημιουργήστε περιορισμό δηλώνοντας και το όνομά του.

ALTER TABLE Persons

ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName);

11
Κατάργηση περιορισμού PRIMARY KEY

ALTER TABLE Persons


DROP PRIMARY KEY

ALTER TABLE Persons


DROP CONSTRAINT pk_PersonID;

Εισαγωγή δεδομένων

insert into persons(p_id,lastname,firstname,address,city) values


(1,'Papadopoulos','Marios','Axarnwn 5','Athens');
OUTPUT

Action Message
insert into 1 row(s) affected
persons(p_id,lastname,firstname,address,city)
values (1,'Papadopoulos','Marios','Axarnwn
5','Athens')

insert into persons(lastname,firstname,address,city) values


('Petrou','Nikos','Patisiwn 12','Athens');
OUTPUT

Action Message
insert into Error Code: 1062.
persons(p_id,lastname,firstname,address,city) Duplicate entry '1' for
values (1,'Petrou','Nikos','Patisiwn key 'PRIMARY'
12','Athens');

Τι συμπέρασμα βγάζετε;

12
6. Ο περιορισμός Foreign Key

Θυμίζουμε τον κλασσικό ορισμό δημιουργώντας τον πίνακα Orders.


CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
);
select* from persons;
p_id LastName FirstName Address City
1 Papadopoulos Marios Axarnwn 5 Athens
2 Petrou Nikos Patisiwn 12 Athens

Εισαγωγή δεδομένων
insert into orders values(1,1000,1),(2,1000,1),(3,1000,2);

OUTPUT
Action Message
insert into orders 3 row(s) affected
values(1,1000,1),(2,1000,1),(3,1000,2); Records: 3 Duplicates: 0
Warnings: 0

insert into orders values(5,1000,3);

OUTPUT
Action Message
insert into orders values(5,1000,3); Error Code: 1452. Cannot add or update a
child row: a foreign key constraint fails
(`db2`.`orders`, CONSTRAINT
`orders_ibfk_1` FOREIGN KEY (`P_Id`)
REFERENCES `persons` (`p_id`))

SELECT * FROM db2.orders;


O_Id OrderNo P_Id
1 1000 1
2 1000 1
3 1000 2

Τι συμπέρασμα βγάζετε;

13
7. Ο περιορισμός DEFAULT

Ο περιορισμός DEFAULT εφαρμόζεται σε μία στήλη του πίνακα και ορίζει μία
προεπιλεγμένη τιμή για τη στήλη. Η δήλωση insert into μπορεί να αλλάξει αυτήν την
τιμή ή να την αφήσει αμετάβλητη.

Ακολουθεί παράδειγμα.
CREATE TABLE dept
(
D_Id int NOT NULL,
department varchar(90) DEFAULT 'Development',
primary key(d_id)
);

Εισαγωγή δεδομένων
insert into dept(d_id, department) values(1,'Marketing');

OUTPUT
Action Message
insert into dept(d_id, department) 1 row(s) affected
values(1,'Marketing')

insert into dept(d_id) values(2)


OUTPUT

Action Message
insert into dept(d_id) values(2) 1 row(s) affected

SELECT * FROM db2.dept;

d_Id Department
1 Marketing
2 Development

Τι συμπέρασμα βγάζετε;

14
8. Ο περιορισμός AUTO_INCREMENT (στο προϊόν mySQL)

Ο περιορισμός AUTO_INCREMENT εφαρμόζεται σε μία στήλη του πίνακα και


διαχειρίζεται αυτόματα σαν αύξοντα αριθμό την τιμή της στήλη. Η δήλωση insert
into δεν μπορεί να αλλάξει τιμή αυτή.

Ακολουθεί παράδειγμα.

CREATE TABLE Project

P_Id int NOT NULL AUTO_INCREMENT,

Project varchar(255),

PRIMARY KEY (P_Id)

);

Εισαγωγή δεδομένων
insert into project(p_id, Project) values(1,'OTE');

OUTPUT
Action Message
insert into project(p_id, Project) 1 row(s) affected
values(1,'OTE');

insert into project(Project) values('TEI');

OUTPUT

Action Message
insert into project(Project) 1 row(s) affected
values('TEI');

SELECT * FROM db2. Project;

d_Id Department
1 OTE
2 TEI

Τι συμπέρασμα βγάζετε;

15
Δείτε και το παρακάτω παράδειγμα

ALTER TABLE Project AUTO_INCREMENT=100

insert into project(Project) values('Web Site');

SELECT * FROM db2. Project;

d_Id department
1 OTE
2 TEI
100 Web Site

Τι συμπέρασμα βγάζετε;

9. Ο περιορισμός Check

CREATE TABLE Persons


(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CHECK (P_Id>0)
);

CREATE TABLE Persons


(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')
);

Οι δηλώσεις CREATE TABLE που γράψατε είναι σωστές. Δοκιμάστε και


δηλώσεις INSERT INTO. Τελικά ο περιορισμός CHECK δουλεύει στην
περίπτωση της mySQL΄

Η απάντηση είναι αρνητική μέχρι σήμερα για τις τρέχουσες versions του προιόντος!
Αποδείξτε το με παραδείγματα!

16
Άσκηση
Καταγράψτε στον παρακάτω πίνακα τα συμπεράσματά σας:

Περιορισμός Διαχείριση Περιορισμών (Constraints) και


συμπεράσματα στο προϊόν mySQL
Ο περιορισμός Not Null Μπορούμε να προσθέσουμε εκ των υστέρων
περιορισμούς NOT NULL για όποιες στήλες του
πίνακα επιθυμούμε.

Αν με τη δήλωση insert into προσπαθήσουμε να


εισάγουμε τιμή NULL σε μία στήλη στην οποία
έχουμε εφαρμόσει τον περιορισμό βλέπουμε ότι το
προϊόν δεν το επιτρέπει.

Αν με τη δήλωση update προσπαθήσουμε …

Αν με τη δήλωση delete προσπαθήσουμε …

Ο περιορισμός Unique σε
στήλη ή στήλες του
πίνακα

Ο περιορισμός Primary
Key

Ο περιορισμός Foreign
Key

Ο περιορισμός DEFAULT

Ο περιορισμός
AUTO_INCREMENT

Ο περιορισμός Check

17
10. Ανασκόπηση των όψεων (VIEW)

Πότε έχουμε Updatable και Insertable Views

Αν μπορούμε να χρησιμοποιήσουμε UPDATE, DELETE, or INSERT για να


ενημερώσουμε τον πίνακα που «υποκρύπτεται».

Πότε μια view δεν είναι ενημερώσιμη (is not updatable):

Όταν περιλαμβάνει

1. Aggregate functions (SUM(), MIN(), MAX(), COUNT(), …)


2. DISTINCT
3. GROUP BY
4. HAVING
5. UNION
6. Subquery (πράξεις κ.λπ.) in the select list
7. Certain joins
8. Nonupdatable view in the FROM clause
9. A subquery in the WHERE clause that refers to a table in the FROM clause
Η υποπρόταση WITH CHECK OPTION (clause) μας προστατεύει στην περίπτωση
updatable view από inserts, updates που παραβιάζουν την υποπρόταση WHERE
(clause) στην εντολή select που χρησιμοποιήσαμε για να ορίσουμε τη view.

18
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 3: Διαφορές στην υλοποίηση στην περίπτωση των προϊόντων mySQL και
Oracle. Δημιουργία βάσης δεδομένων. Διαχείριση περιορισμών. Δημιουργία
μοντέλου.

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα

1. Θέμα πρώτο: Διαχείριση βάσης δεδομένων προσωπικού .............................................. 3


Άσκηση 1........................................................................................................................... 5
Άσκηση 2........................................................................................................................... 5
Άσκηση 3........................................................................................................................... 5
2. Θέμα δεύτερο: Διαχείριση βάσης δεδομένων αμερικανικών εκλογών .......................... 6
Άσκηση 1......................................................................................................................... 16
Άσκηση 2......................................................................................................................... 16
Άσκηση 3......................................................................................................................... 16

Στόχος του τρίτου εργαστηρίου είναι η επισήμανση των διαφορών στην υλοποίηση
με χρήση των προϊόντων mySQL και Oracle. Το εργαστήριο εστιάζει στις διαφορές
αυτές. Μετά την επεξεργασία του εργαστηρίου ο ενδιαφερόμενος θα έχει
επαναλάβει τα εξής σημαντικά θέματα στα δύο προϊόντα:
- Δημιουργία βάσης δεδομένων
- Διαχείριση περιορισμών
- Διαχείριση ερωτημάτων (queries)
Θα γίνει χρήση δύο παραδειγμάτων: διαχείρισης προσωπικού, διαχείρισης
αμερικανικών εκλογών.
Επιπλέον θα γίνει δημιουργία μοντέλου στα δύο παραδείγματα. Τέλος, ο
ενδιαφερόμενος θα εμπεδώσει διαφορές στην υλοποίηση στην περίπτωση των
προϊόντων mySQL και Oracle.

Λέξεις κλειδιά: Διαφορές προϊόντων mySQL και Oracle

2
1. Θέμα πρώτο: Διαχείριση βάσης δεδομένων προσωπικού

Έστω η παρακάτω βάση δεδομένων προσωπικού της εταιρείας e-world.

assign (πίνακας που καταχωρεί ποιοί υπάλληλοι απασχολούνται σε ποιά έργα)


Empno Proj_code A_Time
10 100 40
10 200 60
15 100 100
20 200 100
30 100 100

project (πίνακας έργων)


Proj_code Description
100 PAYROLL
200 PERSONNEL
300 SALES

emp (πίνακας υπαλλήλων)


Empno Ename Job Hiredate Mgr Sal Comm Deptno
10 Codd ANALYST 1/1/89 15 3000 10
15 Elmasri ANALYST 2/5/95 15 1200 150 10
20 Navathe SALESMAN 7/7/77 20 2000 20
30 Date PROGRAMMER 4/5/04 15 1800 200 10

dept (πίνακας τμημάτων)


Deptno Dname Loc
10 ACCOUNTING ATHENS
20 SALES LONDON
30 RESEARCH ATHENS
40 PAYROLL LONDON

Να υλοποιήσετε τη βάση δεδομένων. Να δημιουργήστε τους πίνακες και εισάγετε


τα στοιχεία τους.

Η υλοποίηση θα γίνει με χρήση των προϊόντων mySQL και Oracle.

Ακολουθεί υλοποίηση σε mySQL.

DROP DATABASE NEW_PERSONNEL;

CREATE DATABASE new_personnel;

USE new_personnel;

CREATE TABLE DEPT(DEPTNO INT(2) NOT NULL,

DNAME VARCHAR(14), LOC VARCHAR(14),

PRIMARY KEY(DEPTNO));

CREATE TABLE EMP(EMPNO INT(4) NOT NULL,

ENAME VARCHAR(10), JOB VARCHAR(25),

3
HIREDATE DATE, MGR INT(4), SAL FLOAT(7,2), COMM FLOAT(7,2),

DEPTNO INT(2), PRIMARY KEY(EMPNO),

FOREIGN KEY(DEPTNO) REFERENCES DEPT(DEPTNO));

SHOW TABLES;

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (20, 'RESEARCH', 'DALLAS');

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (30, 'SALES', 'CHICAGO');

INSERT INTO DEPT(DEPTNO, DNAME, LOC)

VALUES (40, 'OPERATIONS', 'BOSTON');

INSERT INTO EMP

VALUES (10, 'CODD', 'ANALYST', '1989/01/01', 15, 3000, NULL, 10);

INSERT INTO EMP

VALUES (15, 'ELMASRI', 'ANALYST', '1995/05/02', 15, 1200, 150, 10);

INSERT INTO EMP

VALUES (20, 'NAVATHE', 'SALESMAN', '1977/07/07', 20, 2000, NULL, 20);

INSERT INTO EMP

VALUES (30, 'DATE', 'PROGRAMMER', '2004/05/04', 15, 1800, 200, 10);

SELECT * FROM EMP;

SELECT * FROM DEPT;

4
Άσκηση 1
Να υλοποιήσετε τη βάση δεδομένων με χρήση του προϊόντος Oracle. Στη συνέχεια
να κάνετε τα παρακάτω και για τις δύο υλοποιήσεις (Oracle, mySQL):

- Να καταργήσετε τους πίνακες. Να ορίσετε τους πίνακες χωρίς κύρια και ξένα
κλειδιά. Να προσθέσετε περιορισμούς (δείτε Εργαστήριο δεύτερο). Να
εισάγετε τις γραμμές των πινάκων.

Άσκηση 2
Δημιουργήστε το μοντέλο κατά προτίμηση με το εργαλείο mySQL Workbennch.

Άσκηση 3
Αναφέρατε διαφορές για την υλοποίηση στα δύο προϊόντα.

5
2. Θέμα δεύτερο: Διαχείριση βάσης δεδομένων αμερικανικών
εκλογών

Ανάλυση δεδομένων - Υλοποίηση - Χρήση γλώσσας SQL

Έστω απλουστευμένη βάση των αμερικανικών προεδρικών εκλογών.


Στο δείγμα παρατίθενται εκλογικά αποτελέσματα για τις αναμετρήσεις
από το 1952 έως το 1992.

YEAR WINNER W_VOTES W-PARTY W_STATE LOSER L_VOTES L_PARTY

1952 EISENHOWER 442 REP TEXAS STEVENSON 89 DEM

1956 EISENHOWER 447 REP TEXAS STEVENSON 73 DEM

1960 KENNEDY 303 DEM MASS. NIXON 219 REP

1964 JOHNSON 486 DEM TEXAS GOLDWATER 52 REP

1968 NIXON 301 REP CALIF. HUMPHREY 191 DEM

1968 NIXON 301 REP CALIF WALLACE 46 IND

1972 NIXON 520 REP CALIF. McGOVERN 17 DEM

1976 CARTER 297 DEM NULL FORD 240 DEM

1980 REAGAN 489 REP NULL CARTER 49 DEM

1980 REAGAN 489 REP NULL ANDERSON 0 IND

1984 REAGAN 525 REP NULL MONDALE 13 DEM

1988 BUSH 426 REP NULL DOUKAKIS 41 DEM

1992 CLINTON NULL DEM NULL BUSH NULL REP

1992 CLINTON NULL DEM NULL PERAULT NULL IND

REP=REPUBLICAN , DEM=DEMOCRAT , IND=INDEPENDENT

Η αναγραφή NULL σε μια θέση του πίνακα σημαίνει ότι το αντίστοιχο πεδίο δεν έχει
τιμή.

6
Γράφουμε περιορισμούς (constraints):
Year χαρακτηρίζει μοναδικά την εκλογική αναμέτρηση

year  winner, w-votes, w-party, w_state

Δηλαδή, το έτος χαρακτηρίζει μοναδικά κάποιες στήλες που


περιγράφουν την εκλογική αναμέτρηση. Αν σκεφτούμε το έτος μίας
εκλογικής αναμέτρησης τότε αυτομάτως έρχεται στο μυαλό μας
ακριβώς ένας νικητής, ο Πρόεδρος, ακριβώς ένα κόμμα, αυτό που
νίκησε στις εκλογές κτλ.

winner  w_party, w_state

Ο νικητής, ανήκει ισόβια ως υποψήφιος στο ίδιο κόμμα και ξεκινά από
την ίδια πολιτεία.

year, loser  l_votes

Στη συνέχεια παραθέτουμε τους τέσσερις (4) πίνακες στους οποίους επιμερίζονται
τα στοιχεία των εκλογών.

PRESIDENTS

WINNER W-PARTY W_STATE

EISENHOWER REP TEXAS

KENNEDY DEM MASS.

JOHNSON DEM TEXAS

NIXON REP CALIF.

CARTER DEM NULL

REAGAN REP NULL

BUSH REP NULL

CLINTON DEM NULL

7
LOSERS

LOSER L_PARTY

STEVENSON DEM

NIXON REP

GOLDWATER REP

HUMPHREY DEM

WALLACE IND

McGOVERN DEM

FORD DEM

CARTER DEM

ANDERSON IND

MONDALE DEM

DOUKAKIS DEM

BUSH REP

PERAULT IND

ELECTIONWINNER

YEAR WINNER W_VOTES

1952 EISENHOWER 442

1956 EISENHOWER 447

1960 KENNEDY 303

1964 JOHNSON 486

1968 NIXON 301

1972 NIXON 520

1976 CARTER 297

1980 REAGAN 489

1984 REAGAN 525

1988 BUSH 426

1992 CLINTON NULL

8
ELECTIONLOSER

YEAR LOSER L_VOTES

1952 STEVENSON 89

1956 STEVENSON 73

1960 NIXON 219

1964 GOLDWATER 52

1968 HUMPHREY 191

1968 WALLACE 46

1972 McGOVERN 17

1976 FORD 240

1980 CARTER 49

1980 ANDERSON 0

1984 MONDALE 13

1988 DOUKAKIS 41

1992 BUSH NULL

1992 PERAULT NULL

Η τρίτη κανονική μορφή – Ορισμός σε Oracle

CREATE TABLE presidents(winner VARCHAR2(15) NOT NULL,

w_party VARCHAR2(15), w_state VARCHAR2(15) );

CREATE TABLE losers(loser VARCHAR2(15) NOT NULL,

l_party VARCHAR2(15));

CREATE TABLE electionwinner(election_year VARCHAR2(4) NOT NULL,

winner VARCHAR2(15),w_votes NUMBER);

CREATE TABLE electionloser(election_year VARCHAR2(4) NOT NULL,

loser VARCHAR2(15) NOT NULL, l_votes NUMBER);

9
- Υλοποίηση
Θα δημιουργήσουμε τέσσερα (4) αρχεία (scripts) που θα περιλαμβάνουν SQL
εντολές:

Δημιουργίας των πινάκων της βάσης (αρχείο CREATE.SQL).

Διαγραφής των πινάκων της βάσης (αρχείο DROP.SQL).

Εισαγωγής στοιχείων στους πίνακες της βάσης (αρχείο INSERT.SQL).

Αναζήτησης στοιχείων από τους πίνακες βάσης (αρχείο SELECT.SQL).

Δημιουργία της βάσης

/* Πρόγραμμα δημιουργίας της βάσης. */

SQL> EDIT CREATE.SQL

Καλείται ο προκαθορισμένος screen editor του συστήματος και εκεί


πληκτρολογούμε τις τέσσερις SQL δηλώσεις δημιουργίας των πινάκων:

CREATE TABLE presidents(winner VARCHAR2(15) NOT NULL,

w_party VARCHAR2(15), w_state VARCHAR2(15) );

CREATE TABLE losers(loser VARCHAR2(15) NOT NULL,

l_party VARCHAR2(15));

CREATE TABLE electionwinner(election_year VARCHAR2(4) NOT NULL,

winner VARCHAR2(15),w_votes NUMBER);

CREATE TABLE electionloser(election_year VARCHAR2(4) NOT NULL,

loser VARCHAR2(15) NOT NULL, l_votes NUMBER);

Για να εκτελέσουμε το πρόγραμμα πληκτρολογούμε την παρακάτω


εντολή.

SQL> @CREATE.SQL

10
Εισαγωγή στοιχείων στους πίνακες
/* Εντολές εισαγωγής στοιχείων */

SQL> EDIT INSERT.SQL

INSERT INTO presidents VALUES


('EISENHOWER','REPUBLICAN','TEXAS');

INSERT INTO losers VALUES('STEVENSON','DEMOCRAT');

INSERT INTO electionwinner


VALUES('1952','EISENHOWER',442);

INSERT INTO electionwinner


VALUES('1956','EISENHOWER',447);

INSERT INTO electionloser VALUES('1952','STEVENSON',89);

INSERT INTO electionloser VALUES('1956','STEVENSON',73);

………

/* τέλος εντολών */

Για να εκτελέσουμε το πρόγραμμα πληκτρολογούμε την παρακάτω


εντολή.

SQL> @INSERT.SQL

Αναζητήσεις (queries)

SQL> EDIT SELECT.SQL

SELECT winner,w_party,w_state

FROM presidents

WHERE w_party = “REPUBLICAN”;

κ.λπ.

11
Για να εκτελέσουμε το πρόγραμμα πληκτρολογούμε την παρακάτω
εντολή.

SQL> @SELECT.SQL

Διαγραφή πινάκων
/* Εντολές διαγραφής πινάκων */

SQL> EDIT DROP.SQL

DROP TABLE presidents;

DROP TABLE losers;

DROP TABLE electionwinner;

DROP TABLE electionloser;

/* τέλος εντολών */

Για να εκτελέσουμε το πρόγραμμα πληκτρολογούμε την


παρακάτω εντολή.

SQL> @DROP.SQL

Δοκιμάστε τα παρακάτω παραδείγματα αναζήτησης στοιχείων (SELECT)

Αναζήτηση στοιχείων
/* Δείξτε όλα τα στοιχεία προέδρων */

SELECT *

FROM presidents;

/* Δείξτε όλα τα στοιχεία προέδρων με άλλη σειρά */

SELECT w_party, winner, w_state

FROM presidents;

12
/* Δείξτε τα ονόματα των προέδρων από τον πίνακα electionwinner μία φορά */

SELECT distinct winner

FROM electionwinner;

/* Δείξτε όλα τα στοιχεία προέδρων ανά κόμμα και αλφαβητικά */

SELECT *

FROM presidents

order by w_party, winner;

/* Δείξτε όλα τα στοιχεία προέδρων που ανήκουν στο κόμμα των ρεπουμπλικάνων
*/

SELECT *

FROM presidents

WHERE w_party = 'REPUBLICAN';

/* Δείξτε όλα τα στοιχεία προέδρων που ανήκουν στο κόμμα των ρεπουμπλικάνων
με άλλη σειρά */

SELECT w_party,w_state, winner

FROM presidents

WHERE w_party = 'REPUBLICAN';

SELECT winner, w_state, w_party

FROM presidents

WHERE w_party = 'REPUBLICAN';

SELECT winner,w_party,w_state

13
FROM presidents

WHERE w_party = 'REPUBLICAN';

/* τι θα δείξουν οι αναζητήσεις; */

SELECT winner, w_party, w_state

FROM presidents

WHERE w_party = 'REP';

SELECT winner, w_party, w_state

FROM presidents

WHERE w_party = 'RepUBLICAN';

SELECT winner, w_party, w_state

FROM presidents

WHERE w_party = 'republican';

SELECT winner,w_party,w_state

FROM presidents

WHERE w_state = 'REPUBLICAN';

/* Δείξτε στοιχεία για τον NIXON */

SELECT winner, w_party, w_state

FROM presidents

WHERE winner = 'NIXON';

14
/* Δείξτε υποψήφιους που έχασαν με ψήφους λιγότερους των 80 */

SELECT loser, election_year , l_votes

FROM electionloser

where l_votes <80;

/* Δείξτε υποψήφιους που έχασαν στις εκλογές πάνω απο μία φορά */

SELECT loser, count(*)

FROM electionloser

GROUP BY loser

HAVING count(*) > 1;

/* Δείξτε όλα τα στοιχεία των εκλογών για κάθε έτος εκλογικής αναμέτρησης */

SELECT electionwinner.election_year, presidents.winner,

w_party, w_votes,

electionloser.loser, l_party, l_votes

FROM presidents, electionwinner, electionloser, losers

WHERE presidents.winner = electionwinner.winner

AND electionwinner.election_year = electionloser.election_year

AND electionloser.loser = losers.loser

order by electionwinner.election_year;

15
Άσκηση 1
Να υλοποιήσετε τη βάση δεδομένων με χρήση του προϊόντος mySQL. Στη συνέχεια
να κάνετε τα παρακάτω και για τις δύο υλοποιήσεις (Oracle, mySQL):

- Να καταργήσετε τους πίνακες. Να ορίσετε τους πίνακες χωρίς κύρια και ξένα
κλειδιά. Να προσθέσετε περιορισμούς (δείτε Εργαστήριο δεύτερο). Να
εισάγετε τις γραμμές των πινάκων.

Άσκηση 2
Δημιουργήστε το μοντέλο κατά προτίμηση με το εργαλείο mySQL Workbennch.

Άσκηση 3
Αναφέρατε διαφορές για την υλοποίηση στα δύο προϊόντα.

16
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 4: Δημιουργία βάσης δεδομένων και διαχείριση της βάσης με χρήση
εναυσμάτων (triggers). Διαφορές στην υλοποίηση στην περίπτωση των προϊόντων
mySQL και Oracle.

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Yλοποίηση Βάσης με τη χρήση του προϊόντος SQL...................................................... 3
Άσκηση.............................................................................................................................. 7

Στόχος του τέταρτου εργαστηρίου είναι η κατανόηση της τεχνολογίας διαχείριση της
βάσης με χρήση triggers. Μετά την επεξεργασία του εργαστηρίου ο
ενδιαφερόμενος θα έχει κατανοήσει και θα έχει εμπεδώσει τον τρόπο χρήσης
αντιπροσωπευτικών triggers για τις εμπορικές εφαρμογές.
Τέλος, ο ενδιαφερόμενος θα εμπεδώσει διαφορές στην υλοποίηση στην περίπτωση
των προϊόντων mySQL και Oracle. Επιπλέον, μάθει πως βλέπουμε πληροφορίες για
τη βάση δεδομένων, τους triggers κ.λπ. στο προϊόν της mySQL

Λέξεις κλειδιά: trigger, mySQL, Oracle

2
1. Υλοποίηση Βάσης με τη χρήση του προϊόντος SQL

Έστω απλοποιημένη βάση δεδομένων διαχείρισης παραγγελιών που περιλαμβάνει


τους τέσσερις παρακάτω πίνακες:

Υλοποίηση με χρήση του προϊόντος mySQL


Κατασκευάζουμε αρχικά τη βάση δεδομένων και τους πίνακες.
DROP DATABASE IF EXISTS myorders;
CREATE DATABASE myorders;
USE myorders;

DROP TABLE IF EXISTS customers;


CREATE TABLE customers(custno INT, cname VARCHAR(255) NOT NULL,
loc VARCHAR(255), PRIMARY KEY (custno) );

DROP TABLE IF EXISTS stocks;


CREATE TABLE stocks(stockno INT, description VARCHAR(255) NOT NULL,
list_price DECIMAL(5,2) NOT NULL, PRIMARY KEY (stockno));

DROP TABLE IF EXISTS orders;


CREATE TABLE orders(orderno INT AUTO_INCREMENT, custno INT NOT NULL,
odate DATETIME NOT NULL, total DECIMAL(5,2),
UNIQUE(custno, odate),
PRIMARY KEY (orderno) );

3
DROP TABLE IF EXISTS orderlines;
CREATE TABLE orderlines(orderno INT, stockno INT, qty INT NOT NULL,
ptotal DECIMAL(5,2), PRIMARY KEY (orderno, stockno));

SHOW TABLES;
DESCRIBE customers;
DESCRIBE stocks;
DESCRIBE orders;
DESCRIBE orderlines;

Ο trigger orders_trig είναι αποθηκευμένος (stored) και εκτελείται πριν από την
εισαγωγή των γραμμών του πίνακα orders. Εισάγει αυτόματα την ημερομηνία και
ώρα της νέας παραγγελίας.

DROP TRIGGER IF EXISTS orders_trig;


CREATE TRIGGER orders_trig
BEFORE INSERT ON orders

4
FOR EACH ROW
SET NEW.odate = NOW();

Ο trigger orderlines_trig_ins είναι αποθηκευμένος (stored) και εκτελείται πριν από


την εισαγωγή των γραμμών του πίνακα orderlines για να υπολογίσει το μερικό
σύνολο της παραγγελίας.

DROP TRIGGER IF EXISTS orderlines_trig_ins;


CREATE TRIGGER orderlines_trig_ins
BEFORE INSERT ON orderlines
FOR EACH ROW
SET NEW.ptotal = (SELECT list_price
FROM stocks
WHERE stockno=NEW.stockno) * NEW.qty;

Ο trigger orderlines_trig_upd είναι αποθηκευμένος (stored) και εκτελείται πριν από


την ενημέρωση των γραμμών του πίνακα orderlines για να υπολογίσει το μερικό
σύνολο της παραγγελίας.
Δρ. Σκουρλάς Χρήστος Τσολακίδης Αναστάσιος
DROP TRIGGER IF EXISTS orderlines_trig_upd;
CREATE TRIGGER orderlines_trig_upd
BEFORE UPDATE ON orderlines
FOR EACH ROW
SET NEW.ptotal = (SELECT list_price
FROM stocks
WHERE stockno=NEW.stockno) * NEW.qty;

Ο trigger orderlines_total_ins είναι αποθηκευμένος (stored) και εκτελείται μετά από


την εισαγωγή των γραμμών του πίνακα orderlines για να υπολογίσει το συνολικό
ποσό της παραγγελίας.
DROP TRIGGER IF EXISTS orderlines_total_ins;
CREATE TRIGGER orderlines_total_ins
AFTER INSERT ON orderlines
FOR EACH ROW
UPDATE orders SET total = (SELECT SUM(ptotal)
FROM orderlines
WHERE orderno=NEW.orderno)
WHERE orderno = NEW.orderno;

Ο trigger orderlines_total_upd είναι αποθηκευμένος (stored) και εκτελείται μετά


από την ενημέρωση των γραμμών του πίνακα orderlines για να υπολογίσει το
συνολικό ποσό της παραγγελίας.
DROP TRIGGER IF EXISTS orderlines_total_upd;
CREATE TRIGGER orderlines_total_upd
AFTER UPDATE ON orderlines
FOR EACH ROW
UPDATE orders SET total = (SELECT SUM(ptotal)
FROM orderlines
WHERE orderno=NEW.orderno)
WHERE orderno = NEW.orderno;

5
Ακολουθούν δοκιμές.
INSERT INTO customers(custno, cname, loc) VALUES(1, 'SMITH', 'ATHENS');
INSERT INTO customers(custno, cname, loc) VALUES(2, 'JONES', 'VOLOS');
INSERT INTO customers(custno, cname, loc) VALUES(3, 'BATES', 'NEW YORK');

INSERT INTO stocks(stockno, description, list_price) VALUES(1, 'APPLE', 1);


INSERT INTO stocks(stockno, description, list_price) VALUES(2, 'ORANGE', 1.5);
INSERT INTO stocks(stockno, description, list_price) VALUES(3, 'LEMON', 1.7);

INSERT INTO orders(custno, odate) VALUES (1, current_date);


INSERT INTO orderlines(orderno, stockno, qty) VALUES (1, 1, 10);
INSERT INTO orderlines(orderno, stockno, qty) VALUES (1, 2, 5);

Βλέπουμε τα στοιχεία.
SELECT * FROM customers;
SELECT * FROM stocks;
SELECT * FROM orders;
SELECT * FROM orderlines;

Προσοχή! Πρέπει η μηχανή που θα χρησιμοποιήσετε να είναι η InnoDB


(DEFAULT ENGINE=InnoDB)

6
Άσκηση
Να υλοποιήσετε triggers χρησιμοποιώντας το προϊόν της Oracle. Επισημάνετε
διαφορές με το προϊόν της mySQL.

Πως θα δούμε πληροφορίες για τη βάση δεδομένων, τους triggers


κ.λπ. στο προϊόν της mySQL

Να και μία ενδιαφέρουσα βάση δεδομένων, η βάση information_schema με πολλές


πληροφορίες για τη βάση δεδομένων που κατασκευάσαμε και άλλες βάσεις..

Τη χρησιμοποιούμε και βλέπουμε τους πίνακές της.

Να οι στήλες του πίνακα triggers

7
Κάποια στοιχεία για τους triggers που ορίσαμε

Να στοιχεία και για συγκεκριμένο trigger

8
Ξαναγυρίζουμε στη βάση που δημιουργήσαμε και βλέπουμε τους triggers

Use myorders;
Select * from information_schema.triggers\G

9
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 5: Χρήση stored procedures: cursors, functions, procedures, triggers

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Δημιουργία βάσης δεδομένων training .......................................................................... 3
2. Παράδειγμα χρήσης Cursor .............................................................................................. 3
3. Ορισμός συνάρτησης για τη διαχείριση Cursor ............................................................... 5
4. Ορισμός triggers για την «αυτόματη» διαχείριση στοιχείων της βάσης ......................... 7
5. Ορισμός trigger για τη διαχείριση τιμής στήλης (salary) ................................................. 8
6. Ορισμός trigger για τη διαχείριση τιμής στήλης (course_name)................................... 11
7. Δοκιμή ορισμού δύο (2) εναυσμάτων (triggers) με την ίδια συνθήκη ενεργοποίησης 13
8. Πως θα διορθώσουμε το πρόβλημα που προέκυψε κατά τη δοκιμή ορισμού δύο (2)
triggers με την ίδια συνθήκη ενεργοποίησης ......................................................................... 15
9. Ορισμός trigger για την αυτόματη εισαγωγή στοιχείων σε πίνακα audit ..................... 17

Στόχος του πέμπτου εργαστηρίου είναι η κατανόηση σε βάθος της τεχνολογίας


διαχείριση της βάσης με χρήση stored procedures:. Ειδικότερα εξετάζονται θέματα
υλοποίησης με: cursors, procedures, functions, triggers. Μετά την επεξεργασία του
εργαστηρίου ο ενδιαφερόμενος θα έχει κατανοήσει και θα έχει εμπεδώσει τον
τρόπο χρήσης stored procedures: cursors, procedures, functions, triggers.

Λέξεις Κλειδιά: stored procedures, cursors, functions, procedures, triggers

2
1. Δημιουργία βάσης δεδομένων training

Η βάση δεδομένων δε βρίσκεται στην Τρίτη Κανονική Μορφή

Lecturer

Lecturer Lecturer_surname Lecturer_name City salary Course Course


_id _id _name

TABLE course(course_id int, course_name varchar(50))

Course

Course_id course_name

Άσκηση

Ανασχεδιάστε τη βάση στην Τρίτη Κανονική Μορφή.

2. Παράδειγμα χρήσης Cursor

Δημιουργία βάσης δεδομένων και πινάκων

Drop database training;

CREATE DATABASE training;

USE training;

CREATE TABLE lecturer(lecturer_id int(3),

lecturer_surname varchar(15), lecturer_name varchar(15),

city varchar(15), salary decimal (8,2), course_id int, course_name varchar(15));

CREATE TABLE course(course_id int, course_name varchar(50));

3
Εισαγωγή στοιχείων

INSERT INTO course VALUES (1, 'DATABASE');

INSERT INTO course VALUES (2, 'WEB DEVELOPMENT');

INSERT INTO course VALUES (3, 'DATA MINING');

INSERT INTO course VALUES (4, 'SEMANTIC WEB');

Select * From COURSE;

INSERT INTO lecturer(lecturer_id, lecturer_name, lecturer_surname, city, salary,


course_id) VALUES (1, 'CHRIS', 'DATE', 'LONDON', 2000, 1), (2, 'GIO', 'WIEDERHOLD',
'ATHENS', 1500, 1), (3, 'PETER', 'CHEN', 'ATHENS', 3500, 2), (4, 'JEFF', 'ULLMAN', 'ATHENS',
1700, 1), (5, 'TED', 'CODD', 'ATHENS', 2500, 2);

SELECT * FROM LECTURER;

SELECT lecturer_id, lecturer_surname, lecturer_name, course_id, course_name

FROM lecturer;

4
3. Ορισμός συνάρτησης για τη διαχείριση Cursor

Παρατηρήστε στη συνέχεια τις εντολές:

- Declare variables
- DECLARE CONTINUE HANDLER
- Open Cursor
- Fetch Cursor
- Close Cursor

DELIMITER //
CREATE FUNCTION lecturer_list() RETURNS VARCHAR(255)
BEGIN
DECLARE record_not_found INTEGER DEFAULT 0;
DECLARE lecturer_name_var VARCHAR(150) DEFAULT "";
DECLARE lecturer_surname_var VARCHAR(150) DEFAULT "";
DECLARE lect_list VARCHAR(255) DEFAULT "";
DECLARE my_cursor CURSOR FOR SELECT lecturer_name, lecturer_surname
FROM lecturer;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET record_not_found =

5
1; OPEN my_cursor;
allLecturers: LOOP
FETCH my_cursor INTO lecturer_name_var, lecturer_surname_var;
IF record_not_found THEN
LEAVE allLecturers;
END IF;
SET lect_list = CONCAT(lect_list, lecturer_surname_var, ", ");
END LOOP allLecturers;
CLOSE my_cursor;
RETURN SUBSTR(lect_list, 1, 70);
END //

DELIMITER ;

Χρήση της συνάρτησης

SELECT lecturer_list();

6
Κατάργηση της συνάρτησης

DROP FUNCTION lecturer_list;

4. Ορισμός triggers για την «αυτόματη» διαχείριση στοιχείων


της βάσης

Να η εικόνα της βάσης χωρίς triggers

Select * From COURSE;

SELECT lecturer_id, lecturer_surname, lecturer_name, course_id, course_name

FROM lecturer;

7
Πως ορίζεται η βάση δεδομένων, οι πίνακές της.

Drop database training;

CREATE DATABASE training;

USE training;

CREATE TABLE lecturer(lecturer_id int(3),

lecturer_surname varchar(15), lecturer_name varchar(15),

city varchar(15), salary decimal (8,2), course_id int, course_name varchar(15));

CREATE TABLE course(course_id int, course_name varchar(50));

5. Ορισμός trigger για τη διαχείριση τιμής στήλης (salary)

drop trigger bi_lecturer;

DELIMITER //

create trigger bi_lecturer before insert on lecturer for each row

Begin

declare name_l int;

set name_l = length(new.lecturer_name);

set new.salary = new.salary + (new.salary * name_l)/10;

end;

//

DELIMITER ;

8
Εισαγωγή στοιχείων. Επηρεάζεται από τον trigger

INSERT INTO course VALUES (1, 'DATABASE');

INSERT INTO course VALUES (2, 'WEB DEVELOPMENT');

INSERT INTO course VALUES (3, 'DATA MINING');

INSERT INTO course VALUES (4, 'SEMANTIC WEB');

Select * From COURSE;

INSERT INTO lecturer(lecturer_id, lecturer_name, lecturer_surname, city, salary,


course_id) VALUES (1, 'CHRIS', 'DATE', 'LONDON', 2000, 1), (2, 'GIO', 'WIEDERHOLD',
'ATHENS', 1500, 1), (3, 'PETER', 'CHEN', 'ATHENS', 3500, 2), (4, 'JEFF', 'ULLMAN', 'ATHENS',
1700, 1), (5, 'TED', 'CODD', 'ATHENS', 2500, 2);

Δείτε τις τιμές της στήλης salary

SELECT lecturer_id, lecturer_surname, lecturer_name, salary, course_id

FROM lecturer;

9
Δείτε τις τιμές της στήλης course_name

SELECT lecturer_id, lecturer_surname, lecturer_name, course_id, course_name

FROM lecturer;

10
6. Ορισμός trigger για τη διαχείριση τιμής στήλης
(course_name)

Drop database training;

CREATE DATABASE training;

USE training;

CREATE TABLE lecturer(lecturer_id int(3),

lecturer_surname varchar(15), lecturer_name varchar(15),

city varchar(15), salary decimal (8,2), course_id int, course_name varchar(15));

CREATE TABLE course(course_id int, course_name varchar(50));

Drop trigger bi_lect_add_dname;

DELIMITER //

create trigger bi_lect_add_dname

before insert on lecturer

for each row

begin

declare dname_var varchar(40);

select course_name into dname_var from course where course_id = new.course_id;

set new.course_name = dname_var;

end;

//

DELIMITER ;

INSERT INTO course VALUES (1, 'DATABASE');

INSERT INTO course VALUES (2, 'WEB DEVELOPMENT');

INSERT INTO course VALUES (3, 'DATA MINING');

INSERT INTO course VALUES (4, 'SEMANTIC WEB');

11
Select * From COURSE;

INSERT INTO lecturer(lecturer_id, lecturer_name, lecturer_surname, city, salary,


course_id) VALUES (1, 'CHRIS', 'DATE', 'LONDON', 2000, 1), (2, 'GIO', 'WIEDERHOLD',
'ATHENS', 1500, 1), (3, 'PETER', 'CHEN', 'ATHENS', 3500, 2), (4, 'JEFF', 'ULLMAN', 'ATHENS',
1700, 1), (5, 'TED', 'CODD', 'ATHENS', 2500, 2);

Να το αποτέλεσμα της εκτέλεσης του trigger κατά την εισαγωγή στοιχείων στον
πίνακα lecturer

SELECT lecturer_id, lecturer_surname, lecturer_name, course_id, course_name

FROM lecturer;

12
7. Δοκιμή ορισμού δύο (2) εναυσμάτων (triggers) με την ίδια
συνθήκη ενεργοποίησης

Drop database training;

CREATE DATABASE training;

USE training;

CREATE TABLE lecturer(lecturer_id int(3),

lecturer_surname varchar(15), lecturer_name varchar(15),

city varchar(15), salary decimal (8,2), course_id int, course_name varchar(15));

CREATE TABLE course(course_id int, course_name varchar(50));

drop trigger bi_lecturer;

DELIMITER //

create trigger bi_lecturer before insert on lecturer for each row

Begin

declare name_l int;

set name_l = length(new.lecturer_name);

set new.salary = new.salary + (new.salary * name_l)/10;

end;

//

DELIMITER ;

DELIMITER //

create trigger bi_stud_add_dname

before insert on lecturer

for each row

begin

declare dnamev varchar(40);

13
select course_name into dnamev from course where course_id = new.course_id;

set new.course_name = dnamev;

end;

//

DELIMITER ;

INSERT INTO course VALUES (1, 'DATABASE');

INSERT INTO course VALUES (2, 'WEB DEVELOPMENT');

INSERT INTO course VALUES (3, 'DATA MINING');

INSERT INTO course VALUES (4, 'SEMANTIC WEB');

Select * From COURSE;

INSERT INTO lecturer(lecturer_id, lecturer_name, lecturer_surname, city, salary,


course_id) VALUES (1, 'CHRIS', 'DATE', 'LONDON', 2000, 1), (2, 'GIO', 'WIEDERHOLD',
'ATHENS', 1500, 1), (3, 'PETER', 'CHEN', 'ATHENS', 3500, 2), (4, 'JEFF', 'ULLMAN', 'ATHENS',
1700, 1), (5, 'TED', 'CODD', 'ATHENS', 2500, 2);

SELECT lecturer_id, lecturer_surname, lecturer_name, course_id, course_name

FROM lecturer;

Μήνυμα που επιστρέφεται

14
8. Πως θα διορθώσουμε το πρόβλημα που προέκυψε κατά τη
δοκιμή ορισμού δύο (2) triggers με την ίδια συνθήκη
ενεργοποίησης

Drop database training;

CREATE DATABASE training;

USE training;

CREATE TABLE lecturer(lecturer_id int(3),

lecturer_surname varchar(15), lecturer_name varchar(15),

city varchar(15), salary decimal (8,2), course_id int, course_name varchar(15));

CREATE TABLE course(course_id int, course_name varchar(50));

drop trigger bi_lecturer;

DELIMITER //

create trigger bi_lecturer before insert on lecturer for each row

Begin

declare name_length int;

declare dname_var varchar(40);

select course_name into dname_var from course where course_id = new.course_id;

set new.course_name = dname_var;

set name_length = length(new.lecturer_name);

set new.salary = new.salary + (new.salary * name_length)/10;

15
end;

//

DELIMITER ;

INSERT INTO course VALUES (1, 'DATABASE');

INSERT INTO course VALUES (2, 'WEB DEVELOPMENT');

INSERT INTO course VALUES (3, 'DATA MINING');

INSERT INTO course VALUES (4, 'SEMANTIC WEB');

Select * From COURSE;

INSERT INTO lecturer(lecturer_id, lecturer_name, lecturer_surname, city, salary,


course_id) VALUES (1, 'CHRIS', 'DATE', 'LONDON', 2000, 1), (2, 'GIO', 'WIEDERHOLD',
'ATHENS', 1500, 1), (3, 'PETER', 'CHEN', 'ATHENS', 3500, 2), (4, 'JEFF', 'ULLMAN', 'ATHENS',
1700, 1), (5, 'TED', 'CODD', 'ATHENS', 2500, 2);

Να τι βλέπουμε

SELECT lecturer_surname, lecturer_name, salary, course_id, course_name

FROM lecturer;

16
9. Ορισμός trigger για την αυτόματη εισαγωγή στοιχείων σε
πίνακα audit

Drop database training;

CREATE DATABASE training;

USE training;

CREATE TABLE lecturer(lecturer_id int(3),

lecturer_surname varchar(15), lecturer_name varchar(15),

city varchar(15), salary decimal (8,2), course_id int, course_name varchar(15));

CREATE TABLE course(course_id int, course_name varchar(50));

DELIMITER //

create table audit (user_name varchar(30), table_name varchar(30), update_date date);

create trigger bi_lecturer_audit before insert on lecturer for each row

begin

insert into audit (user_name, table_name, update_date) values


(current_user(),'lecturer', now());

end;

//

DELIMITER ;

INSERT INTO course VALUES (1, 'DATABASE');

INSERT INTO course VALUES (2, 'WEB DEVELOPMENT');

INSERT INTO course VALUES (3, 'DATA MINING');

INSERT INTO course VALUES (4, 'SEMANTIC WEB');

Select * From COURSE;

INSERT INTO lecturer(lecturer_id, lecturer_name, lecturer_surname, city, salary,


course_id) VALUES (1, 'CHRIS', 'DATE', 'LONDON', 2000, 1), (2, 'GIO', 'WIEDERHOLD',
'ATHENS', 1500, 1), (3, 'PETER', 'CHEN', 'ATHENS', 3500, 2), (4, 'JEFF', 'ULLMAN', 'ATHENS',
1700, 1), (5, 'TED', 'CODD', 'ATHENS', 2500, 2);

17
SELECT lecturer_surname, lecturer_name, salary, course_id, course_name

FROM lecturer;

Select * from audit;

18
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 6: Διαχείριση δοσοληψιών στο προϊόν mySQL

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα

1.Δημιουργία βάσης δεδομένων training ........................................................................ 3


Άσκηση.............................................................................................................................. 3
Ορισμός συνάρτησης για τη διαχείριση Cursor ............................................................... 5
Ορισμός triggers για την «αυτόματη» διαχείριση στοιχείων της βάσης ......................... 7
Ορισμός trigger για τη διαχείριση τιμής στήλης (salary) ................................................. 8
Δοκιμή ορισμού δύο (2) εναυσμάτων (triggers) με την ίδια συνθήκη ενεργοποίησης 12
Πως θα διορθώσουμε το πρόβλημα που προέκυψε κατά τη δοκιμή ορισμού δύο (2)
triggers με την ίδια συνθήκη ενεργοποίησης ................................................................ 14
Ορισμός trigger για την αυτόματη εισαγωγή στοιχείων σε πίνακα audit ..................... 16

Στόχος του έκτου εργαστηρίου είναι η κατανόηση σε βάθος της διαχείρισης


δοσοληψιών. Μετά την επεξεργασία του εργαστηρίου ο ενδιαφερόμενος θα έχει
κατανοήσει και θα έχει εμπεδώσει τον τρόπο διαχείριση δοσοληψιών στο προϊόν
mySQL.

Λέξεις Κλειδιά: Transactions, Transaction processing, mySQL

2
1. Διαχείριση δοσοληψιών στο προϊόν mySQL

Προσοχή το προϊόν της mySQL λειτουργεί όταν συνδεθούμε σε AUTOCOMMIT


mode.

DROP DATABASE TestDB;


CREATE DATABASE TestDB;
use TestDB;
CREATE TABLE T (id INT NOT NULL PRIMARY KEY, s VARCHAR(30), si
SMALLINT);
DESCRIBE T;
INSERT INTO T (id, s) VALUES (1, 'first');
INSERT INTO T (id, s) VALUES (2, 'second');
INSERT INTO T (id, s) VALUES (3, 'third');
SELECT * FROM T;
ROLLBACK;
SELECT * FROM T;

3
Να πως ξεκινάμε και εκτελούμε transaction

START TRANSACTION;
INSERT INTO T (id, s) VALUES (4, 'fourth');
SELECT * FROM T ;
ROLLBACK;
SELECT * FROM T;

Προσοχή! Με την εντολή ROLLBACK ολοκληρώθηκε η TRANSACTION και το προϊόν


της mySQL λειτουργεί και πάλι σε AUTOCOMMIT mode.

4
INSERT INTO T (id, s) VALUES (5, 'fifth');
ROLLBACK;
SELECT * FROM T;

Διαγράψτε τις γραμμές 2. 3. 4 του πίνακα

DELETE FROM T WHERE id > 1;

Switch off the AUTOCOMMIT mode

SET AUTOCOMMIT=0;

Τώρα λειτουργεί σωστά κάθε transaction όπως μπορείτε να διαπιστώσετε.

INSERT INTO T (id, s) VALUES (2, 'second');


INSERT INTO T (id, s) VALUES (3, 'third');
SELECT * FROM T;
ROLLBACK;
SELECT * FROM T;
INSERT INTO T (id, s) VALUES (5, 'fifth');
ROLLBACK;
SELECT * FROM T;

5
Είναι γνωστές οι εντολές της Data Definition Language (DDL): “CREATE
TABLE…”, “CREATE INDEX…”, “DROP TABLE …” κ.λ.π.
Είναι γνωστές επίσης οι εντολές της Data Manipulation Language (DML): “SELECT
FROM…”, “INSERT INTO…”, “DELETE FROM…”. Επηρεάζουν αυτές οι εντολές
την εντολή ROLLBACK;

INSERT INTO T (id, s) VALUES (9, 'will this be committed?');


CREATE TABLE T2 (id INT);
INSERT INTO T2 (id) VALUES (1);
SELECT * FROM T2;
ROLLBACK;
SELECT * FROM T; -- What has happened to T ?
SELECT * FROM T2; -- What has happened to T2 ?
SELECT * FROM T3; -- Oops!
SHOW TABLES;

6
Τι συμπέρασμα βγάλατε;

Επαναφέρετε το αρχικό περιεχόμενο του πίνακα

DELETE FROM T WHERE id > 1;


COMMIT;
SELECT * FROM T;
COMMIT;

Να κάνετε έλεγχο αν ένα σφάλμα (error) σε εντολή SQL οδηγεί ή όχι σε αυτόματο
ROLLBACK στο προϊόν της MySQL. Εκτελέστε τις εντολές στη συνέχεια.

7
INSERT INTO T (id, s) VALUES (2, 'Error test starts here');
-- division by zero should fail
SELECT (1/0) AS dummy FROM DUAL;
-- Now update a non-existing row
UPDATE T SET s = 'foo' WHERE id = 9999 ;
-- and delete an non-existing row
DELETE FROM T WHERE id = 7777 ;
--
INSERT INTO T (id, s) VALUES (2, 'Hi, I am a duplicate');
INSERT INTO T (id, s)
VALUES (3, 'How about inserting too long of a string value?');
INSERT INTO T (id, s, si) VALUES (4, 'Smallint overflow for 32769?', 32769);
INSERT INTO T (id, s) VALUES (5, 'Transaction still active?');
SELECT * FROM T;
COMMIT;
DELETE FROM T WHERE id > 1;
SELECT * FROM T;

8
COMMIT;

ΠΡΟΣΟΧΉ! Η τιμή σφάλματος “23000” είναι η τιμή του SQLSTATE που ορίζεται
στο standard και η τιμή 1062 είναι η τιμή του αντίστοιχου κώδικα σφάλματος του
προϊόντος της MySQL. Συνδέεται με παραβίαση περιορισμού κύριου κλειδιού
(violation of the primary key constraint).

Το προϊόν της MySQL δεν υποστηρίζει CHECK constraints

CREATE TABLE Accounts (


acctID INTEGER NOT NULL PRIMARY KEY,
balance INTEGER NOT NULL,
CONSTRAINT unloanable_account CHECK (balance >= 0)
);
INSERT INTO Accounts (acctID,balance) VALUES (101,1000);
INSERT INTO Accounts (acctID,balance) VALUES (202,2000);
SELECT * FROM Accounts;
COMMIT;
-- let's try the bank transfer
UPDATE Accounts SET balance = balance - 100 WHERE acctID = 101;
UPDATE Accounts SET balance = balance + 100 WHERE acctID = 202;
SELECT * FROM Accounts;
ROLLBACK;
-- Let's test the CHECK constraint actually work:
UPDATE Accounts SET balance = balance - 2000 WHERE acctID = 101;
UPDATE Accounts SET balance = balance + 2000 WHERE acctID = 202;
SELECT * FROM Accounts ;
ROLLBACK;

9
Δοκιμάστε SQL transaction για τη μεταφορά 500 euros από το λογαριασμό 101 σε
ανύπαρκτο λογαριασμό πχ στον acctID=777:
UPDATE Accounts SET balance = balance - 500 WHERE acctID = 101;
UPDATE Accounts SET balance = balance + 500 WHERE acctID = 777;
SELECT * FROM Accounts ;
ROLLBACK;

10
SQL Transaction: Unit of Recovery

Κλείστε βίαια το (client) session για να προσομοιώσετε μία κατάσταση “DBMS


crash”.

Ανοίξτε ένα νέο terminal window (νέα MySQL session) και δείτε τι έγινε.

USE TestDB;
SET AUTOCOMMIT=0;
SELECT * FROM T;
COMMIT;

Ολοκληρώστε τον έλεγχο

11
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 7: Διαχείριση δοσοληψιών στο προϊόν mySQL – Επίπεδα απομόνωσης
(Transactions – Isolation levels)

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Διαχείριση δοσοληψιών στο προϊόν mySQL – Επίπεδα απομόνωσης (Transactions –
Isolation levels) .......................................................................................................................... 3
1.1 Θέμα 1: Προσομοίωση «Τυφλής αντικατάστασης» (Blind Overwriting) ................ 4
1.2 Θέμα 2: Επανάλαβε το Θέμα 1 χρησιμοποιώντας απευθείας “sensitive updates”
χωρίς να χρησιμοποιήσεις τοπικές μεταβλητές -using “sensitive updates” in SELECT-
UPDATE scenarios without local variables-........................................................................... 7
1.3 Θέμα 3: Διατήρηση των S-κλειδαριών(S-locks, Shared Locks) ................................ 9
1.4 Θέμα 4: Επανάληψη με χρήση isolation level REPEATABLE READ......................... 13
1.5 Θέμα 5: Ανταγωνισμός σε δύο “resources” με διαφορετική σειρά ...................... 17
1.6 Θέμα 6: Απόπειρα εμφάνισης dirty read ................................................................ 19
1.7 Θέμα 7: The non-repeatable read anomaly ............................................................ 22
Άσκηση............................................................................................................................ 24
1.8 Θέμα 8: Απόπειρα εμφάνισης insert phantom .................................................... 25

Στόχος του όγδοου εργαστηρίου είναι η κατανόηση σε βάθος της διαχείρισης


δοσοληψιών και ειδικότερα των επιπέδων απομόνωσης. Μετά την επεξεργασία του
εργαστηρίου ο ενδιαφερόμενος θα έχει κατανοήσει και θα έχει εμπεδώσει τον
τρόπο διαχείρισης επιπέδων απομόνωσης στο προϊόν mySQL.

Λέξεις Κλειδιά: Transactions, Transactions processing, Isolation levels, mySQL

2
1. Διαχείριση δοσοληψιών στο προϊόν mySQL – Επίπεδα
απομόνωσης (Transactions – Isolation levels)

Προσοχή το προϊόν της mySQL λειτουργεί όταν συνδεθούμε σε AUTOCOMMIT


mode.

DROP DATABASE IF EXISTS TestDB;

CREATE DATABASE TestDB;

use TestDB;

Το προκαθορισμένο (default) isolation level στη MySQL είναι το REPEATABLE READ:

SELECT @@GLOBAL.tx_isolation, @@tx_isolation;

Αρχικοποίηση του πίνακα Accounts table

USE TestDB;

DROP TABLE IF EXISTS Accounts;

CREATE TABLE Accounts (

acctID INTEGER NOT NULL PRIMARY KEY,

balance INTEGER NOT NULL,

CONSTRAINT remains_nonnegative CHECK (balance >= 0)

);

INSERT INTO Accounts (acctID,balance) VALUES (101,1000);

INSERT INTO Accounts (acctID,balance) VALUES (202,2000);

SELECT * FROM Accounts;

COMMIT;

3
1.1 Θέμα 1: Προσομοίωση «Τυφλής αντικατάστασης» (Blind
Overwriting)

Σημείωση:

Στο βήμα 4 θυμηθείτε ότι το χρονικό όριο της προκαθορισμένης κλειδαριάς στο
προϊόν της MySQL (MySQL’s default lock timeout) είναι 90 seconds. Επομένως, η
συναλλαγή Α - transaction (client)- πρέπει να προχωρήσει χωρίς καθυστέρηση στο
βήμα 5 αμέσως μετά το βήμα 4 της συναλλαγής Β.

Blind Overwriting problem, application simulated by use of local variables

Ste Session A Session B


p

1 SET AUTOCOMMIT=0;

SET TRANSACTION ISOLATION LEVEL

READ COMMITTED;

-- amount to be transfered by A

SET @amountA = 200;

SET @balanceA = 0; -- init value

SELECT balance INTO @balanceA

FROM Accounts

WHERE acctID = 101;

SET @balanceA = @balanceA -


@amountA;

4
SELECT @balanceA;

2 SET AUTOCOMMIT=0;

SET TRANSACTION ISOLATION LEVEL

READ COMMITTED;

-- amount to be transfered by B

SET @amountB = 500;

SET @balanceB = 0; -- init value

SELECT balance INTO @balanceB

FROM Accounts WHERE acctID = 101;

SET @balanceB = @balanceB -


@amountB;

SELECT @balanceB;

3 UPDATE Accounts

SET balance = @balanceA

WHERE acctID = 101;

4 UPDATE Accounts

SET balance = @balanceB

WHERE acctID = 101;

5 SELECT acctID, balance

FROM Accounts

WHERE acctID = 101;

COMMIT;

5
SELECT acctID, balance

FROM Accounts

WHERE acctID = 101;

COMMIT;

SELECT * FROM Accounts;

SELECT * FROM Accounts;

Όλα τα προϊόντα DBMS υποστηρίζουν έλεγχο ταυτοχρονισμού (concurrency


control), έτσι ώστε σε όλα τα επίπεδα απομόνωσης (isolation levels) να μην
εμφανίζεται η ανωμαλία χαμένης ενημέρωσης (the lost update anomaly). Παρόλα
αυτά, υπάρχει πάντα η περίπτωση απρόσεκτα γραμμένου κώδικα της εφαρμογής,
όπου επιχειρείται «τυφλή αντικατάσταση» και η οποία οδηγεί στις ίδιες
καταστροφικές συνέπειες -με την ανωμαλία ενημέρωσης- από την πίσω πόρτα!

6
1.2 Θέμα 2: Επανάλαβε το Θέμα 1 χρησιμοποιώντας απευθείας
“sensitive updates” χωρίς να χρησιμοποιήσεις τοπικές
μεταβλητές -using “sensitive updates” in SELECT-UPDATE
scenarios without local variables-

Φαινόμενο ανταγωνισμού για την ίδια γραμμή

- SELECT-UPDATE competition on the same (row) resource -

DELETE FROM Accounts;

INSERT INTO Accounts (acctID,balance) VALUES (101,1000);

INSERT INTO Accounts (acctID,balance) VALUES (202,2000);

SELECT * FROM Accounts;

COMMIT WORK;

St Session A Session B
e
p

1 USE TestDB;

SET AUTOCOMMIT=0;

SET TRANSACTION ISOLATION LEVEL

SERIALIZABLE;

SELECT balance FROM Accounts

WHERE acctID = 101;

2 USE TestDB;

SET AUTOCOMMIT=0;

SET TRANSACTION ISOLATION LEVEL

SERIALIZABLE;

7
SELECT balance FROM Accounts

WHERE acctID = 101;

3 UPDATE Accounts

SET balance = balance - 200

WHERE acctID = 101;

4 UPDATE Accounts

SET balance = balance - 500

WHERE acctID = 101;

5 SELECT acctID, balance

FROM Accounts

WHERE acctID = 101;

COMMIT;

SELECT acctID, balance

FROM Accounts

WHERE acctID = 101;

COMMIT;

Session A

8
Session B

1.3 Θέμα 3: Διατήρηση των S-κλειδαριών(S-locks, Shared Locks)

Αρχικοποίηση του πίνακα Accounts table

DROP DATABASE IF EXISTS TestDB;

CREATE DATABASE TestDB;

USE TestDB;

DROP TABLE IF EXISTS Accounts;

CREATE TABLE Accounts (

acctID INTEGER NOT NULL PRIMARY KEY,

balance INTEGER NOT NULL,

CONSTRAINT remains_nonnegative CHECK (balance >= 0)

);

INSERT INTO Accounts (acctID,balance) VALUES (101,1000);

INSERT INTO Accounts (acctID,balance) VALUES (202,2000);

SELECT * FROM Accounts;

COMMIT;

9
εναλλακτικά

DELETE FROM Accounts;

INSERT INTO Accounts (acctID,balance) VALUES (101,1000);

INSERT INTO Accounts (acctID,balance) VALUES (202,2000);

SELECT * FROM Accounts;

COMMIT WORK;

keeping the S-locks

Επανάληψη του θέματος 1 αλλά με χρήση isolation level SERIALIZABLE.

St Session A Session B
e
p

1 USE TestDB;

SET AUTOCOMMIT=0;

SET TRANSACTION ISOLATION LEVEL


SERIALIZABLE;

-- amount to be transfered by A

SET @amountA = 200;

SET @balanceA = 0; -- init value

SELECT balance INTO @balanceA

FROM Accounts

WHERE acctID = 101;

SET @balanceA = @balanceA -


@amountA;

SELECT @balanceA;

10
2 USE TestDB;

SET AUTOCOMMIT=0;

SET TRANSACTION ISOLATION LEVEL


SERIALIZABLE;

-- amount to be transfered by B

SET @amountB = 500;

SET @balanceB = 0; -- init value

SELECT balance INTO @balanceB

FROM Accounts WHERE acctID = 101;

SET @balanceB = @balanceB -


@amountB;

SELECT @balanceB;

3 UPDATE Accounts

SET balance = @balanceA

WHERE acctID = 101;

4 UPDATE Accounts

SET balance = @balanceB

WHERE acctID = 101;

5 SELECT acctID, balance

FROM Accounts

WHERE acctID = 101;

COMMIT;

SELECT acctID, balance

FROM Accounts

WHERE acctID = 101;

COMMIT;

11
12
1.4 Θέμα 4: Επανάληψη με χρήση isolation level REPEATABLE READ.

Αρχικοποίηση του πίνακα Accounts table

DROP DATABASE IF EXISTS TestDB;

CREATE DATABASE TestDB;

USE TestDB;

DROP TABLE IF EXISTS Accounts;

CREATE TABLE Accounts (

acctID INTEGER NOT NULL PRIMARY KEY,

balance INTEGER NOT NULL,

CONSTRAINT remains_nonnegative CHECK (balance >= 0)

);

INSERT INTO Accounts (acctID,balance) VALUES (101,1000);

INSERT INTO Accounts (acctID,balance) VALUES (202,2000);

SELECT * FROM Accounts;

COMMIT;

εναλλακτικά

DELETE FROM Accounts;

INSERT INTO Accounts (acctID,balance) VALUES (101,1000);

INSERT INTO Accounts (acctID,balance) VALUES (202,2000);

SELECT * FROM Accounts;

COMMIT WORK;

13
Repeating exercise, but now using isolation level REPEATABLE READ.

St Session A Session B
ep

1 USE TestDB;

SET AUTOCOMMIT=0;

SET TRANSACTION ISOLATION


LEVEL REPEATABLE READ;

-- amount to be transfered by A

SET @amountA = 200;

SET @balanceA = 0; -- init value

SELECT balance INTO


@balanceA

FROM Accounts

WHERE acctID = 101;

SET @balanceA = @balanceA -


@amountA;

SELECT @balanceA;

2 USE TestDB;

SET AUTOCOMMIT=0;

SET TRANSACTION ISOLATION LEVEL

REPEATABLE READ;

-- amount to be transfered by B

14
SET @amountB = 500;

SET @balanceB = 0; -- init value

SELECT balance INTO @balanceB

FROM Accounts WHERE acctID = 101;

SET @balanceB = @balanceB - @amountB;

SELECT @balanceB;

3 UPDATE Accounts

SET balance = @balanceA

WHERE acctID = 101;

4 UPDATE Accounts

SET balance = @balanceB

WHERE acctID = 101;

15
5 SELECT acctID, balance

FROM Accounts

WHERE acctID = 101;

COMMIT;

SELECT acctID, balance

FROM Accounts

WHERE acctID = 101;

COMMIT;

16
1.5 Θέμα 5: Ανταγωνισμός σε δύο “resources” με διαφορετική σειρά

-UPDATE-UPDATE competition on two resources in different order-

DELETE FROM Accounts;

INSERT INTO Accounts (acctID,balance) VALUES (101,1000);

INSERT INTO Accounts (acctID,balance) VALUES (202,2000);

SELECT * FROM Accounts;

COMMIT WORK;

St Session A Session B
e
p

1 USE TestDB;

SET AUTOCOMMIT=0;

SET TRANSACTION ISOLATION LEVEL

READ COMMITTED;

UPDATE Accounts

SET balance = balance - 100

WHERE acctID = 101;

2 USE TestDB;

SET AUTOCOMMIT=0;

SET TRANSACTION ISOLATION LEVEL

READ COMMITTED;

UPDATE Accounts

SET balance = balance -200

WHERE acctID = 202;

17
3 UPDATE Accounts

SET balance = balance+100

WHERE acctID = 202;

4 UPDATE Accounts

SET balance = balance + 200

WHERE acctID = 101;

5 COMMIT;

SELECT acctID, balance

FROM Accounts

WHERE acctID = 101;

COMMIT;

SELECT acctID, balance

FROM Accounts

WHERE acctID = 101;

Session A

18
Session B

Το Επίπεδο απομόνωσης δεν παίζει κάποιο ρόλο σε αυτό το σενάριο, αλλά είναι μια
καλή πρακτική ο καθορισμός επίπεδου απομόνωσης στην αρχή κάθε συναλλαγής!

1.6 Θέμα 6: Απόπειρα εμφάνισης dirty read

(An attempt to produce the occurrence of a dirty read situation).

Transaction A runs in (mySQL’s default) REPEATABLE READ, whereas transaction B is


set to run in READ UNCOMMITTED isolation level

DELETE FROM Accounts;

INSERT INTO Accounts (acctID,balance) VALUES (101,1000);

INSERT INTO Accounts (acctID,balance) VALUES (202,2000);

SELECT * FROM Accounts;

COMMIT WORK;

19
St Session A Session B
e
p

1 USE TestDB;

SET AUTOCOMMIT = 0;

SET TRANSACTION ISOLATION LEVEL

REPEATABLE READ;

UPDATE Accounts

SET balance = balance - 100

WHERE acctID = 101;

UPDATE Accounts

SET balance = balance + 100

WHERE acctID = 202;

2 USE TestDB;

SET AUTOCOMMIT = 0;

SET TRANSACTION ISOLATION LEVEL

READ UNCOMMITTED;

SELECT * FROM Accounts;

COMMIT WORK;

3 ROLLBACK;

SELECT * FROM Accounts;

COMMIT;

20
Dirty read problem

Session A

Session B

21
Questions

A) What if ‘READ UNCOMMITTED’ is replaced ‘READ COMMITTED’ in transaction B?

B) What if ‘READ UNCOMMITTED’ is replaced ‘REPEATABLE READ’ in transaction B?

C) What if ‘READ UNCOMMITTED’ is replaced ‘SERIALIZABLE’ in transaction B?

1.7 Θέμα 7: The non-repeatable read anomaly

DELETE FROM Accounts;

INSERT INTO Accounts (acctID,balance) VALUES (101,1000);

INSERT INTO Accounts (acctID,balance) VALUES (202,2000);

SELECT * FROM Accounts;

COMMIT WORK;

St Session A Session B
e
p

1 USE TestDB;

SET AUTOCOMMIT = 0;

SET TRANSACTION ISOLATION LEVEL

READ COMMITTED;

SELECT *

FROM Accounts

WHERE balance > 500;

2 USE TestDB;

SET AUTOCOMMIT = 0;

SET TRANSACTION ISOLATION LEVEL

22
REPEATABLE READ;

UPDATE Accounts SET balance = balance -


500

WHERE acctID = 101;

UPDATE Accounts SET balance = balance


+ 500

WHERE acctID = 202;

COMMIT WORK;

3 -- repeating the same query

SELECT *

FROM Accounts

WHERE balance > 500;

COMMIT;

Session A

23
Session B

Άσκηση
Τι θα συμβεί αν θέσουμε στην transaction A το επίπεδο απομόνωσης (isolation
level) ίσο με REPEATABLE READ;

24
1.8 Θέμα 8: Απόπειρα εμφάνισης insert phantom

DELETE FROM Accounts;

INSERT INTO Accounts (acctID,balance) VALUES (101,1000);

INSERT INTO Accounts (acctID,balance) VALUES (202,2000);

SELECT * FROM Accounts;

COMMIT WORK;

St Session A Session B
e
p

1 USE TestDB;

SET AUTOCOMMIT = 0;

SET TRANSACTION ISOLATION LEVEL

REPEATABLE READ ;

2 -- Accounts having balance > 1000


euros;

SELECT * FROM Accounts

WHERE balance > 1000;

3 USE TestDB;

SET AUTOCOMMIT = 0;

SET TRANSACTION ISOLATION LEVEL

READ COMMITTED;

INSERT INTO Accounts (acctID, balance)

VALUES (303,3000);

COMMIT;

-- Can we see the new account 303?

25
SELECT * FROM Accounts

WHERE balance > 1000;

COMMIT;

Ερωτήσεις

α) Η συναλλαγή Β πρέπει να περιμένει τη συναλλαγή A;

β) Είναι η (πρόσφατα εισαχθείσα από τη συναλλαγή Β) γραμμή acctID = 303


ορατή στο περιβάλλον της συναλλαγής Α;

γ) Επηρεάζεται το σύνολο αποτελεσμάτων (resultset) του βήματος 4, αν αλλάξετε


τη σειρά των βημάτων 2 και 3;

26
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 8: Εισαγωγή στο σχεδιασμό ιστοσελίδων

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Ιστοσελίδες και web sites ................................................................................................. 3
Παράδειγμα 1: .................................................................................................................. 4
Παράδειγμα 2: .................................................................................................................. 4
2. Web servers ...................................................................................................................... 5
3. Διεύθυνση IP και port ....................................................................................................... 7
4. Domain Name Service....................................................................................................... 8
ΕΙΣΑΓΩΓΗ ΣΤΟ ΣΧΕΔΙΑΣΜΟ ΙΣΤΟΣΕΛΙΔΩΝ ...................................................................... 14

Στόχος του εργαστηρίου είναι η εξοικείωση με τη δημιουργία και τη διαχείριση


ιστοτόπων (web sites). Μετά την επεξεργασία του εργαστηρίου ο ενδιαφερόμενος
θα έχει κατανοήσει τα θέματα δημιουργίας μιας web φόρας και όλων των βασικών
εννοιών που σχετίζονται με το διαδίκτυο.

Λέξεις κλειδιά: Web Site, Html φόρμες, Δικτυακός προγραμματισμός

2
1. Ιστοσελίδες και web sites

Έχετε αναρωτηθεί ποτέ πώς είναι δυνατό να βλέπουμε ιστοσελίδες στο internet; Με
ποιο τρόπο υλοποιείται η διαδικασία αυτή; Για να απαντήσουμε σε αυτό το
ερώτημα πρέπει να εξηγήσουμε πρώτα κάποιες έννοιες.

Τι είναι ένα web site;


Ένα web site είναι μια συλλογή από αρχεία οποιουδήποτε τύπου, αποθηκευμένα
στο σκληρό δίσκο ενός μηχανήματος, τα οποία είναι προσπελάσιμα από κάποιους
χρήστες. Οι χρήστες αυτοί μπορεί να είναι ένας συγκεκριμένος αριθμός (αν το web
site είναι ορατό μόνο σε ένα τοπικό δίκτυο) ή ολόκληρη η κοινότητα του διαδικτύου
(αν το web site είναι ορατό στο internet). Τα αρχεία του web site μπορεί να είναι
δυο ειδών: Ιστοσελίδες ή αρχεία κοινού τύπου (zip, exe, doc, pdf κ.τ.λ). Οι
ιστοσελίδες χρησιμεύουν για να εμφανίζουν πληροφορία στο web browser του
χρήστη. Τα υπόλοιπα αρχεία τοποθετούνται στο web site ώστε να είναι διαθέσιμα
να τα κατεβάσει ο χρήστης.

Τι είναι η ιστοσελίδα;
Η ιστοσελίδα (web page) είναι ένα απλό αρχείο κειμένου (text file). Μπορεί να
είναι μόνο καθαρό κείμενο ASCII. Συνήθως όμως το κείμενο που γράφουμε σε μια
ιστοσελίδα θέλουμε να είναι πιο σύνθετο, με χρώματα, background, bullets κ.τ.λ.
Για το λόγο αυτό, είναι δομημένο σε συγκεκριμένη μορφή, η οποία καθορίζεται από
μια γλώσσα, γνωστή ως HTML (HyperText Markup Language). Με την HTML
περιγράφουμε πώς θα μορφοποιηθεί το κείμενο ώστε να το εμφανίσει ο web
browser στη μορφή που θέλουμε. Κάθε ιστοσελίδα είναι ένα αρχείο που έχει
κατάληξη .html ή .htm.

Τι είναι ο web browser;


Είναι ένα πρόγραμμα στον υπολογιστή του χρήστη που κάνει δυο πράγματα:
 Ψάχνει στο internet για να βρει την ιστοσελίδα που γράφουμε στη γραμμή
διεύθυνσης και την κατεβάζει στον υπολογιστή μας.
 Μεταφράζει το κείμενο της ιστοσελίδας, γραμμένο σε HTML και το
παρουσιάζει στην οθόνη.
Γνωστοί web browsers είναι οι παρακάτω: Internet Explorer, Mozilla Firefox,
Netscape Navigator, Opera κλπ.

Γιατί όμως πρέπει να γράφουμε ιστοσελίδες σε HTML και όχι σε απλό κείμενο; Αν
θέλουμε να εμφανίζεται στην ιστοσελίδα μας απλά ένα κείμενο μη μορφοποιημένο,
τότε δε χρειάζεται να γράψουμε HTML. Κάντε το εξής παράδειγμα:

3
Παράδειγμα 1:
Δημιουργήστε ένα αρχείο test.txt με το notepad. Γράψτε το
παρακάτω κείμενο:

Hello, this is my first web page !!!

Αποθηκεύστε το κείμενο και σώστε το ως test.html. Κάντε δυο κλικ και ανοίξτε το με
τον web browser σας. Όπως βλέπετε, έχετε φτιάξει την πρώτη σας ιστοσελίδα. Το
κείμενο που γράψατε εμφανίζεται ως σελίδα στον browser.

Τι γίνεται όμως αν θέλουμε το κείμενό μας να είναι μορφοποιημένο;


Γράψτε το παρακάτω κείμενο με πλάγια γράμματα:

Hello, this is my first web page !!!

Αποθηκεύστε το κείμενο ως test2.txt και στη συνέχεια μετονομάστε το ως


test2.html. Κάντε δυο κλικ και ανοίξτε το με τον web browser σας. Το αποτέλεσμα
δεν είναι το αναμενόμενο.
Αυτό συμβαίνει φυσικά και με τους υπόλοιπους text processors. Για το λόγο αυτό,
δημιουργήθηκε η γλώσσα HTML η οποία θέτει κάποια standards στον τρόπο
μορφοποίησης των κειμένων, ώστε αυτός να είναι κατανοητός από τους web
browsers.

Παράδειγμα 2:
Γράψτε το εξής κείμενο στο notepad και αποθηκεύστε το ως
test3.html:
<HTML>
<BODY>
<I>Hello, this is my first web page !!!</I>
</BODY>
</HTML>

Ανοίξτε το με το web browser σας. Τώρα εμφανίζεται αυτό που θέλουμε. Με τον
παραπάνω τρόπο γράψαμε ένα κείμενο ώστε να είναι κατανοητή η μορφοποίηση
από τον web browser. Φυσικά η HTML είναι πιο περίπλοκη και παρέχει διάφορες
δυνατότητες, τις οποίες μπορείτε να τις δείτε ανοίγοντας μια ιστοσελίδα στο
internet. Περισσότερα για την HTML θα πούμε σε επόμενη ενότητα.

Μέχρι τώρα πρέπει να έχουμε στο νου μας τα εξής:

 Οι ιστοσελίδες είναι αρχεία κειμένου γραμμένα σε γλώσσα HTML, ώστε να


είναι κατανοητή η μορφοποίησή τους από τους web browsers.
 Οι ιστοσελίδες είναι αρχεία που έχουν κατάληξη .html ή .htm.

4
 Ένα web site είναι ένα σύνολο από ιστοσελίδες και άλλα αρχεία,
αποθηκευμένα στο σκληρό δίσκο ενός μηχανήματος που συνδέεται σε
δίκτυο, και είναι ορατά από τους χρήστες που συνδέονται στο ίδιο δίκτυο.

Πώς όμως ένα web site είναι ορατό στους τερματικούς υπολογιστές των χρηστών
που συνδέονται στο internet;
Αν δηλαδή κάποιος φτιάξει τρεις σελίδες HTML, τις αποθηκεύσει στο σκληρό δίσκο
του και μπει στο internet, οι υπόλοιποι θα μπορούν να τις προσπελάσουν; Όχι
βέβαια. Η προσπέλαση των web sites γίνεται με τη βοήθεια ειδικών εφαρμογών
που ονομάζονται HTTP servers ή web servers.

2. Web servers

Ένας HTTP server ή web server, χρησιμεύει για να παρέχει τις ιστοσελίδες ενός web
site στους browsers των χρηστών, όταν αυτοί ζητούν να τις δουν. Οι ιστοσελίδες
είναι αποθηκευμένες στο σκληρό δίσκο ενός μηχανήματος που παίζει το ρόλο του
server.
Πολλοί νομίζουν ότι ο web server είναι ένα μηχάνημα σε μέγεθος ντουλάπας, με
500 επεξεργαστές. Στην πραγματικότητα ο web server είναι ένα μικρό
«προγραμματάκι» που τρέχει σαν service σε έναν υπολογιστή. Πολλές φορές ως
web server εννοούμε τον υπολογιστή που τρέχει αυτό το «προγραμματάκι».
Υπάρχουν πολλοί διαθέσιμοι web servers. Οι πιο γνωστοί είναι ο Apache web
server (open source), ο IIS της Microsoft, Glassfish,...
Εγκαθιστώντας τα NetBeans θα εγκατασταθεί και ο Glassfish

Προκειμένου να δείτε τους εγκατεστημένους server στα Netbeans επιλέγουμε


services.

Για να ξεκινήσει ο Server θα πρέπει κάνετε

5
Δεξί κλικ>Start

Από τη στιγμή που ο Glassfish τρέχει, ο υπολογιστής σας έχει γίνει ένας web server.
Δηλαδή μπορείτε να γράψετε εφαρμογές web (σελίδες html, web sites, portals) και
οι χρήστες να συνδέονται στον υπολογιστή σας από τον browser και να βλέπουν
σελίδες web (εφόσον ο υπολογιστής είναι συνδεδεμένος στο internet).
Δημιουργήστε έναν καινούριο project:
1. File> New Project
2. Java Web> Web Application
3. Next {Project Name: WebApplication1 } > Next

4. Finish

Μέσα στο project WebApplication1 και το φάκελο Web Pages θα βάζετε τις Web
σελίδες, images, pdf,…
Κατ’ αυτόν τον τρόπο βάλτε το αρχείο test3.html που φτιάξατε μέσα στο φάκελο
Web Pages.

Εν συνεχεία δεξί κλικ πάνω στην σελίδα(test.html)> Run

6
Αν όλα πήγαν καλά, στο browser σας θα έχει εμφανιστεί το περιεχόμενο του
αρχείου σας.
http://localhost:8080/WebApplication1/test3.html

Η διεύθυνση localhost:8080 που γράψαμε στο web browser αναφέρεται στον


ίδιο μας τον υπολογιστή.
• Φτιάξτε ένα αρχείο .zip (ή βρείτε ένα που ήδη υπάρχει στο δίσκο σας). Ας
υποθέσουμε ότι ονομάζεται myzip.zip.
• Βρείτε ένα αρχείο .exe. Ας υποθέσουμε ότι ονομάζεται myexec.exe.

Αντιγράψτε αυτά τα αρχεία μέσα στο φάκελο Web Pages και γράψτε στον browser
τις εξής διευθύνσεις:

http://localhost:8080/myDir/myzip.zip
http://localhost:8080/myDir/myexe.exe

Αν όλα πήγαν καλά, και στις δυο περιπτώσεις θα σας ζητηθεί να κατεβάσετε το
αρχείο, όπως θα σας ζητούσε ένα site στο internet.

3. Διεύθυνση IP και port

Πώς θα συνδεθεί ένας χρήστης στον υπολογιστή μας; Ή καλύτερα, πώς θα


συνδεθεί ο web browser ενός χρήστη στον web server (HTTP server) του
υπολογιστή μας;

Δυο παράμετροι χαρακτηρίζουν τα στοιχεία ενός server (είτε αυτός είναι web/HTTP
server, είτε database server, είτε ftp server, είτε mail server...):
• Η διεύθυνση IP του μηχανήματος στο οποίο είναι εγκατεστημένος ο web
server.

7
• H πόρτα (port) της υπηρεσίας που αντιπροσωπεύει ο server (HTTP, FTP,
email, database).

Η πρώτη παράμετρος (IP) είναι μια διεύθυνση ξεχωριστή για κάθε υπολογιστή
συνδεδεμένο στο internet (η κατάσταση είναι λίγο πιο περίπλοκη, αλλά ας έχουμε
αυτό στο νου μας). Η διεύθυνση αυτή αποτελείται από τέσσερα bytes, δηλαδή
τέσσερις αριθμούς από 1 ως 255. Σε δεκαδική μορφή η διεύθυνση IP γράφεται ως
Α.Β.C.D, για παράδειγμα 192.168.69.17 ή 10.0.0.11 ή 172.16.5.254.
Η δεύτερη παράμετρος (PORT) είναι ένας αριθμός που χρησιμεύει για τον εξής
σκοπό: Σκεφτείτε ότι σε έναν υπολογιστή (ο οποίος συνήθως έχει μόνο μια
διεύθυνση IP) τρέχουν δυο servers: Ο tomcat για HTTP1 και η MySQL για database.
Αν η μόνη παράμετρος που είχαμε ήταν η διεύθυνση IP του υπολογιστή, πώς θα
ξεχωρίζαμε σε ποιον server θα συνδεθούμε; Έχοντας όμως ως παράμετρο την
πόρτα, μπορούμε να ξεχωρίσουμε και το server στον οποίο θα συνδεθούμε. Έτσι,
δεδομένου ότι η port του tomcat είναι η 8080 ενώ η port της MySQL είναι η 3306,
μπορούμε να ξεχωρίσουμε σε ποιον server θα συνδεθούμε.
Για να συνδεθούμε σε έναν web server μέσω του browser μας γράφουμε την
ακόλουθη διεύθυνση:

http://ServerIP:ServerPort

Για παράδειγμα:
http://192.168.1.2:8080

Γράφοντας στην αρχή της διεύθυνσης http://, ο browser καταλαβαίνει ότι ζητάμε να
δούμε ιστοσελίδες και η επικοινωνία θα γίνει μέσω του πρωτοκόλλου HTTP.

Πόρισμα: Για να συνδεθούμε στον Glassfish και να προσπελάσουμε ιστοσελίδες και


αρχεία που έχουμε αποθηκεύσει εκεί, γράφουμε http://ServerIP:8080.

Ας σημειώσουμε βέβαια εδώ ότι ο αριθμός 8080 της πόρτας που χαρακτηρίζει τον
Glassfish / tomcat, μπορεί να αλλάξει, με παραμετροποίηση του configuration του
Glassfish/tomcat. Αυτό δε θα μας απασχολήσει στο εργαστήριο και θα θεωρήσουμε
ότι η πόρτα που χαρακτηρίζει τον Glassfish/tomcat είναι η 8080.

4. Domain Name Service

Πόσες φορές έχετε επισκεφτεί ένα site στο internet και γράψατε τη διεύθυνση IP
του server που το φιλοξενεί; Σχεδόν καμία. Τις περισσότερες φορές επισκέπτεστε
ένα site γράφοντας το όνομά του. Αυτό γίνεται μέσω της υπηρεσίας DNS (Domain
Name Service). Όταν θέλουμε να φτιάξουμε έναν web server και να τον κάνουμε
διαθέσιμο στο internet για να φιλοξενήσει κάποιο site, επικοινωνούμε με κάποια
αρμόδια αρχή ή εταιρία η οποία αναλαμβάνει δυο πράγματα:
• Να δώσει ένα όνομα στο server που θα φιλοξενεί το site μας.

8
• Να αντιστοιχίζει τη διεύθυνση ΙΡ του server μας με το όνομα που του
δώσαμε.
Έτσι, για παράδειγμα, ο web server που φιλοξενεί το eclass έχει όνομα
eclass.cs.teiath.gr και διεύθυνση IP 195.130.109.27. Η αντιστοίχιση των ονομάτων
των servers σε διευθύνσεις IP γίνεται μέσω της υπηρεσίας DNS, που είναι ένα
πρωτόκολλο που μεταφράζει τις διευθύνσεις IP των υπολογιστών σε ονόματα και το
αντίστροφο. Για την επιτέλεση αυτής της διαδικασίας, υπάρχουν servers στο
internet οι οποίοι έχουν καταχωρημένα τα ονόματα και τις διευθύνσεις IP των
διαφόρων υπολογιστών. Οι servers αυτοί, που είναι υπολογιστές που τρέχουν
ασταμάτητα, ονομάζονται DNS servers. Συνήθως κάθε δίκτυο έχει και το δικό του
DNS server που μεταφράζει τα ονόματα των υπολογιστών στους οποίους ζητείται
πρόσβαση σε διευθύνσεις IP. Για να γίνει αυτό καλύτερα αντιληπτό, κάντε το εξής
παράδειγμα:

nslookup eclass.cs.teiath.gr

Οι δυο πρώτες γραμμές δείχνουν το όνομα και τη διεύθυνση IP του DNS server που
έκανε τη μετάφραση. Οι δυο τελευταίες δείχνουν τη διεύθυνση ΙΡ για το όνομα του
site που ζητήσαμε.
Κάντε το ίδιο και για τα sites www.cs.teiath.gr και www.teiath.gr.

Πληκτρολογήστε στο browser σας http://teiServerIP, όπου teiServerIP είναι η


διεύθυνση ΙΡ που αντιστοιχεί στο site www.teiath.gr. Θα δείτε ότι εμφανίζεται ο
site του ΤΕΙ.

Από το παραπάνω είναι προφανές ότι δε χρειάζεται απαραίτητα να έχει το site μας
ένα όνομα. Μπορούν οι χρήστες να το προσπελάσουν και μέσω της διεύθυνσης IP,
αν φυσικά την ξέρουν. Είναι όμως προφανής και η ευχρηστία που παρέχει ένα
αντιπροσωπευτικό όνομα για κάθε site…

Διεύθυνση IP για τοπική σύνδεση


Αν ο server τρέχει τοπικά στο μηχάνημά μας, και θέλουμε από τον browser του
μηχανήματος να συνδεθούμε στο server, τότε η διεύθυνση ΙΡ που θα
χρησιμοποιήσουμε θα είναι η 127.0.0.1, που δηλώνει διεύθυνση IP για τοπική
σύνδεση. Αντί της 127.0.0.1 θα μπορούσαμε να γράψουμε και localhost, που είναι
ένα χαρακτηριστικό όνομα το οποίο δηλώνει τη διεύθυνση 127.0.0.1 για τοπική
σύνδεση (γράψτε σε μια γραμμή εντολών nslookup localhost και θα καταλάβετε).
Εύλογα θα αναρωτηθεί κανείς: Ποιος ο λόγος να συνδεθούμε μέσω ενός web
browser σε έναν web server που τρέχει στο ίδιο μηχάνημα; Γιατί να μην
ανακτήσουμε την πληροφορία κατευθείαν από το σκληρό δίσκο; Η απάντηση είναι:
Κανένας λόγος. Το κάνουμε μόνο για να τεστάρουμε τις ιστοσελίδες που γράψαμε.

Πόρισμα: Για να τεστάρουμε τις εφαρμογές web που έχουμε φτιάξει, συνδεόμαστε
από το μηχάνημά μας, χρησιμοποιώντας ως διεύθυνση ΙΡ τη localhost ή 127.0.0.1.

Απαραίτητη προϋπόθεση φυσικά, είναι να υπάρχει ένας web server εγκατεστημένος


στο μηχάνημα.

9
H port 80
Έχετε γράψει πολλές φορές το όνομα του port στη διεύθυνση ενός web site που
επισκέπτεστε; Μάλλον όχι. Με βάση όσα είπαμε σε προηγούμενη ενότητα, πώς
ξεχωρίζει ο browser σε ποια πόρτα θα συνδεθεί; Αυτό γίνεται μέσω μιας συμφωνίας
που έγινε μεταξύ web browsers και web servers, ορίζοντας μια κοινή πόρτα, την
port με νούμερο 80. Αυτό που συμφωνήθηκε είναι το εξής: Αν είναι επιθυμητό να
γίνεται προσπέλαση ενός site χωρίς να γράφεται ο αριθμός του port στη διεύθυνση
ΙΡ, τότε θα πρέπει να τηρούνται τα εξής:
• Ο web server που θα φιλοξενεί το site θα πρέπει να ακούει στην port 80.
Έτσι, για παράδειγμα στον tomcat, θα πρέπει να αλλάξουμε το
configuration, ώστε να τον προσπελαύνουμε μέσω της port 80, αντί της
8080.
• Οι web browsers θα πρέπει να είναι έτσι φτιαγμένοι ώστε, αν ο χρήστης δεν
πληκτρολογήσει το όνομα της πόρτας μετά τη διεύθυνση IP, τότε η σύνδεση
να γίνει στην port 80.Τα δυο παραπάνω τηρούνται σήμερα και από τις δυο
πλευρές, για ευκολία των χρηστών. Αυτό δε σημαίνει φυσικά ότι δε
μπορούμε να φτιάξουμε έναν web server σε διαφορετική πόρτα. Αρκεί
αυτοί που θα συνδεθούν να ξέρουν το νούμερό της. Για το σκοπό του
εργαστηρίου, δε θα αλλάξουμε το configuration του tomcat και θα
συνδεόμαστε στην default port 8080 που παρέχει, γράφοντάς τη στη
γραμμή διευθύνσεων του web browser μας.

Αντιστοίχιση καταλόγων και διεύθυνσης web


Όλα καλά μέχρι εδώ. Αφού όμως οι χρήστες συνδεθούν στο server με
http://serverIP:8080, πώς θα προσπελάσουν τις ιστοσελίδες που θέλουν; Αυτή τη
δουλεία αναλαμβάνει να κάνει ο web server, αντιστοιχίζοντας τη διαδρομή που
γράφουμε στο web browser, με τη διαδρομή των καταλόγων που υπάρχουν στο
σκληρό δίσκο του web server. Κάθε web server παρέχει έναν default κατάλογο, στον
οποίο, αν βάλουμε αρχεία, θα μπορούν αυτά οι χρήστες να τα προσπελάσουν
δικτυακά, μέσω του browser τους. Ο κατάλογος αυτός, για τον Glassfish είναι το
project WebApplication1

Αν γράψουμε τη διεύθυνση IP του server (μαζί με την port) και στη συνέχεια
γράψουμε τη διαδρομή για ένα αρχείο (directory\subdirectory\file.html) ο server θα
λάβει τη συγκεκριμένη αίτηση, θα ψάξει στον κατάλογο του project για να βρει το
αρχείο file.html και θα εμφανίσει την πληροφορία του στο browser. Φυσικά, αν το
αρχείο αυτό δεν υπάρχει, ή αν το path directory\subdirectory είναι λάθος, τότε o
server θα απαντήσει ότι δε μπορεί να βρει το συγκεκριμένο αρχείο στους
καταλόγους του.
Πόρισμα: Αν φτιάξουμε έναν κατάλογο μέσα στο project και τον φάκλεο Web
Pages, τότε όλα τα αρχεία αυτού του καταλόγου θα μπορούμε να τα
προσπελάσουμε από έναν web browser.

URLs και links


Όλοι έχουμε επισκεφτεί ιστοσελίδες και έχουμε κάνει κλικ πάνω σε συγκεκριμένα
σημεία, που μας παραπέμπουν σε άλλες ιστοσελίδες. Πώς υλοποιείται αυτή η
διαδικασία; Η όλη φιλοσοφία στηρίζεται σε μια χαρακτηριστική διεύθυνση που έχει

11
κάθε αρχείο ή ιστοσελίδα που απαρτίζει ένα web site. Η συγκεκριμένη αυτή
διεύθυνση ονομάζεται URL (Universal Resource Locator). Αποτελείται από τρία
χαρακτηριστικά:

• Τη διεύθυνση IP και την πόρτα του server στον οποίο ανήκει το αρχείο αυτό.
• Τη διαδρομή του αρχείου στο server.
• Το όνομα του αρχείου.

Παράδειγμα URL.1: Έχουμε το αρχείο myFile.html που βρίσκεται μέσα στο project
(myDir) και τον φάκελο Web Pages
Η διεύθυνση ΙΡ του μηχανήματος που τρέχει ο Glassfish είναι η 192.168.1.2. Τότε το
URL του συγκεκριμένου αρχείου είναι:

http:// 192.168.1.2:8080/myDir/myFile.html

Ξεκινήστε τον Glassfish/tomcat αν δεν τρέχει ήδη. Φτιάξτε δυο καταλόγους dir1 και
dir2. Φτιάξτε το αρχείο file1.html και αποθηκεύστε το στον κατάλογο dir1:

<HTML>
<BODY>
You are now in HEAVEN.
<a href="http://localhost:8080/
WebApplication1/dir2/file2.html">GO TO HELL</a>
</BODY>
</HTML>

Φτιάξτε το αρχείο file2.html και αποθηκεύστε το στον κατάλογο dir2:

<HTML>
<BODY>
You are now in HELL.
<a href="
http://localhost:8080/WebApplication1/dir1/file1.html">GO
TO HEAVEN</a>
</BODY>
</HTML>

Γράψτε το URL του πρώτου ή του δεύτερου αρχείου στο browser σας, π.χ.:

http://localhost:8080/WebApplication1/dir1/file1.html

Ακολουθήστε τα links στα αρχεία. Παρατηρήστε ότι τα URLs των αρχείων που
βρίσκεστε φαίνονται στη γραμμή διευθύνσεων του browser. Παρατηρήστε επίσης
ότι τα URL των links φαίνονται στο status bar όταν ακουμπάτε το ποντίκι πάνω.
Τα links δημιουργούνται με τη βοήθεια εντολών HTML. Μπορεί να είναι απόλυτα
(absolute links) ή σχετικά (relative links):

12
Τα absolute links παρέχουν όλο το URL της σελίδας που δείχνουν. Χρησιμοποιούνται
συνήθως για σελίδες που δεν ανήκουν στον ίδιο web server. Absolute links είναι
όλα αυτά που είδαμε παραπάνω.
Τα relative links παρέχουν μόνο το URL που έχει σχέση με τη διαδρομή του
καταλόγου στο σκληρό δίσκο του server. Χρησιμοποιούνται συνήθως για σελίδες
που ανήκουν στον ίδιο web server. Για να καταλάβετε καλύτερα την έννοια των
absolute links κάντε το εξής:
Στα αρχεία file1.html και file2.html που φτιάξατε παραπάνω, αντικαταστήστε την
τέταρτη γραμμή με τις εξής, αντίστοιχα:
<a href="../dir1/file1.html">GO TO HELL</a>
<a href="../dir2/file2.html">GO TO HEAVEN</a>
Παρατηρήστε ότι η εφαρμογή δουλεύει. Εδώ αφαιρέσαμε εντελώς το τμήμα που
δηλώνει τη διεύθυνση του server, αφού και οι δυο σελίδες βρίσκονται στο ίδιο
μηχάνημα. Δηλώσαμε τα links με βάση την τοποθεσία των σελίδων στο σκληρό
δίσκο. Προσοχή όμως, υποθέτουμε ότι ανήκουν στο ίδιο project
Βρείτε ένα αρχείο .exe και αντιγράψτε το στον κατάλογο dir1 που φτιάξατε πριν.
Μετονομάστε το σε setup.exe. Βρείτε ένα αρχείο .pdf και αντιγράψτε το στον
κατάλογο dir1 που φτιάξατε πριν. Μετονομάστε το σε readme.pdf.

Παράδειγμα URL.2: Μέσα στον κατάλογο dir1 δημιουργήστε το αρχείο


MyApplication.html:
<HTML>
<BODY>
This is my Application.<BR>
Click <a href=" http://localhost:8080/WebApplication1/dir1/setup.exe">HERE</a>
to download it.<BR>
Click <a href=" readme.pdf">HERE</a>
to view documentation.
</HTML>
</BODY>

Γράψτε το URL του αρχείου στον browser:

http://localhost:8080/WebApplication1/dir1/MyApplication.html

Προσοχή στα κεφαλαία και στα μικρά γράμματα. Τα URL είναι case sensitive.

Γράψτε τα εξής URL στον υπολογιστή:

http://localhost:8080/WebApplication1/Dir1/MyApplication.html

http://localhost:8080/WebApplication1/dir1/myapplication.html

Όπως θα παρατηρήσετε, τα links δε λειτουργούν, γιατί δε βάλαμε κεφαλαία


γράμματα όπου χρειάζεται.

13
Έχοντας υπόψη τα παραπάνω, γίνεται αντιληπτό ότι, όταν σχεδιάζουμε ένα site, δεν
παραπέμπουμε το χρήστη να πληκτρολογεί ξεχωριστά το URL της κάθε ιστοσελίδας
που θέλει να επισκεφτεί, αλλά φτιάχνουμε links σε συγκεκριμένες ιστοσελίδες οι
οποίες τον παραπέμπουν στη συνέχεια στις υπόλοιπες ιστοσελίδες και αρχεία που
θέλει να επισκεφτεί. Και πάλι όμως, ποτέ δεν πληκτρολογούμε το όνομα κάποιου
αρχείου στο browser όταν θέλουμε να επισκεφτούμε ένα site. Πληκτρολογούμε το
URL του site μόνο. Ο τρόπος με τον οποίο γίνεται αυτό εξηγείται στην επόμενη
ενότητα.

Site URLs και το αρχείο index.html


Όπως θα έχετε παρατηρήσει, όταν επισκεπτόμαστε μια σελίδα στο internet, στη
διεύθυνση γράφουμε μόνο το όνομα του site. Δε γράφουμε και το όνομα κάποιου
αρχείου στο τέλος. Άλλωστε, για ένα site που δεν έχουμε επισκεφτεί ξανά, πώς να
ξέρουμε ποιο όνομα αρχείου να γράψουμε;

Για τους παραπάνω λόγους, κάθε web server παρέχει έναν τρόπο ώστε, όταν ο
χρήστης πληκτρολογήσει το URL ενός site, χωρίς κατάληξη στο τέλος, τότε
φορτώνεται ένα προκαθορισμένο αρχείο.
Ειδικά για τον tomcat υπάρχει η εξής πολιτική: Αν, μέσα στον κατάλογο του site που
φτιάξαμε βάλουμε ένα αρχείο με όνομα index.html, το συγκεκριμένο αρχείο είναι
αυτό που θα εμφανιστεί στο χρήστη αν αυτός πληκτρολογήσει στον browser του
μόνο τη διεύθυνση του site, χωρίς το όνομα κάποιου αρχείου στο τέλος. Για να
γίνει πιο καλά αντιληπτό αυτό, κάντε το εξής παράδειγμα:

Ξεκινήστε τον tomcat ή Glassfish αν δεν τρέχει ήδη. Μετονομάστε το αρχείο


file1.html που είχατε φτιάξει στο προηγούμενο παράδειγμα σε index.html. Γράψτε
στη γραμμή διευθύνσεων του browser σας την εξής διεύθυνση:
http://localhost:8080/WebApplication1/dir1
Θα δείτε ότι εμφανίζεται το παλιό αρχείο file1.html.

Το αρχείο index.html είναι συνήθως μια εισαγωγική σελίδα (welcome page) με


γενικές πληροφορίες για το site, και με links για τις υπόλοιπες ιστοσελίδες και
αρχεία του. Αντίστροφα, σε κάθε ιστοσελίδα υπάρχει συνήθως και ένα link για το
αρχείο index.html, ώστε ο χρήστης να μπορεί να κατευθύνεται εύκολα και στις
υπόλοιπες ιστοσελίδες.

Λίγα λόγια παραπάνω για την HTML


Παρ’ όλο που η HTML δεν αποτελεί αντικείμενο του εργαστηρίου, θα αναφερθούμε
πολύ περιληπτικά στους βασικούς κανόνες σύνταξής της, ώστε να γίνεται
κατανοητή η δομή των αρχείων HTML που θα χρησιμοποιηθούν για το user
interface της εφαρμογής που θα φτιάξουμε.
Όπως είδαμε και στην αρχή του κεφαλαίου, το πιο απλό κείμενο HTML είναι ένα
αρχείο κειμένου ASCII με κατάληξη .html ή .htm. Αν θέλουμε όμως να
μορφοποιήσουμε το κείμενο, πρέπει να ακολουθήσουμε συγκεκριμένη σύνταξη,
που βασίζεται στα HTML tags. Ένα html tag είναι μια εντολή που περικλείεται σε
χαρακτήρες ‘<’ και ‘>’. Κάθε κείμενο HTML αρχίζει και τελειώνει αντίστοιχα με τα

14
εξής tags: <html> και <html>. Ο τίτλος της σελίδας (που εμφανίζεται στην κορυφή
του παραθύρου του browser) περικλείεται ανάμεσα στα tags <title> και </title>.
Τα δυο αυτά tags με τη σειρά τους περικλείονται ανάμεσα στα tags <head> και
</head>. Έτσι, μια απλή σελίδα είναι η ακόλουθη:
<html>
<head>
<title>Test page</title>
</head>
<body>
This is a test web page with simple HTML tags.
</body>
</html>

Αντιγράψτε τον κώδικα στο αρχείο simple.html και ανοίξτε το με έναν web
browser.

Γενικά tags
Κάποια άλλα επιπλέον χρήσιμα tags είναι τα ακόλουθα:

<br> : Αλλαγή γραμμής.

<p> : Αλλαγή παραγράφου.


<body bgcolor="#CCCCCC" text="#000000"> Background / text color.
Εφαρμογή των παραπάνω αποτελεί η παρακάτω ιστοσελίδα:

ΕΙΣΑΓΩΓΗ ΣΤΟ ΣΧΕΔΙΑΣΜΟ ΙΣΤΟΣΕΛΙΔΩΝ


<html>
<head>
<title>Test page</title>
</head>
<body bgcolor="#CCCCCC" text="#000000">

This is a test web page with simple HTML tags. <br>


More tags are added now. <p>
This makes the page more beautiful!
</body>
</html>
Αντιγράψτε τον κώδικα σε ένα νέο αρχείο simple2.html και ανοίξτε το με έναν web
browser.

15
Tags για hyperlink
Το tag που χρησιμοποιούμε για να φτιάξουμε ένα hyperlink είναι το εξής:
<a href="filename.html">Go to file</a>

Εσωκλείουμε το URL του αρχείου (absolute ή relative path) σε quotes. Προσθέτουμε


το χαρακτήρα ‘>’. Μετά το συγκεκριμένο χαρακτήρα γράφουμε το κείμενο που
θέλουμε να εμφανίζεται στο link της σελίδας.

Προσθέστε την παραπάνω γραμμή πάνω από το tag </body> του αρχείου που
φτιάξατε πριν. Ανοίξτε το νέο αρχείο στο browser για να δείτε το link που φτιάξατε.
Κάντε κλικ στο link. Δε θα δουλέψει διότι το αρχείο filename.html δεν υπάρχει.

Tags για form


Για τις απαιτήσεις του εργαστηρίου θα χρειαστούμε φόρμες στα αρχεία html, οπότε
παρατίθενται τα tags με τα οποία φτιάχνουμε μια φόρμα. Τα tags για μια φόρμα
είναι τα εξής:

<form name="formName" method="post" action="file.html">


<input type="text" name="textBoxParam">
<input type="submit" name="ButtonName"
value="ButtonValue">
</form>

Τα παραπάνω tags δημιουργούν μια φόρμα με όνομα formName, η οποία


αποτελείται από ένα text box στο οποίο εισάγουμε κάποιο κείμενο και ένα κουμπί
που το πατάμε για να μας παραπέμψει σε μια άλλη σελίδα.

 Το πρώτο tag δημιουργεί τη φόρμα.


 Η παράμετρος name παίρνει το όνομα της φόρμας.
 Η παράμετρος method δείχνει για τι χρησιμοποιείται η φόρμα. Στην
περίπτωσή μας παίρνει την τιμή post και δε θα μας απασχολήσει παραπάνω.
 Η παράμετρος action δηλώνει το αρχείο που θα κληθεί μόλις πατήσουμε το
κουμπί της φόρμας.
 Τα στοιχεία που περικλείονται μέσα στη φόρμα τα φτιάχνουμε με το tag
input. Έτσι:
o Το δεύτερο tag δημιουργεί το text box. Η παράμετρος type παίρνει
την τιμή text για να δείξει ότι φτιάχνουμε ένα text box.
o Το πεδίο textBoxParam παίρνει το όνομα της παραμέτρου στην οποία
θα αποθηκευτούν τα δεδομένα που θα εισάγουμε στο textbox. Έχετε
υπόψη ότι τις φόρμες τις χρησιμοποιούμε για να εισάγουμε
δεδομένα σε παραμέτρους τις οποίες μετά θα χρησιμοποιήσουμε σε
κάποιο πρόγραμμα.
o Το τρίτο tag δημιουργεί το κουμπί. Η παράμετρος type παίρνει την
τιμή submit για να δείξει ότι φτιάχνουμε ένα button. Το πεδίο value
δείχνει το κείμενο που θα εμφανίζεται πάνω στο κουμπί.

16
Τα στοιχεία που φτιάχνουμε μέσα σε μια φόρμα μπορούμε να τα στοιχίσουμε όπως
ακριβώς θα στοιχίζαμε ένα κείμενο, χρησιμοποιώντας τα γενικά tags που είδαμε
παραπάνω. Για να καταλάβετε την έννοια της φόρμας αντιγράψτε τον παρακάτω
κώδικα σε ένα αρχείο και ονομάστε το form.html.

<html>
<head>
<title>Simple Forms</title>
</head>
<body>
These are two simple forms.<p><p>
This is the first form with horizontal alignment.<p>
<form name="form1" method="post" action="register1.html">
<p>Username: <input type="text" name="username1">
Password: <input type="text" name="password1">
<input type="submit" value="Register 1">
</form>
<p><p>

This is the second form with vertical alignment using tags.<p>


<form name="form2" method="post" action="register2.html">
<p>Username: <input type="text" name="username2">
<p>Password: <input type="text" name="password2">
<p><input type="submit" value="Register 2">
</form>
</body>
</html>

Πρέπει να πούμε ότι η HTML χρησιμοποιείται σήμερα κατά κόρο. Βέβαια, η εύκολη
σύνταξή της έχει επιτρέψει την ανάπτυξη προγραμμάτων που γράφουν αυτόματα
HTML. Τέτοια προγράμματα είναι το MS Front Page και το Macromedia
Dreamweaver. Ακόμη και το MS Word γράφει σελίδες HTML.
Γράψτε ένα κείμενο, μορφοποιήστε το όπως θέλετε και σώστε το σαν αρχείο HTML
(επιλέξτε save as και στο type επιλέξτε .html). Ανοίξτε το αρχείο με έναν browser.
Θα δείτε ότι φαίνεται το κείμενο που φτιάξατε σε μορφή ιστοσελίδας. Παρ’ όλ’
αυτά, μην προσπαθήσετε να καταλάβετε τον κώδικα HTML που έγραψε το Word,
διότι τα γράφει με τον δικό του, ιδιαίτερο τρόπο.

Απ’ όλα τα παραπάνω γίνεται κατανοητό ότι σχεδόν κανένας σχεδιαστής σελίδων
σήμερα δε γράφει καθαρή HTML μόνος του. Οι περισσότεροι χρησιμοποιούν
προγράμματα όπως τα παραπάνω. Φυσικά, η γνώση της HTML είναι απαραίτητη για
το σχεδιασμό μιας καλής ιστοσελίδας, είτε γράφουμε τον κώδικα μόνοι μας, είτε
μέσω κάποιου προγράμματος.

17
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 9: Στατικές και δυναμικές σελίδες (JSP)

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Στατικές και δυναμικές σελίδες (JSP) ............................................................................... 3
Άσκηση 1 ........................................................................................................................... 4
Άσκηση 2........................................................................................................................... 5
Άσκηση 3 ........................................................................................................................... 6
Άσκηση 3.1........................................................................................................................ 6
Άσκηση 4........................................................................................................................... 7
Άσκηση 5 ........................................................................................................................... 8
Άσκηση 6 ......................................................................................................................... 11
Άσκηση 7 ......................................................................................................................... 13
Άσκηση 7.1...................................................................................................................... 14

Στόχος του εργαστηρίου είναι η εξοικείωση με τη δημιουργία και τη διαχείριση


δυναμικών ιστοσελίδων με χρήση της γλώσσας JSP. Μετά την επεξεργασία του
εργαστηρίου ο ενδιαφερόμενος θα έχει κατανοήσει τα θέματα δημιουργίας
δυναμικών φορμών και θέματα διαχείρισης δεδομένων για ενδεχόμενη παραπέρα
επεξεργασία τους.

Λέξεις κλειδιά: Επαναληπτικοί βρόχοι, JSP, Διαχείριση ηλεκτρονικών φορμών

2
1. Στατικές και δυναμικές σελίδες (JSP)

Μέχρι στιγμής είδαμε σελίδες HTML με τις οποίες μπορούμε να γράφουμε κείμενο
και να το μορφοποιούμε όπως εμείς θέλουμε. Το κείμενο όμως που θα εμφανίζει η
ιστοσελίδα μας δεν αλλάζει. Παραμένει πάντα το ίδιο. Τέτοιο κείμενο λέγεται
στατικό και μια ιστοσελίδα που έχει στατικό κείμενο ονομάζεται στατική ιστοσελίδα
(static web page).

Τι γίνεται όμως όταν θέλουμε να έχουμε κείμενο που αλλάζει;

Σκεφτείτε το εξής παράδειγμα στο Word. Έχουμε μια παράγραφο με στατικό


κείμενο και στο τέλος εισάγουμε την ημερομηνία. Το κείμενο που δείχνει την
ημερομηνία ανανεώνεται κάθε φορά που ανοίγουμε το έγγραφο με το word. Ένα
τέτοιο κείμενο ονομάζεται δυναμικό κείμενο. Το Word έχει τον τρόπο να ανανεώνει
την ημερομηνία κάθε φορά που ανοίγει το έγγραφο.

Πώς όμως θα φτιάξουμε μια ιστοσελίδα που κάνει την παραπάνω δουλειά;
Ιστοσελίδες που εμφανίζουν στατικό αλλά και δυναμικό κείμενο ονομάζονται
δυναμικές ιστοσελίδες. Η εργασία αυτή δε μπορεί να γίνει μόνο με HTML.
Χρειάζεται να ενσωματώσουμε και κάποια άλλη τεχνολογία για να γράφουμε
δυναμικό κείμενο. Ο πιο διαδεδομένος τρόπος σήμερα για να γράφουμε δυναμικό
κείμενο σε ιστοσελίδες είναι οι script γλώσσες προγραμματισμού ASP (Active Server
Pages), JSP (Java Server Pages) και PHP (Hypertext PreProcessor). Οι παραπάνω
script γλώσσες μας παρέχουν τον τρόπο να γράφουμε δυναμικό κείμενο και,
γενικότερα, να επιτελούμε κάποιες διεργασίες που θα μπορούσαμε να εκτελέσουμε
με γλώσσες προγραμματισμού. Έτσι, μπορούμε να γράψουμε και να διαβάσουμε
από αρχεία, να ορίσουμε και να μεταβάλλουμε μεταβλητές, να εμφανίσουμε την
τιμή μεταβλητών σε ιστοσελίδες (αντίστοιχα, στις γλώσσες προγραμματισμού θα
εμφανίζαμε την τιμή τους στην οθόνη ή σε ένα παράθυρο, αν επρόκειτο για visual
γλώσσες), να συνδεθούμε σε βάσεις δεδομένων κ.α.

Γενικότερα, μέσω των παραπάνω τεχνολογιών μπορούμε να γράψουμε ιστοσελίδες


που περιέχουν στατικό κείμενο και προγραμματιστική λογική. Στην περίπτωσή μας
θα ασχοληθούμε με τη γλώσσα JSP. Μια ιστοσελίδα JSP αποτελείται από κείμενο
HTML, για να γράψουμε το κείμενο που θέλουμε, και από τμήματα κώδικα JSP όπου
ενσωματώνουμε κώδικα Java. Κάθε αρχείο JSP έχει κατάληξη .jsp.

Ερώτηση: Μπορεί ένα αρχείο που έχει μόνο κώδικα HTML να έχει κατάληξη .jsp;
Απάντηση: ΝΑΙ. Αφού είπαμε ότι ένα αρχείο JSP έχει κώδικα HTML και JSP. Αν δεν
έχει κώδικα JSP παραμένει ακόμη ένα αρχείο JSP, αφού η HTML είναι αναφαίρετο
κομμάτι της γλώσσας JSP. Ένα παράδειγμα JSP είναι το ακόλουθο:

3
Άσκηση 1

<HTML>
<BODY>
<% int x = 3; %>
Hello! The value of the variable x is: <%= x %>.<p>
<% x=x+3; %>
The value of the variable x is changed: <%= x %>.
</BODY>
</HTML>

Αποθηκεύστε το παραπάνω αρχείο ως ex1.jsp, στo project baseis_x που είχατε


φτιάξει για τα παραδείγματα του εργαστηρίου. Δείτε το αποτέλεσμα στο browser
πληκτρολογώντας http://localhost:8080/baseis_x/ex1.jsp.

Στο παραπάνω αρχείο, ορίσαμε μια μεταβλητή x. Ο ορισμός έγινε με κώδικα Java,
που περικλείεται ανάμεσα σε ειδικά σύμβολα που ονομάζονται tags. (<% και %>).

Γράφουμε κώδικα HTML και, στο σημείο που θέλουμε να εμφανίσουμε την τιμή της
μεταβλητής, γράφουμε τη μεταβλητή και την περικλείουμε στα tags <%= και %>. Το
υπόλοιπο μέρος του κώδικα καταλαβαίνετε προφανώς τι κάνει. Όπως βλέπουμε,
τον κώδικα Java τον διαχωρίζουμε από τον κώδικα HTML μέσω ειδικών tags. Ο
ρόλος των tags είναι για να καταλαβαίνει ο compiler ότι δεν πρόκειται για κείμενο
HTML, αλλά για κώδικα Java. Ο κώδικας JSP δεν περιορίζεται σε tags που
εσωκλείουν κώδικα Java. Υπάρχουν πάρα πολλά διαφορετικά tags που τα
χρησιμοποιούμε για να κάνουμε συγκεκριμένες διεργασίες. Στην παρούσα ενότητα
θα δούμε μόνο δυο απλά tags.

Ο ρόλος των Web Containers

Βρείτε ένα αρχείο .html που έχετε φτιάξει. Κάντε διπλό κλικ πάνω του για να ανοίξει
με έναν browser. Έχετε κάποιο πρόβλημα να το δείτε; Μάλλον όχι.

Προσπαθήστε να κάνετε το ίδιο και με το αρχείο ex1.jsp που φτιάξατε παραπάνω,


δηλαδή να το ανοίξετε με έναν web browser. Έχετε κάποιο πρόβλημα να το δείτε;
Μάλλον ναι. Γιατί συμβαίνει αυτό;

Η γλώσσα HTML είναι μια ψευδογλώσσα που μπορεί να τη μεταφράσει ο browser


και να εμφανίσει το κατάλληλο αποτέλεσμα. Δεν ισχύει όμως το ίδιο και με τον
κώδικα των δυναμικών σελίδων όπως οι JSP, οι οποίες περιέχουν και κώδικα Java.
Απαιτείται λοιπόν κάποιος άλλος μηχανισμός από την πλευρά του server ο οποίος
θα φορτώνει τα αρχεία JSP, θα τα μεταφράζει σε καθαρό κώδικα HTML
αντικαθιστώντας τις τιμές των δυναμικών παραμέτρων με στατικές, και θα τα δίνει
στο browser του client, ο οποίος θα μεταφράζει τo κείμενο HTML που του έδωσε ο
server. Ένας τέτοιος μηχανισμός-πρόγραμμα ονομάζεται web container. Ο ρόλος
του web container είναι να καθιστά δυνατή τη χρήση αρχείων JSP σε μια εφαρμογή.
Αν λοιπόν θέλουμε να φτιάξουμε μια εφαρμογή με JSP, δε μας αρκεί ένας απλός

4
web server, αλλά πρέπει να εγκαταστήσουμε και έναν web container. Οι
περισσότεροι μεγάλοι application servers έρχονται σήμερα με ενσωματωμένο web
container (π.χ. Inspire, iPlanet, WebSphere). Υπάρχουν ωστόσο plugins που
εγκαθιστούν web containers σε υπάρχοντες web servers ώστε να τρέχουν τα JSP
(π.χ. JRun, ServletExec). O πιο διαδεδομένος web container είναι ο Apache Tomcat,
o οποίος είναι open source και έχει ενσωματωμένο και web server. Τον Tomcat, ως
γνωστό, τον έχετε ήδη εγκαταστήσει στον υπολογιστή σας.

Scriptlet και expression tags

Ένα τμήμα κώδικα Java που περικλείεται μέσα σε ένα αρχείο JSP ονομάζεται
scriptlet. To scriptlet το περικλείουμε ανάμεσα σε scriptlet tags (<% και %>) ως εξής:

html code
<% Java code %>
html code

Αν θέλουμε να εμφανίσουμε την τιμή μιας μεταβλητής στον browser τότε


γράφουμε τη μεταβλητή στο σημείο που θέλουμε να εμφανιστεί και την
περικλείουμε σε expression tags (<%= και %>) ως εξής:

Html
text <%= paramName %>
text
html

Άσκηση 2
Ακολουθεί ένα παράδειγμα που εμφανίζει την ημερομηνία.

<%@ page import="java.util.*" %>


<html>
<body>
<%
Date theDate = new Date();
%>
Hello! The time is now <%= theDate %>.
</body>
</html>

Σώστε το παρακάτω κομμάτι κώδικα ως ex2.jsp και αποθηκεύστε το στον κατάλογο


baseis_x. Δείτε το αποτέλεσμα στο web browser πληκτρολογώντας το κατάλληλο
URL.
Η πρώτη γραμμή του αρχείου είναι ένα ειδικό tag για να εισάγουμε τις βιβλιοθήκες
της Java για ημερομηνία. Στη συνέχεια αρχίζει ο κώδικας HTML. Παρεμβάλλεται ένα
scriptlet όπου ορίζουμε μια μεταβλητή που κρατά την ημερομηνία. Συνεχίζουμε τον

5
κώδικα HTML και, στο σημείο που θέλουμε να μας εμφανίσει την ημερομηνία
παρεμβάλλουμε expression tags όπου εσωκλείουμε τη μεταβλητή που ορίσαμε πιο
πριν.

Άσκηση 3
Ας δούμε ένα πιο σύνθετο παράδειγμα. Αντιγράψτε τον παρακάτω κώδικα σε ένα
αρχείο και ονομάστε το game.jsp. Δημιουργείστε το project baseis_x. Δείτε το
αποτέλεσμα στο web browser πληκτρολογώντας το κατάλληλο URL. Κάντε reload τη
σελίδα για επανάληψη.
<%
int dice1 = (int)(6*Math.random()+1);
int dice2 = (int)(6*Math.random()+1);
String answer;
if( dice1==dice2 )
answer ="Congradulations. You won!!!";
else
answer = "You are GADEMIS. Please try again...";
%>
<html>
<body>
Let's play <p>
You scored <%= dice1 %> and <%= dice2 %>.<p>
The System says: <%= answer %>
</body>
</html>

Το παραπάνω αρχείο JSP ενσωματώνει ένα κομμάτι κώδικα Java (scriptlet) που
παράγει δυο τυχαίους αριθμούς (dice1 και dice2, καθώς και ένα string (answer), με
βάση το αποτέλεσμα. Στη συνέχεια, με κώδικα HTML και με το expression tag <%=,
φτιάχνουμε το περιεχόμενο της ιστοσελίδας, εμφανίζοντας τα αποτελέσματα στο
χρήστη.
Έχετε υπόψη ότι μπορούμε να γράψουμε τον κώδικα Java οπουδήποτε μέσα στο
αρχείο. Αρκεί να τον ενσωματώνουμε στα scriptlet tags. Για παράδειγμα, στο
παραπάνω, αρχείο θα μπορούσαμε να σπάσουμε τον κώδικα Java σε δυο scriptlets
όπως παρακάτω, και να τα αναμείξουμε με τον κώδικα HTML:

Άσκηση 3.1

<%
int dice1 = (int)(6*Math.random()+1);
int dice2 = (int)(6*Math.random()+1);
String answer;
%>
<html>
<body>
<%
if( dice1==dice2 )

6
answer ="Congradulations. You won!!!";
else
answer = "You are GADEMIS. Please try again...";
%>
Let's play <p>
You scored <%= dice1 %> and <%= dice2 %>.<p>
The System says: <%= answer %>
</body>
</html>

Επαναληπτικοί βρόχοι σε JSP

Μέσω των επαναληπτικών βρόχων που προσφέρει η Java (while, for, do-while)
μπορούμε να εμφανίσουμε επαναληπτικά κείμενο HTML στο browser. Η φιλοσοφία
είναι απλή, αρκεί να καταλάβουμε το παρακάτω παράδειγμα. Δημιουργείστε το
αρχείο loop.jsp και δείτε το αποτέλεσμα στον browser.

Άσκηση 4

<body>
LOOP EXAMPLE:<p>
<%
for (int i=1; i<=5; i++)
{
%>
Loop executed <%= i %> times.<br>
<%
}
%>
</body>
</html>

Όπως βλέπετε, γράψαμε ένα scriptlet όπου ορίζουμε την αρχή του βρόχου. Μέσα
στο scriptlet γράφουμε κώδικα HTML (και αν θέλουμε κάποια JSP tags, όπως το
expression tag που γράψαμε παραπάνω). Κλείνουμε το βρόχο γράφοντας ένα
scriptlet που περιέχει μόνο το άγκιστρο ( } ) που κλείνει το βρόχο. Το κείμενο HTML
που περικλείεται μέσα στο βρόχο θα εκτελεστεί όσες φορές γίνει η επανάληψη.
Προσοχή στη χρήση των scriptlet tags. Η αρχή του βρόχου for είναι ένα κομμάτι
κώδικα Java, οπότε τον περικλείουμε στα tags <% και %>. Το κείμενο HTML που
γράφουμε στο browser και βρίσκεται μέσα στο βρόχο δεν είναι κώδικας Java, οπότε
δεν το περικλείουμε σε scriptlet tags. Ο βρόχος όμως δεν έκλεισε. Μας μένει ένα
άγκιστρο. Ακόμη όμως κι αυτό το αγκιστράκι είναι από μόνο του ένα κομμάτι
κώδικα Java, οπότε πρέπει να το περικλείσουμε σε tags.

7
Τρόπος ανάπτυξης αρχείων JSP

Γενικότερα, η πιο απλή φιλοσοφία για την ανάπτυξη (υλοποίηση) αρχείων JSP είναι
η
εξής:

• Γράφουμε μια στατική σελίδα HTML η οποία θα είναι η δυναμική σελίδα που
θέλουμε να φτιάξουμε, απλά το δυναμικό κομμάτι του κειμένου θα έχει κάποιες
ενδεικτικές τιμές στις παραμέτρους. Στο παραπάνω παράδειγμα στην αρχική
στατική σελίδα που φτιάξαμε, βάλαμε κάποιες ενδεικτικές τιμές για τα χρώματα και
το μέγεθος της γραμματοσειράς. Η παραπάνω διαδικασία είναι εξαιρετικά εύκολη,
αν αναλογιστούμε την πληθώρα προγραμμάτων που γράφουν HTML.
• Αποθηκεύουμε την παραπάνω σελίδα με κατάληξη jsp.
• Προσθέτουμε το τμήμα της προγραμματιστικής λογικής (κώδικας java ή κάτι άλλο,
όπως θα δούμε παρακάτω).
• Αντικαθιστούμε τα δυναμικά μέρη του κειμένου (που, προς το παρόν,
εμφανίζονται στατικά) με τις παραμέτρους των οποίων η τιμή θέλουμε να
εμφανίζεται.

Άσκηση 5

Για να δούμε ένα παράδειγμα, ας παίξουμε λίγο με τα χρώματα. Θέλουμε να


φτιάξουμε μια ιστοσελίδα η οποία, κάθε φορά που φορτώνεται να έχει διαφορετικό
φόντο, και διαφορετικό χρώμα και μέγεθος γραμματοσειράς.

Πρώτα φτιάχνουμε μια απλή σελίδα με τα παραπάνω στοιχεία fixed. Αντιγράψτε


την παρακάτω απλή σελίδα HTML σε ένα αρχείο και ονομάστε το colors.jsp.
Αποθηκεύστε το στον κατάλογο baseis_x και δείτε το αποτέλεσμα στον browser.

<html>

<body bgcolor="#CCCCCC" text="#000000">

<font size="+2">

With dynamic pages you can have different color on each visit
!!! <p>

You can also have different font !!!

</font>

</body>

</html>

8
Ο παραπάνω κώδικας απλά θέτει το background και το text color σε γκρι και μαύρο
αντίστοιχα (υπάρχουν συγκεκριμένοι κωδικοί όπως βλέπετε στη γραμμή 2), αυξάνει
το φόντο κατά το διπλάσιο του default και γράφει ένα απλό μήνυμα. Πώς μπορούμε
να έχουμε διαφορετικό background color, text color και font size κάθε φορά που
φορτώνουμε την ιστοσελίδα; Αρκεί να ορίζονται δυναμικά τρεις τιμές: Η #CCCCCC
που ορίζει το bgcolor, η #000000 που ορίζει το text color και ο αριθμός 2 που ορίζει
το μέγεθος της γραμματοσειράς. Τις τρεις αυτές τιμές πρέπει να τις παράγουμε
τυχαία. Ιδού ο τρόπος. Τροποποιήστε το αρχείο που φτιάξατε πριν όπως παρακάτω
και δείτε το αποτέλεσμα στο browser, κάνοντας refresh τη σελίδα.

<%
String textColor = Integer.toHexString((int)(16777215*Math.random()));
String backgrColor = Integer.toHexString((int)(16777215*Math.random()));
int fontSize = ((int)(4*Math.random()+1));
%>
<html>
<body bgcolor=<%= backgrColor%> text=<%= textColor%>>
<font size="+<%= fontSize%>">
With dynamic pages you can have different color on each visit !!! <p>
You can also have different font size!!!
</font>
</body>
</html>

Αυτό που κάναμε είναι το εξής:

Προγραμματιστική λογική: Προσθέσαμε ένα scriptlet όπου ορίζουμε τρεις


παραμέτρους μέσω Java, οι οποίες παράγουν δυο strings που αντιπροσωπεύουν το
text και το background color καθώς και έναν integer που αντιπροσωπεύει το
μέγεθος της γραμματοσειράς της ιστοσελίδας. Η παραγωγή των strings γίνεται
μετατρέποντας έναν τυχαίο αριθμό σε δεκαεξαδικό και μετά σε string.

Αντικατάσταση στατικού κειμένου με δυναμικό: Αντί να ορίσουμε ένα standard


χρώμα για το text και το background, το ορίζουμε δυναμικά, μέσω των παραμέτρων
που δημιουργήσαμε, οι οποίες παίρνουν διαφορετικές τιμές σε κάθε φόρτωμα της
ιστοσελίδας. Το ίδιο γίνεται και για τo font size.

Πέρασμα πληροφορίας σε αρχείο JSP από φόρμα HTML

Μέχρι στιγμής είδαμε αρχεία JSP που παράγουν δυναμικό κείμενο HTML στο
browser, με βάση κάποιες τυχαίες μεταβλητές ή με κάποιο επαναληπτικό βρόχο.
Στην πλειονότητα των περιπτώσεων όμως, η χρησιμότητα των JSP και, κατ’
επέκταση, των δυναμικών σελίδων, έγκειται στο ότι μπορούν να παράγουν
δυναμικό κείμενο, με βάση πληροφορία που δίνει ο χρήστης. Για παράδειγμα, σε

9
ιστοσελίδες για καταστήματα υπολογιστών, ο χρήστης έχει τη δυνατότητα να δει
όλα τα μοντέλα μιας
συγκεκριμένης μάρκας μόνο, ή όλα τα μοντέλα με συγκεκριμένο τύπο επεξεργαστή.

Για να υλοποιηθεί μια εφαρμογή όπως οι παραπάνω, πρέπει να υπάρχουν τα εξής:


Μια ιστοσελίδα HTML που θα κάνει τα εξής:
● Θα έχει μια φόρμα όπου ο χρήστης θα εισάγει τιμές σε κάποιες παραμέτρους.
● Θα καλέσει ένα αρχείο JSP στο οποίο θα δώσει τις τιμές κάποιων παραμέτρων. Το
αρχείο αυτό θα κληθεί μόλις πατηθεί το κουμπί της φόρμας. Το αρχείο HTML θα
φύγει τότε από το browser και θα φορτωθεί το αρχείο JSP.

Ένα αρχείο JSP που θα κληθεί από την ανωτέρω φόρμα το οποίο θα κάνει τα
ακόλουθα:

● Θα πάρει τις τιμές των παραμέτρων που εισήγαγε ο χρήστης.


● Θα τις επεξεργαστεί με κώδικα Java.
● Θα παράγει ένα δυναμικό κείμενο με HTML, βάσει των τιμών των παραμέτρων
του χρήστη, το οποίο θα εμφανιστεί στο browser.

Έχουμε ήδη δει πώς φτιάχνουμε μια φόρμα και πώς καλούμε ένα άλλο αρχείο (σε
μορφή link), όταν πατηθεί το κουμπί submit της φόρμας. Το πιο βασικό που πρέπει
να θυμόμαστε είναι το εξής:

Στον ορισμό της φόρμας δηλώνουμε και το αρχείο που θα φορτωθεί μόλις πατηθεί
το κουμπί της. Το αρχείο αυτό θα πάρει τις παραμέτρους που έδωσε ο χρήστης.
Η δήλωση αυτή γίνεται ως εξής:
<form name="formName" method="post" action="file.jsp">

Με τη δήλωση action="file.jsp", δηλώνουμε ότι, μόλις πατηθεί το κουμπί της


φόρμας (το οποίο είναι στην ουσία ένα hyperlink), θα φορτωθεί στον browser το
αρχείο file.jsp και θα πάρει τις τιμές απ’ όλες τις παραμέτρους της φόρμας.
Πώς όμως θα πάρουμε τις τιμές των παραμέτρων της φόρμας ενός αρχείου στο
JSP;

Η διαδικασία είναι η εξής:


Μόλις μια φόρμα καλέσει ένα αρχείο JSP, του δίνει κάποιες παραμέτρους. Το JSP
μπορεί να πάρει τις τιμές από αυτές τις παραμέτρους που του δώσανε, μέσω μιας
συνάρτησης της Java:
request.getParameter(“param”)
όπου param είναι το όνομα μιας παραμέτρου της φόρμας. Στο παρακάτω σχήμα
απεικονίζεται γραφικά η διαδικασία κατά την οποία ο χρήστης δίνει σε μια φόρμα
δυο αριθμούς, γίνεται πρόσθεση και εμφανίζεται το αποτέλεσμα.

10
Όπως βλέπουμε, ο ρόλος του JSP είναι τριπλός. Παίρνει τις παραμέτρους από το
αρχείο HTML, επιτελεί το προγραμματιστικό έργο μέσω Java και παράγει το κείμενο
που θα εμφανιστεί στο browser μέσω HTML.

Το παρακάτω παράδειγμα παίρνει τις τιμές που έδωσε ο χρήστης σε μια φόρμα και
τις εμφανίζει στο browser.

Άσκηση 6
Αντιγράψτε τον παρακάτω κώδικα σε ένα αρχείο, ονομάστε το yourself.html.

<html>
<body>
Tell me about yourself...<p>
<form name="yourself" method="post"
action="yourself.jsp">
What is your name?: <input type="text"
name="yourName"><p>
How old are you?: <input type="text" name="yourAge"><p>
Where are you from?: <input type="text"
name="yourCity"><p>
What is your favorite pet?: <input type="text"
name="yourPet"><p>
May I have your email?: <input type="text"
name="yourEmail"><p>
<input type="submit" value="Thank you!">
</form>
</body>
</html>

11
Αντιγράψτε τώρα τον παρακάτω κώδικα σε ένα αρχείο yourself.jsp και αποθηκεύστε
το στον ίδιο φάκελο.

<%
String userName = request.getParameter("yourName");
String userAge = request.getParameter("yourAge");
String userCity = request.getParameter("yourCity");
String userPet = request.getParameter("yourPet");
String userEmail = request.getParameter("yourEmail");
%>
<html>
<body>
This is what I learned from you:<p>
Your name is <%=userName%>.<p>
You are <%=userAge%> years old.<p>
You are from <%=userCity%>.<p>
Your favorite pet is <%=userPet%>.<p>
I can find you in the following address: <%=userEmail%>.<p>
Have a nice day!!!<p>
<a href="yourself.html">Go Back</a>
</body>
</html>

Δείτε το αποτέλεσμα πληκτρολογώντας στο browser το URL του αρχείου


yourself.html.

Το αρχείο yourself.html έχει μια φόρμα με 5 text boxes καθένα από τα οποία
δέχεται τιμή για μια παράμετρο: yourName, yourAge, yourCity, yourPet, yourEmail.
Μόλις πατηθεί το κουμπί “Thank You” θα φορτωθεί το αρχείο yourself.jsp.
Στο αρχείο yourself.jsp γίνονται τα εξής: Αρχικά παίρνουμε τις τιμές από τις
παραμέτρους της φόρμας και τις καταχωρούμε σε τοπικές μεταβλητές: userName,
userAge, userCit, userPet, userEmail. Η φόρμα δε μας απασχολεί πλέον καθόλου.
Δουλεύουμε με τις μεταβλητές που έχουμε ορίσει, οι οποίες κρατούν την
πληροφορία του χρήστη. Στη συνέχεια γράφουμε το κείμενο που θα εμφανιστεί
στον browser. Γράφουμε HTML και, όπου χρειάζεται, παρεμβάλλουμε κάποια
μεταβλητή κλεισμένη σε expression tags.

12
Άσκηση 7
Αντιγράψτε τον παρακάτω κώδικα στο αρχείο input.html και αποθηκεύστε το στο
φάκελο baseis_x.
<html>
<body>
What is your sex?<br>
Type 1 for boy or 2 for girl.<p>
<form name="mySelf" method="post" action="respond.jsp">
<input type="text" name="sex">
<input type="submit" value="Continue">
</form>
</body>
</html>
Αντιγράψτε τον παρακάτω κώδικα στο αρχείο respond.jsp και αποθηκεύστε το στο
φάκελο baseis_x.
<%
String userSex = request.getParameter("sex");
String resp;
if(userSex.equals("1")) resp = "Let's talk about cars.";
else if(userSex.equals("2")) resp = "Let's talk about
fashion.";
else resp = "Invalid choice. Try again.";
%>
<html>
<body>
<%= resp%><p>
<a href="input.html">Go Back</a>
</body>
</html>

Δείτε το αποτέλεσμα πληκτρολογώντας το URL του αρχείου input.html στο browser.

Στο αρχείο HTML έχουμε μια φόρμα όπου ο χρήστης δίνει τιμή σε μια παράμετρο
sex. Μόλις πατηθεί το κουμπί της φόρμας καλείται το αρχείο respond.jsp. Το αρχείο
JSP παίρνει την τιμή της παραμέτρου που του έδωσε η φόρμα και την καταχωρεί σε
μια δική του μεταβλητή με όνομα userSex. Στη συνέχεια παράγει ένα κείμενο στη
μεταβλητή resp, ανάλογα με την τιμή που έδωσε ο χρήστης. Το κείμενο αυτό είναι
μια πρόταση από το κείμενο που θα εμφανιστεί στο browser. Στη συνέχεια
γράφουμε το κείμενο HTML που θα εμφανιστεί στο browser, το οποίο φυσικά
εξαρτάται από την τιμή της μεταβλητής resp.

13
Πέρασμα πληροφορίας σε αρχείο JSP μέσω URL

Πολλές φορές είναι επιθυμητό να περνάμε τις παραμέτρους σε ένα αρχείο JSP μέσω
του URL του, χωρίς να τις έχει δώσει ο χρήστης σε φόρμα. Τέτοιες περιπτώσεις
έχουμε όταν ένα αρχείο JSP ή HTML έχει πάρει ήδη κάποιες παραμέτρους και θέλει
να τις δώσει σε κάποιο άλλο αρχείο JSP. Αυτό γίνεται εύκολα, αν ορίσουμε το όνομα
και την τιμή των παραμέτρων αυτών στο URL του αρχείου JSP που θα τις πάρει. Η
μορφή του URL του αρχείου JSP που θα πάρει τις παραμέτρους θα έχει τότε την
εξής μορφή:

http://server_IP:port/path/file.jsp?param1=value1&param2=value2

Για να γίνει το παραπάνω πιο αντιληπτό, γράψτε στο browser το εξής URL:
http://localhost:8080/baseis_x/respond.jsp?sex=1

Θα παρατηρήσετε ότι έχουμε το ίδιο αποτέλεσμα όπως αν θα χρησιμοποιούσαμε τη


φόρμα του αρχείου input.html. Φυσικά, δεν υπάρχει ποτέ περίπτωση να βάλουμε
το χρήστη να πληκτρολογεί παραμέτρους σε ένα URL που θα γράψει. Τα γράφουμε
εμείς στον κώδικά μας.
Για να γίνει το παραπάνω πιο αντιληπτό, θα αλλάξουμε τον κώδικα του αρχείου
input.html, ώστε η παράμετρος sex να δίνεται από το URL του JSP που θα κληθεί.

Άσκηση 7.1
Αντιγράψτε τον παρακάτω κώδικα σε ένα αρχείο, ονομάστε το input2.html.

<html>
<body>
What is your sex?<p>
<a href="respond.jsp?sex=1" > Boy </a><br>
<a href="respond.jsp?sex=2" > Girl </a><br>
</body>
</html>

Παρατηρήστε ότι έχουμε ακριβώς το ίδιο αποτέλεσμα όπως και στο προηγούμενο
παράδειγμα. Παρατηρήστε επίσης ότι τώρα, μόλις φορτώνεται το αρχείο JSP
φαίνονται και οι παράμετροι που δώσαμε.
Το παραπάνω αρχείο HTML απλά δημιουργεί δυο hyperlinks στο αρχείο JSP,
περνώντας διαφορετική τιμή για την παράμετρο sex κάθε φορά. Δεν έχουμε γράψει
όλο το path του URL (absolute path) αλλά μόνο το όνομα του αρχείου (relative path)
αφού τα δυο αρχεία βρίσκονται στον ίδιο server.
ΠΡΟΣΟΧΗ: Έχετε υπόψη κάτι σημαντικό. Δεν περικλείουμε τις τιμές των
παραμέτρων σε quotes, τις αφήνουμε όπως είναι. Ακόμη και για τα strings. Αν ένα
string έχει και κενά, τότε τα κενά τα αντικαθιστούμε με το σύμβολο ‘ % ’.
Τώρα μπορούμε να καταλάβουμε γιατί όταν σε κάποια sites κάνουμε κλικ σε ένα
link, προκύπτει στο browser ένα URL με μήκος κάποιων χιλιομέτρων και με διάφορα
σύμβολα όπως ‘ ? ‘, ‘ = ‘, ‘ % ‘ κ.α.

14
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 10: Σύνδεση με Βάση Δεδομένων MySql

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Εισαγωγή .......................................................................................................................... 3
2. Σύνδεση στη βάση δεδομένων MySQL μέσω Java ........................................................... 4
3. Insert-delete-update-select statements μέσω Java ......................................................... 8
Άσκηση1. Παράδειγμα χρήσης embedded select statement. ....................................... 11

Στόχος του εργαστηρίου είναι η εξοικείωση με το JDBC API το οποίο μας παρέχει τη
δυνατότητα να διαχειριστούμε μια βάση δεδομένων χρησιμοποιώντας εντολές Java.
Μετά την επεξεργασία του εργαστηρίου ο ενδιαφερόμενος θα είναι σε θέση να
δημιουργήσει μια εφαρμογή διαχείρισης των δεδομένων μιας βάσης κάνοντας
χρήση εντολών jsp.

Λέξεις κλειδιά: JDBC, JSP, MySQL.

2
1. Εισαγωγή

Το JDBC API

H Java παρέχει ένα προγραμματιστικό περιβάλλον (API) για σύνδεση σε βάσεις


δεδομένων, γνωστό ως Java Database Connectivity (JDBC). Το συγκεκριμένο API μας
παρέχει τη δυνατότητα να διαχειριστούμε μια βάση δεδομένων μέσω εντολών SQL.
Για να χρησιμοποιήσουμε το JDBC API απαιτούνται δυο ομάδες βιβλιοθηκών, τις
οποίες πρέπει να φορτώσουμε στο πρόγραμμά μας.

 Η μια μας παρέχει τις απαραίτητες κλάσεις και μεθόδους ώστε να μπορούμε
να συνδεθούμε στη συγκεκριμένη βάση δεδομένων. Η συγκεκριμένη ομάδα
βιβλιοθηκών είναι ξεχωριστή για κάθε βάση δεδομένων (π.χ. Oracle, MySQL,
Access) και παρέχεται από τον εκάστοτε κατασκευαστή της βάσης. Είναι
γνωστή ως JDBC driver.

 Η δεύτερη μας παρέχει τις απαραίτητες κλάσεις και μεθόδους για να


κάνουμε ενέργειες στη βάση δεδομένων, δηλαδή να γράφουμε SQL. Καθώς
η SQL είναι ίδια για όλες τις βάσεις δεδομένων, έτσι και η συγκεκριμένη
βιβλιοθήκη είναι κοινή, ανεξάρτητα της βάσης που θα χρησιμοποιήσουμε. Η
βιβλιοθήκη αυτή περιέχεται ήδη στη Java και είναι το package java.sql.

Αν γράψουμε μια εφαρμογή σε Java, που διαχειρίζεται μια συγκεκριμένη βάση


δεδομένων (π.χ. MySQL), η εφαρμογή αυτή, με λίγες αλλαγές, θα λειτουργεί και σε
άλλη βάση δεδομένων (π.χ. Oracle), αρκεί να αλλάξουμε τον JDBC driver. Για τη
MySQL, ο JDBC driver είναι ένα αρχείο jar το οποίο φορτώνουμε στην εφαρμογή
μας.

Εμβάθυνση στην embedded SQL

Στο παρόν κεφάλαιο θα εμβαθύνουμε στις ειδικές συναρτήσεις που μας παρέχει η
Java για να γράφουμε εντολές SQL. Συγκεκριμένα, θα ασχοληθούμε με την εντολή
myStatement.methodName(sqlString) και με τους διάφορους τρόπους που μας
παρέχει για να διαχειριζόμαστε πληροφορία από βάση δεδομένων.

3
2. Σύνδεση στη βάση δεδομένων MySQL μέσω Java

Για να συνδεθούμε στη βάση δεδομένων MySQL και να γράψουμε εντολές SQL
απαιτούνται οι εξής ενέργειες:

Δήλωση του JDBC driver στο classpath

O JDBC driver για MySQL παρέχεται στη σελίδα της MySQL. Είναι ένα μικρό αρχείο
jar με όνομα mysql-connector-java- 5.1.13 -bin.jar ή mysql.jar(e-class). Το αρχείο
αυτό πρέπει να το βάλουμε στους καταλόγους jre_Home/lib/ext και
jdk_Home/jre/lib/ext ή να το δηλώσουμε στην εφαρμογής μας libraries>δεξί κλικ>
Add Jar/Folder και επιλέγουμε το αρχείο mysql-connector-java- 5.1.13 -bin.jar ή
mysql.jar

.Συνίσταται η τελευταία λύση, καθώς έτσι θα το βλέπει οποιαδήποτε εφαρμογή το


χρειάζεται.

Εισαγωγή του package java.sql στο πρόγραμμά μας

Η εισαγωγή ενός package σε πρόγραμμα java γίνεται με την εντολή

import packageName.className ή import packageName.* (για όλες τις κλάσεις).

Στη δική μας περίπτωση θα πρέπει να γράψουμε την εντολή

import java.sql.*;

4
Φόρτωμα του JDBC driver

Το φόρτωμα του JDBC driver γίνεται φορτώνοντας την κλάση Driver από το

package com.mysql.jdbc. Το φόρτωμα μιας κλάσης γίνεται μέσω της εντολής

Class.forName(“ClassName”);

Στην περίπτωσή μας πρέπει να γράψουμε την εντολή:

Class.forName(“com.mysql.jdbc.Driver”);

Παρατηρήστε ότι γράψαμε ολόκληρο το path της κλάσης Driver, καθώς αυτή
περιέχεται σε package. Θα μπορούσαμε να γράψουμε μόνο το όνομα της κλάσης,
αλλά να είχαμε πριν συμπεριλάβει το αντίστοιχο package στο πρόγραμμά μας,
μέσω της εντολής

import com.mysql.jdbc

Σύνδεση στη βάση δεδομένων

Η σύνδεση στη βάση δεδομένων γίνεται δημιουργώντας ένα αντικείμενο τύπου


Connection. Μέσω του αντικειμένου αυτού θα μπορούμε να γράφουμε εντολές SQL.
Η δημιουργία ενός αντικειμένου τύπου Connection (π.χ. myConnection) γίνεται με
την παρακάτω εντολή:

Connection myConnection = DriverManager.getConnection(myDatabase);

MyDatabase είναι μια συμβολοσειρά (string) τη μορφής:

“jdbc:mysql://ServerName:ServerPort/DatabaseName?user=myUsername&passwor
d=myPassword";

5
 ServerName είναι το όνομα ή η διεύθυνση ΙΡ του database server.

 ServerPort είναι η θύρα επικοινωνίας του database server MySQL


(default=3306).

 DatabaseName είναι το όνομα της βάσης δεδομένων που θα


χρησιμοποιήσουμε.

 myUsername και myPassword είναι το username και το password που


χρησιμοποιούμε για να συνδεθούμε στη mySQL.

Αν χρησιμοποιούσαμε μια βάση δεδομένων με όνομα test, ο MySQL server έτρεχε


τοπικά στο σύστημά μας και συνδεόμασταν με username: teiath και
password:aigaleo, τότε οι εντολές για σύνδεση θα είχαν ως εξής:

String testDatabase =
“jdbc:mysql://localhost:3306/mydb1?user=teiath&password=aigaleo";

Connection myConnection = DriverManager.getConnection(testDatabase);

ΠΡΟΣΟΧΗ: Μη συγχέετε το username και το password με τα οποία συνδεόμαστε


στη βάση δεδομένων με το username και password που πιθανόν να απαιτείται να
δώσει ο χρήστης για να χρησιμοποιήσει την εφαρμογή που φτιάχνουμε. Τα πρώτα
χρησιμοποιούνται από το ίδιο το πρόγραμμα, και μόνο από αυτό, για να συνδεθεί
το πρόγραμμα στη βάση δεδομένων. Τα δεύτερα χρησιμοποιούνται από το χρήστη,
για τη δική μας εφαρμογή, και τα ορίζουμε εμείς, ή βάζουμε το χρήστη να τα ορίσει.

Δημιουργία αντικειμένου για να γράψουμε SQL statements

Έχοντας το αντικείμενο myConnection, το οποίο στην ουσία είναι μια ανοιχτή


σύνδεση με τη βάση δεδομένων, μπορούμε να δημιουργήσουμε αντικείμενο τύπου
Statement (και όνομα, π.χ. myStatement) μέσω του οποίου θα γράφουμε εντολές
SQL. Αυτό γίνεται με την εντολή:

Statement myStatement = myconnection.createStatement();

6
Εγγραφή και εκτέλεση SQL statements

Στη συνέχεια γράφουμε την εντολή SQL που θέλουμε να εκτελεστεί. Η


συγκεκριμένη εντολή γράφεται σε μορφή string, όπως ακριβώς θα τη γράφαμε αν
την εκτελούσαμε από το περιβάλλον της mySQL. Για παράδειγμα:

String sqlString = "INSERT INTO USERS VALUES ('user1', 'password1')";

Για να εκτελέσουμε την εντολή που γράψαμε παραπάνω χρησιμοποιούμε το


αντικείμενο myStatement που δημιουργήσαμε, το οποίο μας παρέχει διάφορες
μεθόδους, ανάλογα με το τι κάνει η εντολή SQL που δίνουμε. H σύνταξη της εντολής
που γράφουμε για να εκτελέσουμε την SQL statement είναι:

myStatement.methodName(sqlString);

Για την εντολή insert που γράψαμε παραπάνω, η μέθοδος θα είχε ως εξής:

myStatement.executeUpdate(sqlString);

Αν η sqlString αφορούσε μια SQL statement τύπου select, η μέθοδος θα ήταν:

myStatement.executeQuery(sqlString);

Τις διάφορες μεθόδους των αντικειμένων τύπου Connection για να εκτελούμε SQL
statements θα τις δούμε αναλυτικά σε επόμενα κεφάλαια.

Κλείσιμο του αντικειμένου εγγραφής SQL statements

Αφού έχουμε τελειώσει με την εκτέλεση των SQL statements πρέπει να κλείσουμε
το αντικείμενο εγγραφής SQL statements. Αυτό γίνεται απλά με την εντολή

myStatement.close();

7
Κλείσιμο της σύνδεσης

Τέλος, για να κλείσουμε τη σύνδεση με τη βάση δεδομένων, γράφουμε την εντολή

myConnection.close();

3. Insert-delete-update-select statements μέσω Java

Στο προηγούμενο κεφάλαιο ασχοληθήκαμε με τη σύνδεση σε μια βάση δεδομένων


MySQL. Μάθαμε ότι, για να γράψουμε μια εντολή SQL, χρησιμοποιούμε τη μέθοδο

myStatement.methodName(sqlString);

όπου myStatement είναι ένα αντικείμενο τύπου Statement και methodName είναι
μια από τις πολλές μεθόδους που παρέχει η κλάση Statement. Θα ασχοληθούμε
λίγο παραπάνω με τις διάφορες μορφές της μεθόδου methodName.

Εισαγωγή δεδομένων (insert statement)

Όπως είδαμε στο προηγούμενο μάθημα, για να κάνουμε εισαγωγή δεδομένων στη

βάση, χρησιμοποιούμε τη μέθοδο executeUpdate μέσω της εντολής:

myStatement.executeUpdate(sqlString);

όπου sqlString είναι μια συμβολοσειρά της μορφής:

String sqlString = "INSERT INTO MYTABLE VALUES ('value1', 'value2')";

Διαγραφή δεδομένων (delete statement)

Για διαγραφή δεδομένων χρησιμοποιούμε πάλι τη μέθοδο executeUpdate μέσω της

εντολής:

myStatement.executeUpdate(sqlString);

όπου τώρα sqlString είναι της μορφής:

String sqlString = "DELETE FROM MYTABLE WHERE PARAM = 'paramValue'";

8
Ανανέωση δεδομένων (update statement)

Για ανανέωση δεδομένων χρησιμοποιούμε τη μέθοδο executeUpdate μέσω της

εντολής:

myStatement.executeUpdate(sqlString);

όπου τώρα sqlString είναι της μορφής:

String sqlString = "UPDATE MYTABLE SET PARAM1='value1' WHERE


PARAM2='value2'";

Επιλογή δεδομένων (select statement)

Για επιλογή δεδομένων χρησιμοποιούμε τη μέθοδο executeQuery μέσω της

εντολής:

ResultSet rs = myStatement.executeQuery(sqlString);

όπου sqlString είναι μια συμβολοσειρά της μορφής:

String sqlString = "SELECT * FROM MYTABLE WHERE PARAM = 'paramValue'";

Η μέθοδος executeQuery μας δίνει τη δυνατότητα να τραβήξουμε από τη βάση


κάποια δεδομένα. Τα δεδομένα αυτά όμως πρέπει να τα αποθηκεύσουμε
προσωρινά σε κάποια δομή στο πρόγραμμά μας, ώστε να τα χρησιμοποιήσουμε. Η
Java μας δίνει μια εύχρηστη δομή μέσω της κλάσης ResultSet. Πιο συγκεκριμένα, η
μέθοδος ExecuteQuery μας επιστρέφει ένα αντικείμενο τύπου ResultSet. Μέσα στο
αντικείμενο αυτό αποθηκεύονται προσωρινά όλες οι εγγραφές (γραμμές πίνακα)
από την ερώτηση που κάναμε στη βάση δεδομένων. Το συγκεκριμένο αντικείμενο
μας παρέχει και έναν δείκτη ο οποίος αρχικά δείχνει ΠΡΙΝ από την πρώτη εγγραφή
που είναι αποθηκευμένη στο αντικείμενο. Μέσω του αντικειμένου αυτού μπορούμε
να επεξεργαστούμε τις εγγραφές στο πρόγραμμά μας. Ας ονομάσουμε το
συγκεκριμένο αντικείμενο rs. Παρακάτω φαίνεται σχηματικά η διαδικασία που
περιγράψαμε προηγουμένως.

9
Το rs (ως αντικείμενο της κλάσης ResultSet) μας παρέχει μεθόδους για να
επεξεργαζόμαστε τις εγγραφές που τραβήξαμε από τη βάση δεδομένων. Οι πιο
σημαντικές μέθοδοι ναφέρονται παρακάτω:

Για να πάρουμε τώρα πληροφορία που είναι καταχωρημένη στο αντικείμενο rs,

πρέπει να κάνουμε δυο πράγματα:

 Να μετακινήσουμε τη δείκτη στην εγγραφή που θέλουμε να πάρουμε (ή να


τον μετακινούμε διαδοχικά αν θέλουμε να τις πάρουμε όλες). Αυτό γίνεται
με μια από τις μεθόδους next(), previous(), first(), last() που είδαμε
παραπάνω.

 Να χρησιμοποιήσουμε μια συνάρτηση που θα πάρουμε πληροφορία από


μια στήλη. Αυτό γίνεται με τις συναρτήσεις getString, getInt, getFloat
getDate κ.τ.λ.

10
Άσκηση1. Παράδειγμα χρήσης embedded select statement.
Θα δούμε ένα τυπικό παράδειγμα χρήσης της executeQuery, καθώς και του τρόπου
που χρησιμοποιούμε τις διάφορες μεθόδους της κλάσης ResultSet.

Ξεκινήστε τη MySQL αν δεν έχει ήδη ξεκινήσει με τα windows, ανοίγοντας μια


γραμμή εντολών και γράφοντας

net start mySQL

Συνδεθείτε στη βάση δεδομένων γράφοντας την εντολή

mysql –u root

Συνδεθείτε στη βάση mydb1:

use mydb1

Δημιουργήστε τον πίνακα myTable,

ID Int

Name Text

δείτε τη δομή του και το τι περιέχει, γράφοντας τις εντολές:

describe myTable

select * from myTable

Έστω ότι έχουμε τον παραπάνω πίνακα με όνομα myTable:

11
Δημιουργείστε ένα αρχείο test.jsp και γράψτε τον παρακάτω κώδικα:

<%@page import="java.sql.*" %>

<%

int j=0;

//Define parameters for retrieving database results

int m[] = new int[5000];

String s[] = new String[5000];

//Load the driver

Class.forName("com.mysql.jdbc.Driver");

//Define the connection parameters

String myDatabase = "jdbc:mysql://localhost:3306/mydb1?user=root";

//Connect to the database

Connection myConnection = DriverManager.getConnection(myDatabase);

//Create object to execute statements

Statement myStatement = myConnection.createStatement();

//Select everything from the database

String sqlString = "SELECT * FROM myTable ";

ResultSet rs=myStatement.executeQuery(sqlString);

//Store the results in vectors in order to pass them to the JSP

while(rs.next()){

m[j]=rs.getInt("id");

s[j]=rs.getString("name");

j++;

//Close the connection to the database

myStatement.close();

myConnection.close();

for(int i=0; i<j; i++)

12
out.println(i+"___"+m[i]+"<br>");

out.println(i+"___"+s[i]+"<br>");

%>

Στη συνέχεια τρέξτε το πρόγραμμα.

Τα βήματα είναι τα παρακάτω.

1. Ορίζουμε δυο παραμέτρους.

2. Στις παραμέτρους αυτές θα καταχωρήσουμε τις τιμές των δυο πεδίων του
πίνακα mytable1.

3. Φορτώνουμε το driver και προετοιμάζουμε τη συμβολοσειρά για σύνδεση.

4. Συνδεόμαστε τοπικά, με username root και κενό password, στη βάση


δεδομένων mydb1.

5. Συνδεόμαστε στη βάση δεδομένων, δημιουργούμε το αντικείμενο τύπου


statement και προετοιμάζουμε την SQL string.

6. Εκτελούμε το SQL Statement.

7. Μέχρι στιγμής έχουμε καταφέρει όλο τον πίνακα να τον καταχωρήσουμε στο
αντικείμενο rs. Μένει να πάρουμε τα στοιχεία του rs. Αυτό γίνεται με έναν
βρόχο while.

8. Η εντολή while(rs.next()) έχει διπλό ρόλο:Εκτελεί την εντολή rs.next().Ελέγχει


αν rs.next()=true. Αυτό σημαίνει ότι, αν rs.next()=true, τότε ο βρόχος θα
εκτελεστεί. Αν rs.next()=false τότε ο βρόχος δε θα εκτελεστεί και το
πρόγραμμα θα προχωρήσει παρακάτω. Βλέποντας τον πίνακα με τις
μεθόδους της resultSet, φαίνεται ότι η rs.next() επιστρέφει true αν υπάρχει
επόμενη εγγραφή για να διαβάσει. Αν δεν υπάρχει επόμενη εγγραφή,
δηλαδή έχει φτάσει στο τέλος, τότε επιστρέφει false. Με τον τρόπο αυτό, αν
υπάρχει επόμενη εγγραφή, ο βρόχος εκτελείται, και σταματά να εκτελείται
όταν οι εγγραφές τελειώσουν. Ο βρόχος κάνει το εξής:

a. Διαβάζει, τα πεδία της τρέχουσας εγγραφής και τα καταχωρεί στις


αντίστοιχες μεταβλητές του προγράμματος (m[j], (m[j],), μέσω της
μεθόδου getString() ή getInt().

b. Τυπώνει στην οθόνη τις παραπάνω μεταβλητές.

13
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 11: Σύνδεση Οντολογιών με Βάσεις Δεδομένων

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Σύνδεση Οντολογιών με Βάσεις Δεδομένων.................................................................... 3
1.1 Παράδειγμα υλοποίησης και χρήσης της βάσης σε mySQL. .................................... 5
1.2 Protégé .................................................................................................................... 12
Βιβλιογραφία-σύνδεσμοι ............................................................................................... 22

Στόχος του εργαστηρίου είναι η εξοικείωση με τις οντολογίες, η σύνδεση μιας


σχεσιακής βάσης με μια οντολογία και η εκτέλεση ερωτημάτων στην οντολογία,
χρησιμοποιώντας τη γλώσσα sparql.

Λέξεις κλειδιά: Protege, Sparql, EER, RDF, Οντολογία.

2
1. Σύνδεση Οντολογιών με Βάσεις Δεδομένων

Θέλετε να υλοποιήσετε μία απλοποιημένη βάση δεδομένων δημοσιεύσεων.

Για παράδειγμα, μπορείτε να ορίσετε μία βάση με όνομα publications που


περιλαμβάνει τουλάχιστον τα εξής στοιχεία:

Στοιχεία περιοδικού (journal)


Μοναδικός αριθμός - ISSN CHAR(9)
Τίτλος – title κ.λπ.

Παραδείγματα περιοδικών είναι τα παρακάτω:

1231-1242 Security and Communication Networks Κ.λπ.


421-442 Journal of Information Science
563-573 Personal and Ubiquitous Computing

Στοιχεία άρθρου περιοδικού (paper)


Μοναδικός αριθμός άρθρου - P_id
Τίτλος - title
Περιοδικό στο οποίο δημοσιεύεται [δηλαδή ISSN char(9)]
Έτος έκδοσης τεύχους κ.λπ.

Παραδείγματα άρθρων περιοδικών είναι τα παρακάτω:

1 1231- Identifying and utilizing secure paths in ad hoc 2011 Κ.λπ.


1242 assistive medical environments
2 421-442 A parametric methodology for text classification 2010
3 563-573 'Providing advanced remote medical treatment 2010
services through pervasive environments

Στοιχεία συγγραφέων (journal)


Μοναδικός αριθμός - A_id
Επώνυμο, όνομα κ.λπ.

Παραδείγματα συγγραφέων είναι τα παρακάτω:


(1, Petros, Belsis, …),
(2, Nikitas, Karanikolas, …),
(3, Christos, Skourlas, …),
(4,Tasos,Tsolakidis, …),
(5,Dimitris,Vassis).
Αυτά τα στοιχεία μαζί με τα στοιχεία για το ποιος έχει γράψει τι πρέπει να τα
καταχωρίσουμε σε πίνακες που θα σχεδιάσετε και θα κατασκευάσετε.

3
1) Αποφασίστε ποια δεδομένα θα διαχειρισθείτε. Δώστε παραδείγματα των
δεδομένων αυτών. Χρησιμοποιήστε τα παραδείγματά μας και εμπλουτίστε.
2) Γράψτε σύντομα τι είναι το ISSN.
3) Σχεδιάστε τη βάση σας και υλοποιήστε χρησιμοποιώντας mySQL και Oracle
Express.
4) Να χρησιμοποιήσετε το εργαλείο mySQL Workbench για να δημιουργήσετε
αυτόματα το μοντέλο οντοτήτων συσχετίσεων από τους πίνακες της βάσης.
Δείτε το ίδιο διάγραμμα σε UML κ.λπ.
5) Δείτε τη δυνατότητα να σχεδιάσετε το μοντέλο και το περιβάλλον mySQL
Workbench να σας δημιουργήσει αυτόματα τους πίνακες (προαιρετικό) σε
παράδειγμα της επιλογής σας.
6) Εισάγετε στοιχεία στους πίνακες και δημιουργήστε εντολές αναζήτησης σε
γλώσσα SQL
7) Γράψτε σύντομα τι είναι οντολογία και που χρησιμοποιείται, τι είναι RDF, τι
είναι XML, τι είναι SPARQL
8) Εγκαταστήστε το λογισμικό Protégé και ότι άλλο χρειασθείτε για οπτικοποίηση
της οντολογίας (βλέπε και υποδείξεις παρακάτω)
9) Δημιουργήστε οντολογία βασιζόμενη στους πίνακες που δημιουργήσατε.
10) Γράψτε queries μέσα από το περιβάλλον του Protégé και με SPARQL.

4
Υποδείξεις

1.1 Παράδειγμα υλοποίησης και χρήσης της βάσης σε mySQL.

DROP DATABASE publications;


CREATE DATABASE publications;
USE publications;

CREATE TABLE journal (


ISSN CHAR(9)NOT NULL,
title varchar(145),
PRIMARY KEY (ISSN));

INSERT INTO journal VALUES


('1231-1242','Security and Communication Networks'),
('421-442','Journal of Information Science'),
('563-573','Personal and Ubiquitous Computing');

SELECT * FROM journal;

CREATE TABLE paper (


P_id int(11) NOT NULL,
title varchar(145),
ISSN char(9),
Pub_year YEAR,
PRIMARY KEY (P_id),
FOREIGN KEY(ISSN) REFERENCES journal(ISSN));

INSERT INTO paper VALUES


(1,'Identifying and utilizing secure paths in ad hoc assistive medical environments',
'1231-1242', '2011'),
(2,'A parametric methodology for text classification', '421-442', '2010'),
(3,'Providing advanced remote medical treatment services through pervasive
environments', '563-573', '2010');

SELECT * FROM paper;

CREATE TABLE author (


A_id int(11) NOT NULL,
Name varchar(45),
Surname varchar(45),
PRIMARY KEY (A_id));

5
INSERT INTO author VALUES
(1, 'Petros','Belsis'),
(2, 'Nikitas', 'Karanikolas'),
(3, 'Christos', 'Skourlas'),
(4,'Tasos','Tsolakidis'),
(5,'Dimitris','Vassis');

SELECT * FROM author;

CREATE TABLE writer (


a_id int(11) NOT NULL,
p_id int(11) NOT NULL,
PRIMARY KEY (a_id,p_id),
FOREIGN KEY(a_id) REFERENCES author(a_id),
FOREIGN KEY(p_id) REFERENCES paper(p_id));

INSERT INTO writer VALUES (1,1), (1,3), (2,2), (3,1),(3,2),(3,3), (4,3),


(5,1), (5,3);

SELECT surname, paper.title, journal.title


FROM author, writer, paper, journal
WHERE author.a_id=writer.a_id
AND writer.p_id=paper.p_id
AND paper.ISSN=journal.ISSN;

Import Backup.sql
Για να φορτώσουμε τα δεδομένα ενός αρχείου (script) τύπου Backup.sql, επιλέγουμε
Manage Import / Export .

Δημιουργία EER model


Για να δημιουργήσουμε ένα ΕΕR model, εκτελούμε τις παρακάτω ενέργειες.

6
Α. Ανοίγουμε το Workbench. Εμφανίζεται η παρακάτω οθόνη στην οποία επιλέγουμε create
ΕΕR model from existing Database. Εναλλακτικά μπορούμε να βασίσουμε τη δημιουργία σε
script με τις εντολές CREATE TABLE.

Β. Συμπληρώνουμε τα στοιχεία της φόρμας (hostname, port, user, password)

7
Γ. Επιλέγουμε το όνομα της βάσης για το οποίο θέλουμε να δημιουργήσουμε το ΕΕR model

Δ. Εμφανίζονται οι πίνακες με τις αντίστοιχες συσχετίσεις.

8
Χρησιμοποιώντας το μενού του περιβάλλοντος μόλις κατασκευάσουμε το διάγραμμα
μπορούμε να δούμε εναλλακτικά το ίδιο διάγραμμα και με άλλους συμβολισμούς πχ σε
UML

Ανάλυση της βάσης publication


Στο παράδειγμά μας, η βάση αποτελείται από τους πίνακες author, journal, paper, writer.
Τα περιεχόμενα των πινάκων ακολουθούν στη συνέχεια

 SELECT * FROM publications.author;

 SELECT * FROM publications.journal;

9
 SELECT * FROM publications.paper;

 SELECT * FROM publications.writer;

10
Γράψτε Queries του τύπου:

«Δείξτε τα επίθετα των συγγραφέων μαζί με τους τίτλους papers, journals στα οποία
συμμετείχαν"

SELECT surname, paper.title, journal.title


FROM author, writer, paper, journal
WHERE author.a_id=writer.a_id
AND writer.p_id=paper.p_id
AND paper.ISSN=journal.ISSN;

11
1.2 Protégé

Σκοπός της παρακάτω ενότητας είναι να δούμε πως μπορούμε να συνδέσουμε


σχεσιακή βάση σε mysql με το protege και να τη μετατρέψουμε σε μια οντολογία.

Αρχικά κατεβάζουμε και εγκαθιστούμε το protégé από τη διεύθυνση


(http://protege.stanford.edu/download/download.html ) .

Στην συνέχεια ανοίγουμε το protégé και επιλεγούμε Νew project

12
Επιλέγουμε OWL/RDF Files

13
Για να μπορέσουμε να φορτώσουμε τη βάση από τη mysql αλλά και να εκτελέσουμε κάποια
queries στην οντολογία χρειαζόμαστε 2 επιπλέον tabs. Για να τα εμφανίσουμε επιλέγουμε
OWL> Preferences

Και επιλέγουμε τα παρακάτω tabs όπως αυτά φαίνονται στην εικόνα

14
Στη συνέχεια και αφού έχουμε ολοκληρώσει την προσθήκη των παραπάνω tabs,
επιλέγουμε το tab-DataMaster και συμπληρώνουμε τα αντίστοιχα πεδία. Πατάμε ok και
αριστερά εμφανίζονται τα περιεχόμενα (οι πίνακες) της βάσης publications.

Επιλέγουμε select all tables, import table contents και στην συνέχεια import

Για να δούμε τα περιεχόμενα των πινάκων επιλέγουμε το tab Instances

15
Για να εκτελέσουμε Queries επιλέγουμε το tab Queries

…….

Για να εκτελέσουμε κάποιο ερώτημα θα πρέπει να επιλέξουμε την κλάση στην οποία θα
εφαρμόσουμε το ερώτημα, το property (slot), τη συνθήκη και τέλος μια τιμή (ένα
δεδομένο).

Επιλέγουμε class.

16
Επιλέγουμε slot

Επιλέγουμε συνθήκη

17
Επιλέγουμε δεδομένο και πατάμε find. Δεξιά εμφανίζονται τα δεδομένα.

Visualisation
Το protege παρέχει τη δυνατότητα να οπτικοποιήσουμε τα περιεχόμενα της οντολογίας.
Προκειμένου να το επιτύχουμε αυτό θα πρέπει να ενεργοποιήσουμε το tab-OWLVizTab

Προσοχή! Μπορεί να εμφανίσει ότι δεν μπορεί να το εκτελέσει. Σε αυτήν την περίπτωση
κατεβάζετε το πρόγραμμα (graphviz) από τον δικτυακό τόπο http://graphviz.org/ και στην
συνέχεια επιλέγετε από τα options το path που είναι εγκατεστημένο το dot.exe του graphviz

18
19
Για να απεικονίσετε την οντολογία επιλέγετε κάποια κλάση, και πατάτε το show classes.

20
Sparql
Στις οντολογίες μπορεί να χρησιμοποιηθεί και η γλώσσα Sparql για να εκτελέσουμε
αναζητήσεις.

Ερώτημα "Δείξτε τα επίθετα και τον κωδικό όλων των συγγραφέων των οποίων ο κωδικός
είναι μεγαλύτερος του 2 και μικρότερος του 4"

21
PREFIX db1: <http://biostorm.stanford.edu/db_table_classes/DSN_jdbc.mysql.//localhost.3306/publications#>
SELECT ?Surname ?d
WHERE
{
?x db1:author.Surname ?Surname.
?x db1:author.A_id ?d
FILTER (
?d > "2"^^xsd:int &&
?d < "4"^^xsd:int
)
}
Στην παρακάτω οθόνη βλέπουμε την εκτέλεση της εντολής και το αποτέλεσμά της.

Βιβλιογραφία-σύνδεσμοι
1. http://www.mysql.com/products/workbench/

2. http://protege.stanford.edu/doc/owl/getting-started.html

3. http://protegewiki.stanford.edu/wiki/Main_Page

22
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 12: Εφαρμογή Android με χρήση Sqlite

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Εφαρμογή Android με χρήση Sqlite ................................................................................. 3
Δημιουργία AVD ............................................................................................................... 8
Παράρτημα ..................................................................................................................... 10

Στόχος του εργαστηρίου είναι η εξοικείωση με τη δημιουργία εφαρμογών σε


android και τη διαχείριση βάσεων δεδομένων σε sqlite. Μετά την επεξεργασία του
εργαστηρίου ο ενδιαφερόμενος θα έχει κατανοήσει τα θέματα δημιουργίας μιας
εφαρμογής σε android και σε sqlite σε περιβάλλον eclipse.

Λέξεις κλειδιά: Android, Sqlite, Eclipse.

2
1. Εφαρμογή Android με χρήση Sqlite

Στις εφαρμογές Android χρησιμοποιείται SQLite database system, το οποίο είναι


open-source, και το οποίο χρησιμοποιείται από μεγάλο πλήθος εφαρμογών όπως
Mozilla Firefox, iPhone.

Προκειμένου να δουλέψουμε με android εφαρμογές θα χρησιμοποιήσουμε το


Eclipse. Επίσης θα χρειαστούμε και το android-sdk-windows.
( http://developer.android.com/sdk/eclipse-adt.html#installing )

Δημιουργία Android Εφαρμογής, Android Development Tools (ADT)

1. File > New > Project.


2. Android > Android Project, and click Next.

3
3. Finish.

Εν συνεχεία ανοίγουμε το project που δημιουργήσαμε το οποίο περιέχει

src/
όλα τα Java αρχεία της εφαρμογής μας τα οποία εκτελούν κάποιες
διαδικασίες( stub Activity) .

res/
Σε αυτό τον φάκελο περιέχονται τα resources της εφαρμογής όπως,drawable
files, layout files,string values, κ.α.

Όποτε αρχικά στον φάκελο src>com.example υπάρχει το αρχείο Database.java

Παρατηρούμε ότι η κλάση κληρονομεί από την Activity . Η Activity χρησιμοποιείται


προκειμένου να εκτελεστούν ενέργειες. Η μέθοδος onCreate() καλείται όταν
ξεκινήσει να εκτελείται η εφαρμογή, οπότε σε αυτό το σημείο εκτελούμε τις
αρχικοποιήσεις και τις δηλώσεις των μεταβλητών που θα χρησιμοποιήσουμε.

Για τις ανάγκες της εφαρμογής θα έχουμε 2 αρχεία.


1. Το Database.java το οποίο θα καλούμε κάθε φορά για να τρέξουμε την
εφαρμογή
2. Το HelpDb.java το οποίο θα περιέχει όλο τον αναγκαίο κώδικα προκειμένου
να αλληλεπιδράσουμε με την βάση και τα δεδομένα της

Αρχικά θα δημιουργήσουμε την βάση «institute» και έναν πίνακα «students».

Students
Id Integer
Name Text
Surname Text
Email Text

4
Δημιουργούμε τα αντίστοιχα String
private static final String DATABASE_NAME = "books";
private static final String DATABASE_TABLE = "titles";
private static final int DATABASE_VERSION = 1;

private static final String DATABASE_CREATE =


"create table titles (_id integer primary key autoincrement, "
+ "isbn text not null, title text not null, "
+ "publisher text not null);";

Εν συνεχεία δημιουργούμε τη μέθοδο DatabaseHelper η οποία κάνει extends την


SQLiteOpenHelper και έχει την δυνατότητα να διαχειριστεί database creation and
version management

private static class DatabaseHelper extends SQLiteOpenHelper


{

DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(DATABASE_CREATE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion)
{
Log.w("HelpDb","Upgrading database from version"+ oldVersion
+ "to" + newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
onCreate(db);
}
}
Τέλος ακολουθούν οι μέθοδοι διαχείρισης των δεδομένων.

//---opens the database---


public HelpDb open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}

//---closes the database---


public void close()
{
DBHelper.close();
}

//---insert a record into the database---


public long insertTitle(String name, String surname, String
email)
{
ContentValues initialValues = new ContentValues();
initialValues.put("name", name);

5
initialValues.put("surname", surname);
initialValues.put("email", email);
return db.insert(DATABASE_TABLE, null, initialValues);
}

//---deletes a particular record ---


public boolean deleteTitle(long rowId)
{
return db.delete(DATABASE_TABLE, "id" +
"=" + rowId, null) > 0;
}

//---retrieves all the records---


public Cursor getAllTitles()
{
return db.query(DATABASE_TABLE, new String[] {
"id",
"name",
"surname",
"email"},
null,
null,
null,
null,
null);
}

//---retrieves a particular record ---


public Cursor getTitle(long rowId) throws SQLException
{
Cursor mCursor =
db.query(true, DATABASE_TABLE, new String[] {
"id",
"name",
"surname",
"email"},
"id" + "=" + rowId,
null,
null,
null,
null,
null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}

//---updates a record ---


public boolean updateTitle(long rowId, String name,
String surname, String email)
{
ContentValues args = new ContentValues();
args.put("name", name);
args.put("surname", surname);
args.put("email", email);
return db.update(DATABASE_TABLE, args,
"id" + "=" + rowId, null) > 0;
}

6
Αφού ολοκληρώσαμε όλες τις μεθόδους διαχείρισης της βάσης, θα
συμπληρώσουμε και το Database.java
Όπως προείπαμε η μέθοδος η οποία είναι υπεύθυνη για την εμφάνιση των
δεδομένων είναι η onCreate οπότε μέσα στην μέθοδο αυτή θα συμπληρώσουμε τις
λειτουργίες που θέλουμε να εκτελεστούν.

HelpDb db = new HelpDb(this);

//---add 2 titles---
db.open();

db.insertTitle(
"CHRISTOS",
"SKOURLAS",
"CSKOURLAS@TEIATH.GR");
db.insertTitle(
"ANASTASIOS",
"TSOLAKIDIS",
"ATSOLAKID@TEIATH.GR");
db.close();
db.open();

Cursor c = db.getTitle(2);
if (c.moveToFirst())
DisplayTitle(c);
else
Toast.makeText(this, "No title found",
Toast.LENGTH_LONG).show();
db.close();

Και η DisplayTitle είναι εκείνη η μέθοδος η οποία καλείται προκειμένου να


εμφανιστούν τα αποτελέσματα.

public void DisplayTitle(Cursor c)


{
// A toast is a view containing a quick little message for the user.
Toast.makeText(this,
"id: " + c.getString(0) + "\n" +
"NAME: " + c.getString(1) + "\n" +
"SURNAME: " + c.getString(2) + "\n" +
"EMAIL: " + c.getString(3),
Toast.LENGTH_LONG).show();
}

Προκείμενο να «τρέψουμε» τις εφαρμογές θα χρησιμοποιήσουμε το simulator του


android Android Virtual Device (AVD)

7
Δημιουργία AVD

Δημιουργία AVD στο Eclipse:

1. Window > Android SDK and AVD Manager,


2. Στο Virtual Devices panel, επιλέγουμε New για να δημιουργήσουμε το καινούριο
AVD.
3. Συμπληρώνουμε τα στοιχεία που μας ζητούνται

4. Create AVD.
5. Εν συνεχεία επιλέγουμε το AVD που έχουμε δημιουργήσει και πατάμε start και
μετά launch

Αφού έχουμε ολοκληρώσει την εφαρμογή και έχουμε δημιουργήσει το AVD εν


συνεχεία
1. Δεξί κλίκ στο project
2. Run as>Android Application
Και εμφανίζονται τα αποτελέσματα

8
Πατώντας DDMS πάνω και δεξιά στο παράθυρο(eclipse)

Μας εμφανίζονται όλες οι πληροφορίες σχετικά με τον emulator.


Ανοίγοντας τους φακέλους /data/data/YOUR_PACKAGE/databases/ βλέπουμε την
βάση που δημιουργήσαμε.

9
Εάν θέλουμε να δουλέψουμε με την βάση που μόλις δημιουργήσαμε τότε.
1. Τρέχουμε το command line(cmd) θέτοντας ως τρέχων φάκελο τον φάκελο
tools του android-sdk.
2. Γράφουμε adb shell
3. Πηγαίνουμε στο φάκελο του βρίσκετε η βάση μας π.χ για το παράδειγμα που
μόλις φτιάξαμε

C:\Program Files\android-sdk-windows\tools>adb shell


# cd data/data
# cd com.example
# ls
# cd databases
# sqlite3 institute
sqlite3 institute
SQLite version 3.6.22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .tables
android_metadata students
sqlite> select * from students;
1|CHRISTOS|SKOURLAS|CSKOURLAS@TEIATH.GR
2|ANASTASIOS|TSOLAKIDIS|ATSOLAKID@TEIATH.GR
3|CHRISTOS|SKOURLAS|CSKOURLAS@TEIATH.GR
4|ANASTASIOS|TSOLAKIDIS|ATSOLAKID@TEIATH.GR
sqlite>.quit
# exit

Παράρτημα

Database.java
package com.example;

import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.Toast;

public class Database extends Activity {


/** Called when the activity is first created. */

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
HelpDb db = new HelpDb(this);

//---add 2 titles---
db.open();

10
db.insertTitle(
"CHRISTOS",
"SKOURLAS",
"CSKOURLAS@TEIATH.GR");
db.insertTitle(
"ANASTASIOS",
"TSOLAKIDIS",
"ATSOLAKID@TEIATH.GR");
db.close();
db.open();

Cursor c = db.getTitle(12);
if (c.moveToFirst())
DisplayTitle(c);
else
Toast.makeText(this, "No title found",
Toast.LENGTH_LONG).show();
db.close();
}
public void DisplayTitle(Cursor c)
{
Toast.makeText(this,
"id: " + c.getString(0) + "\n" +
"NAME: " + c.getString(1) + "\n" +
"SURNAME: " + c.getString(2) + "\n" +
"EMAIL: " + c.getString(3),
Toast.LENGTH_LONG).show();
}
}

HelpDb.java
package com.example;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class HelpDb {

private static final String DATABASE_NAME = "institute";


private static final String DATABASE_TABLE = "students";
private static final int DATABASE_VERSION = 1;

private static final String DATABASE_CREATE =


"create table students (id integer primary key
autoincrement, "
+ "name text not null, surname text not null, "
+ "email text not null);";

//Interface to global information about an application


environment

11
private final Context context;

private DatabaseHelper DBHelper;


private SQLiteDatabase db;

public HelpDb(Context ctx)


{
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
//H DatabaseHelper κάνει extends SQLiteOpenHelper και έχει
την δυνατότητα
//να διαχειριστεί database creation and version management
private static class DatabaseHelper extends
SQLiteOpenHelper
{
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null,
DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(DATABASE_CREATE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int
oldVersion,
int newVersion)
{
Log.w("HelpDb", "Upgrading database from version "
+ oldVersion
+ " to "
+ newVersion + ", which will destroy all
old data");
db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
onCreate(db);
}
}

//---opens the database---


public HelpDb open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}

//---closes the database---


public void close()
{
DBHelper.close();
}

//---insert a record into the database---


public long insertTitle(String name, String surname, String
email)
{
ContentValues initialValues = new ContentValues();

12
initialValues.put("name", name);
initialValues.put("surname", surname);
initialValues.put("email", email);
return db.insert(DATABASE_TABLE, null, initialValues);
}

//---deletes a particular record ---


public boolean deleteTitle(long rowId)
{
return db.delete(DATABASE_TABLE, "id" +
"=" + rowId, null) > 0;
}

//---retrieves all the records---


public Cursor getAllTitles()
{
return db.query(DATABASE_TABLE, new String[] {
"id",
"name",
"surname",
"email"},
null,
null,
null,
null,
null);
}

//---retrieves a particular record ---


public Cursor getTitle(long rowId) throws SQLException
{
Cursor mCursor =
db.query(true, DATABASE_TABLE, new String[] {
"id",
"name",
"surname",
"email"},
"id" + "=" + rowId,
null,
null,
null,
null,
null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}

//---updates a record ---


public boolean updateTitle(long rowId, String name,
String surname, String email)
{
ContentValues args = new ContentValues();
args.put("name", name);
args.put("surname", surname);
args.put("email", email);
return db.update(DATABASE_TABLE, args,
"id" + "=" + rowId, null) > 0;
}
}

13
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 13: Επισκόπηση της χρήσης του jdbc API

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Επισκόπηση της χρήσης jdbc API ..................................................................................... 3
2. Ακολουθούν κάποια απλά αλλά λειτουργικά παραδείγματα χρήσης του API:............... 4
3. Σύνδεση σε βάση δεδομένων στην περίπτωση τoυ προϊόντος MySQL ........................... 5
4. Παραδείγματα διαχείρισης δηλώσεων SQL - Insert-delete-update-select statements .. 7
5. Παράδειγμα χρήσης embedded select statement. .......................................................... 9
6. Case Study «Διαχείριση βάσης προσωπικού» ............................................................... 12
7. Υλοποίηση εφαρμογής ................................................................................................... 18

Στόχος του εργαστηρίου είναι η επισκόπηση της χρήσης του jdbc API για τη
δημιουργία εφαρμογών – jsp pages και τη διαχείριση βάσεων δεδομένων. Μετά την
επεξεργασία του εργαστηρίου ο ενδιαφερόμενος θα έχει κατανοήσει τα θέματα
δημιουργίας μιας εφαρμογής jsp pages.

Λέξεις κλειδιά: jdbc API, netbeans, jsp pages

2
1. Επισκόπηση της χρήσης jdbc API

Στο σχήμα (Martii Leiho) προσφέρεται μία οπτική υπενθύμιση για μία σειρά από
σημαντικές κλάσεις, αντικείμενα, μεθόδους (class, objects, methods) του jdbc API
και με τα βέλη περιγράφεται η επικοινωνία / σύνδεσή / διάταξή τους.

Η βασική αρχή χρήσης του jdbc API είναι απλή:


Ας εστιάσουμε στα βέλη. Για να ορίσω ένα αντικείμενο μιάς κλάσης στην αιχμή ενός
βέλους χρησιμοποιώ την κατάλληλη μέθοδο και αντικείμενο της «προηγούμενης»
κλάσης που βρίσκεται στην αρχή του ιδίου βέλους.

Statement myStatement = myconnection.createStatement();

Δηλαδή για να ορίσουμε το αντικείμενο myStatement «εφαρμόζουμε» τη μέθοδο


createStatement στο αντικείμενο myconnection.

Τα αντικείμενα της βάσης δεδομένων ορίζονται σαν συμβολοσειρές (string).


Ακολουθούν παραδείγματα:

String testDatabase =
“jdbc:mysql://localhost:3306/mydb?user=admin&password=1234";

3
Προσοχή! Η παρακάτω εντολή είναι λανθασμένη
String sqlString = "INSERT INTO USERS VALUES ('user1', 'password1')";

Η σωστή διαμορφώνεται ως εξής: … VALUES('"+user1+"','"+password1+"')

Άρα, String sql="insert into users values ('"+user1+"','"+password1+"')";

2. Ακολουθούν κάποια απλά αλλά λειτουργικά παραδείγματα


χρήσης του API:

Η DriverManagerClass παρέχει τη μέθοδο getConnection. Μπορούμε να ορίσουμε


ένα αντικείμενο, για παράδειγμα το αντικείμενο myConnection τύπου Connection
ως εξής:

Connection myConnection = DriverManager.getConnection(testDatabase);

Αυτό προϋποθέτει ότι έχουμε ορίσει ένα αντικείμενο testDatabase τύπου string που
«ορίζει» τον driver που χρησιμοποιούμε, το URL, τη βάση μας, username και
password. Άρα θα έχουμε:

String testDatabase =
“jdbc:mysql://localhost:3306/mydb?user=admin&password=1234";
Connection myConnection = DriverManager.getConnection(testDatabase);

Σημείωση: Το αντικείμενο myConnection είναι τύπου Connection και μπορούμε να


χρησιμοποιήσουμε τη μέθοδο CreateStatement της κλάσης Connection για να
ορίσουμε ένα αντικείμενο, για παράδειγμα το αντικείμενο myStatement τύπου
Statement. Μέσω του αντικειμένου myStatement θα γράφουμε και θα εκτελούμε
δηλώσεις SQL (INSERT, UPDATE, DELETE, SELECT).

Statement myStatement = myconnection.createStatement();

Το αντικείμενο myStatement είναι τύπου Statement και μπορούμε να το


«εκτελέσουμε» χρησιμοποιώντας μία από τις δύο σχετικές μεθόδους της κλάσης
δηλαδή τη μέθοδο executeUpdate ή τη μέθοδο executeQuery. Ποια είναι
κατάλληλη μέθοδος εξαρτάται από τη δήλωση SQL. Στην περίπτωση δήλωσης
INSERT έχουμε:

myStatement.executeUpdate(sqlString);

Η συγγραφή της SQL δήλωσης γίνεται σε ένα αντικείμενο τύπου string, για
παράδειγμα στο αντικείμενο με όνομα sqlString.

String sqlString = "INSERT INTO USERS VALUES ('"+user1+"','"+password1+"')

4
('user1', 'password1')";
Έτσι για να εκτελέσουμε μία SQL δήλωση:

String sql="insert into users values ('"+user1+"','"+password1+"')";


myStatement.executeUpdate(sqlString);

Ειδικά στην περίπτωση δήλωσης SELECT μπορούμε να ορίσουμε ένα αντικείμενο,


για παράδειγμα το αντικείμενο με όνομα rs, τύπου ResultSet. Στο αντικείμενο
«αποθηκεύονται» τα αποτελέσματα της δήλωσης SELECT. Προηγουμένως, θα
χρειασθεί να ορίσουμε το αντικείμενο sqlString που είναι μια συμβολοσειρά που
«περιέχει» τη δήλωση SELECT:

String sqlString = "SELECT * FROM MYTABLE WHERE PARAM = '"+paramValue+"'";


ResultSet rs = myStatement.executeQuery(sqlString);

Η κλάση ResultSet παρέχει μεθόδους για να διαχειριστούμε τις γραμμές που


«αποθηκεύονται» στο rs:

next(), previous(), first(), last()

Επίσης, παρέχει μία σειρά από μεθόδους κάθε μία από τις οποίες μπορεί να
χρησιμοποιηθεί για να πάρουμε πληροφορία από μια στήλη:

getString, getInt, getFloat getDate.

3. Σύνδεση σε βάση δεδομένων στην περίπτωση τoυ προϊόντος


MySQL

Για να συνδεθούμε στη βάση δεδομένων στην περίπτωση τoυ προϊόντος MySQL και
να γράψουμε δηλώσεις SQL (SQL statements) απαιτούνται οι εξής ενέργειες:

1. Δήλωση του JDBC driver

libraries>δεξί κλικ> Add Jar/Folder και επιλέγουμε το αρχείο mysql-connector-java-


5.1.13 -bin.jar ή mysql.jar

2. Εισαγωγή του package java.sql στο πρόγραμμά μας

<%@page import="java.sql.*" %> (χρησιμοποιούμε .*, ;έτσι ώστε να μπορούμε να


χρησιμοποιήσουμε όλες τις κλάσεις του package java.sql)

3. «Φόρτωση» του JDBC driver στο πρόγραμμά μας

Class.forName(“com.mysql.jdbc.Driver”);

5
// Φορτώνουμε την κλάση Driver από το package com.mysql.jdbc.

4. Σύνδεση στη βάση δεδομένων

String testDatabase =
“jdbc:mysql://localhost:3306/mydb?user=admin&password=1234";

// Ορίζουμε για τη βάση δεδομένων μας (‘εστω ότι την ονομάζουμε mydb) ένα
αντικείμενο testDatabase τύπου συμβολοσειράς (string) της μορφής:
“jdbc:mysql://ServerName:ServerPort/DatabaseName?user=myUsername&password=myP
assword";

Connection myConnection = DriverManager.getConnection(testDatabase);

// Δημιουργούμε ένα αντικείμενο τύπου Connection. Tο αντικείμενό μας,


myConnection, είναι μια ανοιχτή σύνδεση με τη βάση δεδομένων

5. Δημιουργία αντικειμένου για να γράψουμε SQL statements

Statement myStatement = myconnection.createStatement();

// Δημιουργούμε το αντικείμενο myStatement τύπου Statement. Μέσω του


αντικειμένου myStatement θα γράφουμε δηλώσεις SQL.

6. Εγγραφή SQL statements


Λανθασμένη εντολή
String sqlString = "INSERT INTO USERS VALUES ('user1', 'password1')";
Σωστή εντολή
String sql="insert into users values ('"+user1+"','"+password1+"')";

// Ορίζουμε ένα αντικείμενο sqlString τύπου string για να γράψουμε τη δήλωση SQL
(που θέλουμε να εκτελεστεί στη συνέχεια).

7. Εκτέλεση SQL statements

myStatement.executeUpdate(sqlString);

// Εκτελούμε τη δήλωση SQL που γράψαμε και πιο συγκεκριμένα χρησιμοποιούμε


το αντικείμενο myStatement που δημιουργήσαμε. Επειδή έχουμε στην περίπτωση
αυτή εντολή INSERT χρησιμοποιήσαμε τη μέθοδο executeUpdate. Το ίδιο θα κάναμε
και σε δήλωση UPDATE ή DELETE.

Αν η sqlString αφορούσε μια SQL statement τύπου select, η μέθοδός μας θα ήταν:η
executeQuery:
myStatement.executeQuery(sqlString);

6
8. Κλείσιμο του αντικειμένου «αναγραφής» SQL statements

myStatement.close();

// Αφού εκτελέσουμε την SQL statement πρέπει να κλείσουμε το αντικείμενο που


χρησιμοποιείται για την εγγραφή της SQL statements.

9. Κλείσιμο της σύνδεσης

myConnection.close();

// Κλείνουμε τη σύνδεση με τη βάση δεδομένων.

4. Παραδείγματα διαχείρισης δηλώσεων SQL - Insert-delete-


update-select statements

Για να γράψουμε μια εντολή SQL, χρησιμοποιούμε τη μέθοδο

myStatement.methodName(sqlString);

όπου myStatement είναι ένα αντικείμενο τύπου Statement και methodName είναι
μια από τις μεθόδους που παρέχει η κλάση Statement.

Θα μελετήσουμε διάφορες μορφές της μεθόδου methodName.

Στη συνέχεια, διορθώστε το διαγραμμένο μέρος των δηλώσεων.

Εισαγωγή δεδομένων (insert statement)

Χρησιμοποιούμε τη μέθοδο executeUpdate μέσω της εντολής:

myStatement.executeUpdate(sqlString);

όπου sqlString είναι μια συμβολοσειρά της μορφής:


String sqlString = "INSERT INTO MYTABLE VALUES ('value1', 'value2')";

Διαγραφή δεδομένων (delete statement)

Χρησιμοποιούμε τη μέθοδο executeUpdate μέσω της εντολής:

myStatement.executeUpdate(sqlString);

όπου το sqlString είναι της μορφής:

8
String sqlString = "DELETE FROM MYTABLE WHERE PARAM = 'paramValue'";

Ενημέρωση δεδομένων (update statement)

Χρησιμοποιούμε τη μέθοδο executeUpdate μέσω της εντολής:

myStatement.executeUpdate(sqlString);

όπου το sqlString είναι της μορφής:


String sqlString = "UPDATE MYTABLE SET PARAM1='value1' WHERE
PARAM2='value2'";

Επιλογή δεδομένων (select statement)

Για επιλογή δεδομένων χρησιμοποιούμε τη μέθοδο executeQuery μέσω της


εντολής:
ResultSet rs = myStatement.executeQuery(sqlString);
όπου sqlString είναι μια συμβολοσειρά της μορφής:
String sqlString = "SELECT * FROM MYTABLE WHERE PARAM = 'paramValue'";
Η μέθοδος executeQuery μας δίνει τη δυνατότητα να ανακτήσουμε γραμμές
δεδομένων από τη βάση δεδομένα. Τα δεδομένα αυτά πρέπει να τα
αποθηκεύσουμε προσωρινά σε κάποια δομή ώστε να τα χρησιμοποιήσουμε.

Η Java παρέχει μια εύχρηστη δομή μέσω της κλάσης ResultSet. Πιο συγκεκριμένα, η
μέθοδος ExecuteQuery μας επιστρέφει ένα αντικείμενο τύπου ResultSet. Ας
ονομάσουμε το συγκεκριμένο αντικείμενο rs. Μέσα στο αντικείμενο αυτό
αποθηκεύονται προσωρινά όλες οι γραμμές δεδομένων που επιστρέφει η δήλωση
SELECT που εκτελέσαμε. Μέσω του αντικειμένου αυτού μπορούμε να
επεξεργαστούμε τις γραμμές στο πρόγραμμά μας

Το αντικείμενο rs μας παρέχει και έναν δείκτη ο οποίος αρχικά δείχνει πρίν από την
πρώτη γραμμή αποτελεσμάτων που είναι αποθηκευμένα στο αντικείμενο rs.

Το rs (ως αντικείμενο της κλάσης ResultSet) μας παρέχει μεθόδους για να


επεξεργαζόμαστε τις γραμμές που ανακτήσαμε από τη βάση δεδομένων. Οι πιο
σημαντικές μέθοδοι αναφέρονται παρακάτω:

Για να χρησιμοποιήσουμε την πληροφορία που είναι καταχωρημένη στο


αντικείμενο rs, θα πρέπει:
 Να μετακινήσουμε το δείκτη στη γραμμή που θέλουμε να επεξεργασθούμε ή
να τον μετακινούμε διαδοχικά αν θέλουμε να επεξεργασθούμε όλες τις
αποθηκευμένες γραμμές. Αυτό γίνεται με χρήση των μεθόδων: next(),
previous(), first(), last()
 Να χρησιμοποιήσουμε την κατάλληλη μέθοδο για να πάρουμε πληροφορία
από μια στήλη. Αυτό γίνεται με τις συναρτήσεις getString, getInt, getFloat
getDate κ.τ.λ.

9
Πρακτικός κανόνας για τη συγγραφή δήλωσης SQL στα προγράμματά μας:

Δοκιμάζουμε τη δήλωση με συγκεκριμένες τιμές στις μεταβλητές.

Τοποθετούμε την εντολή σε " " και αντικαθιστούμε κάθε συγκεκριμένη τιμή, για
παράδειγμα την τιμή 'ANALYST'με το όνομα της μεταβλητής γραμμένο με "+ +",
ως εξής: '"+job+"'

Δείτε και το παράδειγμα:

String sql="insert into emp(ename,job,sal,deptno) values


('"+name+"','"+job+"','"+sal+"',"+deptno+")";

5. Παράδειγμα χρήσης embedded select statement.

Ακολουθεί παράδειγμα χρήσης της executeQuery που βοηθά στην κατανόηση του
τρόπου που χρησιμοποιούμε τις διάφορες μεθόδους της κλάσης ResultSet.

Έστω ότι έχουμε τον παραπάνω πίνακα myTable:

myTable,

ID Int

Name Text

select * from myTable

10
Δημιουργείστε ένα αρχείο test.jsp και γράψτε τον παρακάτω κώδικα

<%--
Document : test
Created on : April 31, 2014, 8:24:04 AM
Author :
--%>
// Import the package java.sql – all the classes
<%@page import="java.sql.*" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%
int j=0;
// Define parameters for retrieving database results
int m[] = new int[5000];
String s[] = new String[5000];
// Load the driver
Class.forName("com.mysql.jdbc.Driver");
// Define the connection parameters
String myDatabase =
"jdbc:mysql://localhost:3306/personnel?user=root";
// Connect to the database
Connection myConnection = DriverManager.getConnection(myDatabase);
// Create object to execute statements
Statement myStatement = myConnection.createStatement();
// Select everything from the database table
String sqlString = "SELECT * FROM myTable ";
ResultSet rs=myStatement.executeQuery(sqlString);
// Store the results in vectors in order to pass them to the JSP
while(rs.next()){
m[j]=rs.getInt("id");
s[j]=rs.getString("name");
j++;
}
// Close the connection to the database
myStatement.close();
myConnection.close();
// Print
out.println("j="+j+"<br>");
for(int i=0; i<j; i++)
{
out.println(m[i]+"");
out.println(s[i]+"<br>");
}
%>

11
Στη συνέχεια τρέξτε το πρόγραμμα.

j=3
11
1 ann
1 tom

Σύνοψη – Επισκόπηση

Αρχικά βλέπουμε τον πίνακα myTable. Τα βήματα είναι τα παρακάτω:


ID Int
myTable
Name Text

1. Oρίζουμε δυο παραμέτρους.


2. Στις παραμέτρους αυτές καταχωρούμε τις τιμές των δυο στηλών του πίνακα
mytable.
3. Φορτώνουμε το driver και προετοιμάζουμε τη συμβολοσειρά για σύνδεση.
4. Συνδεόμαστε, στην περίπτωσή μας, με username root και κενό password,
στη βάση δεδομένων mydb.
5. Συνδεόμαστε στη βάση δεδομένων, personnel, δημιουργούμε το αντικείμενο
τύπου statement και προετοιμάζουμε την SQL string.
6. Εκτελούμε το SQL Statement.
7. Μέχρι στιγμής έχουμε καταχωρήσει όλον τον πίνακα αποτελεσμάτων στο
αντικείμενο rs. Μένει να «διαβάσουμε» τα στοιχεία του rs. Αυτό γίνεται με
έναν βρόχο while.
8. Η εντολή while(rs.next()) έχει διπλό ρόλο:Εκτελεί την εντολή rs.next().
Επιπλέον, ελέγχει αν rs.next()=true. Αυτό σημαίνει ότι, αν rs.next()=true,
τότε ο βρόχος θα εκτελεστεί. Αν rs.next()=false τότε ο βρόχος δε θα
εκτελεστεί και το πρόγραμμα θα προχωρήσει παρακάτω. Η μέθοδος next()
της resultSet επιστρέφει true αν υπάρχει επόμενη γραμμή για να διαβάσει.
Αν δεν υπάρχει επόμενη γραμμή, δηλαδή έχουμε φτάσει στο τέλος των
αποτελεσμάτων, τότε επιστρέφει false. Με τον τρόπο αυτό, αν υπάρχει
επόμενη γραμμή, ο βρόχος εκτελείται, και σταματά να εκτελείται όταν οι
γραμμές «τελειώσουν». Ο βρόχος κάνει το εξής:
a. Διαβάζει, τις στήλες της τρέχουσας γραμμής και τις καταχωρεί στις
αντίστοιχες μεταβλητές του προγράμματος (m[j], (m[j],), μέσω της
μεθόδου getString() ή getInt().
b. Τυπώνει στην οθόνη τις παραπάνω μεταβλητές.

12
6. Case Study «Διαχείριση βάσης προσωπικού»

Σας αναθέτουν να σχεδιάσετε και μα υλοποιήσετε εφαρμογή η οποία αφορά τη διαχείριση


του προσωπικού εταιρείας. Στην εφαρμογή θα έχουν πρόσβαση μόνο όσοι χρήστες είναι
εγγεγραμμένοι και διαθέτουν username –password. Αρχικά θα εμφανίζεται στο χρήστη μια
login φόρμα όπου θα δίνεται η δυνατότητα στον χρήστη να συνδεθεί. Αφού συνδεθεί ο
χρήστης θα έχει τις παρακάτω δυνατότητες:

1. Προβολή όλων των τμημάτων της εταιρείας μαζί με τα στοιχεία εργαζομένων που
ανήκουν σε αυτά.
2. Εισαγωγή ενός νέου εργαζόμενου.
3. Διαγραφή ενός εργαζόμενου
4. Ενημέρωση των στοιχείων των εργαζομένων.

Οι πίνακες της εφαρμογής θα είναι οι παρακάτω:

13
DROP DATABASE personnel_db;

CREATE DATABASE personnel;

USE personnel;

CREATE TABLE Dept(DEPTNO INT(2) NOT NULL,

DNAME VARCHAR(14), LOC VARCHAR(14),

NO_OF_EMPLOYEES INT(3),

PRIMARY KEY(DEPTNO));

CREATE TABLE Emp(EMPNO INT(4) NOT NULL AUTO_INCREMENT,

ENAME VARCHAR(10), JOB VARCHAR(9),

SAL FLOAT(7,2),

DEPTNO INT(2), PRIMARY KEY(EMPNO),

FOREIGN KEY(DEPTNO) REFERENCES Dept(DEPTNO));

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (20, 'RESEARCH', 'DALLAS');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (30, 'SALES', 'CHICAGO');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (40, 'OPERATIONS', 'BOSTON');

14
INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'SMITH', 'CLERK', 800, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'ALLEN', 'SALESMAN', 1600, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'WARD', 'SALESMAN', 1250, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'JONES', 'MANAGER', 2975, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'MARTIN', 'SALESMAN', 1250, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'BLAKE', 'MANAGER', 2850, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'CLARK', 'MANAGER', 2450, 10);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'SCOTT', 'ANALYST', 3000, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'KING', 'PRESIDENT', 5000, 10);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'TURNER', 'SALESMAN', 1500, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'ADAMS', 'CLERK', 1100, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'JAMES', 'CLERK', 950, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'FORD', 'ANALYST', 3000, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'MILLER', 'CLERK', 1300, 10);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'BATES', 'ANALYST', 1300, NULL);

UPDATE dept

SET no_of_employees =

(SELECT COUNT(*)

FROM emp

WHERE emp.deptno = dept.deptno);

Select * from dept;

Select * from emp;

15
CREATE TABLE user(

uname text,

upass text,

Uid int(11),

Uphone varchar(45), Ucity varchar(45));

INSERT INTO `user` VALUES ('admin','1234',1,NULL,NULL);

Select * from user;

16
Χρήση Cursor

DELIMITER $$

DROP PROCEDURE IF EXISTS CursorProc$$

CREATE PROCEDURE CursorProc()

BEGIN

DECLARE no_more_depts, available_employees INT DEFAULT 0;

DECLARE dept_code VARCHAR(255);

DECLARE cur_dept CURSOR FOR

SELECT deptno FROM dept;

DECLARE CONTINUE HANDLER FOR NOT FOUND

SET no_more_depts = 1;

/* for loggging information */

CREATE TABLE infologs (

Id int(11) NOT NULL AUTO_INCREMENT,

Msg varchar(255) NOT NULL, PRIMARY KEY (Id));

OPEN cur_dept;

FETCH cur_dept INTO dept_code;

REPEAT

SELECT no_of_employees INTO available_employees

FROM dept

WHERE deptno = dept_code;

IF available_employees < 5 THEN

INSERT INTO infologs(msg)VALUES (dept_code);

END IF;

FETCH cur_dept INTO dept_code;

UNTIL no_more_depts = 1

END REPEAT;

17
CLOSE cur_dept;

SELECT * FROM infologs;

DROP TABLE infologs;

END$$

DELIMITER ;

CALL CURSORPROC();

18
7. Υλοποίηση εφαρμογής

Τα στοιχεία της σύνδεσης είναι:

Ip:localhost

Port:3306

Database: personnel

User=root

Password=

Υπενθυμίζουμε ότι ο χρήστης (βλέπε και πίνακα user) έχει:

User=root

Password=1234

Στάδια:
I. Διαχείριση Σύνδεσης
Υλοποιείται με χρήση δύο (2) σελίδων: index.jsp, check.jsp

Index.jsp

Αν δοθούν λανθασμένα στοιχεία τότε

19
<%--

Document : index

Created on : April 30, 2014, 2:04:01 PM

Author :

--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;


charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

WELCOME<p></p>

LOGIN<p></p>

<p></p>

<form name="formName" method="post" action="check.jsp" >

Name: <input type="text" name="y"><p></p>

Password:<input type="text" name="k"><P></P>

<input type="submit" value="LOGIN"><p></p>

</form>

</body>

</html>

20
<%--

Document : check

Created on : April 30, 2014, 2:12:02 PM

Author :

--%>

<%@page import="java.sql.*" %>

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;


charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<%

Boolean found;

String x =request.getParameter("y");

String p = request.getParameter("k");

String URL;

Class.forName("com.mysql.jdbc.Driver");

String DB =
"jdbc:mysql://localhost:3306/personnel?user=root";

Connection myConnection = DriverManager.getConnection(DB);

Statement SMT = myConnection.createStatement();

String sql="SELECT * FROM user WHERE Uname='"+x+"'AND


Upass='"+p+"' ";

ResultSet rs=SMT.executeQuery(sql);

found= rs.first();

if (found){

URL = "home.jsp?p1="+x+"";

21
response.sendRedirect(URL);

else

out.println("INCORRECT TRY AGAIN");%><P></P>

<a href="index.jsp">Try Again</a><%

SMT.close();

myConnection.close();

%>

</body>

</html>

Σημαντική σημείωση

Έστω ότι τα στοιχεία της σύνδεσης είναι:

Ip:localhost

Port:3306

Database: personnel

User=root

Password=1234

Τότε αντί της εντολής

String DB = "jdbc:mysql://localhost:3306/personnel?user=root";

Χρησιμοποιούμε την εντολή:

String DB =
"jdbc:mysql://localhost:3306/personnel_db?user=root&password=1234";

22
II. Προβολή όλων των εργαζομένων και των τμημάτων στα οποία ανήκουν.
Υλοποιείται με χρήση της σελίδας (home.jsp)

κ.λπ.

23
<%--

Document : home

Created on : April 30, 2014, 2:26:58 PM

Author :

--%>

<%@page import="java.sql.*" %>

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<%

Integer empno[]=new Integer[100];

String name[]=new String[100];

String job[]=new String[100];

int i;

Class.forName("com.mysql.jdbc.Driver");

String DB =
"jdbc:mysql://localhost:3306/personnel?user=root";

Connection myConnection = DriverManager.getConnection(DB);

Statement SMT = myConnection.createStatement();

Statement SMT1 = myConnection.createStatement();

%>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;


charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<%

String sql="SELECT * FROM dept ";

24
ResultSet rs=SMT.executeQuery(sql);

String dname;

int count=0;

while (rs.next())

i=rs.getInt("deptno");

String sql1="SELECT * FROM emp WHERE deptno='"+i+"' ";

ResultSet rs1=SMT1.executeQuery(sql1);

dname=rs.getString("dname");

%>

<br> <INPUT TYPE="BUTTON" VALUE="ΠΡΟΣΘΗΚΗ ΕΝΟΣ ΝΕΟΥ


ΕΡΓΑΖΟΜΕΝΟΥ" style="font-size:7px"

ONCLICK="window.location.href='insert.jsp?deptno=<%= i%>'">

<%

out.println(" <br>Oι εργαζόμενοι στο Τμήμα:"+dname+" είναι


οι:");

while(rs1.next())

name[count]=rs1.getString("ename");

job[count]=rs1.getString("job");

empno[count]=rs1.getInt("empno");

%> <br>

<%= name[count]%> (<%= job[count]%>)

<INPUT TYPE="BUTTON" VALUE="ΑΛΛΑΓΗ" style="font-size:7px"

ONCLICK="window.location.href='update.jsp?empno=<%=
empno[count]%>'">

<INPUT TYPE="BUTTON" VALUE="ΔΙΑΓΡΑΦΗ " style="font-size:7px"

ONCLICK="window.location.href='delete.jsp?empno=<%=
empno[count]%>'">

25
<br>

<% String x="o";

}}%>

<%

SMT.close();

SMT1.close();

myConnection.close();

%>

</body>

</html>

III. Εισαγωγή Νέου εργαζόμενου (insert.jsp, ins_submit.jsp)

Για παράδειγμα

IV. Ενημέρωση στοιχείων εργαζομένων (update.jsp, up_submit.jsp)

Αν συνδεθούμε εκ νέου θα δούμε

26
κ.λπ.

Επιλέγουμε ΑΛΛΑΓΗ για τον υπάλληλο ANDREW.

Αλλάζουμε τα στοιχεία

Επιλέγουμε update οπότε ενημερώνεται η γραμμή και επιστρέφουμε στην αρχική φόρμα:

27
V. Διαγραφή ενός εργαζομένου (delete.jsp)

Αν συνδεθούμε εκ νέου θα δούμε

κ.λπ.

Αν επιλέξουμε ΔΙΑΓΡΑΦΗ για τον υπάλληλο ANDREW διαγράφεται ο υπάλληλος.

Σημείωση: Θα έπρεπε να βλέπαμε όλα τα στοιχεία του πριν τον διαγράψουμε.


Επιπλέον, θα έπρεπε να υπάρχει και επιβεβαίωση πριν από τη διαγραφή.

Γενικά θα μπορούσαμε να βελτιώσουμε σε πολλά σημεία την εφαρμογή με


σχετικά απλό τρόπο!

28
<%--

Document : insert

Created on : April 30, 2014, 2:32:55 PM

Author :

--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;


charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<form name="insert" method="get" action="ins_submit.jsp">

Name<input type="text" name="ename"><br>

Job<input type="text" name="job"><br>

Salary<input type="text" name="sal"><br>

<input type="hidden" name="deptno" value="<%=


request.getParameter("deptno") %>">

<input type="submit" value="insert">

</form>

</body>

</html>

29
<%--

Document : ins_submit

Created on : April 30, 2014, 2:34:18 PM

Author :

--%>

<%@page import="java.sql.*"%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;


charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<%

Class.forName("com.mysql.jdbc.Driver");

String DB =
"jdbc:mysql://localhost:3306/personnel?user=root";

Connection myConnection = DriverManager.getConnection(DB);

Statement SMT = myConnection.createStatement();

String name=request.getParameter("ename");

String job=request.getParameter("job");

String sal=request.getParameter("sal");

int deptno=Integer.parseInt(request.getParameter("deptno"));

String sql="insert into emp(ename,job,sal,deptno) values


('"+name+"','"+job+"','"+sal+"',"+deptno+")";

SMT.executeUpdate(sql);

String URL = "index.jsp";

response.sendRedirect(URL);

%>

30
<%

SMT.close();

myConnection.close();

%>

</body>

</html>

31
<%--

Document : update

Created on : April 30, 2014, 2:35:38 PM

Author :

--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<%@page import="java.sql.*"%>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;


charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<%

Class.forName("com.mysql.jdbc.Driver");

String DB =
"jdbc:mysql://localhost:3306/personnel?user=root";

Connection myConnection = DriverManager.getConnection(DB);

Statement SMT = myConnection.createStatement();

String job="",sal="",ename="";

int empno=Integer.parseInt(request.getParameter("empno"));

String sql="select * from emp where empno="+empno;

ResultSet rs= SMT.executeQuery(sql);

while(rs.next()){

32
job=rs.getString("job");

sal=rs.getString("sal");

ename=rs.getString("ename");

%>

<form name="insert" method="get" action="up_submit.jsp">

Name<input type="text" name="ename" value="<%=


ename%>"><br>

Job<input type="text" name="job"value="<%= job%>"><br>

Salary<input type="text" name="sal" value="<%=


sal%>"><br>

<input type="hidden" name="empno" value="<%= empno%>">

<input type="submit" value="update">

</form>

</body>

</html>

33
<%--

Document : up_submit

Created on : April 30, 2014, 2:37:10 PM

Author :

--%>

<%@page import="java.sql.*"%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;


charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<%

Class.forName("com.mysql.jdbc.Driver");

String DB =
"jdbc:mysql://localhost:3306/personnel?user=root";

Connection myConnection = DriverManager.getConnection(DB);

Statement SMT = myConnection.createStatement();

String name=request.getParameter("ename");

String job=request.getParameter("job");

String sal=request.getParameter("sal");

int empno=Integer.parseInt(request.getParameter("empno"));

String sql="update emp set ename ='"+name+"' where


empno="+empno;

SMT.executeUpdate(sql);

34
sql="update emp set job ='"+job+"' where empno="+empno;

SMT.executeUpdate(sql);

sql="update emp set sal ='"+sal+"' where empno="+empno;

SMT.executeUpdate(sql);

String URL = "index.jsp";

response.sendRedirect(URL);

SMT.close();

myConnection.close();

%>

</body>

</html>

35
<%--

Document : delete

Created on : April 30, 2014, 2:38:19 PM

Author :

--%>

<%@page import="java.sql.*"%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;


charset=UTF-8">

<title>JSP Page</title>

</head>

<body>

<%

Class.forName("com.mysql.jdbc.Driver");

String DB =
"jdbc:mysql://localhost:3306/personnel?user=root";

Connection myConnection = DriverManager.getConnection(DB);

Statement SMT = myConnection.createStatement();

int empno=Integer.parseInt(request.getParameter("empno"));

String sql="delete from emp where empno="+empno;

SMT.executeUpdate(sql);

String URL = "index.jsp";

response.sendRedirect(URL);

SMT.close();

myConnection.close();

%>

</body>

</html>

36
Δημιουργία βάσης δεδομένων

CREATE DATABASE personnel;

USE personnel;

CREATE TABLE Dept(DEPTNO INT(2) NOT NULL,

DNAME VARCHAR(14), LOC VARCHAR(14),

NO_OF_EMPLOYEES INT(3),

PRIMARY KEY(DEPTNO));

CREATE TABLE Emp(EMPNO INT(4) NOT NULL AUTO_INCREMENT,

ENAME VARCHAR(10), JOB VARCHAR(9),

SAL FLOAT(7,2),

DEPTNO INT(2), PRIMARY KEY(EMPNO),

FOREIGN KEY(DEPTNO) REFERENCES Dept(DEPTNO));

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (20, 'RESEARCH', 'DALLAS');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (30, 'SALES', 'CHICAGO');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (40, 'OPERATIONS', 'BOSTON');

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'SMITH', 'CLERK', 800, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'ALLEN', 'SALESMAN', 1600, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'WARD', 'SALESMAN', 1250, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'JONES', 'MANAGER', 2975, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'MARTIN', 'SALESMAN', 1250, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'BLAKE', 'MANAGER', 2850, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'CLARK', 'MANAGER', 2450, 10);

37
INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'SCOTT', 'ANALYST', 3000, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'KING', 'PRESIDENT', 5000, 10);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'TURNER', 'SALESMAN', 1500, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'ADAMS', 'CLERK', 1100, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'JAMES', 'CLERK', 950, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'FORD', 'ANALYST', 3000, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'MILLER', 'CLERK', 1300, 10);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'BATES', 'ANALYST', 1300, NULL);

UPDATE dept

SET no_of_employees =

(SELECT COUNT(*)

FROM emp

WHERE emp.deptno = dept.deptno);

Select * from dept;

Select * from emp;

CREATE TABLE user(

uname text,

upass text,

Uid int(11),

Uphone varchar(45), Ucity varchar(45));

INSERT INTO `user` VALUES ('admin','1234',1,NULL,NULL);

Select * from user;

38
Βάσεις Δεδομένων ΙΙ (Ε)
Ενότητα 14: Επισκόπηση της Διαχείρισης triggers στο περιβάλλον mySQL και σε
Oracle

Χ. Σκουρλάς, Α. Τσολακίδης, Δ. Βάσσης

Τμήμα Μηχανικών Πληροφορικής ΤΕ


Περιεχόμενα
1. Επισκόπηση της Διαχείρισης triggers στο περιβάλλον mySQL και σε Oracle .................. 3
1.1 Υποδείξεις για τη διαχείριση triggers στο περιβάλλον mySQL ................................. 3
1.2 Δημιουργία βάσης δεδομένων με χρήση mySQL ..................................................... 3
1.3 Διαχείριση triggers στο περιβάλλον Oracle PL/SQL ................................................ 12
1.4 Κάποιες άλλες χρήσιμες υποδείξεις για τη διαχείριση των triggers στο προϊόν της
Oracle 21

Στόχος του εργαστηρίου είναι η επισκόπηση της χρήσης triggers για τη δημιουργία
εφαρμογών στο περιβάλλον mySQL αλλά και τη διαχείριση βάσεων δεδομένων.
Μετά την επεξεργασία του εργαστηρίου ο ενδιαφερόμενος θα έχει κατανοήσει τα
θέματα της χρήσης triggers και δημιουργίας εφαρμογής βάσεων δεδομένων. Τέλος,
ο ενδιαφερόμενος θα έχει κατανοήσει τα θέματα της χρήσης triggers και
δημιουργίας εφαρμογής βάσεων δεδομένων και στο περιβάλλον της Oracle.

Λέξεις κλειδιά: triggers, mySQL, Oracle

2
1. Επισκόπηση της Διαχείρισης triggers στο περιβάλλον mySQL
και σε Oracle

1.1 Υποδείξεις για τη διαχείριση triggers στο περιβάλλον mySQL


Έστω το απλοποιημένο σύστημα διαχείρισης στοιχείων προσωπικού στο
περιβάλλον της mySQL που περιλαμβάνει τους πίνακες: EMP, DEPT, USER.

1.2 Δημιουργία βάσης δεδομένων με χρήση mySQL


DROP DATABASE personnel;

CREATE DATABASE personnel;

USE personnel;

CREATE TABLE Dept(DEPTNO INT(2) NOT NULL,

DNAME VARCHAR(14), LOC VARCHAR(14),

NO_OF_EMPLOYEES INT(3),

PRIMARY KEY(DEPTNO));

CREATE TABLE Emp(EMPNO INT(4) NOT NULL AUTO_INCREMENT,

ENAME VARCHAR(10), JOB VARCHAR(9),

SAL FLOAT(7,2),

DEPTNO INT(2), PRIMARY KEY(EMPNO),

FOREIGN KEY(DEPTNO) REFERENCES Dept(DEPTNO));

CREATE TABLE user(

uname text,

upass text,

Uid int(11),

Uphone varchar(45), Ucity varchar(45));

3
INSERT INTO `user` VALUES ('admin','1234',1,NULL,NULL);

Select * from user;

Οι πίνακες emp, dept παρατίθενται με ενδεικτικό δείγμα δεδομένων.

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (20, 'RESEARCH', 'DALLAS');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (30, 'SALES', 'CHICAGO');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (40, 'OPERATIONS', 'BOSTON');

Select * from dept;

DEPTN NO_OF_EMPLOYEES
O DNAME LOC

10 ACCOUNTING NEW YORK

20 RESEARCH DALLAS

30 SALES CHICAGO

40 OPERATIONS BOSTON

4 rows selected. 0,06 seconds

4
INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'SMITH', 'CLERK', 800, 20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'ALLEN', 'SALESMAN', 1600,
30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'WARD', 'SALESMAN', 1250,
30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'JONES', 'MANAGER', 2975,
20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'MARTIN', 'SALESMAN',
1250, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'BLAKE', 'MANAGER', 2850,
30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'CLARK', 'MANAGER', 2450,
10);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'SCOTT', 'ANALYST', 3000,
20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'KING', 'PRESIDENT', 5000,
10);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'TURNER', 'SALESMAN',
1500, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'ADAMS', 'CLERK', 1100,
20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'JAMES', 'CLERK', 950, 30);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'FORD', 'ANALYST', 3000,
20);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'MILLER', 'CLERK', 1300,
10);

INSERT INTO Emp( ENAME, JOB, SAL, DEPTNO) VALUES ( 'BATES', 'ANALYST', 1300,
NULL);

5
Select * from emp;

ENAME JOB SAL DEPTNO


SMITH CLERK 800 20
ALLEN SALESMA 1600 30
N
WARD SALESMA 1250 30
N
JONES MANAGER 2975 20
MARTIN SALESMA 1250 30
N
BLAKE MANAGER 2850 30
CLARK MANAGER 2450 10
SCOTT ANALYST 3000 20
KING PRESIDEN 5000 10
T
TURNER SALESMA 1500 30
N
ADAMS CLERK 1100 20
JAMES CLERK 950 30
FORD ANALYST 3000 20
MILLER CLERK 1300 10
BATES ANALYST 1300 -

15 rows selected. 0,12 seconds

6
DROP TRIGGER emp_insert;

DROP TRIGGER emp_delete;

DROP TRIGGER emp_update;

DELIMITER //

CREATE TRIGGER emp_insert

AFTER INSERT ON emp

FOR EACH ROW

BEGIN

UPDATE dept

SET no_of_employees = IFNULL(no_of_employees, 0) + 1

WHERE deptno = NEW.deptno;

END //

DELIMITER ;

DELIMITER //

CREATE TRIGGER emp_delete

AFTER DELETE ON emp

FOR EACH ROW

BEGIN

UPDATE dept

SET no_of_employees = IFNULL(no_of_employees, 0) - 1

WHERE deptno = OLD.deptno;

END //

DELIMITER ;

7
DELIMITER //

CREATE TRIGGER emp_update

AFTER UPDATE ON emp

FOR EACH ROW

BEGIN

UPDATE dept

SET no_of_employees = NVL(no_of_employees,0) + 1

WHERE deptno = NEW.deptno;

UPDATE dept

SET no_of_employees = IFNULL(no_of_employees, 0) - 1

WHERE deptno = OLD.deptno;

END //

DELIMITER ;

8
Ακολουθούν δοκιμές / έλεγχοι.

INSERT INTO dept VALUES(11,'Belle Epoque', 'PARIS', 0);

INSERT INTO dept VALUES(12,'Rasors edge', 'PARIS', 0);

INSERT INTO emp(empno,ename,deptno) VALUES (102,'Luers',11);

INSERT INTO emp(empno,ename,deptno) VALUES (103,'Atwood',11);

INSERT INTO emp(empno,ename,deptno) VALUES (104,'Gennick',12);

SELECT * FROM dept WHERE deptno IN (11,12);

DELETE FROM emp WHERE empno = 103;

SELECT * FROM dept WHERE deptno IN (11,12);

UPDATE emp

SET deptno = 11

WHERE empno = 104;

SELECT * FROM dept WHERE deptno IN (11,12);

SELECT * FROM dept;

SELECT * FROM emp;

Διόρθωση τιμών της στήλης NO_OF_EMPLOYEES.

UPDATE dept

9
SET no_of_employees = (SELECT COUNT(*)

FROM emp

WHERE emp.deptno = dept.deptno);

1.3 Διαχείριση triggers στο περιβάλλον Oracle PL/SQL


Έστω το απλοποιημένο σύστημα διαχείρισης στοιχείων προσωπικού που συνοδεύει
το προϊόν της Oracle. Θα δοθούν κάποια βοηθητικά παραδείγματα που δουλεύουν
με παρόμοια στοιχεία με αυτά των γνωστών πινάκων EMP, DEPT της Oracle.

Σημείωση

Οι πίνακες emp, dept παρατίθενται με ενδεικτικό δείγμα δεδομένων.

SELECT * FROM EMP

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO


7369 SMITH CLERK 7902 17/12/80 800 - 20
7499 ALLEN SALESMAN 7698 20/02/81 1600 300 30
7521 WARD SALESMAN 7698 22/02/81 1250 500 30
7566 JONES MANAGER 7839 02/04/81 2975 - 20
7654 MARTIN SALESMAN 7698 28/10/81 1250 1400 30
7698 BLAKE MANAGER 7839 01/05/81 2850 - 30
7782 CLARK MANAGER 7839 09/06/81 2450 - 10
7788 SCOTT ANALYST 7566 19/04/87 3000 - 20
7839 KING PRESIDENT - 17/11/81 5000 - 10
7844 TURNER SALESMAN 7698 08/10/81 1500 0 30
7876 ADAMS CLERK 7788 23/05/87 1100 - 20
7900 JAMES CLERK 7698 03/12/81 950 - 30
7902 FORD ANALYST 7566 03/12/81 3000 - 20
7934 MILLER CLERK 7782 23/01/82 1300 - 10
7999 BATES ANALYST 7566 23/01/04 1300 - -

15 rows selected. 0,12 seconds

10
SELECT * FROM DEPT

DEPTNO DNAME LOC

10 ACCOUNTING NEW YORK

20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

4 rows selected. 0,06 seconds

Αν θέλετε να δημιουργήσετε πίνακες σαν αυτούς με τα στοιχεία τους μπορείτε να


χρησιμοποιήσετε τις εντολές:

/* Κατασκευάστε τους πίνακες Emp, Dept */

CREATE TABLE Dept(DEPTNO NUMBER(2) NOT NULL,

DNAME VARCHAR2(14), LOC VARCHAR2(14),

PRIMARY KEY(DEPTNO));

CREATE TABLE Emp(EMPNO NUMBER(4) NOT NULL,

ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4),

HIREDATE DATE, SAL NUMBER(7,2), COMM NUMBER(7,2),

DEPTNO NUMBER(2), PRIMARY KEY(EMPNO),

FOREIGN KEY(DEPTNO) REFERENCES Dept(DEPTNO));

/* Εισαγωγή στοιχείων στους πίνακες */

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (20, 'RESEARCH', 'DALLAS');

INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (30, 'SALES', 'CHICAGO');

11
INSERT INTO Dept(DEPTNO, DNAME, LOC)

VALUES (40, 'OPERATIONS', 'BOSTON');

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7369, 'SMITH', 'CLERK', 7902, '17/12/1980', 800, NULL, 20);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '20/02/1981', 1600, 300, 30);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7521, 'WARD', 'SALESMAN', 7698, '22/02/1981', 1250, 500, 30);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7566, 'JONES', 'MANAGER', 7839, '02/04/1981', 2975, NULL, 20);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '28/10/1981', 1250, 1400, 30);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7698, 'BLAKE', 'MANAGER', 7839, '01/05/1981', 2850, NULL, 30);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7782, 'CLARK', 'MANAGER', 7839, '09/06/1981', 2450, NULL, 10);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7788, 'SCOTT', 'ANALYST', 7566, '19/04/1987', 3000, NULL, 20);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7839, 'KING', 'PRESIDENT', NULL, '17/11/1981', 5000, NULL, 10);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7844, 'TURNER', 'SALESMAN', 7698, '08/10/1981', 1500, 0, 30);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7876, 'ADAMS', 'CLERK', 7788, '23/05/1987', 1100, NULL, 20);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

12
VALUES (7900, 'JAMES', 'CLERK', 7698, '03/12/1981', 950, NULL, 30);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7902, 'FORD', 'ANALYST', 7566, '03/12/1981', 3000, NULL, 20);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7934, 'MILLER', 'CLERK', 7782, '23/01/1982', 1300, NULL, 10);

INSERT INTO Emp(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

VALUES (7999, 'BATES', 'ANALYST', 7566, '23/01/2004', 1300, NULL, NULL);

/* τέλος εντολών */

Επομένως, βασιζόμενοι στα παραπάνω κατασκευάστε αρχικά τους πίνακες


MY_EMP, MY_DEPT που έχουν ανάλογη γραμμογράφηση και στοιχεία με τους EMP,
DEPT.

CREATE TABLE my_emp(empno NUMBER(4) NOT NULL,

ename VARCHAR2(10),

deptno NUMBER(2));

Αν θέλετε με την επόμενη εντολή μπορείτε να «φορτώσετε» από τον πίνακα emp
δεδομένα στον νέο πίνακα.

INSERT INTO my_emp

SELECT empno,ename,deptno FROM emp WHERE empno > 1000;

CREATE TABLE my_dept(deptno NUMBER(2) NOT NULL,

dname VARCHAR2(14));

13
Ο επόμενος trigger, είναι αποθηκευμένος (stored) και εκτελείται πριν από την
εισαγωγή / ενημέρωση των στοιχείων του πίνακα my_dept και μεταγράφει τα
στοιχεία αυτά με κεφαλαία γράμματα.

CREATE OR REPLACE TRIGGER dept_insert_update

BEFORE INSERT OR UPDATE ON my_dept

FOR EACH ROW

BEGIN

DBMS_OUTPUT.PUT_LINE('Εκτέλεση σκανδαλισμού dept_insert_update');

:NEW.dname := UPPER(:NEW.dname);

/* :NEW.dname contains the new value */

END;

Ακολουθούν δοκιμές.

INSERT INTO my_dept VALUES(10, 'Learn');

INSERT INTO my_dept VALUES(20, 'Discover');

INSERT INTO my_dept VALUES(30, 'Explore');

SELECT * FROM my_dept;

UPDATE my_dept

SET dname = 'Research'

WHERE deptno = 30;

SELECT * FROM my_dept;

14
Στη συνέχεια βλέπουμε τα στοιχεία του πίνακα my_emp και προσθέτουμε στον
πίνακα my_dept στήλη που έχει τον αριθμό των υπαλλήλων για κάθε τμήμα.

SELECT * FROM my_emp;

ALTER TABLE my_dept

ADD (no_of_employees NUMBER(4));

Αρχικοποιούμε τη νέα στήλη.

UPDATE my_dept

SET no_of_employees = (SELECT COUNT(*)

FROM my_emp

WHERE my_emp.deptno = my_dept.deptno);

και βλέπουμε τα στοιχεία του πίνακα.

SELECT * FROM my_dept;

Στη συνέχεια γράφουμε τρεις triggers για να αυτοματοποιήσουμε τη διαχείριση


της νέας στήλης του πίνακα my_dept όταν έχουμε μεταβολή στον πίνακα
my_emp.

CREATE OR REPLACE TRIGGER emp_insert

AFTER INSERT ON my_emp

FOR EACH ROW

BEGIN

UPDATE my_dept

SET no_of_employees = no_of_employees + 1

15
WHERE deptno = :NEW.deptno;

/* :NEW.deptno contains the new value

:OLD.deptno contains NULL value */

END;

CREATE OR REPLACE TRIGGER emp_delete

AFTER DELETE ON my_emp

FOR EACH ROW

BEGIN

UPDATE my_dept

SET no_of_employees = no_of_employees - 1

WHERE deptno = :OLD.deptno;

/* :OLD.deptno contains the old value

:NEW.deptno contains NULL value */

END;

CREATE OR REPLACE TRIGGER emp_update

AFTER UPDATE ON my_emp

FOR EACH ROW

BEGIN

/* :NEW.deptno contains the new value

:OLD.deptno contains the old value */

/* Increments the count for the employee's new department */

16
UPDATE my_dept

SET no_of_employees = NVL(no_of_employees,0) + 1

WHERE deptno = :NEW.deptno;

/* Decreases the count for the employee's old department */

UPDATE my_dept

SET no_of_employees = no_of_employees - 1

WHERE deptno = :OLD.deptno;

END;

Ακολουθούν δοκιμές / έλεγχοι.

INSERT INTO my_dept VALUES(11,'Belle Epoque',0);

INSERT INTO my_dept VALUES(12,'Rasors edge',0);

INSERT INTO my_emp(empno,ename,deptno) VALUES (102,'Luers',11);

INSERT INTO my_emp(empno,ename,deptno) VALUES (103,'Atwood',11);

INSERT INTO my_emp(empno,ename,deptno) VALUES (104,'Gennick',12);

SELECT * FROM my_dept WHERE deptno IN (11,12);

DELETE FROM my_emp WHERE empno = 103;

SELECT * FROM my_dept WHERE deptno IN (11,12);

UPDATE my_emp

SET deptno = 11

WHERE empno = 104;

SELECT * FROM my_dept WHERE deptno IN (11,12);

17
1.4 Κάποιες άλλες χρήσιμες υποδείξεις για τη διαχείριση των triggers
στο προϊόν της Oracle

Πως θα δούμε τη γραμμογράφηση και κάποια στοιχεία πινάκων του συστήματος


που σχετίζονται με τους triggers.

DESCRIBE USER_TRIGGERS;

SELECT trigger_name,triggering_event,trigger_type

FROM USER_TRIGGERS

WHERE table_name = 'MY_EMP'

ORDER BY trigger_name;

SELECT trigger_name,trigger_body

FROM USER_TRIGGERS

WHERE table_name= 'MY_EMP'

ORDER BY trigger_name;

Πως θα περιορίσουμε τη χρήση της βάσης για συγκεκριμένες ώρες.

CREATE OR REPLACE TRIGGER only_during_my_hours

BEFORE INSERT OR UPDATE OR DELETE ON my_emp

BEGIN

DBMS_OUTPUT.PUT_LINE('only_during_my_hours trigger');

IF TO_NUMBER(TO_CHAR(SYSDATE,'hh24')) < 8

/* nothing before 8:00 am */

18
OR TO_NUMBER(TO_CHAR(SYSDATE,'hh24')) >= 5

/* changes must be made before 5:00 pm */

OR TO_CHAR(SYSDATE,'dy') IN ('sun') THEN

/* nothing on Sunday */

RAISE_APPLICATION_ERROR(-20000,

'Αλλαγές μόνο τις ώρες που θέλουμε');

END IF;

END;

19

You might also like