21.01.2015 Views

1 1 CS3336a, Alex Babanski CS3336a, Alex Babanski <?php echo ...

1 1 CS3336a, Alex Babanski CS3336a, Alex Babanski <?php echo ...

1 1 CS3336a, Alex Babanski CS3336a, Alex Babanski <?php echo ...

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Database is simply a collection of data.<br />

In relational database, data is organized into tables.<br />

Student_ID Name Major Grade<br />

10145 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

… … …<br />

Database Management System (DBMS) is a software to maintain<br />

and utilize the collections of data (Oracle, DB2, MySQL)<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Database<br />

The overall collection of data –may consist of many tables<br />

Table<br />

An individual "relation" in the relational database<br />

Relates keys to values.<br />

Table Column<br />

An attribute in the table<br />

Table Row<br />

An entity in the table<br />

Typically has a value for each column<br />

Student_ID Name Major Grade<br />

10145 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

… … …<br />

1


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Key<br />

An attribute that uniquely identifies an entity<br />

Example: Student ID 10147 identifies student 'Boris'<br />

Foreign Key<br />

Key used to relate data in one table with data in another table<br />

Schema<br />

A description of a particular collection of data<br />

(a set of table designs that determine a database).<br />

Does not yet include the data –simply shows how it will be<br />

structured in the database<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Transaction<br />

A sequence of database actions (reads/writes).<br />

ACID Properties:<br />

Atomicity (all‐or‐nothing property)<br />

Consistency (rows affected by transaction remain consistent)<br />

Isolation (no transaction interference)<br />

Durability (committed transactions are protected against crashes)<br />

Database Engine ("Storage Engine")<br />

Is the underlying software component for storing, processing and<br />

securing data.<br />

2


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Query Optimization<br />

and Execution<br />

A typical DBMS has a layered architecture.<br />

Each database system has its own variations.<br />

Relational Operators<br />

Files and Access Methods<br />

Buffer Management<br />

Disk Space Management<br />

These layers must consider concurrency<br />

control and recovery.<br />

DB<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Relationships: how does the data in different tables relate<br />

One‐to‐One<br />

An entity in a table corresponds to a single entity in another table.<br />

The relationship is typically established using a foreign key for one or both entities.<br />

Example: If we have a table for Student_Info and a table for Academic_History,<br />

there is a one‐to‐one relationship between them.<br />

One‐to‐Many<br />

An entity in a table corresponds to 1 or more entities in another table.<br />

Example: If the table for Academic_History has an entry for each term, the relationship now<br />

becomes one student to many terms.<br />

3


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Many‐to‐Many<br />

Mu<strong>lt</strong>iple entities in one table correspond to mu<strong>lt</strong>iple entities in another table.<br />

This relationship is often defined by a separate table,<br />

which in fact changes it into 2 One-to-Many relationships<br />

Example: Tables Student_Info and Courses_Taken have a many to many relationship,<br />

since a student can take many courses and each course can be taken by many students.<br />

However, if we create a new table Student_Courses, we can have each entity be a pair:<br />

Student_Id, Course_id<br />

Now Student_Info has a one to many relationship with Student_Courses,<br />

and so does Courses_Taken<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

There is a lot of database theory about how to best create a schema:<br />

• Best modeling the data you are storing<br />

• Storing it most efficiently<br />

• Designing most efficient queries<br />

The process of organizing data to minimize redundancy is called normalization.<br />

We will talk about it later on. Check introduction:<br />

http://babanski.com/files/MySQL‐intro‐to‐database‐normalization.pdf<br />

We are concerned with the fundamentals, and for using MySQL<br />

through PHP and a Web interface.<br />

4


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

MySQL is a Database Management System.<br />

SQL stands for the Structured Query Language.<br />

It defines how to insert, retrieve, modify and delete data<br />

Most Popular open source software: http://www.mysql.com<br />

Who uses it<br />

Virtually every major company/corporation: http://www.mysql.com/why‐mysql/marketshare/<br />

• MySQL is a free and open source relational database management system.<br />

• MySQL has more than 20 million installations.<br />

• MySQL runs as a server providing mu<strong>lt</strong>i‐user access to a number of databases.<br />

• It is a cross platform database server.<br />

• Mu<strong>lt</strong>iple storage engines (MyISAM, InnoDB…)<br />

• Views creation and update<br />

• Transactions with the InnoDB Engine<br />

• Sub Queries / Nested Select<br />

• Primary key and indexing Current Versions: 5.1 (released in 2009), 5.5 (released in 2011)<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

• Create table<br />

• Insert records<br />

• Retrieve records<br />

• Update records<br />

• Delete records<br />

• Modify table<br />

• Join table<br />

• Drop table<br />

• Count, Like, Order by, Group by, limit<br />

• Optimize table<br />

• Advanced (sub‐queries, stored procedures, triggers, views …)<br />

http://dev.mysql.com/doc/refman/5.5/en/differences‐from‐ansi.html<br />

5


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CSV<br />

The engine stores data in text files using comma‐separated values format.<br />

Memory<br />

The engine creates tables with contents that are stored in memory.<br />

MyISAM<br />

Defau<strong>lt</strong> in 5.1.<br />

Non‐transaction Engine.<br />

No transaction overhead: much faster, lower disk space requirements, less memory required to<br />

perform updates.<br />

Atomicity (all‐or‐nothing property)<br />

Consistency (rows affected by transaction remain consistent)<br />

Isolation (no transaction interference)<br />

Durability (committed transactions are protected against crashes)<br />

InnoDB<br />

Defau<strong>lt</strong> in 5.5.<br />

Transaction‐safe (ACID compliant) Engine.<br />

Safe, can combine many statements with one COMMIT, can execute ROLLBACK, row‐level locking.<br />

http://dev.mysql.com/doc/refman/5.5/en/storage‐engines.html<br />

http://dev.mysql.com/doc/refman/5.1/en/storage‐engine‐compare‐transactions.html<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

A MySQL server can store several databases.<br />

Databases are usually stored as directories (MyISAM).<br />

Tables are stored as files inside each database (directory).<br />

Defau<strong>lt</strong> location for all files: /var/lib/mysql/<br />

Each MyISAM table has three files:<br />

• table.FRM file containing information about the table structure.<br />

• table.MYD file containing the row data.<br />

• table.MYI containing any indexes belonging with this table, as well as some<br />

statistics about the table.<br />

InnoDB:<br />

Data and indexes in tablespaces. Made up of one of more datafiles.<br />

6


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

MySQL allows console access:<br />

mysql –h hostname –u username –p [password]<br />

Typical usage (localhost):<br />

shell> mysql ‐u someusername ‐p<br />

Enter password: *****<br />

Create file .my.cnf<br />

[client]<br />

user="someusername"<br />

pass="1234567"<br />

Server version: 5.xx.xxxx (Debian)<br />

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.<br />

This software comes with ABSOLUTELY NO WARRANTY.<br />

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.<br />

mysql><br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CREATE<br />

create databases and tables<br />

ALTER<br />

a<strong>lt</strong>er the structure of a table<br />

INSERT<br />

insert a new row in a table<br />

UPDATE<br />

update rows in a table<br />

SELECT<br />

select table rows based on certain conditions<br />

DELETE<br />

delete one or more rows of a table<br />

Data Manipulation Statements<br />

http://dev.mysql.com/doc/refman/5.5/en/sql‐syntax‐data‐manipulation.html<br />

7


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CREATE a database:<br />

mysql> CREATE DATABASE databasename;<br />

USE a database:<br />

mysql> USE databasename;<br />

Important!! You need to have permissions to create a database.<br />

Your CS3336.com account doesn't have enough privileges to create a database.<br />

However, you can create as many tables as you want in the database given to you.<br />

For CPANEL users:<br />

In CPANEL databasename starts with login name and '_'.<br />

For instance, if your login name is csab123 then all your databases should start with csab123_<br />

‐ i.e. csab123_db , csab123_db2 , etc<br />

Keep it in mind when you create databases in shell on a server with CPANEL installed.<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

MySQL commands are NOT case‐sensitive.<br />

Often, command keywords are written in all caps, just to<br />

distinguish them from your user‐specific values such as table<br />

and column names. However, this isn’t necessary.<br />

MySQL commands have to end with a semicolon (;).<br />

If you forget this, the system will put an arrow on the next line: ‐><br />

which means it is waiting for you to finish the command.<br />

mysql> show databases<br />

‐><br />

8


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Execute Two statements,<br />

Fist statement –we need to select<br />

database 'babanski_db'<br />

Resu<strong>lt</strong><br />

http://<strong>php</strong>myadmin.cs3336.com<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

What are the current databases on the server<br />

mysql> SHOW databases;<br />

+--------------------+<br />

| Database |<br />

+--------------------+<br />

| information_schema |<br />

+--------------------+<br />

Use PHPMyAdmin SQL statements<br />

http://<strong>php</strong>myadmin.cs3336.com<br />

Create a database (make a directory):<br />

mysql> CREATE database cs3336_db;<br />

Select database to use:<br />

mysql> USE cs3336_db;<br />

Database changed<br />

Can do it as root‐privileged user only<br />

What tables are currently stored in the cs3336_db database<br />

mysql> SHOW tables;<br />

Empty set (0.00 sec)<br />

9


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Show tables in the database (select database first using 'use' command):<br />

mysql> SHOW tables;<br />

Describe structure of a table in the database:<br />

mysql> DESCRIBE tablename;<br />

mysql> use cs3336_hw4;<br />

Database changed<br />

mysql> desc countries;<br />

+-----------+------------------+------+-----+---------+-------+<br />

| Field | Type | Null | Key | Defau<strong>lt</strong> | Extra |<br />

+-----------+------------------+------+-----+---------+-------+<br />

| countryID | char(2) | NO | PRI | | |<br />

| country | varchar(200) | YES | | NULL | |<br />

| active | enum('YES','NO') | NO | | YES | |<br />

+-----------+------------------+------+-----+---------+-------+<br />

3 rows in set (0.00 sec)<br />

Select all data/records from a table:<br />

mysql> SELECT * from tablename;<br />

Use a condition clause to get a specific data/records from a table:<br />

mysql> SELECT * from students WHERE name='Boris';<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Grant access to a database:<br />

mysql> GRANT all on databasename.* to username@localhost identified by 'password';<br />

Grant limited access to a database:<br />

mysql> GRANT select, insert on databasename.* to username@localhost identified by 'password';<br />

Delete user/privileges:<br />

mysql> DROP USER 'username';<br />

Flush privileges!:<br />

mysql> FLUSH privileges;<br />

See a list of the privileges granted to a specific user:<br />

mysql> SHOW GRANTS for 'username'@'localhost';<br />

mysql> show grants for 'root'@'localhost';<br />

+----------------------------------------------------------------------------------------------------------------+<br />

| Grants for root@localhost |<br />

+----------------------------------------------------------------------------------------------------------------+<br />

| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*ED1B38B………' WITH GRANT OPTION |<br />

| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |<br />

+----------------------------------------------------------------------------------------------------------------+<br />

2 rows in set (0.00 sec)<br />

10


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CHAR () (size < 255 bytes)<br />

VARCHAR() (size < 255 bytes)<br />

BLOB or TEXT (size < 65,535 bytes)<br />

MEDIUMBLOB or MEDIUMTEXT (size < 16,777,215 bytes)<br />

LONGBLOB or LONGTEXT (size < 4 GB)<br />

ENUM (, ,…)<br />

TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT<br />

are integers of 1, 2, 3, 4, and 8 bytes, respectively.<br />

DECIMAL or NUMERIC(M, D)<br />

FLOAT<br />

DOUBLE<br />

DATE (defau<strong>lt</strong> format YYYY‐MM‐DD)<br />

http://dev.mysql.com/doc/refman/5.5/en/data‐types.html<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

File: table.sql<br />

DROP TABLE IF EXISTS `students`;<br />

SET character_set_client = utf8;<br />

CREATE TABLE `students` (<br />

`studentID` int unsigned NOT NULL auto_increment,<br />

`name` varchar(100) NOT NULL defau<strong>lt</strong> '',<br />

`major` varchar(50) NOT NULL defau<strong>lt</strong> '',<br />

`grade` tinyint NOT NULL defau<strong>lt</strong> '0',<br />

PRIMARY KEY (`studentID`)<br />

) ENGINE=MyISAM DEFAULT CHARSET=utf8;<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

… … …<br />

Import into cs3336_db database using console access:<br />

shell> mysql ‐u username ‐p < table.sql<br />

11


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CREATE TABLE `students` (<br />

`studentID` int unsigned NOT NULL auto_increment,<br />

`name` varchar(100) NOT NULL defau<strong>lt</strong> '',<br />

`major` varchar(50) NOT NULL defau<strong>lt</strong> '',<br />

`grade` tinyint NOT NULL defau<strong>lt</strong> '0',<br />

PRIMARY KEY (`studentID`)<br />

) ENGINE=MyISAM DEFAULT CHARSET=utf8;<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

INSERT data into the table:<br />

mysql> insert into students values ('','Michael', 'CS', 95);<br />

We 'override' auto_increment<br />

mysql> insert into students values (10146,'Dennis', 'PHYS', 75);<br />

mysql> insert into students (name, major, grade) values ('Boris', 'MATH', 89);<br />

mysql> insert into students set name='Katya', major='CS';<br />

Different syntax<br />

http://dev.mysql.com/doc/refman/5.5/en/insert.html<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CREATE TABLE `students` (<br />

`studentID` int unsigned NOT NULL auto_increment,<br />

`name` varchar(100) NOT NULL defau<strong>lt</strong> '',<br />

`major` varchar(50) NOT NULL defau<strong>lt</strong> '',<br />

`grade` tinyint NOT NULL defau<strong>lt</strong> '0',<br />

PRIMARY KEY (`studentID`)<br />

) ENGINE=MyISAM DEFAULT CHARSET=utf8;<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

SELECT all records from the table:<br />

mysql> select * from students;<br />

+-----------+---------+-------+-------+<br />

| studentID | name | major | grade |<br />

+-----------+---------+-------+-------+<br />

| 1 | Michael | CS | 95 |<br />

| 10146 | Dennis | PHYS | 75 |<br />

| 10147 | Boris | MATH | 89 |<br />

| 10148 | Katya | CS | 0 |<br />

+-----------+---------+-------+-------+<br />

http://dev.mysql.com/doc/refman/5.5/en/select.html<br />

Use \G modifier for many‐column data:<br />

mysql> select * from students\G;<br />

*************************** 1. row ***************************<br />

studentID: 1<br />

name: Michael<br />

major: CS<br />

grade: 95<br />

*************************** 2. row ***************************<br />

studentID: 10146<br />

name: Dennis<br />

major: PHYS<br />

grade: 75<br />

*************************** 3. row ***************************<br />

studentID: 10147<br />

name: Boris<br />

major: MATH<br />

grade: 89<br />

*************************** 4. row ***************************<br />

studentID: 10148<br />

name: Katya<br />

major: CS<br />

grade: 0<br />

12


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CREATE TABLE `students` (<br />

`studentID` int unsigned NOT NULL auto_increment,<br />

`name` varchar(100) NOT NULL defau<strong>lt</strong> '',<br />

`major` varchar(50) NOT NULL defau<strong>lt</strong> '',<br />

`grade` tinyint NOT NULL defau<strong>lt</strong> '0',<br />

PRIMARY KEY (`studentID`)<br />

) ENGINE=MyISAM DEFAULT CHARSET=utf8;<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

SELECT specific data/columns from the table:<br />

mysql> select studentID, name from students;<br />

+-----------+---------+<br />

| studentID | name |<br />

+-----------+---------+<br />

| 1 | Michael |<br />

| 10146 | Dennis |<br />

| 10147 | Boris |<br />

| 10148 | Katya |<br />

+-----------+---------+<br />

http://dev.mysql.com/doc/refman/5.5/en/select.html<br />

Important!<br />

Always select only data you need!<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CREATE TABLE `students` (<br />

`studentID` int unsigned NOT NULL auto_increment,<br />

`name` varchar(100) NOT NULL defau<strong>lt</strong> '',<br />

`major` varchar(50) NOT NULL defau<strong>lt</strong> '',<br />

`grade` tinyint NOT NULL defau<strong>lt</strong> '0',<br />

PRIMARY KEY (`studentID`)<br />

) ENGINE=MyISAM DEFAULT CHARSET=utf8;<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

SELECT specific data from the table and limit output:<br />

mysql> select studentID, name from students limit 2;<br />

+-----------+---------+<br />

| studentID | name |<br />

+-----------+---------+<br />

| 1 | Michael |<br />

| 10146 | Dennis |<br />

+-----------+---------+<br />

Important to create 'pages' with records<br />

Syntax: limit offset, row_count<br />

limit 2 is equivalent to limit 0, 2<br />

http://dev.mysql.com/doc/refman/5.5/en/select.html<br />

13


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CREATE TABLE `students` (<br />

`studentID` int unsigned NOT NULL auto_increment,<br />

`name` varchar(100) NOT NULL defau<strong>lt</strong> '',<br />

`major` varchar(50) NOT NULL defau<strong>lt</strong> '',<br />

`grade` tinyint NOT NULL defau<strong>lt</strong> '0',<br />

PRIMARY KEY (`studentID`)<br />

) ENGINE=MyISAM DEFAULT CHARSET=utf8;<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

SELECT specific data from the table with WHERE clause:<br />

mysql> select name, major, grade from students where major='cs';<br />

mysql> select name, major, grade from students where major='c%';<br />

+---------+-------+-------+<br />

| name | major | grade |<br />

+---------+-------+-------+<br />

| Michael | CS | 95 |<br />

| Katya | CS | 0 |<br />

+---------+-------+-------+<br />

http://dev.mysql.com/doc/refman/5.5/en/select.html<br />

Question: Is anything wrong with my select<br />

Check Case‐Sensitivity issue!<br />

http://dev.mysql.com/doc/refman/5.0/en/case‐sensitivity.html<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CREATE TABLE `students` (<br />

`studentID` int unsigned NOT NULL auto_increment,<br />

`name` varchar(100) NOT NULL defau<strong>lt</strong> '',<br />

`major` varchar(50) NOT NULL defau<strong>lt</strong> '',<br />

`grade` tinyint NOT NULL defau<strong>lt</strong> '0',<br />

PRIMARY KEY (`studentID`)<br />

) ENGINE=MyISAM DEFAULT CHARSET=utf8;<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

More examples of WHERE clause:<br />

mysql> select * from students where grade>75;<br />

mysql> select name, grade from students where major in ('CS', 'phys');<br />

mysql> select * from students where name='michael' and major='cs';<br />

mysql> select studentID from students where name='dennis' or major='cs';<br />

http://dev.mysql.com/doc/refman/5.5/en/select.html<br />

14


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CREATE TABLE `students` (<br />

`studentID` int unsigned NOT NULL auto_increment,<br />

`name` varchar(100) NOT NULL defau<strong>lt</strong> '',<br />

`major` varchar(50) NOT NULL defau<strong>lt</strong> '',<br />

`grade` tinyint NOT NULL defau<strong>lt</strong> '0',<br />

PRIMARY KEY (`studentID`)<br />

) ENGINE=MyISAM DEFAULT CHARSET=utf8;<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

SELECT and ORDER data from the table:<br />

mysql> select * from students order by grade asc;<br />

mysql> select * from students order by grade asc, name desc;<br />

+-----------+---------+-------+-------+<br />

| studentID | name | major | grade |<br />

+-----------+---------+-------+-------+<br />

| 10148 | Katya | CS | 0 |<br />

| 10146 | Dennis | PHYS | 75 |<br />

| 10147 | Boris | MATH | 89 |<br />

| 1 | Michael | CS | 95 |<br />

+-----------+---------+-------+-------+<br />

http://dev.mysql.com/doc/refman/5.5/en/select.html<br />

Secondary rule<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

CREATE TABLE `students` (<br />

`studentID` int unsigned NOT NULL auto_increment,<br />

`name` varchar(100) NOT NULL defau<strong>lt</strong> '',<br />

`major` varchar(50) NOT NULL defau<strong>lt</strong> '',<br />

`grade` tinyint NOT NULL defau<strong>lt</strong> '0',<br />

PRIMARY KEY (`studentID`)<br />

) ENGINE=MyISAM DEFAULT CHARSET=utf8;<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

SELECT , ORDER and apply WHERE clause to the data:<br />

mysql> select * from students where grade>75 order by grade asc;<br />

+-----------+---------+-------+-------+<br />

| studentID | name | major | grade |<br />

+-----------+---------+-------+-------+<br />

| 10147 | Boris | MATH | 89 |<br />

| 1 | Michael | CS | 95 |<br />

+-----------+---------+-------+-------+<br />

http://dev.mysql.com/doc/refman/5.5/en/select.html<br />

15


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

How many students have the same major<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

mysql> select major, count(*) as size from students;<br />

mysql> select major, count(*) as size from students ORDER BY major asc;<br />

Not what we expected!!!<br />

+-------+------+<br />

| major | size |<br />

+-------+------+<br />

| CS | 4 |<br />

+-------+------+<br />

mysql> select major, count(*) as size from students GROUP BY major asc;<br />

+-------+------+<br />

| major | size |<br />

+-------+------+<br />

| CS | 2 |<br />

| MATH | 1 |<br />

| PHYS | 1 |<br />

+-------+------+<br />

Use in conjunction with aggregate functions<br />

http://dev.mysql.com/doc/refman/5.5/en/group‐by‐functions.html<br />

http://dev.mysql.com/doc/refman/5.5/en/group‐by‐functions‐and‐modifiers.html<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

UPDATE data in the table:<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

mysql> update students set grade='65';<br />

mysql> update students set grade='65' where grade>75;<br />

mysql> update students set grade='65' where name='Boris';<br />

mysql> update students set grade='65' where studentID='10147';<br />

mysql> update students set grade='65', major='CS' where studentID='10147';<br />

DELETE data from the table:<br />

mysql> delete from students;<br />

mysql> delete from students where studentID='10147';<br />

mysql> delete from students where studentID'10147';<br />

http://dev.mysql.com/doc/refman/5.5/en/update.html<br />

http://dev.mysql.com/doc/refman/5.5/en/delete.html<br />

16


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

http://dev.mysql.com/doc/refman/5.5/en/functions.html<br />

mysql> select 1+1 as sumoftwo;<br />

+----------+<br />

| sumoftwo |<br />

+----------+<br />

| 2 |<br />

+----------+<br />

mysql> select IF (1 select now() as currentTime;<br />

+---------------------+<br />

| currentTime |<br />

+---------------------+<br />

| 2012-11-16 03:39:35 |<br />

+---------------------+<br />

mysql> select concat_ws('‐', 'Go', 'Canada');<br />

+--------------------------------+<br />

| concat_ws('-', 'Go', 'Canada') |<br />

+--------------------------------+<br />

| Go-Canada |<br />

+--------------------------------+<br />

Operators, Control Flow functions, String Functions, Date and Time Functions<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

MySQL has many functions available to a<strong>lt</strong>er or format the data stored in tables.<br />

When using a MySQL function specify a column name.<br />

Functions are:<br />

• case insensitive<br />

• no space between function name and parentheses<br />

Typical syntax:<br />

Add extra clauses if needed<br />

(WHERE, ORDER BY, etc)<br />

SELECT FUNCTION( columnName ) FROM tableName;<br />

SELECT column1, FUNCTION( column2 ), column3 FROM tableName;<br />

http://dev.mysql.com/doc/refman/5.5/en/functions.html<br />

17


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Name<br />

=<br />

Description<br />

http://dev.mysql.com/doc/refman/5.5/en/non‐typed‐operators.html<br />

Equal operator or Assign a value (as part of a SET statement, or as<br />

part of the SET clause in an UPDATE statement)<br />

:= Assign a value<br />

BETWEEN ... AND ...<br />

Check whether a value is within a range of values<br />

& , ^, |, >>, , = ,


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Function Usage Purpose<br />

CONCAT() CONCAT(x,y,…) Creates a new string of the form xy<br />

CONCAT_WS() CONCAT_WS(separator,x,y) Creates a new strung with separator<br />

CONV() CONV(n, base, to_base) Converts numbers between diff base<br />

TRIM() TRIM(column) Trims space from the beginning and end.<br />

UPPER() UPPER(str) Capitalizes the string<br />

LOWER() LOWER(str) Makes a string lowercase<br />

SUBSTR() SUBSTR(str, pos, len) Returns a substring<br />

LENGTH() LENGTH(str) Returns string length<br />

http://dev.mysql.com/doc/refman/5.5/en/string‐functions.html<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Function Usage Purpose<br />

DAY() / MONTH() DAY(date) / MONTH(date) Returns day/month of the date<br />

CURTIME() CURTIME() Returns the current time<br />

CURDATE() CURDATE() Returns the current date<br />

NOW() NOW() Returns the current date and time<br />

UNIX_TIMESTAMP() UNIX_TIMESTAMP() Returns seconds since 1970‐01‐01<br />

DATE_ADD() DATE_ADD(date, expr) Returns date adjusted by expr<br />

DATE_SUB() DATE_SUB(date,expr) Returns date adjusted by expr<br />

TO_DAYS() TO_DAYS(date) Returns number of days since year 0.<br />

MySQL Defau<strong>lt</strong> Datetime format is: 'YYYY‐MM‐DD HH:MM:SS'<br />

http://dev.mysql.com/doc/refman/5.5/en/date‐and‐time‐functions.html<br />

MySQL uses what is known as a proleptic Gregorian calendar.<br />

19


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Other Important Functions:<br />

• Control Flow Functions:<br />

IF(), IFNULL(), NULLIF(), etc<br />

• Information Functions:<br />

FOUND_ROWS(), LAST_INSERT_ID(), etc<br />

• Encryption and Compression Functions:<br />

AES_DECRYPT(), AES_ENCRYPT(), MD5(), ENCODE(), etc<br />

• XML Functions:<br />

ExtractValue(), UpdateXML()<br />

• Functions and Modifiers for GROUP BY clauses:<br />

COUNT(), SUM(), MAX(), MIN()<br />

http://dev.mysql.com/doc/refman/5.5/en/functions.html<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

• Functions and Modifiers for GROUP BY clauses:<br />

COUNT()<br />

‐ Returns the number of matching entries<br />

SUM()<br />

‐ Returns the sum of matching values<br />

MAX() / MIN() ‐ Returns maximum/minimum value of a group<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

mysql> select MAX(grade) from students;<br />

+------------+<br />

| MAX(grade) |<br />

+------------+<br />

| 95 |<br />

+------------+<br />

mysql> select MAX(grade) from students GROUP BY major;<br />

+------------+<br />

| MAX(grade) |<br />

+------------+<br />

| 95 |<br />

| 89 |<br />

| 75 |<br />

+------------+<br />

http://dev.mysql.com/doc/refman/5.5/en/group‐by‐functions‐and‐modifiers.html<br />

20


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

MySQL supports a number of date and time column formats:<br />

DATE<br />

‐ Stores a date value in the form YYYY‐MM‐DD.<br />

For example 2008‐10‐23.<br />

DATETIME<br />

‐ Stores a date and time value of the form YYYY‐MM‐DD HH:MM:SS.<br />

For example 2008‐10‐23 10:37:22.<br />

The supported range is 1000‐01‐01 00:00:00 to 9999‐12‐31 23:59:59<br />

TIMESTAMP<br />

‐ Similar to DATETIME. The main difference is that it's tied to a time zone.<br />

If you change time_zone on a server then you change TIMESTAMP value.<br />

The supported range is 1970‐01‐01 00:00:00 UTC to 2038‐01‐03 03:14:07 UTC<br />

Acceptable (relaxed) values of date/time:<br />

YYYYMMDDHHMMSS ; YYYY/MM/DD HH*MM*SS; YYYYMMDD ; YYMMDD ; YYYY/MM/DD<br />

For example, '20070523091528' and '070523091528' are interpreted as '2007‐05‐23 09:15:28',<br />

but '071122129015' is illegal (it has a nonsensical minute part) and becomes '0000‐00‐00 00:00:00'.<br />

http://dev.mysql.com/doc/refman/5.5/en/date‐and‐time‐literals.html<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Automatic Initialization and Updating of TIMESTAMP:<br />

http://dev.mysql.com/doc/refman/5.5/en/timestamp‐initialization.html<br />

One TIMESTAMP column in a table can have the current timestamp as the defau<strong>lt</strong> value for initializing the<br />

column, as the auto‐update value, or both.<br />

CREATE TABLE t1 (<br />

ts TIMESTAMP DEFAULT 0<br />

);<br />

The defau<strong>lt</strong> is the given value.<br />

In this case, the column has no automatic properties at all.<br />

CREATE TABLE t1 (<br />

ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP<br />

);<br />

The defau<strong>lt</strong> is the current timestamp.<br />

Column is not automatically updated to the current timestamp.<br />

CREATE TABLE t1 (<br />

ts TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP<br />

);<br />

Can be NULL<br />

CREATE TABLE t1 (<br />

ts TIMESTAMP<br />

);<br />

Equivalent to:<br />

ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP<br />

The column is automatically updated to the current<br />

timestamp and has the given constant defau<strong>lt</strong> value.<br />

The column has the current timestamp for its defau<strong>lt</strong> value and is<br />

automatically updated to the current timestamp.<br />

21


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Tutorial on MySQL Date and Time Functions:<br />

http://www.t<strong>echo</strong>topia.com/index.<strong>php</strong>/Working_with_Dates_and_Times_in_MySQL<br />

http://dev.mysql.com/doc/refman/5.5/en/date‐and‐time‐functions.html<br />

Most MySQL indexes (PRIMARY KEY, UNIQUE, INDEX, andFULLTEXT) are stored in B-trees.<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

The whole point of using a database, as opposed to a flat file, is to speed up searches.<br />

One way to markedly increase search speed is to make an index based on your most<br />

common search criteria.<br />

Index is a Data structure that improves the speed of data retrieval from a database table<br />

at the cost of slower writes and increased storage space.<br />

http://dev.mysql.com/doc/refman/5.5/en/optimization‐indexes.html<br />

MySQL indexes: PRIMARY KEY, UNIQUE, INDEX, and FULLTEXT<br />

MySQL uses indexes for these operations:<br />

• To find the rows matching a WHERE clause quickly.<br />

• To eliminate rows from consideration.<br />

• To retrieve rows from other tables when performing joins.<br />

• To find the MIN() or MAX() value for a specific indexed column.<br />

• To sort or group a table.<br />

• In some cases, a query can be optimized to retrieve values without consu<strong>lt</strong>ing the data rows.<br />

22


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

UNIQUE Index (constraint)<br />

All values in the index must be distinct.<br />

An error occurs if you try to add a new row with a key value that matches an existing row.<br />

It permits mu<strong>lt</strong>iple NULL values for columns that can contain NULL.<br />

PRIMARY KEY<br />

Is a unique index (can be mu<strong>lt</strong>i‐column) where all key columns must be defined as NOT NULL.<br />

A table can have only one PRIMARY KEY.<br />

When table is created, an index based on the primary key is automatically constructed.<br />

In the created table, a PRIMARY KEY is placed first, followed by all UNIQUE indexes, and<br />

then the non‐unique indexes.<br />

Primary Key uniquely identifies the rest of the data in any given row.<br />

Example: Social Insurance Number<br />

In InnoDB tables, keep the PRIMARY KEY short to minimize storage overhead for secondary indexes.<br />

Each secondary index entry contains a copy of the primary key.<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Foreign Keys<br />

If a table has many columns, and you query many different combinations of columns, it<br />

might be efficient to split the less‐frequently used data into separate tables with a few<br />

columns each, and relate them back to the main table by duplicating the numeric ID column<br />

from the main table. That way, each small table can have a primary key for fast lookups of its<br />

data, and you can query just the set of columns that you need using a join operation.<br />

Column Indexes / Mu<strong>lt</strong>iple‐Column Indexes<br />

The most common type of index involves a single column, storing copies of the values from<br />

that column in a data structure, allowing fast lookups for the rows with the corresponding<br />

column values.<br />

A mu<strong>lt</strong>iple‐column index can be considered a sorted array. MySQL can use mu<strong>lt</strong>iple‐column<br />

indexes for queries that test all the columns in the index, or queries that test just the first<br />

column, the first two columns, the first three columns, and so on.<br />

23


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Create an Index<br />

• A column contains a wide rage of values,<br />

many NULL values.<br />

• Columns frequently used in a WHERE clause.<br />

• To retrieve rows < 2~4 % of the total rows<br />

Do NOT Create an Index<br />

• Small table<br />

• Rarely used columns<br />

• To retrieve rows > 2~4 % of the total rows<br />

• Frequently updated table.<br />

An index is made from one or more columns, using the syntax<br />

CREATE INDEX index_name ON table_name (column_name1, column_name2, ...)<br />

Confirm Indexes:<br />

mysql> SHOW INDEX from students;<br />

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+<br />

| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type |<br />

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+<br />

| students | 0 | PRIMARY | 1 | studentID | A | 4 | NULL | NULL | | BTREE |<br />

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

mysql> EXPLAIN [EXTENDED] SELECT ………<br />

To obtain information about how MySQL executes a SELECT statement.<br />

Information from the optimizer about the query execution plan.<br />

mysql> explain extended select * from students;<br />

+----+-------------+----------+------+---------------+------+---------+------+------+----------+-------+<br />

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | fi<strong>lt</strong>ered | Extra |<br />

+----+-------------+----------+------+---------------+------+---------+------+------+----------+-------+<br />

| 1 | SIMPLE | students | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | |<br />

+----+-------------+----------+------+---------------+------+---------+------+------+----------+-------+<br />

To show overall estimated cost of query:<br />

mysql> SHOW SESSION STATUS LIKE 'Last_query_cost';<br />

+-----------------+----------+<br />

| Variable_name | Value |<br />

+-----------------+----------+<br />

| Last_query_cost | 0.000000 |<br />

+-----------------+----------+<br />

24


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

MySQL and Client/Server Model:<br />

PHP<br />

Script<br />

Local<br />

Recources<br />

MySQL<br />

Server<br />

MySQL<br />

Server<br />

Remote<br />

Resources<br />

Before you can access a database, a connection to the database must be created.<br />

The interaction with MySQL server consists of the following steps:<br />

• Connect to MySQL server (requires a username and password).<br />

• Select the active database ('use database' analog).<br />

• Perform SQL queries and retrieve resu<strong>lt</strong>s.<br />

• Free Resu<strong>lt</strong>s<br />

• Close connection to MySQL (not needed unless you are using persistent connections)<br />

http://www.<strong>php</strong>.net/manual/en/set.mysqlinfo.<strong>php</strong><br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Connection<br />

$db_link = mysql_connect("localhost", "dbuser", "dbpass");<br />

If ($db_link == false)<br />

die("Could not connect: ". mysql_error());<br />

Database selection:<br />

mysql_select_db("CS3336_db", $db_link) or die("Could not select database:" . mysql_error());<br />

Perform a query:<br />

$query = "SELECT name, major from students where studentID='10147'";<br />

$resu<strong>lt</strong> = mysql_query($query, $db_link);<br />

If (!$resu<strong>lt</strong>) {<br />

<strong>echo</strong> "Could not perform insert: ". mysql_error(); }<br />

else {<br />

$studentID = mysql_insert_id($db_link);<br />

}<br />

mysql_free_resu<strong>lt</strong>($resu<strong>lt</strong>); // Free Resu<strong>lt</strong><br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

mysql_close($db_link);<br />

// Close Connection<br />

http://www.<strong>php</strong>.net/manual/en/set.mysqlinfo.<strong>php</strong><br />

25


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Connection<br />

$db_link = mysql_connect("localhost", "dbuser", "dbpass");<br />

If ($db_link == false)<br />

die("Could not connect: ". mysql_error());<br />

Database selection:<br />

mysql_select_db("CS3336_db", $db_link) or die("Could not select database:" . mysql_error());<br />

Processing Mu<strong>lt</strong>iple Records:<br />

$resu<strong>lt</strong> = @mysql_query('Select name, grade as gr FROM students');<br />

while ($row = mysql_fetch_array($resu<strong>lt</strong>)) {<br />

$name=$row['name'];<br />

$grade=$row['gr'];<br />

<strong>echo</strong> "$name $grade" .'';<br />

}<br />

StudentID name major grade<br />

1 Michael CS 95<br />

10146 Dennis PHYS 75<br />

10147 Boris MATH 89<br />

10148 Katya CS 0<br />

There are a number of ways for retrieving the resu<strong>lt</strong>s of a query. The most commonly used are:<br />

• mysql_fetch_assoc() returns an associative array where the keys are the record field names.<br />

• mysql_fetch_object() returns a record as an object. There are object attributes for each record field.<br />

http://www.<strong>php</strong>.net/manual/en/set.mysqlinfo.<strong>php</strong><br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

SQL Injection –Trust NO One!<br />

Usually you would get the data that you put in your database from the user.<br />

Make sure that the data will not break your SQL queries. (SQL Injection)<br />

$sql=" SELECT * FROM students WHERE name = '$badName' "<br />

// What happens when you pass $badName === " ' OR 1;' "<br />

$sql=" SELECT * FROM students WHERE name = '' OR 1;'' "<br />

Always executes!<br />

//What about $badName==" '; DELETE FROM students where 1 or name=' "<br />

mysql_real_escape_string()<br />

a useful function for escaping characters before using a string in an SQL query.<br />

26


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

function prepare_insert_sql (& $sql_arr) {<br />

$sql_fields = implode ( ',', array_keys ( $sql_arr ) );<br />

$sql_values = implode ( ',', array_map ( 'escape_string', array_values ( $sql_arr ) ) );<br />

return "({$sql_fields}) values ({$sql_values})";<br />

}<br />

Recall INSERT syntax:<br />

insert into students (name, major, grade) values ('Boris', 'MATH', 89)<br />

function prepare_update_sql (& $sql_arr) {<br />

$arr=array();<br />

foreach($sql_arr as $key=>$value) {<br />

$arr[]= $key .'='.escape_string($value);<br />

}<br />

return implode(', ', array_values($arr));<br />

}<br />

$sql_arr= array (<br />

'name'=>'Boris',<br />

'major'=>'Math',<br />

grade=>'89'<br />

);<br />

Recall UPDATE syntax:<br />

update students set name='Boris', major='MATH', grade='89'<br />

function escape_string($str) {<br />

return "'" . mysql_real_escape_string($str) . "'";<br />

}<br />

Any Problems<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

function add_record(&$HTML) {<br />

$users_arr=array();<br />

$keys='name,major,grade';<br />

foreach( explode(',',$keys) as $index => $key ) {<br />

$users_arr[$key]=$HTML[$key];<br />

}<br />

$HTML= array (<br />

'name'=>'Boris',<br />

'major'=>'Math',<br />

grade=>'89',<br />

phone=>'….',<br />

e‐mail=>'something'<br />

);<br />

$resu<strong>lt</strong> = @mysql_query('INSERT INTO table ' . prepare_insert_sql($users_arr));<br />

if ($resu<strong>lt</strong>) {<br />

$user_id=mysql_insert_id();<br />

@mysql_free_resu<strong>lt</strong>($resu<strong>lt</strong>);<br />

}<br />

…………<br />

}<br />

return $user_id;<br />

27


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Sometimes you have 100+ records that you need to show on more than 1 page<br />

mysql> select count(studentID) as total_records from students;<br />

+---------------+<br />

| total_records |<br />

+---------------+<br />

| 4 |<br />

+---------------+<br />

In PHP get SQL records for a specific page number $page with $max_list records per page:<br />

list($total_records) = mysql_fetch_row(@mysql_query('select count(studentID) as ……'));<br />

$total_pages = ceil($total_records / $max_list);<br />

$start = ($page‐1) * $max_list;<br />

$sql_query .= " LIMIT $start, $max_list";<br />

Note: this is faster than using MySQL SQL_CALC_FOUND_ROWS and FOUND_ROWS()<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

The MySQLi extension provides various benefits with respect to its predecessor.<br />

It supports all the latest features in MySQL server 4.1 or higher.<br />

Major features:<br />

• An object‐oriented interface<br />

• Procedural interface (all the function names begin with mysqli_ instead of mysql_)<br />

• Support for the full feature set of the MySQL c‐client library<br />

• Support for prepared statements<br />

• Support for mu<strong>lt</strong>iple statements<br />

• Support for transactions<br />

• Enhanced debugging support<br />

• Embedded server support<br />

Advantages:<br />

• Maintainable<br />

• Similar Syntax<br />

• New Interface<br />

• Advanced Options<br />

• Speed<br />

• Security<br />

http://www.<strong>php</strong>.net/manual/en/book.mysqli.<strong>php</strong><br />

28


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

MySQLi: Dual Procedural and Object‐Oriented interface<br />

connect_errno) {<br />

<strong>echo</strong> "Failed to connect to MySQL: " . $mysqli‐>connect_error;<br />

exit;<br />

}<br />

If ( $resu<strong>lt</strong> = $mysqli‐>query("SELECT name, major from students where studentID='10147'") ) {<br />

$row = $resu<strong>lt</strong>‐>fetch_assoc();<br />

<strong>echo</strong> $row['name'];<br />

$resu<strong>lt</strong>‐>close();<br />

}<br />

><br />

http://<strong>php</strong>.net/manual/en/mysqli.quickstart.dual‐interface.<strong>php</strong><br />

// close database connection<br />

mysqli_close($mysqli);<br />

// close database connection<br />

$mysqli‐>close();<br />

else {<br />

<strong>echo</strong> mysqli_error();<br />

}<br />

else {<br />

<strong>echo</strong> mysqli‐>error;<br />

}<br />

MySQLi: Prepared Statements<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Using this new feature, available in MySQLi, it is possible to create queries that are:<br />

• More secure<br />

• Have better performance<br />

• More convenient to write<br />

Two types of Prepared Statements:<br />

• Bound Parameter<br />

• Bound Resu<strong>lt</strong><br />

The '' placeholders can be used in most places that could have literal data.<br />

A query could be transformed from:<br />

SELECT name, major FROM students WHERE studentID = '10147';<br />

to:<br />

SELECT name, major FROM students WHERE studentID = ;<br />

http://www.<strong>php</strong>.net/manual/en/mysqli.quickstart.prepared‐statements.<strong>php</strong><br />

No quotes around ''<br />

29


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Bound Parameter Prepared Statements<br />

• A Query template is created and sent to the MySQL server<br />

• MySQL server validates it, stores it and returns a special handle for future use<br />

• When a query needs to be executed, data to fill in the template is sent to the server<br />

• A complete query is formed and then executed<br />

Advantages<br />

• The body of the query is sent only once, later only data to fill in are sent<br />

• Most of the work required to validate and parse the query only needs to be done a single<br />

time, instead of each time the query is executed.<br />

• The data for the query does not need to be passed through a function like<br />

mysql_real_escape_string()<br />

to ensure that no SQL injection attacks occur. Instead, the sent data is handled safely by<br />

server when it is combined with the prepared statement.<br />

http://www.<strong>php</strong>.net/manual/en/mysqli.quickstart.prepared‐statements.<strong>php</strong><br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Example 1:<br />

$stmt = $mysqli‐>stmt_init(); // create a prepared statement<br />

if( $stmt = $mysqli‐>prepare("INSERT INTO students VALUES ('', , , )") ){<br />

$name ='Boris';<br />

$major ='MATH'; Parameters to be passed by reference<br />

$grade = 89;<br />

$stmt‐>bind_param('ssi', $name, $major, $grade);<br />

StudentID name major grade<br />

10147 Boris MATH 89<br />

}<br />

/* execute prepared statement */<br />

$stmt‐>execute();<br />

<strong>echo</strong> $stmt‐>affected_rows. " row inserted.\n";<br />

/* a<strong>lt</strong>ernative output */<br />

printf("%d row inserted.\n", $stmt‐>affected_rows);<br />

/* close statement and connection */<br />

$stmt‐>close();<br />

BIND Type<br />

i<br />

d<br />

b<br />

s<br />

COLUMN Type<br />

All INT types<br />

DOUBLE and FLOAT<br />

BLOBs<br />

All other types<br />

http://www.<strong>php</strong>.net/manual/en/mysqli.quickstart.prepared‐statements.<strong>php</strong><br />

http://www.<strong>php</strong>.net/manual/en/mysqli‐stmt.bind‐param.<strong>php</strong><br />

30


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Example 2:<br />

$stmt = $mysqli‐>stmt_init();<br />

if( $stmt = $mysqli‐>prepare("SELECT name, grade FROM students where studentID =") ){<br />

$IDs= array('10147', '10148');<br />

$stmt‐>bind_param('i', $studentID);<br />

}<br />

foreach($IDs as $studentID) {<br />

/* execute prepared statement */<br />

$stmt‐>execute();<br />

$resu<strong>lt</strong>= $stmt‐>get_resu<strong>lt</strong>();<br />

/* fetch values: */<br />

while ($row = $resu<strong>lt</strong>‐>fetch_assoc()) {<br />

printf ("Name: %s , Grade: %d ', $row['name'], $row['grade']);<br />

}<br />

}<br />

/* close statement and connection */<br />

Can we simplify this<br />

$stmt‐>close();<br />

http://www.<strong>php</strong>.net/manual/en/mysqli.quickstart.prepared‐statements.<strong>php</strong><br />

http://www.<strong>php</strong>.net/manual/en/mysqli‐stmt.bind‐param.<strong>php</strong><br />

StudentID name major Grade<br />

10147 Boris MATH 89<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Bound Resu<strong>lt</strong> Prepared Statements<br />

• Allow the value of variables in a PHP script to be tied to the value of fields of data in a<br />

query resu<strong>lt</strong> set.<br />

• Create a query<br />

• Prepare the query<br />

• Ask the MySQL server to execute the query<br />

• Bind PHP variables to columns in the query resu<strong>lt</strong><br />

• Request that a new row of data be loaded into the bound variables.<br />

It is possible to use bound parameters and bound resu<strong>lt</strong>s together in a single prepared statement.<br />

http://www.<strong>php</strong>.net/manual/en/mysqli.quickstart.prepared‐statements.<strong>php</strong><br />

31


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Example:<br />

$stmt = $mysqli‐>stmt_init();<br />

if( $stmt = $mysqli‐>prepare("SELECT name, grade from students limit 5") ){<br />

/* execute prepared statement */<br />

$stmt‐>execute();<br />

StudentID name major grade<br />

10147 Boris MATH 89<br />

/* bind variables to prepared statement */<br />

$stmt‐>bind_resu<strong>lt</strong>($name, $grade);<br />

/* fetch values: */<br />

while ($stmt‐>fetch()) {<br />

printf ("Name: %s , Grade: %d ', $name, $grade);<br />

}<br />

}<br />

/* close statement and connection */<br />

$stmt‐>close();<br />

http://www.<strong>php</strong>.net/manual/en/mysqli.quickstart.prepared‐statements.<strong>php</strong><br />

http://www.<strong>php</strong>.net/manual/en/mysqli‐stmt.bind‐param.<strong>php</strong><br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Using Bound Parameters and Bound Resu<strong>lt</strong>s together:<br />

$stmt = $mysqli‐>stmt_init(); // create a prepared statement<br />

if( $stmt = $mysqli‐>prepare("SELECT name, grade FROM students where major =") ){<br />

$major ='MATH';<br />

$stmt‐>bind_param('s', $major);<br />

$stmt‐>execute();<br />

/* bind variables to prepared statement */<br />

$stmt‐>bind_resu<strong>lt</strong>($name, $grade);<br />

/* fetch values: */<br />

while ($stmt‐>fetch()) {<br />

printf ("Name: %s , Grade: %d ', $name, $grade);<br />

}<br />

StudentID name major grade<br />

10147 Boris MATH 89<br />

}<br />

/* close statement and connection */<br />

$stmt‐>close();<br />

http://www.<strong>php</strong>.net/manual/en/book.mysqli.<strong>php</strong><br />

32


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Persistent connections are links that do not close when the execution of your script ends.<br />

When a persistent connection is requested, PHP checks if there's already an identical persistent<br />

connection (that remained open from earlier) ‐ and if it exists, it uses it.<br />

To use in PHP: mysql_pconnect(…) , mysqli_connect("p:example.com", ….)<br />

In reality, persistent connections are evil !<br />

1) they can be left in unpredictable states by clients. For example, a table lock might be activated before<br />

a client terminates unexpectedly. A new client process reusing this persistent connection will get the<br />

connection "as is".<br />

2) In PHP is used as a 'CGI' wrapper, an instance of the PHP interpreter is created and destroyed for every<br />

PHP page. Because it is destroyed after every request, any resources that it acquires (such as a link to<br />

an SQL database server) are closed when it is destroyed. Hence, persistent connections don't persist.<br />

3) In mu<strong>lt</strong>i‐process environment if the same client makes a second request to the server, it may be<br />

served by a different child process than the first time.<br />

4) If you have 20 different child processes that ran a script that made a persistent connection to your<br />

MySQL server, you'd be keeping active 20 different connections<br />

http://www.<strong>php</strong>.net/manual/en/features.persistent‐connections.<strong>php</strong><br />

When do we need<br />

mysql_close() <br />

Good part:<br />

Can reduce overhead when you create a link to remote MySQL server.<br />

They cause the PHP child process to simply connect only once for its entire lifespan, instead of every<br />

time it processes a page that requires connecting to the MySQL server.<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Normalization was first proposed by Codd as an integral part of the relational model.<br />

It encompasses a set of best practices designed to eliminate the duplication of data,<br />

which in turn prevents data manipulation anomalies and loss of data integrity.<br />

The most common form of normalization applied to databases are called the<br />

normal forms.<br />

Example: What's wrong with this database<br />

Title Author1 Author2 ISBN Subject Pages Publisher<br />

Database<br />

System<br />

Concepts<br />

Abraham<br />

Silberschatz<br />

Henry F.<br />

Korth<br />

0072958863<br />

MySQL,<br />

Computers<br />

1168 McGraw-Hill<br />

Operating<br />

System<br />

Concepts<br />

Abraham<br />

Silberschatz<br />

Henry F.<br />

Korth<br />

0471694665 Computers 944 McGraw-Hill<br />

33


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Database normalization is also the process in which a database structure is free<br />

from any uncertainties like update, insertion, and deletion incidences.<br />

In order to normalize a database it must be designed in the third normal form. In<br />

the third normal form, all data will be secured, and only certain areas of the table<br />

are subjected to any change.<br />

There are three major problems encountered in database normalization and they<br />

are: the update anomaly, the insertion anomaly, and the deletion anomaly.<br />

Normalization is criticized because it increases complexity and processing overhead<br />

required to join mu<strong>lt</strong>iple tables representing what are conceptually a single item.<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Title Author1 Author2 ISBN Subject Pages Publisher<br />

Database<br />

System<br />

Concepts<br />

Abraham<br />

Silberschatz<br />

Henry F.<br />

Korth<br />

0072958863<br />

MySQL,<br />

Computers<br />

1168 McGraw-Hill<br />

This table is not very efficient with storage.<br />

This design does not protect data integrity.<br />

Third, this table does not scale well.<br />

Operating<br />

System<br />

Concepts<br />

Abraham<br />

Silberschatz<br />

Henry F.<br />

Korth<br />

0471694665 Computers 944 McGraw-Hill<br />

• we have more than one author field,<br />

• subject field contains more than one piece of information.<br />

With more than one value in a single field, it would be very difficu<strong>lt</strong> to search for all books<br />

on a given subject.<br />

First Normal Form (1NF) sets the very basic rules for an organized database:<br />

Eliminate duplicative columns from the same table.<br />

Create separate tables for each group of related data.<br />

Identify each row with a unique column or set of columns (the primary key).<br />

34


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

What about this table<br />

Book Table<br />

Title Author ISBN Subject Pages Publisher<br />

Database System<br />

Concepts<br />

Abraham<br />

Silberschatz<br />

0072958863 MySQL 1168 McGraw-Hill<br />

Database System<br />

Concepts<br />

Operating System<br />

Concepts<br />

Henry F. Korth 0072958863 Computers 1168 McGraw-Hill<br />

Henry F. Korth 0471694665 Computers 944 McGraw-Hill<br />

Operating System<br />

Concepts<br />

Abraham<br />

Silberschatz<br />

0471694665 Computers 944 McGraw-Hill<br />

We now have two rows for a single book.<br />

We need to separate the data into separate tables:<br />

• Author table<br />

• Subject table<br />

Problems<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Title Author ISBN Subject Pages Publisher<br />

Database System<br />

Concepts<br />

Database System<br />

Concepts<br />

Operating System<br />

Concepts<br />

Operating System<br />

Concepts<br />

Abraham<br />

Silberschatz<br />

0072958863 MySQL 1168 McGraw-Hill<br />

Henry F. Korth 0072958863 Computers 1168 McGraw-Hill<br />

Henry F. Korth 0471694665 Computers 944 McGraw-Hill<br />

Abraham<br />

Silberschatz<br />

0471694665 Computers 944 McGraw-Hill<br />

Book Table<br />

Subject Table<br />

Subject_ID Subject<br />

1 MySQL<br />

2 Computers<br />

Author Table<br />

Author_ID Last Name First Name<br />

1 Silberschatz Abraham<br />

2 Korth Henry<br />

ISBN Title Pages Publisher<br />

0072958863<br />

0471694665<br />

What did we achieve<br />

Database System<br />

Concepts<br />

Operating System<br />

Concepts<br />

1168 McGraw-Hill<br />

944 McGraw-Hill<br />

35


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Book Table<br />

ISBN Title Pages Publisher<br />

0072958863<br />

0471694665<br />

Database System<br />

Concepts<br />

Operating System<br />

Concepts<br />

1168 McGraw-Hill<br />

944 McGraw-Hill<br />

Subject Table<br />

Subject_ID Subject<br />

1 MySQL<br />

2 Computers<br />

Author Table<br />

Author_ID Last Name First Name<br />

1 Silberschatz Abraham<br />

2 Korth Henry<br />

Each table has a primary key, used for joining tables together when querying the data.<br />

A primary key value must be unique with in the table (no two books can have the<br />

same ISBN number), and a primary key is also an index, which speeds up data retrieval<br />

based on the primary key.<br />

How to define relationships between the tables<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Subject Table<br />

Author Table<br />

Subject_ID Subject<br />

Author_ID Last Name First Name<br />

1 MySQL<br />

1 Silberschatz Abraham<br />

2 Computers<br />

Book Table<br />

2 Korth Henry<br />

ISBN Title Pages Publisher<br />

0072958863 Database System Concepts 1168 McGraw-Hill<br />

0471694665 Operating System Concepts 944 McGraw-Hill<br />

Book_Author Table<br />

Book_Subject Table<br />

ISBN<br />

Subject_ID<br />

ISBN<br />

Author_ID<br />

0072958863 1<br />

0072958863 1<br />

0072958863 2<br />

0072958863 2<br />

0471694665 2<br />

0471694665 1<br />

0471694665 2<br />

Through Primary keys define relationships between the tables.<br />

36


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Subject Table<br />

Author Table<br />

Subject_ID Subject<br />

Author_ID Last Name First Name<br />

1 MySQL<br />

1 Silberschatz Abraham<br />

2 Computers<br />

2 Korth Henry<br />

Book Table<br />

ISBN Title Pages Publisher<br />

0072958863 Database System Concepts 1168 McGraw-Hill<br />

Book_Subject Table<br />

ISBN<br />

Subject_ID<br />

0072958863 1<br />

0072958863 2<br />

0471694665 2<br />

0471694665 Operating System Concepts 944 McGraw-Hill<br />

Book_Author Table<br />

ISBN<br />

Author_ID<br />

0072958863 1<br />

0072958863 2<br />

0471694665 1<br />

0471694665 2<br />

Here we have a one‐to‐many relationship between the Book table and the Publisher.<br />

A book has only one publisher, and a publisher will publish many books.<br />

When we have a one‐to‐many relationship, we place a foreign key in the Book Table, pointing to the<br />

primary key of the Publisher Table.<br />

Second Normal Form (2NF) requires that database doesn't have any data in a table with a<br />

composite key that does not relate to all portions of the composite key.<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

First Normal Form deals with redundancy of data across a horizontal row.<br />

Second Normal Form (or 2NF) deals with redundancy of data in vertical columns.<br />

The normal forms are progressive, so to achieve Second Normal Form, the tables<br />

must already be in First Normal Form.<br />

Requirements for Second Normal Form (2NF):<br />

• Meet all the requirements of the First Normal Form.<br />

• Remove subsets of data that apply to mu<strong>lt</strong>iple rows of a table and place them in separate tables.<br />

• Create relationships between these new tables and their predecessors through the use of foreign keys.<br />

37


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Subject Table<br />

Book_Subject Table<br />

ISBN Title Pages Publisher<br />

0072958863 Database System Concepts 1168 McGraw-Hill<br />

0471694665 Operating System Concepts 944 McGraw-Hill<br />

Can't have 'McGraw‐Hill' as a key<br />

Author Table<br />

Book_Author Table<br />

Book Table<br />

ISBN Title Pages Publisher_ID<br />

0072958863<br />

0471694665<br />

Database System<br />

Concepts<br />

Operating System<br />

Concepts<br />

1168 1<br />

944 1<br />

Publisher Table<br />

Publisher_ID Publisher Name<br />

1 McGraw‐Hill<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Third Normal Form goes one step further:<br />

• Meet all the requirements of the second normal form.<br />

• Remove columns that are not dependent upon the primary key.<br />

• All of the non‐primary key attributes are mutually independent<br />

Publisher Table<br />

Publisher_ID Name Address1 City State Zip<br />

1<br />

Sams<br />

Publishing<br />

800 East 96th<br />

Street<br />

Indianapolis Indiana 46240<br />

Publisher_ID Name Address Zip<br />

1 Sams Publishing 800 East 96th Street 46240<br />

Zip City State<br />

Problem<br />

46240 Indianapolis Indiana<br />

38


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Transitive relation:<br />

In mathematics, a binary relation R over asetX is transitive if whenever an<br />

element a is related to an element b, and b is in turn related to an<br />

element c, then a is also related to c.<br />

Example: A> B and B>C then A>C<br />

Transitive dependency:<br />

A functional dependency which holds by virtue of transitivity. Conditions:<br />

1. A B<br />

2. Not the case that B A<br />

3. B C<br />

Then A C<br />

3NF excludes certain types<br />

of transitive dependencies<br />

Example:<br />

1. {Book} {Author}<br />

2. {Author} does NOT {Book}<br />

3. {Author} {AuthorNationality}<br />

( here means 'knowing')<br />

{Book} {AuthorNationality}<br />

IF we know the book, we know Author's Nationality<br />

Both 'Author' and 'AuthorNationality' are non‐key attributes<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

No transitive<br />

dependency<br />

between nonkey<br />

attributes<br />

All determinants<br />

are candidate<br />

keys - Single<br />

mu<strong>lt</strong>ivalued<br />

dependency<br />

First Normal Form (1NF)<br />

Second Normal Form (2NF)<br />

Third Normal Form (3NF)<br />

Boyce‐Codd Normal Form (BCNF)<br />

Fourth Normal Form (4NF)<br />

Fifth Normal Form (5NF)<br />

Boyce-<br />

Codd<br />

and<br />

Higher<br />

Functional<br />

dependency<br />

of nonkey<br />

attributes on<br />

the primary<br />

key - Atomic<br />

values only<br />

Full<br />

Functional<br />

dependeny<br />

of nonkey<br />

attributes<br />

on the<br />

primary key<br />

39


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

A fully normalized database schema can fail to provide adequate system<br />

response time due to excessive table join operations.<br />

http://www.siue.edu/~dbock/cmis564/denormal.htm<br />

1. Perform a detailed view analysis in order to identify situations where an excessive<br />

number of table joins appears to be required to produce a specific end‐user view.<br />

Any view requiring more than three joins should be considered as a candidate for<br />

denormalization.<br />

2. Reduce the number of foreign keys in order to reduce index maintenance during<br />

insertions and deletions. Reducing foreign keys is closely related to reducing the<br />

number of relational tables.<br />

3. The ease of data maintenance provided by normalized table structures must also be<br />

provided by the denormalized schema. Thus, a satisfactory approach would not require<br />

excessive programming code (triggers) to maintain data integrity and consistency.<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Hillyer Mike, MySQL AB. An Introduction to Database Normalization,<br />

http://babanski.com/files/MySQL‐intro‐to‐database‐normalization.pdf<br />

Microsoft. Description of the database normalization basics,<br />

http://support.microsoft.com/kb/283878<br />

Wikipedia. Database Normalization.<br />

http://en.wikipedia.org/wiki/Database_normalization.html<br />

40


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

mysql> select * from demo_people;<br />

+------------+--------------+------+<br />

| name | phone | pid |<br />

+------------+--------------+------+<br />

| Mr Brown | 01225 708225 | 1 |<br />

| Ms Smith | 01225 899360 | 2 |<br />

| Mr Pullen | 01380 724040 | 3 |<br />

+------------+--------------+------+<br />

mysql> select * from demo_property;<br />

+------+------+----------------------+<br />

| spid | pid | selling |<br />

+------+------+----------------------+<br />

| 1 | 1 | Old House Farm |<br />

| 2 | 3 | The Willows |<br />

| 3 | 3 | Tall Trees |<br />

| 4 | 3 | The Melksham Florist |<br />

| 5 | 4 | Dun Roamin |<br />

+------+------+----------------------+<br />

Cross‐Join: select * from TABLE1, TABLE2<br />

We end up with all the possible combinations<br />

Person number 1 is selling<br />

property number 1 – Old House Farm<br />

Person number 2 doesn't sell anything<br />

Person number 3 is selling:<br />

property number 2 – The Willows<br />

property number 3 – Tall Trees<br />

property number 4 – The Melksham Florist<br />

Person number 4 is selling<br />

property number 5 – Dun Roamin.<br />

pid = person ID<br />

spid = selling property ID<br />

Worst join ever!<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Cross‐Join: select * from TABLE1, TABLE2<br />

We end up with all the possible combinations<br />

Worst join ever!<br />

mysql> select * from demo_people,demo_property;<br />

+-----+--------------+-----------+------+------+----------------------+<br />

| pid | phone | name | spid | pid | selling |<br />

+-----+--------------+-----------+------+------+----------------------+<br />

| 1 | 01225 708225 | Mr Brown | 1 | 1 | Old House Farm |<br />

| 2 | 01225 899360 | Ms Smith | 1 | 1 | Old House Farm |<br />

| 3 | 01380 724040 | Mr Pullen | 1 | 1 | Old House Farm |<br />

| 1 | 01225 708225 | Mr Brown | 2 | 3 | The Willows |<br />

| 2 | 01225 899360 | Ms Smith | 2 | 3 | The Willows |<br />

| 3 | 01380 724040 | Mr Pullen | 2 | 3 | The Willows |<br />

| 1 | 01225 708225 | Mr Brown | 3 | 3 | Tall Trees |<br />

| 2 | 01225 899360 | Ms Smith | 3 | 3 | Tall Trees |<br />

| 3 | 01380 724040 | Mr Pullen | 3 | 3 | Tall Trees |<br />

| 1 | 01225 708225 | Mr Brown | 4 | 3 | The Melksham Florist |<br />

| 2 | 01225 899360 | Ms Smith | 4 | 3 | The Melksham Florist |<br />

| 3 | 01380 724040 | Mr Pullen | 4 | 3 | The Melksham Florist |<br />

| 1 | 01225 708225 | Mr Brown | 5 | 4 | Dun Roamin |<br />

| 2 | 01225 899360 | Ms Smith | 5 | 4 | Dun Roamin |<br />

| 3 | 01380 724040 | Mr Pullen | 5 | 4 | Dun Roamin |<br />

+-----+--------------+-----------+------+------+----------------------+<br />

Cross joins are also called Cartesian products<br />

41


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

JOIN / INNER JOIN / CROSS JOIN (all are syntactic equivalents) :<br />

We get all records that match in the appropriate way in the two tables.<br />

Records in both incoming tables that do not match are not reported:<br />

mysql> select name, phone, selling from demo_people<br />

join demo_property on demo_people.pid = demo_property.pid;<br />

+-----------+--------------+----------------------+<br />

| name | phone | selling |<br />

+-----------+--------------+----------------------+<br />

| Mr Brown | 01225 708225 | Old House Farm |<br />

| Mr Pullen | 01380 724040 | The Willows |<br />

| Mr Pullen | 01380 724040 | Tall Trees |<br />

| Mr Pullen | 01380 724040 | The Melksham Florist |<br />

+-----------+--------------+----------------------+<br />

on demo_people.pid = demo_property.pid<br />

can be replaced with<br />

using (demo_people.pid)<br />

Record pid=2 is not reported (No properties):<br />

| Ms Smith | 01225 899360 | 2 |<br />

Note: we don't have OUTER JOIN !!!<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

LEFT JOIN / LEFT OUTER JOIN:<br />

We get all records that match in the same way and IN ADDITION<br />

we get an extra record for each unmatched record in the left table of the join<br />

(Example: we want to ensure that every PERSON gets a mention).<br />

mysql> select name, phone, selling from demo_people<br />

left join demo_property on demo_people.pid = demo_property.pid;<br />

+------------+--------------+----------------------+<br />

| name | phone | selling |<br />

+------------+--------------+----------------------+<br />

| Mr Brown | 01225 708225 | Old House Farm |<br />

| Ms Smith | 01225 899360 | NULL |<br />

| Mr Pullen | 01380 724040 | The Willows |<br />

| Mr Pullen | 01380 724040 | Tall Trees |<br />

| Mr Pullen | 01380 724040 | The Melksham Florist |<br />

+------------+--------------+----------------------+<br />

Note: we don't have LEFT INNER JOIN !!!<br />

42


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

RIGHT JOIN / RIGHT OUTER JOIN:<br />

We get all records that match in the same way and IN ADDITION<br />

we get an extra record for each unmatched record in the right table of the join<br />

(Example: we want to ensure that every PROPERTY gets a mention).<br />

mysql> select name, phone, selling from demo_people<br />

right join demo_property on demo_people.pid = demo_property.pid;<br />

+-----------+--------------+----------------------+<br />

| name | phone | selling |<br />

+-----------+--------------+----------------------+<br />

| Mr Brown | 01225 708225 | Old House Farm |<br />

| Mr Pullen | 01380 724040 | The Willows |<br />

| Mr Pullen | 01380 724040 | Tall Trees |<br />

| Mr Pullen | 01380 724040 | The Melksham Florist |<br />

| NULL | NULL | Dun Roamin |<br />

+-----------+--------------+----------------------+<br />

Note: we don't have RIGHT INNER JOIN !!!<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

MyISAM storage engine does not support foreign keys. You need to use InnoDB engine.<br />

• employee: a table of company employees where each member is assigned a unique ID<br />

• borrowed: a table of borrowed books. Every record will reference a borrower’s employee ID.<br />

CREATE TABLE employee (<br />

id smallint(5) unsigned NOT NULL,<br />

firstName varchar(30),<br />

lastName varchar(30),<br />

PRIMARY KEY (id),<br />

KEY idx_lastName (lastName)<br />

) ENGINE=InnoDB;<br />

We want to add Foreign Key Constraint called 'FK_borrowed'<br />

http://dev.mysql.com/doc/refman/5.5/en/innodb‐foreign‐key‐constraints.html<br />

CREATE TABLE borrowed (<br />

ref int(10) unsigned NOT NULL auto_increment,<br />

employeeid smallint(5) unsigned NOT NULL,<br />

book varchar(50),<br />

PRIMARY KEY (ref)<br />

) ENGINE=InnoDB;<br />

ALTER TABLE borrowed<br />

ADD CONSTRAINT FK_borrowed FOREIGN KEY (employeeid) REFERENCES employee(id)<br />

ON UPDATE CASCADE<br />

ON DELETE RESTRICT<br />

The FOREIGN KEY clause is specified in the child table.<br />

CASCADE: Delete or update the row from the parent table, and automatically delete or update the matching rows in the child table.<br />

RESTRICT: Rejects the delete or update operation for the parent table (defau<strong>lt</strong> if not set otherwise).<br />

43


CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

Remember that parent table (employees) must be added/populated with data first:<br />

employee<br />

borrowed<br />

id firstName lastName<br />

ref employeeid book<br />

1 John Smith<br />

1 1 Simply SQL<br />

2 Laura Jones<br />

2 1 U<strong>lt</strong>imate HTML Reference<br />

3 1 U<strong>lt</strong>imate CSS Reference<br />

3 Jane Green<br />

4 2 Art of JavaScript<br />

SELECT book FROM borrowed<br />

JOIN employee ON employee.id=borrowed.employeeid<br />

WHERE employee.lastname='Smith';<br />

UPDATE employee SET id=22 WHERE id=2;<br />

No need to update 'borrowed' table directly!!<br />

What about this<br />

DELETE FROM employee WHERE id=1;<br />

Won't work with RESTRICT; deletes records from borrowed with CASCADE<br />

Resu<strong>lt</strong>:<br />

Simply SQL<br />

U<strong>lt</strong>imate HTML Reference<br />

U<strong>lt</strong>imate CSS Reference<br />

borrowed<br />

ref employeeid book<br />

1 1 Simply SQL<br />

2 1 U<strong>lt</strong>imate HTML Reference<br />

3 1 U<strong>lt</strong>imate CSS Reference<br />

4 22 Art of JavaScript<br />

CS3336A, <strong>Alex</strong> <strong>Babanski</strong><br />

MySQL 5.5 Reference Manual<br />

http://dev.mysql.com/doc/refman/5.5/en/index.html<br />

44

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!