You are on page 1of 101

PHP/SQL 1: Introduction to Database Programming

Lesson 1: Int roduct ion


Understanding the Learning Sandbox
Experimenting with Examples
MySQL Syntax
Databases and Permissions
Creating Databases
The Command Line
Lesson 2: Creat ing Tables
Reconnecting to MySQL
Creating and Checking Tables
Creating a Table
Checking Tables
Inserting Values into Tables
Inserting Specific Column Values
Retrieving Data from Tables
Lesson 3: Searching Through Tables
Exploring the 'where' Keyword
The 'like' Selector
Updating and Deleting Data
Updating Entries
Deleting Entries
Lesson 4: Managing Tables
Altering Tables
Deleting and Reordering Columns
Changing Column Type
Renaming Tables
Deleting Tables
Lesson 5: Managing Table Ent ries
Optimizing with Keys/Indexes
Auto_increment and Primary Keys
The Primary Key
Lesson 6: Relat ional Dat abasing
What is a Relational Database?
Inner Joins
Outer Joins
Aliases
Lesson 7: Managing Query Result s
Group By
Using Distinct to Prevent Duplicate Results
Searching and Counting within Groups
Searching Within Groups
Renaming Results
Ordering Results
Descending Results
Nesting Groups and Orders
Limiting Results
Lesson 8: Dat abase Programming wit h PHP
The PHP/MySQL Relationship
Connecting to a Database in PHP
Executing SQL Commands
Delimiting Queries
Lesson 9: Project Address/Phone Book, Part 1
Project Description
Table Layout
Table Creation
Lesson 10: Project Address/Phone Book, Part 2
Starting with the HTML Form
Storing the Data into SQL through PHP
Breaking Down addentry.php
Lesson 11: Project Address/Phone Book, Part 3
Construction of viewbook.php
Lesson 12: Advanced SQL Synt ax, Part 1
Date and Time Functions
DAYOFWEEK(date)
WEEKDAY(date)
DAYOFMONTH(date)
DAYOFYEAR(date)
YEAR(date)
MONTH(date)
DAYNAME(date)
MONTHNAME(date)
QUARTER(date)
WEEK(date)
WEEK(date,weekday)
TO_DAYS(date)
FROM_DAYS(x)
CURDATE(), CURRENT_DATE
PERIOD_ADD(period,x)
PERIOD_DIFF(period1,period2)
DATEDIFF(date1,date2)
DATE_FORMAT(date,format)
Date/Time Mathematical Functions
DATE_ADD(date/time,INTERVAL expr type), ADDDATE(date/time,INTERVAL expr
type)
DATE_SUB(date/time,INTERVAL expr type), SUBDATE(date/time,INTERVAL expr
type)
EXTRACT(expr type FROM date/time
CURRENT_TIME()
HOUR(time)
MINUTE(time)
SECOND(time)
TIME_TO_SEC(time)
SEC_TO_TIME(sec)
TIME_FORMAT(time,format)
NOW(), SYSDATE(), CURRENT_TIMESTAMP()
UNIX_TIMESTAMP(), UNIX_TIMESTAMP(date)
FROM_UNIXTIME(unix_timestamp), FROM_UNIXTIME(unix_timestamp, format)
Lesson 13: Advanced SQL Synt ax, Part 2
Math Functions
MOD(x,y)
ABS(x)
SIGN(x)
LEAST(x,y,...)
GREATEST(x,y,...)
TRUNCATE(x,y)
FLOOR(x)
CEILING(x)
ROUND(x), ROUND(x,y)
SIN(x)
COS(x)
TAN(x)
ASIN(x)
ACOS(x)
ATAN(x)
ATAN2(x,y)
COT(x)
PI()
DEGREES(x)
RADIANS(x)
EXP(x)
LOG(x)
LOG10(x)
SQRT(x)
POW(x,y), POWER(x,y)
Lesson 14: Advanced SQL Synt ax, Part 3
String and Character Functions
ASCII(str)
CONV(x,y,z)
BIN(x)
OCT(x)
HEX(x)
CHAR(x,y,z,...)
LENGTH(str), CHAR_LENGTH(str), OCTET_LENGTH(str),
CHARACTER_LENGTH(str)
LOCATE(str1,str2), POSITION(str1 IN str2)
LOCATE(str1,str2,x)
INSTR(str1, str2)
SOUNDEX(str)
CONCAT(str1,str2,...)
LPAD(str1,x,str2)
RPAD(str1,x,str2)
LEFT(str,x)
RIGHT(str,x)
LTRIM(str)
RTRIM(str)
LOAD_FILE(filen)
SPACE(x)
REPLACE(str1,str2,str3)
REPEAT(str,x)
REVERSE(str)
INSERT(str1,x,y,str2)
ELT(x,str1,str2,str3,...)
FIELD(str1,str2,str3,str4,...)
TRIM([[BOTH | LEADING | TRAILING] [str2] FROM] str1)
SUBSTRING(str,x), SUBSTRING(str FROM x)
SUBSTRING(str,x,y), SUBSTRING(str FROM x FOR y), MID(str,x,y)
SUBSTRING_INDEX(str1,str2,x)
LCASE(str), LOWER(str)
UCASE(str), UPPER(str)
MAKE_SET(bit,str1,str2,...)
EXPORT_SET(bit,str1,str2,[str3,[x]])
FIND_IN_SET(str1,strlist)
Lesson 15: Final Project
Final Project, Part 1
Final Project, Part 2

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Introduction
Welco me to the O'Reilly Scho o l o f Techno lo gy's PHP/SQL 1: Int ro duct io n t o Dat abase Pro gram m ing co urse!

Course Objectives
When yo u co mplete this co urse, yo u will be able to :

create, search, and manage SQL tables and entries.


perfo rm basic SQL queries and jo ins, and manage the results.
demo nstrate understanding o f advanced SQL syntax fo r date, time, math, and string functio ns.
implement SQL database pro gramming into a PHP-based web applicatio n.
build a full-fledged o nline address/pho ne bo o k using PHP and MySQL.

SQL(Structured Query Language) is the language fo r databases such as Oracle, MySQL, MS Access, etc. Kno wing SQL is
paramo unt to using these databases. In this co urse, yo u will learn basic SQL database creatio n and manipulatio n, as well as
ho w to search databases and ho w to inco rpo rate them into PHP-based pro grams and applicatio ns.

Fro m beginning to end, yo u will learn by do ing yo ur o wn SQL-based pro jects using PHP, and then handing them in fo r
instructo r feedback. These pro jects, as well as the final pro ject, will add to yo ur po rtfo lio and will co ntribute to certificate
co mpletio n. Besides a bro wser and internet co nnectio n, all so ftware is pro vided o nline by the O'Reilly Scho o l o f Techno lo gy.

Learning with O'Reilly School of T echnology Courses


As with every O'Reilly Scho o l o f Techno lo gy co urse, we'll take a user-active appro ach to learning. This means that yo u
(the user) will be active! Yo u'll learn by do ing, building live pro grams, testing them and experimenting with them—
hands-o n!

To learn a new skill o r techno lo gy, yo u have to experiment. The mo re yo u experiment, the mo re yo u learn. Our system
is designed to maximize experimentatio n and help yo u learn to learn a new skill.

We'll pro gram as much as po ssible to be sure that the principles sink in and stay with yo u.

Each time we discuss a new co ncept, yo u'll put it into co de and see what YOU can do with it. On o ccasio n we'll even
give yo u co de that do esn't wo rk, so yo u can see co mmo n mistakes and ho w to reco ver fro m them. Making mistakes
is actually ano ther go o d way to learn.

Abo ve all, we want to help yo u to learn to learn. We give yo u the to o ls to take co ntro l o f yo ur o wn learning experience.

When yo u co mplete an OST co urse, yo u kno w the subject matter, and yo u kno w ho w to expand yo ur kno wledge, so
yo u can handle changes like so ftware and o perating system updates.

Here are so me tips fo r using O'Reilly Scho o l o f Techno lo gy co urses effectively:

T ype t he co de . Resist the temptatio n to cut and paste the example co de we give yo u. Typing the co de
actually gives yo u a feel fo r the pro gramming task. Then play aro und with the examples to find o ut what else
yo u can make them do , and to check yo ur understanding. It's highly unlikely yo u'll break anything by
experimentatio n. If yo u do break so mething, that's an indicatio n to us that we need to impro ve o ur system!
T ake yo ur t im e . Learning takes time. Rushing can have negative effects o n yo ur pro gress. Slo w do wn and
let yo ur brain abso rb the new info rmatio n tho ro ughly. Taking yo ur time helps to maintain a relaxed, po sitive
appro ach. It also gives yo u the chance to try new things and learn mo re than yo u o therwise wo uld if yo u
blew thro ugh all o f the co ursewo rk to o quickly.
Expe rim e nt . Wander fro m the path o ften and explo re the po ssibilities. We can't anticipate all o f yo ur
questio ns and ideas, so it's up to yo u to experiment and create o n yo ur o wn. Yo ur instructo r will help if yo u
go co mpletely o ff the rails.
Acce pt guidance , but do n't de pe nd o n it . Try to so lve pro blems o n yo ur o wn. Go ing fro m
misunderstanding to understanding is the best way to acquire a new skill. Part o f what yo u're learning is
pro blem so lving. Of co urse, yo u can always co ntact yo ur instructo r fo r hints when yo u need them.
Use all available re so urce s! In real-life pro blem-so lving, yo u aren't bo und by false limitatio ns; in OST
co urses, yo u are free to use any reso urces at yo ur dispo sal to so lve pro blems yo u enco unter: the Internet,
reference bo o ks, and o nline help are all fair game.
Have f un! Relax, keep practicing, and do n't be afraid to make mistakes! Yo ur instructo r will keep yo u at it
until yo u've mastered the skill. We want yo u to get that satisfied, "I'm so co o l! I did it!" feeling. And yo u'll have
so me pro jects to sho w o ff when yo u're do ne.
Lesson Format
We'll try o ut lo ts o f examples in each lesso n. We'll have yo u write co de, lo o k at co de, and edit existing co de. The co de
will be presented in bo xes that will indicate what needs to be do ne to the co de inside.

Whenever yo u see white bo xes like the o ne belo w, yo u'll type the co ntents into the edito r windo w to try the example
yo urself. The CODE TO TYPE bar o n to p o f the white bo x co ntains directio ns fo r yo u to fo llo w:

CODE TO TYPE:
White boxes like this contain code for you to try out (type into a file to run).

If you have already written some of the code, new code for you to add looks like this.

If we want you to remove existing code, the code to remove will look like this.

We may also include instructive comments that you don't need to type.

We may run pro grams and do so me o ther activities in a terminal sessio n in the o perating system o r o ther co mmand-
line enviro nment. These will be sho wn like this:

INTERACTIVE SESSION:

The plain black text that we present in these INTERACTIVE boxes is


provided by the system (not for you to type). The commands we want you to type look lik
e this.

Co de and info rmatio n presented in a gray OBSERVE bo x is fo r yo u to inspect and absorb. This info rmatio n is o ften
co lo r-co ded, and fo llo wed by text explaining the co de in detail:

OBSERVE:
Gray "Observe" boxes like this contain information (usually code specifics) for you to
observe.

The paragraph(s) that fo llo w may pro vide additio n details o n inf o rm at io n that was highlighted in the Observe bo x.

We'll also set especially pertinent info rmatio n apart in "No te" bo xes:

Note No tes pro vide info rmatio n that is useful, but no t abso lutely necessary fo r perfo rming the tasks at hand.

T ip Tips pro vide info rmatio n that might help make the to o ls easier fo r yo u to use, such as sho rtcut keys.

WARNING Warnings pro vide info rmatio n that can help prevent pro gram crashes and data lo ss.

T he CodeRunner Screen
This co urse is presented in Co deRunner, OST's self-co ntained enviro nment. We'll discuss the details later, but here's
a quick o verview o f the vario us areas o f the screen:
These video s explain ho w to use Co deRunner:

File Management Demo

Co de Edito r Demo

Co ursewo rk Demo

Understanding the Learning Sandbox


Co deRunner is a multi-purpo se edito r that allo ws yo u to create applicatio ns in many techno lo gies. One o f these
techno lo gies is MySQL.

Experimenting with Examples


All o f the co mmunicatio n to o ls and learning co ntent will be in the upper part o f the screen. We'll ask yo u
frequently to type co de into the MySQL shell that we've set up fo r yo u, and to experiment by making yo ur o wn
changes. To access yo ur MySQL shell, click the Ne w T e rm inal butto n to co nnect to Unix and lo g in fro m
there, o r click the Co nne ct t o MySQL butto n to co nnect directly to the MySQL she ll. Fo r this co urse, yo u
can use either metho d to get to yo ur MySQL she ll, altho ugh yo u sho uld be familiar with bo th metho ds.

Click the Ne w T e rm inal butto n to co nnect to Unix no w. Yo u will see pro mpts fo r the lo gin and passwo rd
yo u were given when yo u registered with OST, altho ugh the system may fill o ne o r bo th o f these in fo r yo u. If
the system do esn't auto matically lo g yo u in, type yo ur lo gin and passwo rd when pro mpted. (Yo u may need to
click inside the Unix Terminal windo w to be able to type. When typing yo ur passwo rd, yo u will no t see any
characters reflected back to yo u as yo u type.) Yo u will then be lo gged in to o ne o f the OST servers.

Yo u sho uld see so mething like this:

Login: certjosh
Password:
Last login: Thu Aug 5 20:47:25 from 63.171.219.116
cold:~$

Then, to start yo ur MySQL she ll, type the fo llo wing at the Unix pro mpt. (Do n't wo rry if yo u're no t familiar with
Linux, UNIX, o r SSH.)
Type the fo llo wing co mmand at yo ur Unix pro mpt:

cold:~$ mysql -h sql.oreillyschool.com -p -u username username

Make sure that yo u type yo ur username twice, just as it appears abo ve! Of co urse yo u sho uld
Note use yo ur actual Sandbo x lo gin, which is listed fo r yo u o n yo ur Student Start Page.

Yo u're pro mpted fo r yo ur passwo rd. Enter it and yo u're set to start MySQL. No w yo u sho uld see a MySQL
pro mpt that lo o ks like this:

OBSERVE:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 16168
Server version: 5.0.62-log Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

Since yo ur SQL acco unt is sto red o n o ur servers, yo u can access it fro m anywhere, thro ugh any SSH
pro gram yo u may have - no t just the o ne we pro vided fo r yo u in Co deRunner. If yo u like, just SSH into yo ur
do main(ie. yo urdo m ain.o re illyst ude nt .co m ) that we set up fo r yo u (ask yo ur instructo r if yo u're no t sure
what yo urs is), then fo llo w the steps abo ve to lo g in to yo ur MySQL she ll.

MySQL Syntax
No w that we're in an interface enviro nment, let's dive into MySQL and start learning a few keywo rds and syntax. First up
is the se le ct keywo rd. Yo u use se le ct to retrieve data fro m yo ur database, query info rmatio n (such as the date in the
example belo w), inquire abo ut the MySQL versio n, and view o ther database info . Try this:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select current_date(), current_time();


+----------------+----------------+
| current_date() | current_time() |
+----------------+----------------+
| 2010-09-21 | 15:53:59 |
+----------------+----------------+
1 row in set (0.00 sec)

Yo u may have no ticed that MySQL tried to put the info rmatio n yo u requested into a nice, neat little table. Well, as nice
and neat as tables get when they're built o ut o f plus and minus signs, anyway.

See ho w fast the retrieval time was? 0 .0 0 seco nds! With a larger database o r a mo re co mplicated query, yo u'd have a
slightly lo nger respo nse time.

In MySQL, co mmands such as se le ct are case insensitive.

Note This applies to keywo rds o nly. The fo llo wing lines will all return the same result:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> SELECT CURRENT_TIME(), CURRENT_DATE();


mysql> select current_time(), current_date();
mysql> SeLeCt CuRrEnT_tImE(), cUrReNt_DaTe();
Did all three lines return identical results? If no t, spell check yo ur co mmand lines and make sure the o nly
discrepancies are in the cases (upper o r lo wer) o f the letters. No w type in the fo llo wing co mmand and hit e nt e r:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select current_time()

What happened? No thing sho wed up except fo r this weird -> pro mpt.

Mo st MySQL keywo rds require a semico lo n (;) at the end in o rder fo r the co mmand to be executed. If MySQL do esn't
find a semico lo n, it'll simply mo ve o n to the next line with a new pro mpt ->. The MySQL pro gram will repeat this until it
finds the next semico lo n entered. This feature is useful when yo ur co mmand line is really, really lo ng. It allo ws yo u to
break it up o ver several different pro mpt lines. Pro grammers in Java, C/C++, PERL, and o ther languages sho uld have
no pro blem understanding this co ncept, since it ho lds true in tho se languages as well. So ho w do yo u execute that
co mmand yo u entered o n the last line? Yo u can either enter the semico lo n and press Ent e r to execute yo ur
co mmand and retrieve the date, o r yo u can enter \c at the pro mpt to cancel the previo us co mmand and start with a
fresh pro mpt.

To retrieve the versio n o f MySQL yo u're using, simply use the ve rsio n() functio n. Let's find o ut abo ut yo ur MySQL
versio n by trying this:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select current_date(),


-> version();
+----------------+------------+
| current_date() | version() |
+----------------+------------+
| 2010-09-21 | 5.0.62-log |
+----------------+------------+
1 row in set (0.00 sec)

To speed up yo ur MySQL experience, here's a quick tip yo u may have figured o ut already. Yo u can use the Up arro w
key to recall the previo us co mmand lines yo u've typed. The mo re times yo u press the up key, the deeper into histo ry o f
co mmand lines it go es.

Yo u can use semico lo ns to co mbine multiple co mmand lines to gether. Fo r example:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select current_time(); select version();


+----------------+
| current_time() |
+----------------+
| 15:55:41 |
+----------------+
1 row in set (0.00 sec)

+------------+
| version() |
+------------+
| 5.0.62-log |
+------------+
1 row in set (0.00 sec)

Databases and Permissions


When wo rking with SQL, yo u're always o perating within a database enviro nment. In yo ur case, at OST, the name o f
yo ur database will be identical to yo ur lo gin. Let's go ahead and pull it up.
Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> show databases;

Do yo u see a list o f databases? These are the names o f the databases o n the OST server to which yo u have access.
Do yo u see yo ur database? Let's access it.

Type the fo llo wing blue and green text at yo ur MySQL pro mpt:

mysql> use username;


Database changed
mysql>

What wo uld happen if yo u tried to access a database to which yo u didn't have permissio n? Try it:

Type the fo llo wing blue and green text at yo ur MySQL pro mpt:

mysql> use zyla;


ERROR 1044: Access denied for user: 'certjosh@cold.local.oreillyschool..com' to databa
se 'zyla'
mysql>

Turns o ut yo u can't access any o f them except yo urs—by the same to ken, no bo dy but yo u can lo o k at yo ur database.

Why is this? When we created a database fo r yo u o n o ur OST servers, we were able to grant and deny privileges o n
yo ur database, so that o nly yo ur lo gin (and yo ur instructo r's) co uld access it. Permissio ns and privileges are co vered
in mo re depth in the PHP/SQL 2 co urse.

Creating Databases
Who co uld have guessed that in o rder to sho w a list o f databases, yo u had to type sho w dat abase s;? Can
yo u predict which co mmand we use to create databases? Well, if yo u said cre at e , yo u're right. To create a
database we do the fo llo wing:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> create database yourdatabasename;

Did yo u get an erro r message? Just like befo re, that's because o n the OST servers, yo u o nly have access to
yo ur o wn database; yo u do n't have permissio n to create new o nes o n o ur servers. But, o n yo ur o wn SQL
server (fo r instance, in PHP/SQL 2) yo u wo uld be able to use the cre at e co mmand to build new databases.

When yo u're finished with yo ur MySQL sessio n, type in quit to exit o ut o f the MySQL sessio n. This is o ne o f the few
keywo rds that do n't require a semico lo n. Yo u sho uld see so mething like this:

INTERACTIVE SESSION:

mysql> quit
Bye
cold:~$

Yo u can also use the keywo rd e xit .

T he Command Line
Since yo u've exited the MySQL shell, it's a go o d time to revisit the co mmand yo u typed to enter MySQL in the first
place:

OBSERVE:
cold:~$ mysql -h sql.oreillyschool.com -p -u username username

Mo st o f this co urse will be spent within the MySQL she ll itself; ho wever, because the command line is used o ften in
advanced SQL to pics, it's go o d to kno w a bit abo ut that as well.

The co mmand line is a way to enter co mmands into a co mputer thro ugh the keybo ard. The co mmand line is used
mo stly in open source o perating systems like Linux o r UNIX, but yo u can find ways to o pen a co mmand line terminal in
Windo ws, Mac, o r any o ther o perating system. m ysql is the co mmand name used to launch the MySQL pro gram
that's been installed by the system administrato r. Everything written after that co mmand are param e t e rs that are
passed into the co mmand to give the applicatio n instructio ns to execute upo n launch.

The -h flag tells MySQL to read all the databases o ff a separate server—in yo ur case, instead o f
co ld.o reillyscho o l.co m, yo u use the OST database server, sql.o re illyscho o l.co m , because that's where
yo ur database resides.
The -p flag tells mysql to pro mpt fo r a passwo rd, so yo u can lo g in safely.
The -u flag tells mysql to lo g in the user specified by username.
The last username parameter specifies the default database to use—in yo ur case, we created yo ur
database name to be the same as yo ur Sandbo x lo gin. In the later co urse, yo u might create a database with
any name yo u wish.

Just fo r kicks, let's try to access that pesky 'zyla' database again, using the co mmand line:

Type this into yo ur UNIX pro mpt:

cold:~$ mysql -h sql.oreillyschool.com -p -u username zyla


Password:
ERROR 1044: Access denied for user: 'certjosh@cold.local.oreillyschool.com' to databas
e 'zyla'
mysql>

Even tho ugh it still asked fo r yo ur passwo rd, MySQL did no t allo w yo u to lo g in, because yo u attempted to default to a
database yo u co uldn't access.

We've co vered a lo t o f gro und already, but we've barely started the fun. See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Creating Tables

Reconnecting to MySQL
Welco me to the seco nd lesso n. Do yo u remember ho w to lo g into yo ur MySQL shell? Just to refresh yo ur memo ry,
click the Ne w T e rm inal butto n ( to o pen a new terminal sessio n and type in yo ur Sandbo x username and passwo rd
to lo g in. Once yo u're in, type the fo llo wing to launch MySQL:

Type the fo llo wing co mmand at yo ur Unix pro mpt:

cold:~$ mysql -h sql.useractive.com -p -u username username


Password:

Welcome to the MySQL monitor. Commands end with ; or \g.


Your MySQL connection id is 16168
Server version: 5.0.62-log Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

Creating and Checking T ables


By no w, yo u kno w that yo u're using a database named after yo ur Sandbo x lo gin, that we created especially fo r yo u. But
what's in that database?

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> show tables;


Empty set (0.00 sec)

mysql>

Creating a T able
OK, yo u're sitting in an empty database. It's time to add a table. No w, we need to think o f a purpo se fo r this
table. Fo r no w, let's make a table that will ho ld a list o f yo ur friends and so me o f their statistics. Let's think o f
so me info rmatio n abo ut yo ur friends that yo u might want in a database.

Let's try first name, last name, birthday, gender, height, and weight.

When yo u create tables, it's best to be careful fro m the start. Plan everything in advance befo re
Note yo u actually begin creating anything.

Any idea what the co mmand wo uld be to create a table? If yo u tho ught o f cre at e , yo u're catching o n quickly.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> create table friends (first_name varchar(20),


-> last_name varchar(20), birthday date, gender char(1),
-> height int(3) unsigned, weight int(4) unsigned);

Check o ut the table that yo u just created by using the sho w t able s; co mmand. The table f rie nds sho uld be
in the list.
INTERACTIVE SESSION:

mysql> show tables;


+--------------------+
| Tables_in_certjosh |
+--------------------+
| friends |
+--------------------+
1 row in set (0.00 sec)

Phew! That was a lo t o f text just to create a table! Let's go o ver what we just did. First, we cre at e d a table
named f rie nds. Then, in a set o f parentheses, we put in all the data and the co rrespo nding data types.

We have first_name as a varchar data type, which stands fo r varying characters. The number 20 (in
parentheses) fo llo wing varchar indicates that the first_name data entries can be up to 20 characters lo ng.

The char is very similar to varchar in that it also takes ASCII characters such as "a","b","c","1","2","\",">", and
so o n. The char data type can be set to take in a maximum o f 255 characters, while varchar can take up to
6 5,535 characters. The key difference between the two lies in the fact that they allo cate a different amo unt o f
memo ry space.

To make a memo ry-efficient table, try to fo llo w these guidelines:

If yo u do n't kno w exactly ho w many characters the data will be, o r if it might be mo re than 255
characters, use varchar.
If yo u kno w the data's exact size and it's less than 255 characters, use char.

To illustrate, it's wise to use varchar fo r names since yo u do n't kno w exactly ho w many characters will be
invo lved fro m entry to entry. Fo r gender (gender) (m/f), yes/no fields, and o ther sho rt data fields, it's go o d to
use char.

Mo ving right alo ng, the birthday is o f the dat e data type. A date in MySQL is in the fo rmat year-mo nth-day,
such as 20 15-0 9 -21. It's mo re advantageo us to use the dat e data type fo r dates than to use the char type—
we'll see why in a bit.

We can represent gender using a single character (m o r f—and yo u can use o ther co des like "d" fo r decline to
answer), so we'll use the char data type. Height and weight are integers. Integers refer to all who le numbers,
including negative who le numbers (52, 5, 0 , -1, -40 ). Ho wever, no tice the wo rd unsigne d that is within the
co de. Unsigne d disables negative numbers. This is useful here since we wo n't need negative numbers fo r
height and weight. Cho o sing the right type o f variables will save a lo t o f disk space (especially when yo ur
database is huge) and minimize the data access time.

Oo ps, I almo st fo rgo t o ne o f the data types!

The t e xt data type is very similar to the varchar and char data types, except that we do no t specify the
maximum length in parentheses after the wo rd t e xt . The text data type might be useful if yo u need a data
co lumn to sto re a lengthy descriptio n o f an item o r so me o ther lo ng piece o f text. Be careful with lo ng text
entries; the who le structure o f a database is such that entries are stable and so mewhat permanent. So , say
yo u make a spelling erro r in that lo ng text variable that yo u sto red and no w yo u want to change it. It wo uld be
do -able, but co rrecting such erro rs is difficult. (We co uld use the alt e r co mmand to do so , but let's wo rry
abo ut that later.)

Checking T ables
No w that yo u've created the table named f rie nds, let's make sure everything is in o rder. Try this:
Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> describe friends;


+------------+-----------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------------+------+-----+---------+-------+
| first_name | varchar(20) | YES | | NULL | |
| last_name | varchar(20) | YES | | NULL | |
| birthday | date | YES | | NULL | |
| gender | char(1) | YES | | NULL | |
| height | int(3) unsigned | YES | | NULL | |
| weight | int(4) unsigned | YES | | NULL | |
+------------+-----------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

Fo r no w, do n't wo rry abo ut the Null, Ke y, and Ext ra co lumns. The De f ault co lumn simply states that if no
data is entered in that particular field, a NULL value is assigned (basically, it's left empty). The useful co lumns
here are Fie ld and T ype . So metimes database pro grammers can get lo st and fo rget the types o f data and
what names they've created. To find o ut the names o f the fields and the data types, we simply use de scribe .
Pretty handy, eh?

Okay, no w that the table is set up, we'll need to enter so me data. But befo re we do that, let me just give yo u a
quick reference table o f all data types o ut there that yo u can use. We wo n't co ver all o f them here, but the data
types we will co ver can handle just abo ut any no rmal database.

Num e ric Dat a T ype s Space Re quire d


TINYINT 1 byte
SMALLINT 2 bytes
MEDIUMINT 3 bytes
INT 4 bytes
INTEGER 4 bytes
BIGINT 8 bytes
FLOAT(4) 4 bytes
FLOAT(8 ) 8 bytes
FLOAT 4 bytes
DOUBLE 8 bytes
DOUBLE PRECISION 8 bytes
REAL 8 bytes
DECIMAL(N,D) N bytes (D+2, if N<D)
NUMERIC(N,D) N bytes (D+2, if N<D)
Dat e and T im e Dat a
Space Re quire d
T ype s
DATE 3 bytes
DATETIME 8 bytes
TIMESTAMP 4 bytes
TIME 3 bytes
YEAR 1 byte
St ring Dat a T ype s Space Re quire d
CHAR(X) X bytes, where X <= 2^8 (255)
VARCHAR(X) L+1 o r 2 bytes, where X <= 2^16 (6 5,535)
TINYBLOB, TINYTEXT L+1 bytes, where L < 2^8 (255)
BLOB, TEXT L+2 bytes, where L < 2^16 (6 5,535)
MEDIUMBLOB,
L+3 bytes, where L < 2^24 (16 ,777,215)
MEDIUMTEXT
LONGBLOB, LONGTEXT L+4 bytes, where L < 2^32 (4,29 4,9 6 7,29 5)
1 o r 2 bytes, depending o n the number o f enumeratio n values (6 5,535 values
ENUM('value1','value2',...)
maximum)
1, 2, 3, 4 o r 8 bytes, depending o n the number o f set members (6 4 members
SET('value1','value2',...)
maximum)

Inserting Values into T ables


No w, let's enter so me values into the table "friends" that we've already set up.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> insert into friends values ('Hoyoul', 'Kang',


-> '1979-08-08', 'm', 165, 145);
Query OK, 1 row affected (0.00 sec)

If so mething went wro ng (fo r example, if yo u fo rgo t to type a character), o ften MySQL will tell yo u the appro ximate
lo catio n o f the erro r.

We've successfully inserted o ne entry into the friends table, using the co mmand inse rt int o . The table name fo llo ws
the co mmand, fo llo wed by the co lumn values within a set o f parentheses.

Within the parentheses, yo u must enter the values in the exact o rder yo u specified when yo u first created
Note the table fo rmat. In o ther wo rds, "Ho yo ul" and "Kang" are the first_name and the last_name co lumns,
respectively, that yo u created previo usly.

Values that fit into the varchar, char, t e xt , and dat e data types need to be within either single o r do uble quo tes (if the
values co ntain quo tes, there are o ther rules fo r entry; fo r example, using backticks (`) instead o f quo tes). When we get
into PHP interfacing, we'll need to use single quo tes due to int e rpo lat io n, so yo u might want to make a habit o f
using single quo tes to define values fro m no w o n.

Inserting Specific Column Values


Yo u can also cho o se which specific fields yo u want to enter using the Inse rt int o statement. Let's say we
want to enter ano ther ro w into o ur f rie nds table with first name = 'Jo e', birthday = '19 55-12-12', gender = 'm',
weight = '16 0 '. Here's ho w yo u wo uld go abo ut do ing it.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> insert into friends (first_name, birthday, gender, weight)


-> values ('Joe', '1955-12-12', 'm', '160');

Right after the table name, yo u type the names o f the fields yo u want to insert values into and then enter the
co rrespo nding values, in the same order, into the table. So 'Jo e' co rrespo nds to f irst _nam e , '19 55-12-12'
co rrespo nds to birt hday, and so o n. The fields fo r which yo u didn't supply a value wo uld simply co ntain the
default NULL (an empty value).

Retrieving Data from T ables


Let's retrieve the data we've just entered.
Type the fo llo wing into yo ur MySQL pro mpt:

mysql> select * from friends;


+------------+-----------+------------+--------+--------+--------+
| first_name | last_name | birthday | gender | height | weight |
+------------+-----------+------------+--------+--------+--------+
| Hoyoul | Kang | 1979-08-08 | m | 165 | 145 |
| Joe | NULL | 1955-12-12 | m | NULL | 160 |
+------------+-----------+------------+--------+--------+--------+
2 rows in set (0.00 sec)

Here we have the keywo rd se le ct , which retrieves the co lumns and their values in a certain table—in o ur case,
f rie nds. The star (*) is a wildcard—a sho rtcut—that in o ur case means all column values.

Take so me time to insert so me mo re o f yo ur friends and their statistics into yo ur table. Try to add at least five mo re.
That sho uld get yo u really co mfo rtable with using the Insert syntax. Try to enter different values fo r all the different fields
so yo u have a go o d amo unt o f variety in yo ur data—the mo re friends yo u enter at this po int, the mo re fun yo u can have
later when we start to play aro und with querying.

Be sure to play aro und with cre at e , se le ct , and inse rt , and to hand in yo ur assignm e nt s fro m the syllabus. Please make
sure to read all the co mments o n the Graded links o nce yo ur co ursewo rk has been returned. See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Searching Through Tables

Exploring the 'where' Keyword


We to o k a quick lo o k at the se le ct keywo rd in o ur previo us lab. Do yo u remember the syntax o f that co mmand? Let's
lo o k at it again.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select * from friends;

Here we're selecting to view all the co lumns (the asterisk * symbo l o r "wildcard" represents "all") fro m the table
f rie nds.

Let's try a mo re co mplicated query. Say we want to get a list o f the first names o f all yo ur female friends. We can do this
in o ne co mmand:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select first_name from friends where gender = 'f';


+------------+
| first_name |
+------------+
| Trish |
| Kerry |
| Dessie |
+------------+
3 rows in set (0.00 sec)

mysql>

This statement is very similar to an English sentence, isn't it? The previo us co mmand line co uld be read, "se le ct the
f irst _nam e co lumn f ro m table f rie nds whe re ge nde r is equal to 'f '." The part after the keywo rd whe re is called the
co ndit io nal st at e m e nt , and it's used just like yo u wo uld use it in any pro gramming language—fo r instance, a PHP
if /e lse statement.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select first_name from friends where gender = 'f' or gender = 'm';

The o perato r o r is used here to expand o ur o ptio ns when retrieving data. Basically, this means that if the gender
matches 'f' or 'm', then MySQL returns the first_name value fo r the entry to be displayed.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select first_name, last_name, birthday


-> from friends where height > 175 and weight < 160;

The three names o f the fields (first_name, last_name, and birthday) are given (separated by co mmas) to specify that
yo u want tho se three fields to be displayed. Since we have two co nditio ns, and we need to satisfy bo th o f them, we use
the and o perato r. The first co nditio n was that the height must be greater than 175 centimeters, which was indicated with
he ight > 17 5 . The seco nd co nditio n was that weight was under 16 0 po unds, represented by we ight < 16 0 .

Observe the fo llo wing co mpariso n o perato rs:


Ope rat o r Me aning
= equal
< less than
<= less than o r equal to
> greater than
>= greater than o r equal to
!= no t equal

Try playing aro und with the and, o r, and o ther o perato rs using the se le ct statements befo re mo ving o n.

T he 'like' Selector
If yo u've wo rked with pro gramming languages, yo u pro bably reco gnized the co nditio nal statement o perato rs.
Ho wever, yo u may no t have seen the special SQL like selecto r yet.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select first_name,birthday from friends where first_name like ("Des%");


+------------+------------+
| first_name | birthday |
+------------+------------+
| Dessie | 1975-08-01 |
+------------+------------+
1 row in set (0.00 sec)

In MySQL, the keywo rd like is used as an operator, to search fo r co lumn values that match a certain string pattern—in
o ur case, we wanted to find Dessie's birthday, but co uldn't remember ho w her name was spelled. Because we kno w it
starts with "Des," we use the percent sign (% ) wildcard to represent the rest o f her name, ho wever it may be spelled. Of
co urse, if yo u have friends named "Destiny" o r "Deshawn," their birthdays will be listed as well.

Updating and Deleting Data


Being able to search a table is great, but tables aren't much go o d if yo u can't update o r delete entries. Luckily, do ing
these tasks is just as simple as searching.

Updating Entries
When yo u retrieved yo ur friends' data using the se le ct keywo rd, did yo u no tice so mething strange abo ut
Ho yo ul's height? His weight lo o ks no rmal in po unds—145 po unds is a reaso nable human weight—but if we
take his height in inches, 16 5 inches wo uld make him o ver 13 feet tall!

To make o ur data co nsistent, we sho uld pick either the Imperial o r the Metric system fo r bo th co lumns. Let's
go with Imperial, which wo uld make his height 6 9 inches. Update it as sho wn:

Type the fo llo wing into yo ur MySQL pro mpt:

mysql> update friends set height=69 where first_name='Hoyoul';


Query OK, 1 rows affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql>

No w let's use se le ct again to check o ur results:


Type the fo llo wing into yo ur MySQL pro mpt:

mysql> select * from friends where first_name='hoyoul';


+------------+-----------+------------+---------+--------+--------+
| first_name | last_name | birthday | gender | height | weight |
+------------+-----------+------------+---------+--------+--------+
| Hoyoul | Kang | 1979-08-08 | m | 69 | 145 |
+------------+-----------+------------+---------+--------+--------+
1 row in set (0.00 sec)

And if yo u want to update multiple co lumn values:

Type the fo llo wing into yo ur MySQL pro mpt:

mysql> update friends set birthday='1975-09-30',gender='f' where last_name='Parm


elee';
+------------+-----------+------------+--------+--------+--------+
| first_name | last_name | birthday | gender | height | weight |
+------------+-----------+------------+--------+--------+--------+
| Kerry | Parmelee | 1975-09-30 | f | NULL | NULL |
+------------+-----------+------------+--------+--------+--------+
1 row in set (0.00 sec)

Deleting Entries
We've decided that since we do n't kno w Jo e's last name, we can't really co nsider him a friend—mo re o f an
acquaintance, really. So we need to remo ve him fro m o ur table, alo ng with anyo ne who se last name was
never mentio ned:

Type the fo llo wing into yo ur MySQL pro mpt:

mysql> delete from friends where last_name is null;


Query OK, 1 row affected (0.00 sec)

mysql>

And no w check o ur table, using the se le ct keywo rd:

Type the fo llo wing into yo ur MySQL pro mpt:

mysql> select * from friends;


+------------+-----------+------------+--------+--------+--------+
| first_name | last_name | birthday | gender | height | weight |
+------------+-----------+------------+--------+--------+--------+
| Hoyoul | Kang | 1979-08-08 | m | 69 | 145 |
| Trish | Gray | 0000-00-00 | f | 63 | 116 |
| Kerry | Beck | 0000-00-00 | f | 72 | 135 |
| Dessie | Coale | 1975-08-01 | f | 68 | 125 |
| Kerry | Parmelee | 1975-09-30 | f | 0 | 0 |
+------------+-----------+------------+--------+--------+--------+
5 rows in set (0.00 sec)

Here, the de le t e keywo rd was used to delete ro ws o f data, cho sen by the co nditio nal statement last _nam e
is null. There's no need to specify a wildcard (*) o r any co lumn names, since the entire ro w will always be
deleted.

But why was the wo rd is used instead o f the equality o perato r (=)? Since null is a special keywo rd indicating
an empty cell, MySQL requires the o perato r is in o rder to prevent null fro m being co nfused with a string, such
as 'hello ' o r, incidentally, 'null.'

Get in yo ur fill o f practice, and be sure to hand in yo ur assignments. See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Managing Tables

Altering T ables
The o verall idea o f having a database is to allo w many entries o ver a lo ng perio d o f time. The database co lumns
sho uld therefo re be well tho ught-o ut befo rehand, and we sho uld try to anticipate po ssible future changes. Ho wever,
o nce in a while, so mething co mpletely unexpected happens and yo u have to alt e r the table co lumns to add new
catego ries o r change existing o nes.

Befo re we discuss the alt e r co mmand, let's create ano ther table to play with:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> create table officeproducts (product_name varchar(20),


-> price decimal(6,2));
Query OK, 0 rows affected (0.02 sec)

mysql>

Yo u no w have a table called o f f ice pro duct s with two co lumns o f info rmatio n—pro duct _nam e and price .

As it turns o ut, we fo rgo t to add a de script io n co lumn. Luckily, SQL co ntains many co mmands to deal with human
erro r, and o ne o f tho se is alt e r t able . Let's alter o ur o f f ice pro duct s table to add a de script io n co lumn.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> alter table officeproducts add description text;


Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql>

No w let's check the table to make sure it was changed co rrectly.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> describe officeproducts;


+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| product_name | varchar(20) | YES | | NULL | |
| price | decimal(6,2) | YES | | NULL | |
| description | text | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>

We simply used the alt e r t able and add co mmands to add a de script io n co lumn with type t e xt .

Deleting and Reordering Columns


If we decide that we no lo nger want a co lumn in o ur table, we can dro p it. Ho wever, if we have data in that
co lumn, we will lo se it, so we must be very careful when we use dro p. Suppo se we want to dro p the
de script io n co lumn.
Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> alter table officeproducts drop description;


Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql>

Note Be careful using the dro p co mmand! When yo u dro p the co lumn, yo u dro p all o f its data.

We used the dro p co mmand to delete the co lumn called de script io n fro m the table o f f ice pro duct s.
No tice that, unlike adding co lumns, when dro pping co lumns we do n't need to specify the co lumn type.

No w, suppo se we really do want that descriptio n co lumn, but we want it to co me after pro duct _nam e . Try
this:

Type the fo llo wing co mmands at yo ur MySQL pro mpt:

mysql> alter table officeproducts add description text after product_name;


Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> describe officeproducts;


+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| product_name | varchar(20) | YES | | NULL | |
| description | text | YES | | NULL | |
| price | decimal(6,2) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

mysql>

This time, we added af t e r co lum n_nam e to o ur co mmand line. When yo u insert a co lumn using the alt e r
co mmand, the new co lumn is appended after the last co lumn by default. Using af t e r enables yo u to specify
where the new co lumn go es. To put yo ur new co lumn up fro nt as the first co lumn o f the table, yo u can use
f irst instead o f af t e r:

OBSERVE:

alter table officeproducts add description text first;

To reo rder a table witho ut lo sing any data, use alt e r t able with m o dif y. Suppo se we decide after all this that
we'd like to mo ve de script io n after price again. Try this:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> alter table officeproducts modify description text after price;


Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql>

No w let's check the table to make sure it was changed co rrectly.


Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> describe officeproducts;


+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| product_name | varchar(20) | YES | | NULL | |
| price | decimal(6,2) | YES | | NULL | |
| description | text | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>

Changing Column T ype


What if yo u want to change the data type o f an existing co lumn? Suppo se we want to change the data type o f
co lumn de script io n fro m t e xt to varchar(25 5 ). Here's ho w we wo uld do it:

Type the fo llo wing co mmands at yo ur MySQL pro mpt:

mysql> alter table officeproducts modify description varchar(255);


Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> describe officeproducts;


+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| product_name | varchar(20) | YES | | NULL | |
| description | varchar(255) | YES | | NULL | |
| price | decimal(6,2) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>

Syntax-wise, the m o dif y co mmand abo ve is almo st exactly like the add co mmand. Ho wever, rather than
adding a new co lumn, it takes an existing co lumn and alters o nly its data type, to whatever yo u specify. In o ur
case, it takes the de script io n co lumn and changing its data type fro m t e xt to varchar(25 5 ).

Renaming T ables
So metimes, yo u might need to change the name o f a table after creating it. Instead o f recreating the table and typing all
o f the co lumn names and co lumn types all o ver again, yo u can just rename the table.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> alter table officeproducts rename as office_prod;


Query OK, 0 rows affected (0.00 sec)

mysql> describe officeproducts;


ERROR 1146: Table 'certjosh.officeproducts' doesn't exist

mysql>

What just happened? By using the co mmand re nam e as, we've taken the table o f f ice pro duct s and renamed it
o f f ice _pro d. As a result, the table o f f ice pro duct s no longer exists. Let's try this:
Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> describe office_prod;


+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| product_name | varchar(20) | YES | | NULL | |
| description | varchar(255) | YES | | NULL | |
| price | decimal(6,2) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>

No w that lo o ks better.

Deleting T ables
We kno w ho w to create, alter, and rename tables. But what if we had an o ld table we no lo nger needed and wanted to
remo ve? We'll need to dro p the table, meaning we'll remo ve the table and all the entries inside o f it. Let's go ahead
and drop o f f ice _pro d alto gether.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> drop table office_prod;


Query OK, 0 rows affected (0.00 sec)

mysql> describe office_prod;


ERROR 1146: Table 'certjosh.office_prod' doesn't exist

mysql>

By simply typing dro p t able , then the table name o f f ice _pro d, we have deleted the entire table fro m o ur SQL
database.

When yo u dro p a table, it is go ne fo rever! If yo u have an essential table with lo ts o f entries in it, all
WARNING will be lo st. Use extreme cautio n with the dro p co mmand!

Befo re mo ving o n, be sure to hand in yo ur assignm e nt s fo r this lesso n. See yo u in the next o ne!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Managing Table Entries
Yo u've learned ho w to create, alter, search, update, and delete tables in SQL. Theo retically, yo u co uld get by in SQL with these
skills alo ne—especially with the limited data we've been using so far.

Ho wever, the reality is that an SQL table will pro bably end up with to ns and to ns o f data. That's really the reaso n fo r creating an
auto mated database system, isn't it? And since that's the case, we need to take mo re care with o ur tables to ensure their
integrity and efficiency.

Optimizing with Keys/Indexes


Are yo u co nnected to yo ur SQL database? Go o d. Let's create a new table, a t able _o f _co nt e nt s, that co ntains the
chapter names, descriptio ns, and to pics o f a bo o k we want to po st o nline:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> create table table_of_contents (chapter_name varchar(250), chapter_description


text, chapter_topic varchar(25));
Query OK, 0 rows affected (0.01 sec)

mysql>

No w let's fill the table with so me bo o k chapters.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> insert into table_of_contents values ('The Client Program',


mysql> 'Recipes for the mysql interface itself.','queries');
Query OK, 0 rows affected (0.01 sec)
mysql> insert into table_of_contents values ('Writing External Programs',
mysql> 'Recipes for MySQL-based programs.','DBI');

Query OK, 0 rows affected (0.01 sec)


mysql> insert into table_of_contents values ('Record Selection',
mysql> 'Recipes for formatting MySQL output.','SELECT');
Query OK, 0 rows affected (0.01 sec)

mysql>

Fill this table with a few mo re chapters, and yo u'll have so mething that lo o ks like this:
INTERACTIVE SESSION:

mysql> select * from table_of_contents;


+----------------------------------+---------------------------------------------------
-+------------------+
| chapter_name | chapter_description
| chapter_topic |
+----------------------------------+---------------------------------------------------
-+------------------+
| The Client Program | Recipes for the mysql interface itself.
| queries |
| Writing External Programs | Recipes for MySQL-based programs.
| DBI |
| Record Selection | Recipes for formatting MySQL output.
| SELECT |
| Working with Strings | Recipes for controlling strings in output.
| pattern matching |
| Working with Dates and Times | Recipes for controlling date/time in output.
| TIMESTAMP |
| Sorting Query Results | Recipes for sorting SELECT results.
| ORDER BY |
| Generating Summaries | Recipes for using groupings, count(), min and max.
| GROUP BY |
| Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| DBI |
+----------------------------------+---------------------------------------------------
-+------------------+
8 rows in set (0.00 sec)

This table lo o ks pretty o rganized and intuitive fo r a bo o k, right? In fact, yo u can use the chapt e r_t o pic co lumn to find
the chapter that co ntains it.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select chapter_name,chapter_description from table_of_contents where chapter_top


ic='GROUP BY';
+----------------------+----------------------------------------------------+
| chapter_name | chapter_description |
+----------------------+----------------------------------------------------+
| Generating Summaries | Recipes for using groupings, count(), min and max. |
+----------------------+----------------------------------------------------+
1 row in set (0.00 sec)

mysql>

Pretty handy, huh? Think abo ut it. If yo u wanted to find a specific to pic in a physical bo o k, unless it had the rare, really
great index, yo u'd pro bably have to flip thro ugh many pages in that bo o k in o rder to find what yo u're lo o king fo r. And,
o nce yo u fo und yo ur to pic, there'd be no guarantee that the to pic didn't sho w up again o ther chapters. If that bo o k
happened to be several hundred pages lo ng, it wo uld take way to o lo ng to find all the instances o f yo ur to pic.

But wait—is SQL searching any differently fro m ho w yo u wo uld search?


Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> EXPLAIN select chapter_name,chapter_description from table_of_contents where cha


pter_topic='GROUP BY';
+----+-------------+-------------------+------+---------------+------+---------+------+
------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |
rows | Extra |
+----+-------------+-------------------+------+---------------+------+---------+------+
------+-------------+
| 1 | SIMPLE | table_of_contents | NULL | NULL | NULL | NULL | NULL |
8 | Using where |
+----+-------------+-------------------+------+---------------+------+---------+------+
------+-------------+
1 row in set (0.00 sec)

mysql>

The EXPLAIN keywo rd can be used in fro nt o f any SELECT statement, to analyze the o ptimizatio n o f that
Note search.

Wo w. Turns o ut SQL searches exactly like yo u do —lo o king at all eight rows in a table to find the to pic in questio n. No
big deal, tho ugh, right? I mean, it's o nly eight ro ws, after all.

But what if we were lo o king fo r "GROUP BY" in an entire o nline library, like Safari Online Bo o ks? What if we were
lo o king fo r "GROUP BY" in 550 BILLION web pages wo rth o f data, like Go o gle? Imagine waiting ho urs and ho urs fo r
yo ur Go o gle search to co mplete—witho ut o ptimizatio n, even super-fast SQL wo uld get unacceptably bo gged do wn.

Let's get real here. When yo u are lo o king up a to pic in a physical bo o k, yo u do n't flip thro ugh indiscriminately. Yo u
lo o k in the inde x in the back o f the bo o k to find it:

As it turns o ut, SQL can also create an inde x o r ke y to help with searches.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> alter table table_of_contents add key(chapter_topic);


Query OK, 8 rows affected (0.01 sec)
Records: 8 Duplicates: 0 Warnings: 0

mysql>

In the statement abo ve, we've added a ke y fo r the co lumn chapt e r_t o pic to let SQL kno w that we plan to search o n
that co lumn quite a bit. SQL respo nded by creating a new, invisible table, specially designed to speed up any search
we do o n chapt e r_t o pic.
Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> describe table_of_contents;


+---------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+-------+
| chapter_name | varchar(250) | YES | | NULL | |
| chapter_description | text | YES | | NULL | |
| chapter_topic | varchar(25) | YES | MUL | NULL | |
+---------------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>

As yo u can see, the chapt e r_t o pic co lumn is no w flagged as a multiple key, meaning that a value can be allo wed
mo re than o nce in this co lumn (like the SELECT to pic in o ur table).

So ho w do es this help o ur search? Let's find o ut:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> EXPLAIN select chapter_name,chapter_description from table_of_contents where cha


pter_topic='GROUP BY';
+----+-------------+-------------------+------+---------------+---------------+--------
-+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len
| ref | rows | Extra |
+----+-------------+-------------------+------+---------------+---------------+--------
-+-------+------+-------------+
| 1 | SIMPLE | table_of_contents | ref | chapter_topic | chapter_topic | 28
| const | 1 | Using where |
+----+-------------+-------------------+------+---------------+---------------+--------
-+-------+------+-------------+
1 row in set (0.00 sec)

mysql>

And there yo u have it—suddenly, SQL go es fro m having to lo o k at every single entry in the table, to finding "GROUP
BY" in o ne sho t. That's a po werful thing, especially as the size and co mplexity o f yo ur tables increases.

Auto_increment and Primary Keys


Yo u may have already no ticed that we have left o ut a very impo rtant co lumn in o ur t able _o f _co nt e nt s table: the
chapter number itself! The o rder o f chapters is incredibly impo rtant in a bo o k, so there has to be a way to specify which
go es where.

Let's add the chapter number:

mysql> alter table table_of_contents add chapter int unsigned NOT NULL first;
Query OK, 8 rows affected (0.00 sec)
Records: 8 Duplicates: 0 Warnings: 0

mysql>

Here we've added a new co lumn named chapt e r, with type int (fo r "integer"). unsigne d indicates that it canno t be a
negative number, and NOT NULL tells SQL no t to allo w any NULL values fo r chapt e r. f irst causes the co lumn to be
inserted, well, first—befo re all the o ther co lumns.
Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select * from table_of_contents;


+---------+----------------------------------+-----------------------------------------
-----------+------------------+
| chapter | chapter_name | chapter_description
| chapter_topic |
+---------+----------------------------------+-----------------------------------------
-----------+------------------+
| 0 | The Client Program | Recipes for the mysql interface itself.
| queries |
| 0 | Writing External Programs | Recipes for MySQL-based programs.
| DBI |
| 0 | Record Selection | Recipes for formatting MySQL output.
| SELECT |
| 0 | Working with Strings | Recipes for controlling strings in outpu
t. | pattern matching |
| 0 | Working with Dates and Times | Recipes for controlling date/time in out
put. | TIMESTAMP |
| 0 | Sorting Query Results | Recipes for sorting SELECT results.
| ORDER BY |
| 0 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | GROUP BY |
| 0 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| DBI |
+---------+----------------------------------+-----------------------------------------
-----------+------------------+
8 rows in set (0.01 sec)

mysql>

At this po int, we co uld simply updat e the table with all the chapter numbers by hand. Ho wever, because we kno w that
each chapter will have o ne unique, incremental number assigned to it, it makes sense to auto mate this pro cess to
prevent human erro r.

In o rder to do that, first we need to tell MySQL (like we did befo re with chapt e r_t o pic) that chapt e r will be a ke y
co lumn.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> alter table table_of_contents add key(chapter);


Query OK, 8 rows affected (0.01 sec)
Records: 8 Duplicates: 0 Warnings: 0

mysql>

No w, use alt e r t able to m o dif y the type o f chapt e r:

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> alter table table_of_contents modify chapter int unsigned NOT NULL auto_incremen
t;
Query OK, 8 rows affected (0.01 sec)
Records: 8 Duplicates: 0 Warnings: 0

mysql>

When we mo dified the type o f chapt e r, we left everything intact and simply added aut o _incre m e nt to the end. Here's
what SQL did:
Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select * from table_of_contents;


+---------+----------------------------------+-----------------------------------------
-----------+------------------+
| chapter | chapter_name | chapter_description
| chapter_topic |
+---------+----------------------------------+-----------------------------------------
-----------+------------------+
| 1 | The Client Program | Recipes for the mysql interface itself.
| queries |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| DBI |
| 3 | Record Selection | Recipes for formatting MySQL output.
| SELECT |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | pattern matching |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | TIMESTAMP |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| ORDER BY |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | GROUP BY |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| DBI |
+---------+----------------------------------+-----------------------------------------
-----------+------------------+
8 rows in set (0.00 sec)

mysql>

Vo ila! SQL has filled in the chapter o rder, just ho w we wanted. No w, when we want to add a chapter, we can simply
leave chapt e r blank, and it will be filled in fo r us. Like this:
Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> insert into table_of_contents values ('','Modifying Tables',


-> 'Dropping, adding, and changing columns','ALTER TABLE');
Query OK, 1 row affected (0.00 sec)

mysql> select * from table_of_contents;


+---------+----------------------------------+-----------------------------------------
-----------+------------------+
| chapter | chapter_name | chapter_description
| chapter_topic |
+---------+----------------------------------+-----------------------------------------
-----------+------------------+
| 1 | The Client Program | Recipes for the mysql interface itself.
| queries |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| DBI |
| 3 | Record Selection | Recipes for formatting MySQL output.
| SELECT |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | pattern matching |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | TIMESTAMP |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| ORDER BY |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | GROUP BY |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| DBI |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| ALTER TABLE |
+---------+----------------------------------+-----------------------------------------
-----------+------------------+
9 rows in set (0.00 sec)

mysql>

T he Primary Key
Because o ur chapt e r co lumn is co nsidered a unique ide nt if ie r, we can go o ne step further than simply
naming it as a key. In this case, the o ptimal thing to do wo uld be to name chapt e r as the table's primary key.
Type this co mmand at yo ur MySQL pro mpt:

mysql> alter table table_of_contents add primary key(chapter);


Query OK, 8 rows affected (0.01 sec)
Records: 8 Duplicates: 0 Warnings: 0

mysql> describe table_of_contents;


+---------------------+------------------+------+-----+---------+---------------
-+
| Field | Type | Null | Key | Default | Extra
|
+---------------------+------------------+------+-----+---------+---------------
-+
| chapter | int(10) unsigned | | PRI | NULL | auto_increment
|
| chapter_name | varchar(250) | YES | | NULL |
|
| chapter_description | text | YES | | NULL |
|
| chapter_topic | varchar(25) | YES | MUL | NULL |
|
+---------------------+------------------+------+-----+---------+---------------
-+
4 rows in set (0.00 sec)

mysql>

Only o ne prim ary ke y can be named fo r a table, because this indicates to SQL that this co lumn is indeed the
table's unique ide nt if ie r. Fo r this reaso n, o f co urse, every ro w in that co lumn abso lutely must be unique.

No w that we've learned ho w to keep o ur tables o ptimized, we're ready to increase the co mplexity o f o ur database. Be sure to
hand in yo ur assignm e nt s, and see yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Relational Databasing
So far, we've wo rked with simple tables in SQL, and they have wo rked well fo r o ur simple examples. Ho wever, databases can
quickly beco me eno rmo us and incredibly co mplex. Ho w do we deal with info rmatio n when it o utgro ws o ne table?

What is a Relational Database?


Let's go back to o ur o nline bo o k example. Are yo u co nnected to yo ur SQL Database? Go o d.

Type the fo llo wing co mmand at yo ur MySQL pro mpt:

mysql> select * from table_of_contents;


+---------+----------------------------------+-----------------------------------------
-----------+------------------+
| chapter | chapter_name | chapter_description
| chapter_topic |
+---------+----------------------------------+-----------------------------------------
-----------+------------------+
| 1 | The Client Program | Recipes for the mysql interface itself.
| queries |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| DBI |
| 3 | Record Selection | Recipes for formatting MySQL output.
| SELECT |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | pattern matching |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | TIMESTAMP |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| ORDER BY |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | GROUP BY |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| DBI |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| ALTER TABLE |
+---------+----------------------------------+-----------------------------------------
-----------+------------------+
9 rows in set (0.00 sec)

mysql>

There's a big pro blem with this table: the to pic co lumn. If yo u think abo ut it, a bo o k chapter's almo st always go ing to
co ver lo ts o f to pics, no t just o ne. But ho w do we include all the chapter to pics witho ut inserting the chapter name and
descriptio n o ver and o ver again? The chapt e r co lumn is auto -increment, so it wo n't even allo w duplicate chapters
anyway.

There's a simple so lutio n to this dilemma: Let's create a new table, just fo r the chapter to pics.

First, we need to dro p the chapter_to pic co lumn fro m table_o f_co ntents:

mysql> alter table table_of_contents drop chapter_topic;


Query OK, 9 rows affected (0.02 sec)
Records: 9 Duplicates: 0 Warnings: 0

mysql>
No w, create the new table, called chapter_to pics:

mysql> create table chapter_topics (topic_id int unsigned NOT NULL auto_increment,
-> chapter int unsigned NOT NULL, topic varchar(25) NOT NULL,
-> primary key(topic_id), key(chapter), key(topic));
Query OK, 0 rows affected (0.00 sec)

mysql> describe chapter_topics;


+----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+------------------+------+-----+---------+----------------+
| topic_id | int(10) unsigned | | PRI | NULL | auto_increment |
| chapter | int(10) unsigned | | MUL | 0 | |
| topic | varchar(25) | | MUL | | |
+----------+------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql>

Did yo u see ho w we were able to do all the o ptimizatio n fro m the last lesso n within one cre at e t able
Note statement? Pretty handy!

By splitting o ur data between two tables, we've created a perfect example o f a relational database. The two tables are
related because o f the chapt e r co lumn, mirro red in bo th tables as a to uch po int. This can be do ne with any number o f
tables. Fo r so me definitio ns o f relatio nal databases, see this answers.co m article.

In fact, MySQL is co nsidered a relational database management system (RDBMS), and SQL as a language was built
specifically fo r many RDBMS, no t just MySQL. Here's what Wikipedia has to say.

Befo re mo ving o n, we need to fill the chapt e r_t o pics table with so me values. Use the inse rt int o statement to get
so mething like the fo llo wing:

OBSERVE:
mysql> select * from chapter_topics;
+----------+---------+------------------+
| topic_id | chapter | topic |
+----------+---------+------------------+
| 1 | 1 | queries |
| 2 | 2 | DBI |
| 3 | 2 | PHP |
| 4 | 3 | SELECT |
| 5 | 3 | WHERE |
| 6 | 3 | LIMIT |
| 7 | 3 | temporary tables |
| 8 | 4 | pattern matching |
| 9 | 5 | TIMESTAMP |
| 10 | 5 | date_format |
| 11 | 6 | ORDER BY |
| 12 | 7 | GROUP BY |
| 13 | 8 | DBI |
| 14 | 8 | HTML |
+----------+---------+------------------+
14 rows in set (0.00 sec)

mysql>

Inner Joins
No w that we have o ur tables ready, let's get into so me basic relatio nal databasing. To co mbine the two tables we just
created abo ve, we wo uld perfo rm an inne r jo in o n the two tables, using o ne o f the fo llo wing co mmands:
Type any o f the fo llo wing co mmands at yo ur MySQL pro mpt:

mysql> select * from table_of_contents, chapter_topics;


mysql> select * from table_of_contents join chapter_topics;
mysql> select * from table_of_contents cross join chapter_topics;

Altho ugh MySQL suppo rts all three o f these statements, the first o ne is preferred o ver the o thers due to
Note so me limitatio ns o n the o ther two .
Observe the results:

+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
| chapter | chapter_name | chapter_description
| topic_id | chapter | topic |
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
| 1 | The Client Program | Recipes for the mysql interface itself.
| 1 | 1 | queries |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 1 | 1 | queries |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 1 | 1 | queries |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 1 | 1 | queries |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 1 | 1 | queries |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 1 | 1 | queries |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 1 | 1 | queries |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 1 | 1 | queries |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 1 | 1 | queries |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 2 | 2 | DBI |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 2 | 2 | DBI |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 2 | 2 | DBI |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 2 | 2 | DBI |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 2 | 2 | DBI |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 2 | 2 | DBI |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 2 | 2 | DBI |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 2 | 2 | DBI |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 2 | 2 | DBI |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 3 | 2 | PHP |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 3 | 2 | PHP |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 3 | 2 | PHP |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 3 | 2 | PHP |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 3 | 2 | PHP |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 3 | 2 | PHP |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 3 | 2 | PHP |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 3 | 2 | PHP |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 3 | 2 | PHP |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 4 | 3 | SELECT |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 4 | 3 | SELECT |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 4 | 3 | SELECT |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 4 | 3 | SELECT |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 4 | 3 | SELECT |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 4 | 3 | SELECT |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 4 | 3 | SELECT |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 4 | 3 | SELECT |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 4 | 3 | SELECT |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 5 | 3 | WHERE |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 5 | 3 | WHERE |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 5 | 3 | WHERE |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 5 | 3 | WHERE |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 5 | 3 | WHERE |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 5 | 3 | WHERE |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 5 | 3 | WHERE |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 5 | 3 | WHERE |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 5 | 3 | WHERE |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 6 | 3 | LIMIT |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 6 | 3 | LIMIT |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 6 | 3 | LIMIT |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 6 | 3 | LIMIT |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 6 | 3 | LIMIT |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 6 | 3 | LIMIT |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 6 | 3 | LIMIT |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 6 | 3 | LIMIT |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 6 | 3 | LIMIT |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 7 | 3 | temporary tables |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 7 | 3 | temporary tables |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 7 | 3 | temporary tables |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 7 | 3 | temporary tables |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 7 | 3 | temporary tables |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 7 | 3 | temporary tables |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 7 | 3 | temporary tables |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 7 | 3 | temporary tables |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 7 | 3 | temporary tables |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 8 | 4 | pattern matching |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 8 | 4 | pattern matching |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 8 | 4 | pattern matching |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 8 | 4 | pattern matching |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 8 | 4 | pattern matching |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 8 | 4 | pattern matching |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 8 | 4 | pattern matching |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 8 | 4 | pattern matching |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 8 | 4 | pattern matching |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 9 | 5 | TIMESTAMP |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 9 | 5 | TIMESTAMP |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 9 | 5 | TIMESTAMP |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 9 | 5 | TIMESTAMP |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 9 | 5 | TIMESTAMP |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 9 | 5 | TIMESTAMP |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 9 | 5 | TIMESTAMP |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 9 | 5 | TIMESTAMP |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 9 | 5 | TIMESTAMP |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 10 | 5 | date_format |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 10 | 5 | date_format |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 10 | 5 | date_format |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 10 | 5 | date_format |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 10 | 5 | date_format |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 10 | 5 | date_format |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 10 | 5 | date_format |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 10 | 5 | date_format |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 10 | 5 | date_format |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 11 | 6 | ORDER BY |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 11 | 6 | ORDER BY |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 11 | 6 | ORDER BY |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 11 | 6 | ORDER BY |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 11 | 6 | ORDER BY |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 11 | 6 | ORDER BY |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 11 | 6 | ORDER BY |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 11 | 6 | ORDER BY |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 11 | 6 | ORDER BY |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 12 | 7 | GROUP BY |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 12 | 7 | GROUP BY |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 12 | 7 | GROUP BY |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 12 | 7 | GROUP BY |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 12 | 7 | GROUP BY |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 12 | 7 | GROUP BY |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 12 | 7 | GROUP BY |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 12 | 7 | GROUP BY |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 12 | 7 | GROUP BY |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 13 | 8 | DBI |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 13 | 8 | DBI |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 13 | 8 | DBI |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 13 | 8 | DBI |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 13 | 8 | DBI |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 13 | 8 | DBI |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 13 | 8 | DBI |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 13 | 8 | DBI |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 13 | 8 | DBI |
| 1 | The Client Program | Recipes for the mysql interface itself.
| 14 | 8 | HTML |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 14 | 8 | HTML |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 14 | 8 | HTML |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 14 | 8 | HTML |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 14 | 8 | HTML |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 14 | 8 | HTML |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 14 | 8 | HTML |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 14 | 8 | HTML |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| 14 | 8 | HTML |
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
126 rows in set (0.01 sec)

mysql>

Who a, that's a lo t o f data! What yo u just did was a simple inne r jo in with so mething called the cartesian product.
Here's what happened: MySQL to o k the t able _o f _co nt e nt s table entries and matched(multiplied) it with each entry
in the chapt e r_t o pics table. So yo u go t 126 (9 table_o f_co ntents x 14 chapter_to pics) entries to tal.
Usually, this is an undesirable result—why wo uld we want every to pic in the bo o k listed o ver and o ver again with every
chapter? So we're go ing to refine o ur SQL query a little bit. Try this:

Type the fo llo wing co mmandat yo ur MySQL pro mpt:

mysql> select * from table_of_contents, chapter_topics where


-> table_of_contents.chapter = chapter_topics.chapter;
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
| chapter | chapter_name | chapter_description
| topic_id | chapter | topic |
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
| 1 | The Client Program | Recipes for the mysql interface itself.
| 1 | 1 | queries |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 2 | 2 | DBI |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 3 | 2 | PHP |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 4 | 3 | SELECT |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 5 | 3 | WHERE |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 6 | 3 | LIMIT |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 7 | 3 | temporary tables |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 8 | 4 | pattern matching |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 9 | 5 | TIMESTAMP |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 10 | 5 | date_format |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 11 | 6 | ORDER BY |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 12 | 7 | GROUP BY |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 13 | 8 | DBI |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 14 | 8 | HTML |
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
14 rows in set (0.01 sec)

mysql>

No w we go t rid o f the cartesian effect and go t a table with 14 ro ws o f entries. This makes a lo t mo re sense—using the
WHERE clause in o ur SQL statement, we matched the related chapt e r co lumns to ensure that the co rrect to pics are
listed alo ng with the pro per chapters.

Outer Joins
Did yo u no tice so mething missing in the abo ve inne r jo in results? One o f o ur t able _o f _co nt e nt s entries, chapter
9 , was no t included. Why?
Take ano ther lo o k at o ur two tables:

mysql> select * from table_of_contents;


+---------+----------------------------------+-----------------------------------------
-----------+
| chapter | chapter_name | chapter_description
|
+---------+----------------------------------+-----------------------------------------
-----------+
| 1 | The Client Program | Recipes for the mysql interface itself.
|
| 2 | Writing External Programs | Recipes for MySQL-based programs.
|
| 3 | Record Selection | Recipes for formatting MySQL output.
|
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
|
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
|
| 9 | Modifying Tables | Dropping, adding, and changing columns
|
+---------+----------------------------------+-----------------------------------------
-----------+
9 rows in set (0.01 sec)

mysql> select * from chapter_topics;

Observe the results:

+----------+---------+------------------+
| topic_id | chapter | topic |
+----------+---------+------------------+
| 1 | 1 | queries |
| 2 | 2 | DBI |
| 3 | 2 | PHP |
| 4 | 3 | SELECT |
| 5 | 3 | WHERE |
| 6 | 3 | LIMIT |
| 7 | 3 | temporary tables |
| 8 | 4 | pattern matching |
| 9 | 5 | TIMESTAMP |
| 10 | 5 | date_format |
| 11 | 6 | ORDER BY |
| 12 | 7 | GROUP BY |
| 13 | 8 | DBI |
| 14 | 8 | HTML |
+----------+---------+------------------+
14 rows in set (0.00 sec)

mysql>

Lo o king at o ur two tables, yo u can see that there are no entries in chapt e r_t o pics fo r chapter 9 . Because we used an
inne r jo in to co mbine o ur tables, o nly the entries which exist in both tables are included in the resulting table.

But what if we wanted to include EVERY entry in t able _o f _co nt e nt s, regardless o f the existence o f a matching
chapt e r_t o pics entry? This is where outer joins co me into the picture. Let's try the o uter jo in:
Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select * from table_of_contents


-> left outer join chapter_topics on table_of_contents.chapter = chapter_topics.cha
pter;
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
| chapter | chapter_name | chapter_description
| topic_id | chapter | topic |
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
| 1 | The Client Program | Recipes for the mysql interface itself.
| 1 | 1 | queries |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 2 | 2 | DBI |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 3 | 2 | PHP |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 4 | 3 | SELECT |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 5 | 3 | WHERE |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 6 | 3 | LIMIT |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 7 | 3 | temporary tables |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 8 | 4 | pattern matching |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 9 | 5 | TIMESTAMP |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 10 | 5 | date_format |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 11 | 6 | ORDER BY |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 12 | 7 | GROUP BY |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 13 | 8 | DBI |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 14 | 8 | HTML |
| 9 | Modifying Tables | Dropping, adding, and changing columns
| NULL | NULL | NULL |
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
15 rows in set (0.00 sec)

mysql>

Ah, there's chapter 9 ! It's no w included in the resulting table, with NULL listed fo r its no nexistent chapt e r_t o pics
values.

Take ano ther lo o k at this SQL statement:


select * from table_of_contents
left outer join chapter_topics ON table_of_contents.chapter = chapter_topics.chapter;

While an inner jo in requires that matching entries exist in both tables in o rder to include them in the result, a le f t o ut e r
jo in includes ALL the table entries in the le f t table - in o ur case, t able _o f _co nt e nt s—and then matches entries in
the right table—chapt e r_t o pics—if they exist.

The wo rd "o uter" in le f t o ut e r jo in is o ptio nal—le f t jo in will also wo rk. By the way, there is also a
Note right o ut e r jo in in MySQL, but it is no t used nearly as much as the le f t o ut e r jo in.

The impo rtant new thing we enco unter here is the ON keywo rd. This keywo rd is similar to the whe re keywo rd, in that a
co nditio n must fo llo w the keywo rd ON as it wo uld fo llo w the whe re keywo rd. Ho wever, ON signifies a co nditio n that is
not required, whereas WHERE requires the co nditio n to be met in o rder fo r an entry to be included in the results.

In fact, if yo u want to require a co nditio n within a le f t o ut e r jo in statement, yo u have to add a WHERE keywo rd as
well. Let's see ho w o ur statement wo uld change if we wanted to search o n a to pic:

Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select table_of_contents.chapter, table_of_contents.chapter_name from table_of_c


ontents
-> left outer join chapter_topics on table_of_contents.chapter = chapter_topics.cha
pter WHERE chapter_topics.topic = 'ORDER BY';
+---------+-----------------------+
| chapter | chapter_name |
+---------+-----------------------+
| 6 | Sorting Query Results |
+---------+-----------------------+
1 row in set (0.00 sec)

mysql>

Aliases
Let's take ano ther lo o k at the previo us SQL statement:

OBSERVE:
select table_of_contents.chapter, table_of_contents.chapter_name from table_of_contents
left outer join chapter_topics on table_of_contents.chapter = chapter_topics.chapter WH
ERE chapter_topics.topic = 'ORDER BY';

Did yo u no tice that every time we mentio n a co lum n nam e within a jo in statement, the t able nam e is included? This
is to ensure no ambiguity in co lumn names—fo r example, there is a chapt e r co lumn in bo th the
t able _o f _co nt e nt s and the chapt e r_t o pics tables. In mo re co mplex tables, there are many mo re chances fo r
duplicate co lumn names, so it's best to get into the habit o f specifying the table in every instance.

That being said, there's a way to sho rten the statement, using aliases.

Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select tc.chapter, tc.chapter_name from table_of_contents AS tc


-> left outer join chapter_topics AS ct on tc.chapter = ct.chapter WHERE ct.topic =
'ORDER BY';
+---------+-----------------------+
| chapter | chapter_name |
+---------+-----------------------+
| 6 | Sorting Query Results |
+---------+-----------------------+
1 row in set (0.00 sec)

mysql>

Here, thro ugh the AS keywo rd, we've simply renamed the t able _o f _co nt e nt s table to t c and the chapt e r_t o pics
table to ct . Why did we do this? Simply put, renaming the tables with aliase s do es bo th yo u and yo ur po o r keybo ard a
favo r.

Co ngratulatio ns, yo u no w kno w the gro undwo rk o f relatio nal databasing! Relatio nal databasing can get tricky so metimes, so try
playing aro und with the MySQL queries to get a stro ng grasp o f the co ncept. See yo u in the next lesso n.

Copyright © 1998-2014 O'Reilly Media, Inc.


This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Managing Query Results
In this lesso n, we'll take a lo o k at two very impo rtant and useful SQL to o ls: gro uping and o rdering. So rting thro ugh query o utput
with gro up by and o rde r by is simple in SQL, yet it perfo rms a po werful service - it makes a pro grammer's life easier by
preventing the need fo r pro cessing query results after the fact.

Make sure yo u're co nnected to yo ur MySQL database, and let's get started!

Group By
Let's take ano ther lo o k at o ur two tables, t able _o f _co nt e nt s and chapt e r_t o pics, using an inne r jo in.

Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select * from table_of_contents as tc, chapter_topics as ct where


-> tc.chapter = ct.chapter;
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
| chapter | chapter_name | chapter_description
| topic_id | chapter | topic |
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
| 1 | The Client Program | Recipes for the mysql interface itself.
| 1 | 1 | queries |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 2 | 2 | DBI |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 3 | 2 | PHP |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 4 | 3 | SELECT |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 5 | 3 | WHERE |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 6 | 3 | LIMIT |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 7 | 3 | temporary tables |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 8 | 4 | pattern matching |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 9 | 5 | TIMESTAMP |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 10 | 5 | date_format |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 11 | 6 | ORDER BY |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 12 | 7 | GROUP BY |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 13 | 8 | DBI |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 14 | 8 | HTML |
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
14 rows in set (0.00 sec)

mysql>

Just like befo re, we go t an entry fo r every chapter to pic that exists - 14 results to tal. But what if we wanted to gather o nly
a sampling o f results; say, o ne to pic per chapter? Here's where gro up by co mes in handy.
Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select * from table_of_contents as tc, chapter_topics as ct where


-> tc.chapter = ct.chapter GROUP BY tc.chapter;
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
| chapter | chapter_name | chapter_description
| topic_id | chapter | topic |
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
| 1 | The Client Program | Recipes for the mysql interface itself.
| 1 | 1 | queries |
| 2 | Writing External Programs | Recipes for MySQL-based programs.
| 2 | 2 | DBI |
| 3 | Record Selection | Recipes for formatting MySQL output.
| 4 | 3 | SELECT |
| 4 | Working with Strings | Recipes for controlling strings in outpu
t. | 8 | 4 | pattern matching |
| 5 | Working with Dates and Times | Recipes for controlling date/time in out
put. | 9 | 5 | TIMESTAMP |
| 6 | Sorting Query Results | Recipes for sorting SELECT results.
| 11 | 6 | ORDER BY |
| 7 | Generating Summaries | Recipes for using groupings, count(), mi
n and max. | 12 | 7 | GROUP BY |
| 8 | Introduction to MySQL on the Web | Formatting MySQL output into web pages.
| 13 | 8 | DBI |
+---------+----------------------------------+-----------------------------------------
-----------+----------+---------+------------------+
8 rows in set (0.00 sec)

mysql>

Remember, when we use an inne r jo in, chapter 9 isn't included—it do esn't have a matching result in
Note chapter_to pics.

This time, we go t o nly 8 results. That's because, by gro uping the results by chapt e r, we get o nly one result per
chapter. If there is mo re than o ne entry in chapt e r_t o pics fo r a chapter, SQL simply grabs the first o ne it finds.

Using gro up by o n a certain co lumn, we can ensure that o nly distinct results are returned fo r that co lumn, no matter
ho w many times it's repeated no rmally.

Using Distinct to Prevent Duplicate Results


Turns o ut, if yo u simply want to prevent duplicate results in a query fo r a certain co lumn, yo u do n't necessarily have to
use gro up by.

Fo r instance, perhaps we o nly care abo ut getting the chapter names fo r all o f the chapters that co ntain any to pics at all,
but we do n't necessarily care abo ut seeing any o f the to pics. Fo r this purpo se, we co uld still use gro up by. Or, we
co uld use a keywo rd called DIST INCT :
Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select DISTINCT tc.chapter, tc.chapter_name from table_of_contents as tc, chapte


r_topics as ct where
-> tc.chapter = ct.chapter;
+---------+----------------------------------+
| chapter | chapter_name |
+---------+----------------------------------+
| 1 | The Client Program |
| 2 | Writing External Programs |
| 3 | Record Selection |
| 4 | Working with Strings |
| 5 | Working with Dates and Times |
| 6 | Sorting Query Results |
| 7 | Generating Summaries |
| 8 | Introduction to MySQL on the Web |
+---------+----------------------------------+
8 rows in set (0.00 sec)

mysql>

Altho ugh DIST INCT is a rather limiting keywo rd, it has its purpo se in SQL, making it a wo rthy weapo n in yo ur arsenal
o f co mmands. Here's the MySQL manual page o n DISTINCT.

Searching and Counting within Groups


No w, distinct results aren't the o nly reaso n to use gro up by. This keywo rd is useful anytime we want to find statistics
within co lumn gro ups.

Fo r instance, what if we want to find o ut just ho w many to pics are listed under each chapter in o ur o nline bo o k?

Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select tc.chapter,tc.chapter_name AS Title,count(ct.topic) from table_of_content


s as tc LEFT OUTER JOIN chapter_topics as ct
-> ON tc.chapter = ct.chapter GROUP BY tc.chapter;
+---------+----------------------------------+-----------------+
| chapter | chapter_name | count(ct.topic) |
+---------+----------------------------------+-----------------+
| 1 | The Client Program | 1 |
| 2 | Writing External Programs | 2 |
| 3 | Record Selection | 4 |
| 4 | Working with Strings | 1 |
| 5 | Working with Dates and Times | 2 |
| 6 | Sorting Query Results | 1 |
| 7 | Generating Summaries | 1 |
| 8 | Introduction to MySQL on the Web | 2 |
| 9 | Modifying Tables | 0 |
+---------+----------------------------------+-----------------+
9 rows in set (0.00 sec)

mysql>

No w that's handy. Simply by using the gro up by keywo rd o n the co lumn t c.chapt e r, alo ng with the gro up by
functio n co unt (), we're able to see exactly ho w many to pics go alo ng with each chapter in o ur bo o k.

There are many mo re gro up by functio ns, such as sum (), avg(), m in() and m ax(). See MySQL's web site fo r
additio nal gro up by functio ns. Be sure to take so me time and experiment with these!

Searching Within Groups


OK, let's up the ante here. Say we're lo o king fo r ONLY the chapters which co ntain 2 or more to pics. Let's give
it a try with the WHERE keywo rd:
Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select tc.chapter,tc.chapter_name AS Title,count(ct.topic) from table_of_


contents as tc LEFT OUTER JOIN chapter_topics as ct
-> ON tc.chapter = ct.chapter WHERE count(ct.topic) >= 2 GROUP BY tc.chapter
;
ERROR 1111: Invalid use of group function
mysql>

Uh o h, that's no t go o d. Yo u see, the keywo rd WHERE canno t be used with a gro up co lum n f unct io n, like
co unt (). This is because gro up co lumns depend o n GROUP BY. Fo rtunately, there's a different keywo rd to
use: HAVING.

Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select tc.chapter,tc.chapter_name AS Title,count(ct.topic) from table_of_


contents as tc LEFT OUTER JOIN chapter_topics as ct
-> ON tc.chapter = ct.chapter GROUP BY tc.chapter HAVING count(ct.topic) >=
2 ;
+---------+----------------------------------+-----------------+
| chapter | chapter_name | count(ct.topic) |
+---------+----------------------------------+-----------------+
| 2 | Writing External Programs | 2 |
| 3 | Record Selection | 4 |
| 5 | Working with Dates and Times | 2 |
| 8 | Introduction to MySQL on the Web | 2 |
+---------+----------------------------------+-----------------+
4 rows in set (0.00 sec)

mysql>

That's mo re like it.

No tice that the HAVING keywo rd phrase co mes after the GROUP BY keywo rd. This syntax
Note o rder is essential.

Renaming Results
We've already talked abo ut renaming tables, co ndensing their names and giving o ur carpal tunneled hands a rest by
sho rtening o ur queries. But did yo u kno w that we can even rename o ur query results? While this wo n't sho rten o ur
queries, it will pro vide o ur result co lumns with mo re intuitive labels.

Fo r instance, co unt (ct .t o pic) do esn't mean much to so meo ne simply lo o king at o ur query results. Perhaps a name
like num be r_o f _t o pics wo uld make mo re sense.
Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select tc.chapter,tc.chapter_name AS Title,count(ct.topic) AS number_of_topics


-> from table_of_contents as tc LEFT OUTER JOIN chapter_topics as ct
-> ON tc.chapter = ct.chapter GROUP BY tc.chapter;
+---------+----------------------------------+------------------+
| chapter | chapter_name | number_of_topics |
+---------+----------------------------------+------------------+
| 1 | The Client Program | 1 |
| 2 | Writing External Programs | 2 |
| 3 | Record Selection | 4 |
| 4 | Working with Strings | 1 |
| 5 | Working with Dates and Times | 2 |
| 6 | Sorting Query Results | 1 |
| 7 | Generating Summaries | 1 |
| 8 | Introduction to MySQL on the Web | 2 |
| 9 | Modifying Tables | 0 |
+---------+----------------------------------+------------------+
9 rows in set (0.00 sec)

mysql>

That co lum n alias no t o nly lo o ks nicer, it will co me in handy when it's time to pro gram in PHP. Plus, aliases can be
used in gro up searches, like this:

Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select tc.chapter,tc.chapter_name AS Title,count(ct.topic) AS number_of_topics


-> from table_of_contents as tc LEFT OUTER JOIN chapter_topics as ct
-> ON tc.chapter = ct.chapter GROUP BY tc.chapter HAVING number_of_topics >= 1;
+---------+----------------------------------+------------------+
| chapter | chapter_name | number_of_topics |
+---------+----------------------------------+------------------+
| 1 | The Client Program | 1 |
| 2 | Writing External Programs | 2 |
| 3 | Record Selection | 4 |
| 4 | Working with Strings | 1 |
| 5 | Working with Dates and Times | 2 |
| 6 | Sorting Query Results | 1 |
| 7 | Generating Summaries | 1 |
| 8 | Introduction to MySQL on the Web | 2 |
+---------+----------------------------------+------------------+
8 rows in set (0.01 sec)

mysql>

And guess what? Co lum n aliase s aren't even limited to gro up co lum ns. Let's have a little fun:
Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select tc.chapter,tc.chapter_name AS Title,count(ct.topic) AS number_of_topics


-> from table_of_contents as tc LEFT OUTER JOIN chapter_topics as ct
-> ON tc.chapter = ct.chapter WHERE tc.chapter_name like ("Working%")
-> GROUP BY tc.chapter HAVING number_of_topics >= 1;
+---------+------------------------------+------------------+
| chapter | Title | number_of_topics |
+---------+------------------------------+------------------+
| 4 | Working with Strings | 1 |
| 5 | Working with Dates and Times | 2 |
+---------+------------------------------+------------------+
2 rows in set (0.00 sec)

mysql>

We co uldn't use the co lum n alias in the WHERE clause. Any ideas why? Hint: it has to do with the o rder
Note in which SQL perfo rms tasks.

Ordering Results
Let's say we want to list o ur bo o k's index, just like we wo uld at the back o f a physical bo o k. Of co urse, an index is
useless unless it's so rted alphabetically.

Let's give it a try:

mysql> select topic, chapter from chapter_topics


-> ORDER BY topic;
+------------------+---------+
| topic | chapter |
+------------------+---------+
| date_format | 5 |
| DBI | 2 |
| DBI | 8 |
| GROUP BY | 7 |
| HTML | 8 |
| LIMIT | 3 |
| ORDER BY | 6 |
| pattern matching | 4 |
| PHP | 2 |
| queries | 1 |
| SELECT | 3 |
| temporary tables | 3 |
| TIMESTAMP | 5 |
| WHERE | 3 |
+------------------+---------+
14 rows in set (0.01 sec)

mysql>

This seems simple eno ugh. When we used the ORDER BY clause o n the t o pic co lumn, the results were
auto matically so rted. SQL's o rdering o f a co lumn depends o n its t ype , so since t o pic is o f a string type, SQL knew to
so rt in alphabetical o rder, rather than numerically o r by date.

Descending Results
And if we wanted to reverse the o rder o f o ur results?
Type the fo llo wing into yo ur MySQL pro mpt:

mysql> select topic, chapter from chapter_topics


-> ORDER BY topic DESC;
+------------------+---------+
| topic | chapter |
+------------------+---------+
| WHERE | 3 |
| TIMESTAMP | 5 |
| temporary tables | 3 |
| SELECT | 3 |
| queries | 1 |
| PHP | 2 |
| pattern matching | 4 |
| ORDER BY | 6 |
| LIMIT | 3 |
| HTML | 8 |
| GROUP BY | 7 |
| DBI | 2 |
| DBI | 8 |
| date_format | 5 |
+------------------+---------+
14 rows in set (0.01 sec)

mysql>

As yo u can see, we can list the results in descending o rder simply by fo llo wing the ORDER BY with the
keywo rd DESC.

Nesting Groups and Orders


The ORDER BY clause can even be used in co njunctio n with GROUP BY. Let's revisit o ur o uter jo in fro m
abo ve:

Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select tc.chapter,tc.chapter_name AS Title,count(ct.topic) AS number_of_t


opics
-> from table_of_contents as tc LEFT OUTER JOIN chapter_topics as ct
-> ON tc.chapter = ct.chapter GROUP BY tc.chapter HAVING number_of_topics >=
1
-> ORDER BY number_of_topics;
+---------+----------------------------------+------------------+
| chapter | chapter_name | number_of_topics |
+---------+----------------------------------+------------------+
| 4 | Working with Strings | 1 |
| 6 | Sorting Query Results | 1 |
| 7 | Generating Summaries | 1 |
| 1 | The Client Program | 1 |
| 5 | Working with Dates and Times | 2 |
| 8 | Introduction to MySQL on the Web | 2 |
| 2 | Writing External Programs | 2 |
| 3 | Record Selection | 4 |
+---------+----------------------------------+------------------+
8 rows in set (0.01 sec)

mysql>

In case yo u haven't no ticed, the way we o rder o ur SQL syntax is really impo rtant! The ORDER
Note BY clause must go after the GROUP BY clause.
As yo u can see, we were able to o rder by the gro up co lumn alias num be r_o f _t o pics. The nesting o f these
two clauses creates numero us po werful po ssibilities in SQL.

In fact, nesting SQL statements, in general, allo ws fo r sco res o f query o ptio ns, while keeping the general
syntax quite simple. Fo r instance, altho ugh we're o rdering by num be r_o f _t o pics abo ve, we might want to
sub-order the chapt e r_nam e co lumn—that is, o rder the chapter names alphabetically within the gro up o f
fo ur entries that has 1 to pic, and so o n.

Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select tc.chapter,tc.chapter_name AS Title,count(ct.topic) AS number_of_t


opics
-> from table_of_contents as tc LEFT OUTER JOIN chapter_topics as ct
-> ON tc.chapter = ct.chapter GROUP BY tc.chapter HAVING number_of_topics >=
1
-> ORDER BY number_of_topics, tc.chapter_name;
+---------+----------------------------------+------------------+
| chapter | chapter_name | number_of_topics |
+---------+----------------------------------+------------------+
| 7 | Generating Summaries | 1 |
| 6 | Sorting Query Results | 1 |
| 1 | The Client Program | 1 |
| 4 | Working with Strings | 1 |
| 8 | Introduction to MySQL on the Web | 2 |
| 5 | Working with Dates and Times | 2 |
| 2 | Writing External Programs | 2 |
| 3 | Record Selection | 4 |
+---------+----------------------------------+------------------+
8 rows in set (0.00 sec)

mysql>

See ho w that wo rks? num be r_o f _t o pics was so rted first, but in the case where this co lumn's value was the
same, SQL sub-so rted the chapt e r_nam e co lumn.

Hey, yo u can also nest GROUP BY co lumns, multiple jo in tables, and WHERE clauses. As
Note yo ur SQL statements beco me mo re co mplex, there's no end to ho w much nesting yo u can do
to refine yo ur results.

Limiting Results
There's o ne mo re majo r way yo u can co ntro l ho w SQL o utputs query results: the LIMIT keywo rd.

INTERACTIVE SESSION:

mysql> select chapter, topic from chapter_topics


-> ORDER BY chapter LIMIT 0, 5;
+---------+---------+
| chapter | topic |
+---------+---------+
| 1 | queries |
| 2 | DBI |
| 2 | PHP |
| 3 | SELECT |
| 3 | WHERE |
+---------+---------+
5 rows in set (0.00 sec)

mysql>

Here, we were able to limit o ur query results to list only the first five ro ws, using the LIMIT keywo rd at the end o f o ur
query. But what do the numbers 0 , 5 signify?

The LIMIT clause can have the fo llo wing fo rmats:

OBSERVE:
LIMIT x[, y]

With two arguments, x represents the desired starting ro w in yo ur results (the o ffset), and y represents the number o f
ro ws to display. This is why LIMIT 0 , 5 listed 5 ro ws, beginning with the first ro w. LIMIT 5, 8 wo uld list 8 ro ws, starting
with the 6 th ro w.

OBSERVE:
LIMIT x

With o ne argument, x represents the number o f resulting ro ws to display. It will return the ro ws starting fro m the first
ro w in the results.

So if we wanted to find the chapter having the mo st to pics?

Type the fo llo wing text at yo ur MySQL pro mpt:

mysql> select tc.chapter,tc.chapter_name AS Title,count(ct.topic) AS number_of_topics


-> from table_of_contents as tc LEFT OUTER JOIN chapter_topics as ct
-> ON tc.chapter = ct.chapter GROUP BY tc.chapter HAVING number_of_topics >= 1
-> ORDER BY number_of_topics DESC, tc.chapter_name LIMIT 0, 1;
+---------+------------------+------------------+
| chapter | chapter_name | number_of_topics |
+---------+------------------+------------------+
| 3 | Record Selection | 4 |
+---------+------------------+------------------+
1 row in set (0.00 sec)

mysql>

Wo w, we've co vered a lo t o f gro und! It's time to start applying o ur new SQL skills. Be sure to practice, and hand in yo ur
assignments. See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Database Programming with PHP

T he PHP/MySQL Relationship
While almo st all pro gramming languages can co nnect to and exchange info rmatio n with an SQL database, PHP has a
special relatio nship with this language—especially thro ugh the MySQLi DBMS (The "i" stands fo r "impro ved"). In fact,
PHP and MySQLi wo rk so well to gether o n Linux Apache systems, the term LAMP Stack has been co ined in the
so ftware develo pment wo rld to describe this impo rtant set o f techno lo gies.

Yo u see, PHP co mes with a MySQLi e xt e nsio n built right into the language, as well as an embedded MySQLi library.
This means that we can simply use built-in PHP functio ns to access o ur SQL databases o n MySQL. Fo r mo re
info rmatio n, check o ut the Wikipedia page o n PHP, o r the PHP manual o n the MySQLi extensio n.

With a go o d grasp o f HTML, PHP, and SQL, yo u can give yo ur website the po wer to utilize SQL databases. Let's get
started!

Connecting to a Database in PHP


We reco mmend creating a fo lder fo r yo ur pro gram files fo r this co urse. In the File Bro wser panel at left, right-click the
Ho m e fo lder and select Ne w f o lde r.... Name the fo lder phpsql1 o r a similar name to describe this co urse.

In additio n to accessing the Unix Terminal and MySQL shell, the Co deRunner Edito r is a multi-purpo se Integrated
Develo pment Enviro nment (IDE) that can be used fo r editing HTML and PHP, alo ng with several o ther languages. To
change the syntax to PHP, click o n the Syntax dro pdo wn menu and select PHP fro m the list o f pro gramming
languages.

No w we can start experimenting with the built-in MySQLi functio ns within PHP. Let's start by co nnecting to o ur
database. Enter the fo llo wing co de in the Co de Edito r area belo w:
CODE TO TYPE:
<?php
$host = "sql.useractive.com"; // This is the server where your database resides
$user = "username"; // This should be your OST username
$pw = "password"; // This should be your OST password
$database = "username"; // Your database name is the same as your OST username

$db = new mysqli($host,$user,$pw,$database)


or die("Cannot connect to MySQL.");

echo "Success! Connected to database ".$database;

$db->close();
?>

Remember, we created yo ur database, and it has the same name as yo ur OST username. Be sure to
Note replace username with yo ur Sandbo x lo gin, and password with yo ur passwo rd.

Save it in the /phpsql1 fo lder as co nne ct .php and click Pre vie w ( ):

Success! Connected to database certjosh

MySQLi functio ns fo llo w the naming co nventio n m ysqli_*(), where the ast e risk represents the functio n
name. The m ysqli_co nne ct () functio n is an exceptio n to this rule. It is a co nstructo r, meaning it is used
to create new o bjects. Co nstructo rs have unique naming co nventio ns, and so this functio n appears as
m ysqli() in o ur co de.

PHP allo ws the MySQLi functio ns to be used with two different syntaxes: o bject-o riented and pro cedural.
Fo r this co urse, we will use the o bject-o riented style, because it is generally mo re po pular amo ng real-
Note wo rld pro grammers. Keep in mind thro ugho ut the lesso ns that the functio n names may be intro duced as
m ysqli_clo se (), but when used in the co de, will appear as $variable->clo se ().

Object-o riented style:


$db->clo se();

Pro cedural style:


mysqli_clo se($db);

Let's take ano ther lo o k at the co de.

OBSERVE:
$db = new mysqli($host,$user,$pw,$database)
or die("Cannot connect to MySQL.");
.
.
.
$db->close();

Here, we use two built-in MySQLi functio ns in PHP. The first, m ysqli_co nne ct () (see PHP.net), is a constructor that
returns a resource called a link identifier to the MySQL server. We sto re this value in the $ db variable, so we can use it
to perfo rm SQL tasks. Because the functio n is a co nstructo r, we use the keywo rd ne w to indicate that we are creating a
new co nnectio n. The m ysqli_co nne ct () functio n is ho w we co nnect to a MySQL server. To use it, we pass in fo ur
parameters: $ ho st , which in o ur case happens to be " sql.use ract ive .co m " ; $ use r, which is o ur OST username;
$ passwo rd, o ur passwo rd; and o f co urse, $ dat abase , the database to which we are co nnecting. Essentially,
m ysqli_co nne ct () perfo rms the exact same functio n as the Linux/Unix co mmand we use to co nnect and the
co mmand we use to select o ur database:
OBSERVE:
cold:~$ mysql -h sql.useractive.com -u yourlogin -p password
mysql> use username;

If the co nnectio n do esn't wo rk fo r any reaso n, the functio n die () simply exits the pro gram with an erro r
Note message. Fo r mo re info rmatio n, see PHP.net.

The seco nd functio n, m ysqli_clo se () (see PHP.net), simply clo ses the co nnectio n to the MySQL server, much as the
SQL e xit co mmand wo uld.

Executing SQL Commands


No w let's try using PHP to retrieve info rmatio n fro m o ur f rie nds table.

CODE TO TYPE:
<?php
$host = "sql.useractive.com"; // This is the server where your database resides
$user = "username"; // This should be your OST username
$pw = "password"; // This should be your OST password
$database = "username"; // Your database name is the same as your OST username

$db = new mysqli($host,$user,$pw,$database)


or die("Cannot connect to MySQL.");

echo "Success! Connected to database ".$database;

$command = "SELECT * FROM friends;";


echo "Command: ".$command."<br>;";

$result = $db->query($command);
echo "Result: ".$result."<br>;";

$db->close();
?>

and to see what happens.

Command: SELECT * FROM friends;


Cat chable f at al error: Object of class mysqli_result could not be converted to string in
/users/cert josh/lesson08.php on line 15

OK, the co mmand lo o ks familiar. But what's with the result? Let's take ano ther lo o k:

OBSERVE:
$result = $db->query($command);
echo "Result: ".$result."<br>;";

As yo u may have already guessed, m ysqli_que ry() perfo rms the query passed in as $ co m m and, just as it wo uld in
the MySQL shell. Ho wever, it do es no t return a text-based table as we wo uld expect. Instead, m ysqli_que ry() returns
a re so urce , much like m ysqli_co nne ct () do es. We've sto red this reso urce in a variable called $ re sult . We tried to
use e cho to print o ut the value o f the reso urce, but it yields the erro r we saw abo ve. Fo rtunately, we can access this
reso urce thro ugh o ther means.
CODE TO TYPE:
<?php
$host = "sql.useractive.com"; // This is the server where your database resides
$user = "username"; // This should be your OST username
$pw = "password"; // This should be your OST password
$database = "username"; // Your database name is the same as your OST username

$db = new mysqli($host,$user,$pw,$database)


or die("Cannot connect to MySQL.");

$command = "SELECT *first_name,last_name FROM friends;";


echo "Command: ".$command."<br>;";

$result = $db->query($command);
echo "Result: ".$result."<br>";

if ($result = $db->query($command)) {
while ($data = $result->fetch_object()) {
echo $data->first_name." ";
echo $data->last_name."<br>;";
}
$result->free();
}

$db->close();
?>

and to see what happens.

Hoyoul Kang
Trish Gray
Kerry Beck
Dessie Coale
Kerry Parmelee

No w, tho se are tangible results! Ho w were we able to co nvert that " Obje ct o f class m ysqli_re sult " into real data?
Take a lo o k:

OBSERVE:
if ($result = $db->query($command)) {
while ($data = $result->fetch_object()) {
echo $data->first_name." ";
echo $data->last_name."<br>;";
}
$result->free();
}

Here we've used o ne mo re built-in functio n, m ysqli_f e t ch_o bje ct () (see PHP.net). This functio n is special in that it
takes in the reso urce we called $ re sult and returns an o bje ct that we call $ dat a. This PHP o bje ct co ntains within it
pro pe rt ie s that co rrespo nd to each ro w's co lumn names—in o ur case, f irst _nam e and last _nam e . We can access
these pro perties thro ugh the o perato r -> to get strings that we can print o ut. After calling m ysqli_f e t ch_o bje ct () o n a
reso urce, when we are finished using the reso urce, we use m ysqli_re sult _f re e () to free the memo ry that was
sto ring it.
We o nly have to free the memo ry if the co mmand was o ne that wo uld have returned a table (SELECT,
SHOW, DESCRIBE, o r EXPLAIN). If entering the co mmand into a MySQL shell wo uld have caused a table
to be printed o ut, then that data is being sto red in the PHP variable when we make the same query fro m
Note PHP. Ho wever, co mmands that perfo rm an actio n witho ut returning anything (INSERT, DELETE, etc.) do
no t sto re values in the variables, so we do n't need to use mysqli_result::free() in tho se instances. Fo r
mo re info rmatio n see the php.net do cumentatio n.

Delimiting Queries
No w let's try using m ysqli_que ry() to insert a new friend into o ur table:

CODE TO TYPE:

<?php
$host = "sql.useractive.com"; // This is the server where your database resides
$user = "username"; // This should be your OST username
$pw = "password"; // This should be your OST password
$database = "username"; // Your database name is the same as your OST username

$db = new mysqli($host,$user,$pw,$database)


or die("Cannot connect to MySQL.");

$new_first_name = "Tim";
$new_last_name = "O'Reilly";
$command = "INSERT INTO friends (first_name, last_name) VALUES ('"
.$new_first_name."','".$new_last_name."');";
$result = $db->query($command);

$command = "SELECT first_name,last_name FROM friends;";


if ($result = $db->query($command)) {
while ($data = $result->fetch_object()) {
echo $data->first_name." ";
echo $data->last_name."<br>;";
}
$result->free();
}

$db->close();
?>

The (f irst _nam e , last _nam e ) co de in the SQL co mmand allo ws us to insert o nly the specified
Note co lumns. The remaining co lumns simply get their default values.

Since an INSERT INT O co mmand do esn't return any ro ws, we do n't need to do anything beyo nd m ysqli_que ry() to
execute the co mmand.

No w and to see o ur new friend:

Hoyoul Kang
Trish Gray
Kerry Beck
Dessie Coale
Kerry Parmelee

Hey, where's o ur new friend? Obvio usly so mething has go ne wro ng. Time to debug:
CODE TO TYPE:
<?php
$host = "sql.useractive.com"; // This is the server where your database resides
$user = "username"; // This should be your OST username
$pw = "password"; // This should be your OST password
$database = "username"; // Your database name is the same as your OST username

$db = new mysqli($host,$user,$pw,$database)


or die("Cannot connect to MySQL.");

$new_first_name = "Tim";
$new_last_name = "O'Reilly";
$command = "INSERT INTO friends (first_name, last_name) VALUES ('"
.$new_first_name."','".$new_last_name."');";

echo "Command = ".$command."<br>;";

$result = $db->query($command);

$command = "SELECT first_name,last_name FROM friends;";


if ($result = $db->query($command)) {
while ($data = $result->fetch_object()) {
echo $data->first_name." ";
echo $data->last_name."<br>;";
}
$result->free();
}

$db->close();
?>

and to find o ut what's go ing o n:

Command = INSERT INTO friends (first_name, last_name) VALUES ('Tim','O'Reilly');


Hoyoul Kang
Trish Gray
Kerry Beck
Dessie Coale
Kerry Parmelee

Hmm. So mething lo o ks fishy with that SQL co mmand. Switch back o ver to yo ur MySQL she ll and type that co de in:

INTERACTIVE SESSION:

mysql> INSERT INTO friends (first_name, last_name) VALUES ('Tim','O'Reilly');


'>

Uh o h, that's no t go o d. MySQL is telling us that we never co mpleted a single quo te ('), and lo o king at o ur co mmand,
we can see why—"O'Reilly" actually co ntains an apo stro phe—a single quo te! We need a way to handle unexpected
quo tes in o ur SQL co mmands so that kind o f thing do esn't happen.
CODE TO TYPE:
<?php
$host = "sql.useractive.com"; // This is the server where your database resides
$user = "username"; // This should be your OST username
$pw = "password"; // This should be your OST password
$database = "username"; // Your database name is the same as your OST username

$db = new mysqli($host,$user,$pw,$database)


or die("Cannot connect to MySQL.");

$new_first_name = "Tim";
$new_last_name = "O'Reilly";
$command = "INSERT INTO friends (first_name, last_name) VALUES ('"
.$new_first_name."','".$new_last_name."');";

$new_first_name = "Tim";
$new_last_name = "O'Reilly";
$command = "INSERT INTO friends (first_name, last_name) VALUES ('"
.$db->real_escape_string($new_first_name)."','".$db->real_escape_string($new_last_name
)."');";

echo "Command = ".$command."<br>;";

$result = $db->query($command);

$command = "SELECT first_name,last_name FROM friends;";


if ($result = $db->query($command)) {
while ($data = $result->fetch_object()) {
echo $data->first_name." ";
echo $data->last_name."<br>;";
}
$result->free();
}

$db->close();
?>

and :

Command = INSERT INTO friends (first_name, last_name) VALUES ('Tim','O\'Reilly');


Hoyoul Kang
Trish Gray
Kerry Beck
Dessie Coale
Kerry Parmelee
Tim O'Reilly

Ah, there's o ur new friend Tim. Ho w did we fix the pro blem? Using the built-in PHP functio n
m ysqli_re al_e scape _st ring() o n o ur input data, we co nverted all the single quo tes(') to backslash single quo tes(\').
Do ing this helps us to avo id erro rs we might o therwise enco unter in the MySQL co mmand line—it's called delimiting.
Any time we insert o r update data o f type string into a table, it makes sense to use m ysqli_re al_e scape _st ring() to
delimit the data as a precautio n.

In the next few lesso ns, we'll see ho w to use mo re SQL statements to make web-based applicatio ns in PHP.

Be sure to hand in yo ur assignments; see yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Project Address/Phone Book, Part 1

Project Description
No w that we've go ne o ver the basics o f the PHP MySQL extensio n, we'll make an o nline web-based address/pho ne
bo o k. With an address bo o k o n yo ur website, yo u can access yo ur pho ne numbers and addresses anywhere in the
wo rld so lo ng as yo u have Internet access. We'll also make an HTML fo rm so that yo u o r yo ur friends can go o nline
and enter info rmatio n into the address bo o k.

We will co nstruct an HTML fo rm o n a page named adde nt ry.ht m l which submits data to a PHP pro gram called
adde nt ry.php. The adde nt ry.php pro gram will in turn sto re the data into the MySQL database, as lo ng as the data is
valid. Next, we'll make vie wbo o k.php, which will retrieve MySQL database entries and display the data we've sto red,
allo wing us to view o ur address bo o k. Here is a general diagram to help yo u visualize ho w it will wo rk:

Procedure

Int eract ion 1

Int eract ion 2

Int eract ion 3

Int eract ion 4

Int eract ion 5

T able Layout
Befo re we jump into making the HTML fo rms and PHP pro grams, we'll need a standard database layo ut/descriptio n.
What kind o f data wo uld yo u ho ld in an address/pho ne bo o k? This is where many database designs go awry. Mo re
o ften than no t, a go o d database is the result o f lo t o f go o d database design and relatively little actual pro gramming.
Let's take a lo o k at o ur addre ssbo o k table design.

Dat a Nam e Dat a T ype


id int unsigned NOT NULL auto _increment
first_name varchar(20 )
last_name varchar(20 )
pho ne varchar(15)
address varchar(10 0 )
city varchar(20 )
state char(2)
zipco de int(5) unsigned
birthday date

T able Creation
With the data names and types in mind, let's create a table in yo ur MySQL shell and name it addre ssbo o k.

Type the fo llo wing co mmands at yo ur MySQL pro mpt:

mysql> create table addressbook (id int unsigned NOT NULL auto_increment,
-> first_name varchar(20), last_name varchar(20), phone varchar(15),
-> address varchar(100), city varchar(20), state char(2),
-> zipcode int(5) unsigned, birthday date, primary key(id));
Query OK, 0 rows affected (0.00 sec)

mysql> describe addressbook;>


+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| first_name | varchar(20) | YES | | NULL | |
| last_name | varchar(20) | YES | | NULL | |
| phone | varchar(15) | YES | | NULL | |
| address | varchar(100) | YES | | NULL | |
| city | varchar(20) | YES | | NULL | |
| state | char(2) | YES | | NULL | |
| zipcode | int(5) unsigned | YES | | NULL | |
| birthday | date | YES | | NULL | |
+------------+------------------+------+-----+---------+----------------+
9 rows in set (0.00 sec)

The pho ne number was set as varchar(15 ) instead o f int (15 ) fo r two reaso ns: First, by do ing this, peo ple are able to
enter dashes and parentheses in the fo rm, bo th o f which wo uld be unacceptable fo r an integer data type in SQL.
Seco nd, by using varchar instead o f int , peo ple who have pho ne numbers that use text to allo w easy memo rizatio n
like "1-8 0 0 -CONTACT" will be able to enter them as well.

Once yo u're do ne setting up the table, yo u're do ne with this leg o f o ur pro ject. As always, be sure to hand in yo ur assignments!
See yo u in the next lesso n.

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Project Address/Phone Book, Part 2

Starting with the HT ML Form


Befo re we get started o n this lesso n, be sure yo u've made the addre ssbo o k table in the last lesso n.

No w we can get started o n the PHP pro gramming part o f the pro ject. Our PHP script needs to allo w web users to enter
data into the addre ssbo o k table that we just set up. But first, we'll need an HTML fo rm to pro vide inputs fo r the PHP
script to pro cess and sto re.

Set the Co deRunner Edito r syntax to HT ML. We'll be creating bo th HT ML and PHP files fo r this pro ject.

Type the fo llo wing co de, with the syntax set to HTML:
<html>
<head><title>This the Address Book Form</title></head>
<body>
<h1>Welcome to my address book!</h1>
<form action="addentry.php" method="POST">

First Name: <input type="text" name="first_name" size="20"><br>


Last Name: <input type="text" name="last_name" size="20"><br>
Phone Number: <input type="text" name="phone" size="15"><br>
Address: <input type="text" name="address" size="20"><br>
City: <input type="text" name="city" size="20"><br>
State: <input type="text" name="state" size="2"><br>
Zip Code: <input type="text" name="zipcode" size="5"><br>
Birthday (MM-DD-YYYY):
<input type="text" name="month" size="2">-
<input type="text" name="day" size="2">-
<input type="text" name="year" size="4"><br>
<input type="submit" value="Submit">

</form>
</body>
</html>

Save it in yo ur /phpsql1 fo lder as adde nt ry.ht m l, and click :

Welcome to my address book!


First Name:
Last Name:
Phone Number:
Address:
City:
State:
Zip Code:
Birthday (MM-DD-YYYY): - -

Submit
No tice that the entry fields match the co lumns we created fo r o ur addre ssbo o k table in SQL. Setting up the elements
o f o ur fo rms and tables to co rrespo nd with each o ther makes it easier to dro p the info rmatio n we want into o ur
database.
Storing the Data into SQL through PHP
No w that we have o ur HTML fo rm ready to submit o ur data, let's wo rk o n the PHP script that will put the data into the
MySQL database fo r us.

We'll o rganize the PHP script into several sub-co mpo nents, breaking the pro gram do wn into the fo llo wing:

A f unct io ns area
A use r variable s sectio n
A m ain pro gram bo dy

The main reaso n we divide the script into these sectio ns is to make it easier fo r o thers to edit, read, and ultimately,
reuse o ur co de.

Start a new file and switch the Co deRunner Edito r syntax to PHP.
Type the fo llo wing blue text, with the syntax set to PHP:

<?php

#----------------------#
# Functions #
#----------------------#

function check_input ($form_array) {


if ($form_array['first_name'] && $form_array['last_name'] &&
$form_array['phone'] && $form_array['address'] &&
$form_array['city'] && $form_array['state'] &&
$form_array['zipcode'] && $form_array['month'] &&
$form_array['day'] && $form_array['year']) {
return 1;
}
else return 0;
}
function get_birthday ($form_array) {
$birthday = $form_array['year']."-".$form_array['month']."-".$form_array['day'];
return $birthday;
}

#----------------------#
# User Variables #
#----------------------#

$host = "sql.useractive.com"; // This is the server where your database resides


$user = "username"; // This should be your OST username
$pw = "password"; // This should be your OST password
$database = "yourlogin"; // Your database is the same as your OST username
$table_name = "addressbook";

#----------------------#
# Main Body #
#----------------------#

if (check_input($_POST)) {

$birthday = get_birthday($_POST);
$db = new mysqli($host,$user,$pw,$database)
or die("Cannot connect to MySQL.");

$command = "insert into $table_name


values('','".$db->real_escape_string($_POST['first_name'])."',

'".$db->real_escape_string($_POST['last_name'])."',
'".$db->real_escape_string($_POST['phone'])."',
'".$db->real_escape_string($_POST['address'])."',
'".$db->real_escape_string($_POST['city'])."',
'".$db->real_escape_string($_POST['state'])."',
'".$db->real_escape_string($_POST['zipcode'])."',
'".$db->real_escape_string($birthday)."');";
$result = $db->query($command);

print "Data was successfully entered.<br>";


$db->close();
}
else { print "Data was NOT entered due to errors.<br>"; }

?>

<a href="/viewbook.php">View my address book</a>


Save it in yo ur /phpsql1 fo lder as adde nt ry.php.

In the preview o f yo ur adde nt ry.ht m l page, start entering data. Submit the fo rm. Yo u sho uld see a respo nse letting
yo u kno w whether the data was successfully entered into the database.

Fo r instance, if yo u entered the fo llo wing into yo ur fo rm:

Welcome to my address book!


First Name: Trish
Last Name: Gray
Phone Number: 555-555-5555
Address: 555 5th Street
City: Fiveville
State: CA
Zip Code: 55555
Birthday (MM-DD-YYYY): 05 - 05 - 1955

Submit

Data was successfully entered.


View my address book

No w, if yo u check yo ur SQL addre ssbo o k table, yo u sho uld get so mething like this:

INTERACTIVE SESSION:

mysql> select * from addressbook;


+----+------------+-----------+--------------+----------------+-----------+-------+----
-----+------------+
| id | first_name | last_name | phone | address | city | state | zip
code | birthday |
+----+------------+-----------+--------------+----------------+-----------+-------+----
-----+------------+
| 1 | Trish | Gray | 555-555-5555 | 555 5th Street | Fiveville | CA | 5
5555 | 1955-05-05 |
+----+------------+-----------+--------------+----------------+-----------+-------+----
-----+------------+
1 row in set (0.00 sec)

Breaking Down addentry.php


Let's lo o k mo re clo sely at the script. First, let's study the new functio ns we've defined (che ck_input () and
ge t _birt hday()). After that, we'll go o ver the main bo dy.

The first functio n, che ck_input (), lo o ks like this:


OBSERVE:
function check_input ($form_array) {
if ($form_array['first_name'] && $form_array['last_name'] &&
$form_array['phone'] && $form_array['address'] &&
$form_array['city'] && $form_array['state'] &&
$form_array['zipcode'] && $form_array['month'] &&
$form_array['day'] && $form_array['year']) {
return 1;
}
else return 0;
}

The che ck_input () functio n checks to see whether the user filled o ut the fo rm co mpletely. It takes in the parameter
$ f o rm _array, which is assumed to be a superglobal like $ _POST . If any o f the fo rm fields are left blank, the if
statement in the che ck_input () functio n wo uld return "false", causing the functio n to re t urn a ze ro . Ho wever, if all
the fo rm fields have been co mpleted, it re t urns a value o f 1.

Note Remember that in PHP a zero o r NULL is false in a co nditio nal statement, and anything else is true.

The o ther functio n we've defined is ge t _birt hday():

OBSERVE:
function get_birthday ($form_array) {
$birthday = $form_array['year']."-".$form_array['month']."-".$form_array['day'];
return $birthday;
}

Since the dates must be in the fo rmat YYYY-MM-DD (Year-Mo nth-Day), the ge t _birt hday functio n reads the date
fro m the fo rm fields (again, passed into the parameter $ f o rm _array), assembles them to gether into a variable named
$ birt hday, and returns it.

No w let's talk abo ut the main mo dy o f the pro gram. Here it is again:

OBSERVE:
if (check_input($_POST)) {

$birthday = get_birthday($_POST);
$db = new mysqli($host,$user,$pw,$database)
or die("Cannot connect to MySQL.");

$command = "insert into $table_name


values('','".$db->real_escape_string($_POST['first_name'])."',

'".$db->real_escape_string($_POST['last_name'])."',
'".$db->real_escape_string($_POST['phone'])."',
'".$db->real_escape_string($_POST['address'])."',
'".$db->real_escape_string($_POST['city'])."',
'".$db->real_escape_string($_POST['state'])."',
'".$db->real_escape_string($_POST['zipcode'])."',
'".$db->real_escape_string($birthday)."');";
$result = $db->query($command);

print "Data was successfully entered\n";


$db->close();
}
else { print "Data was NOT entered due to errors.\n"; }

The argument o f the if statement calls the che ck_input () functio n, which will return t rue if the user has filled
everything in o r f alse if she has no t filled in everything. If che ck_input () returns true, we run the m ysqli_co nne ct ()
functio n to initialize o ur database co nnectio n as befo re. Then we run the m ysqli_que ry() functio n to execute the SQL
statement sto red in the variable $ co m m and. We use the m ysqli_re al_e scape _st ring() functio n to delimit each o f
the fo rm inputs, so that no thing unexpected happens to cause an SQL erro r.

No w that we're able to enter data into o ur addressbo o k fro m the web, it wo uld be nice to be able to read the things we've put
into it. In the next lesso n, we'll learn to make vie wbo o k.php, which we'll use to read elements o f o ur database.

Keep up the great wo rk! Hand in yo ur assignments, and see yo u in the next lesso n.

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Project Address/Phone Book, Part 3

Construction of viewbook.php
We're already halfway do ne with o ur address/pho ne bo o k. The next part will be easier no w that yo u've made
adde nt ry.php. So , what sho uld vie wbo o k.php do ? Let's keep it simple and have it list all the entries that are sto red
in the addre ssbo o k table.

To get started, create a new file in the Co deRunner Edito r with the syntax set to PHP. Be sure yo u have saved
adde nt ry.php fro m the last lesso n befo re yo u go o n!

Type the fo llo wing co de with the syntax set to PHP:


<?php

#----------------------#
# User Variables #
#----------------------#

$host = "sql.useractive.com"; // This is the server where your database resides


$user = "username"; // This should be your OST username
$pw = "password"; // This should be your OST password
$database = "yourlogin"; // Your database is the same as your OST username
table_name = "addressbook";

#----------------------#
# Main Body #
#----------------------#

$db = new mysqli($host,$user,$pw,$database)


or die("Cannot connect to MySQL.");

?>;

<h1>;My Address Book</h1>;


<TABLE BORDER="1">;
<TR>;<TD>;Name</TD>;<TD>;Phone Number</TD>;
<TD>;Address</TD>;<TD>;Birthday</TD>;</TR>;

<?
$command = "select * from ".$table_name;
$result = $db->query($command);
while ($data = $result->fetch_object()) {
print "<TR>;<TD>;".$data->last_name.",". $data->first_name."</TD>;<TD>;".$data->pho
ne."</TD>;";
print "<TD>;".$data->address."<BR>;".$data->city.",". $data->state."<BR>;".$data->z
ipcode."</TD>;";
print "<TD>;".$data->birthday."</TD>;</TR>;\n";
}
$result->free();
$db->close;

?>;
</TABLE>;
<br>;
<a href="/addentry.html">;Add a new entry</a>;

Save it in yo ur /phpsql1 directo ry as vie wbo o k.php. No w click , o r call up vie wbo o k.php directly in the web
bro wser, to make sure it wo rks:
Name Phone Number Address Birthday
555 5th Street
Gray,Trish 555-555-5555 Fiveville,CA 1955-05-05
55555
1500 Licoln
Kang, Hoyoul 555-278-0512 Urbana, IL 1979-05-20
61801
P.O.Box 153
John's, Eat at 555-123-4567 Urbana, IL 0000-00-00
61801
Add a new entry
The o nly new thing within this co de is the while lo o p we used to display the SQL data, fetched by the
m ysql_f e t ch_o bje ct () functio n. Let's take a clo ser lo o k at the details:

OBSERVE:

$command = "select * from ".$table_name;


$result = $db->query($command);
while ($data = $result->fetch_object()) {
print "<TR>;<TD>;".$data->last_name.",". $data->first_name."</TD>;<TD>;".$data->pho
ne."</TD>;";
print "<TD>;".$data->address."<BR>;".$data->city.",". $data->state."<BR>;".$data->z
ipcode."</TD>;";
print "<TD>;".$data->birthday."</TD>;</TR>;\n";
}

Once the m ysql_f e t ch_o bje ct () functio n fetches a ro w fro m the $ re sult reso urce, it auto matically mo ves to the
next ro w, and the next, until it finally hits NULL. This is why we're able to use the while lo o p witho ut causing an infinite
lo o p. Pretty handy fo r tasks like these, huh?

Co ngratulatio ns, o ur pro ject is finally co mplete! See yo u in the next lesso n.

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Advanced SQL Syntax, Part 1

Date and T ime Functions


We'll co ver these functio ns in this lesso n:

Dat e Funct io ns T im e Funct io ns


DAYOFWEEK(date) CURRENT_TIME()
WEEKDAY(date) HOUR(time)
DAYOFMONTH(date) MINUTE(time)
DAYOFYEAR(date) SECOND(time)
YEAR(date) TIME_TO_SEC(time)
MONTH(date) SEC_TO_TIME(sec)
DAYNAME(date) TIME_FORMAT(time,fo rmat)
MONTHNAME(date)
QUARTER(date)
WEEK(date) Dat e - and T im e -Re lat e d Funct io ns
WEEK(date,weekday) NOW()
TO_DAYS(date) SYSDATE()
FROM_DAYS(x) CURRENT_TIMESTAMP
CURDATE() UNIX_TIMESTAMP()
CURRENT_DATE UNIX_TIMESTAMP(date)
PERIOD_ADD(perio d,x) FROM_UNIXTIME(unix_timestamp)
PERIOD_DIFF(perio d1,perio d2) FROM_UNIXTIME(unix_timestamp,fo rmat)
DATEDIFF(date1,date2)
DATE_FORMAT(date,fo rmat)
Dat e /T im e Mat he m at ical Funct io ns
DATE_ADD(date/time,INTERVAL expr type)
ADDDATE(date/time,INTERVAL expr type)
DATE_SUB(date/time,INTERVAL expr type)
SUBDATE(date/time,INTERVAL expr type)
EXTRACT(expr type FROM date/time)

We'll explain each o f these functio ns in detail, with examples o f its usage, in this lesso n. We'll explain the parameters
o f the functio ns and the o utput as well.

DAYOFWEEK(date)
This functio n returns the weekday o f the particular date in integers that co nfo rm with the ODBC standards. 1 =
Sunday, 2 = Mo nday, 3 = Tuesday, etc.
INTERACTIVE SESSION:

mysql> select dayofweek('2019-11-02');


+-------------------------+
| dayofweek('2019-11-02') |
+-------------------------+
| 7 |
+-------------------------+

WEEKDAY(date)
This functio n returns the weekday o f the particular date in integers. 6 = Sunday, 0 = Mo nday, 1 = Tuesday, etc.

INTERACTIVE SESSION:

mysql> select weekday('2019-11-02');


+-----------------------+
| weekday('2019-11-02') |
+-----------------------+
| 5 |
+-----------------------+

DAYOFMONT H(date)
Returns the day o f the mo nth o f the dat e parameter as an integer.

INTERACTIVE SESSION:

mysql> select dayofmonth('2019-11-02');


+--------------------------+
| dayofmonth('2019-11-02') |
+--------------------------+
| 2 |
+--------------------------+

DAYOFYEAR(date)
Returns the day o f the year o f the dat e parameter, ranging fro m 1 to 36 6 .

INTERACTIVE SESSION:

mysql> select dayofyear('2019-11-02');


+-------------------------+
| dayofyear('2019-11-02') |
+-------------------------+
| 306 |
+-------------------------+

YEAR(date)
Returns the year o f the dat e parameter as an integer between 10 0 0 and 9 9 9 9 .
INTERACTIVE SESSION:

mysql> select year('2019-11-02'), year('2019-09-09');


+--------------------+-------------------+
| year('2019-11-02') | year('2019-09-09')|
+--------------------+-------------------+
| 2019 | 2019 |
+--------------------+-------------------+

MONT H(date)
Returns the mo nth o f the dat e parameter as an integer between 1 and 12.

INTERACTIVE SESSION:

mysql> select month('2019-11-02'), month('2019-09-09');


+---------------------+--------------------+
| month('2019-11-02') | month('2019-09-09')|
+---------------------+--------------------+
| 11 | 9 |
+---------------------+--------------------+

DAYNAME(date)
This functio n resembles the weekday() functio n, except that instead o f returning an integer between 0 and 6 , it
returns a text string describing the day, like "Mo nday."

INTERACTIVE SESSION:

mysql> select dayname('2019-11-02');


+-----------------------+
| dayname('2019-11-02') |
+-----------------------+
| Saturday |
+-----------------------+

MONT HNAME(date)
Returns the mo nth name o f the dat e parameter as a string between "January" and "December."

INTERACTIVE SESSION:

mysql> select monthname('2019-11-02');


+-------------------------+
| monthname('2019-11-02') |
+-------------------------+
| November |
+-------------------------+

QUART ER(date)
Returns the quarter (as an integer) o f the year o f the dat e parameter between 1 and 4.
INTERACTIVE SESSION:

mysql> select quarter('2019-11-02');


+-----------------------+
| quarter('2019-11-02') |
+-----------------------+
| 4 |
+-----------------------+

WEEK(date)
Returns the week number o f the year o f the dat e parameter, with Sunday as the first day o f the week. Fo r
example, January 1 falls o n the first week o f the year, and December 31 falls o n the 52nd week.

INTERACTIVE SESSION:

mysql> select week('2019-11-02');


+--------------------+
| week('2019-11-02') |
+--------------------+
| 44 |
+--------------------+

WEEK(date,weekday)
In this functio n, we e kday can be either a 1 o r a 0 . This is identical to the week() functio n. This functio n returns
the week number o f the year o f the dat e parameter with Sunday as the first day o f the week if we e kday is 0 ,
and Mo nday as the first day o f the week if we e kday is 1.

INTERACTIVE SESSION:

mysql> select week('2019-10-31',0), week('2019-10-31',1);


+----------------------+----------------------+
| week('2019-10-31',0) | week('2019-10-31',1) |
+----------------------+----------------------+
| 43 | 44 |
+----------------------+----------------------+

T O_DAYS(date)
Co nverts the date to number o f days as an integer.

INTERACTIVE SESSION:

mysql> select to_days('2019-10-31');


+-----------------------+
| to_days('2019-10-31') |
+-----------------------+
| 737728 |
+-----------------------+

FROM_DAYS(x)
This functio n is co mplementary to the to _days() functio n. Co nverts the integer x to a date.
INTERACTIVE SESSION:

mysql> select from_days(737728);


+-------------------+
| from_days(737728) |
+-------------------+
| 2019-10-31 |
+-------------------+

CURDAT E(), CURRENT _DAT E


Bo th these functio ns return the current date in the standard SQL fo rmat o f YYYY-MM-DD. No tice that the latter
functio n do es no t have parentheses.

INTERACTIVE SESSION:

mysql> select curdate(), current_date;


+------------+--------------+
| curdate() | current_date |
+------------+--------------+
| 2014-11-03 | 2014-11-03 |
+------------+--------------+

PERIOD_ADD(period,x)
Adds x mo nths to perio d and returns the result in the fo rmat o f YYYYMM. The pe rio d parameter can be in the
fo rmat o f YYYYMM o r YYMM.

INTERACTIVE SESSION:

mysql> select period_add(1911,2), period_add(201911,2);


+--------------------+----------------------+
| period_add(1911,2) | period_add(201911,2) |
+--------------------+----------------------+
| 202001 | 202001 |
+--------------------+----------------------+

PERIOD_DIFF(period1,period2)
Returns the difference between the two perio ds (perio d1 and perio d2 in either YYYYMM o r YYMM fo rmat) as a
number o f mo nths.

INTERACTIVE SESSION:

mysql> select period_diff(201911,1901);


+--------------------------+
| period_diff(201911,1901) |
+--------------------------+
| 10 |
+--------------------------+

DAT EDIFF(date1,date2)
Returns the number o f days between date1 and date2. date1 and date2 may be either date o r date-and-time
expressio ns, including no w().
INTERACTIVE SESSION:

mysql> select datediff('2019-01-17','2018-12-20');


+-------------------------------------+
| datediff('2019-01-17','2018-12-20') |
+-------------------------------------+
| 28 |
+-------------------------------------+

DAT E_FORMAT (date,format)


Fo rmats the date as specified by the f o rm at parameter. Here is a list o f fo rmat items yo u can use in yo ur
fo rmat string (info fro m mysql.co m):

Fo rmat Items:

%M - month name (January..December)


%W - weekday name (Sunday..Saturday)
%D - day of the month with suffix (1st, 2nd, 3rd, etc.)
%Y - year, numeric, 4 digits
%y - year, numeric, 2 digits
%a - abbreviated weekday name (Sun..Sat)
%d - day of the month, numeric (00..31)
%e - day of the month, numeric (0..31)
%m - month, numeric (01..12)
%c - month, numeric (1..12)
%b - abbreviated month name (Jan..Dec)
%j - day of year (001..366)
%H - hour (00..23)
%k - hour (0..23)
%h - hour (01..12)
%I - hour (01..12)
%l - hour (1..12)
%i - minutes, numeric (00..59)
%r - time, 12-hour (hh:mm:ss [AP]M)
%T - time, 24-hour (hh:mm:ss)
%S - seconds (00..59)
%s - seconds (00..59)
%p - AM or PM
%w - day of the week (0=Sunday..6=Saturday)
%U - week (0..52), where Sunday is the first day of the week
%u - week (0..52), where Monday is the first day of the week
%% - the % symbol
All other characters are just copied to the result without interpretation.

INTERACTIVE SESSION:

mysql> select date_format(now(), '%W, %m/%d/%Y - %h:%i %p CST') as formatted_dat


e;
+-------------------------------------+
| formatted_date |
+-------------------------------------+
| Monday, 11/03/2014 - 04:27 PM CST |
+-------------------------------------+

Date/T ime Mathematical Functions


The next fo ur functio ns require date/time as well an interval parameters.
List o f fo rmats:
Type Value Definition Expected Expression Format
SECOND Seconds SECONDS
MINUTE Minutes MINUTES
HOUR Hours HOURS
DAY Days DAYS
MONTH Months MONTHS
YEAR Years YEARS
MINUTE_SECOND Minutes and seconds MINUTES:SECONDS
HOUR_MINUTE Hours and minutes HOURS:MINUTES
DAY_HOUR Days and hours DAYS HOURS
YEAR_MONTH Years and months YEARS-MONTHS
HOUR_SECOND Hours, minutes, HOURS:MINUTES:SECONDS
DAY_MINUTE Days, hours, minutes DAYS HOURS:MINUTES
DAY_SECOND Days, hours, minutes, seconds DAYS HOURS:MINUTES:SECONDS

Typing a negative sign (-) in fro nt o f expressio n numbers causes Date_Add functio ns to subtract and
Note Date_Sub functio ns to add. (Table info fro m mysql.co m.)

DAT E_ADD(date/time,INT ERVAL expr type),


ADDDAT E(date/time,INT ERVAL expr type)
Adds the time interval expressio n to the dat e /t im e parameter and returns it.

INTERACTIVE SESSION:

mysql> select date_add('2019-10-31 02:44:10', interval '5 10:03' day_minute);


+----------------------------------------------------------------+
| date_add('2019-10-31 02:44:10', interval '5 10:03' day_minute) |
+----------------------------------------------------------------+
| 2019-11-05 12:47:10 |
+----------------------------------------------------------------+

mysql> select adddate('2019-10-31 02:44:10', interval '5 10:03' day_minute);


+---------------------------------------------------------------+
| adddate('2019-10-31 02:44:10', interval '5 10:03' day_minute) |
+---------------------------------------------------------------+
| 2019-11-05 12:47:10 |
+---------------------------------------------------------------+

DAT E_SUB(date/time,INT ERVAL expr type), SUBDAT E(date/time,INT ERVAL


expr type)
Subtracts the time interval expressio n fro m the dat e /t im e parameter and returns it.
INTERACTIVE SESSION:

mysql> select date_sub('1999-10-31 02:44:10', interval '5 -10:03' day_minute);


+-----------------------------------------------------------------+
| date_sub('1999-10-31 02:44:10', interval '5 -10:03' day_minute) |
+-----------------------------------------------------------------+
| 1999-10-25 16:41:10 |
+-----------------------------------------------------------------+

mysql> select subdate('1999-10-31 02:44:10', interval '5 -10:03' day_minute);


+----------------------------------------------------------------+
| subdate('1999-10-31 02:44:10', interval '5 -10:03' day_minute) |
+----------------------------------------------------------------+
| 1999-10-25 16:41:10 |
+----------------------------------------------------------------+

EXT RACT (expr type FROM date/time


Returns a po rtio n o f the date/time.

INTERACTIVE SESSION:

mysql> select extract(year from '2019-03-31');


+---------------------------------+
| extract(year from '2019-03-31') |
+---------------------------------+
| 2019 |
+---------------------------------+
mysql> select extract(day_hour FROM '2019-03-31 07:04:11');
+----------------------------------------------+
| extract(day_hour from '2019-03-31 07:04:11') |
+----------------------------------------------+
| 3107 |
+----------------------------------------------+

CURRENT _T IME()
Returns the current time in the fo rmat 'HH:MM:SS' as a string.

INTERACTIVE SESSION:

mysql> select current_time();


+----------------+
| current_time() |
+----------------+
| 15:02:50 |
+----------------+

HOUR(time)
Returns the ho ur o f the t im e parameter.
INTERACTIVE SESSION:

mysql> select hour('15:02:50');


+------------------+
| hour('15:02:50') |
+------------------+
| 15 |
+------------------+

MINUT E(time)
Returns the minutes o f the t im e parameter.

INTERACTIVE SESSION:

mysql> select minute('15:02:50');


+--------------------+
| minute('15:02:50') |
+--------------------+
| 2 |
+--------------------+

SECOND(time)
Returns the seco nds o f the t im e parameter.

INTERACTIVE SESSION:

mysql> select second('15:02:50');


+--------------------+
| second('15:02:50') |
+--------------------+
| 50 |
+--------------------+

T IME_T O_SEC(time)
Co nverts the time into seco nds since midnight (0 0 :0 0 :0 0 ).

INTERACTIVE SESSION:

mysql> select time_to_sec('15:02:50');


+-------------------------+
| time_to_sec('15:02:50') |
+-------------------------+
| 54170 |
+-------------------------+

SEC_T O_T IME(sec)


Co nverts the seco nds(since midnight) back to time.
INTERACTIVE SESSION:

mysql> select sec_to_time(54170);


+--------------------+
| sec_to_time(54170) |
+--------------------+
| 15:02:50 |
+--------------------+

T IME_FORMAT (time,format)
Identical to Date_Fo rmat except that o nly the ho ur, minute, and seco nds specifiers in the f o rm at parameter
will wo rk. Otherwise a NULL is returned.

INTERACTIVE SESSION:

mysql> select time_format('15:32:33', '%h:%i %p');


+-------------------------------------+
| time_format('15:32:33', '%h:%i %p') |
+-------------------------------------+
| 03:32 PM |
+-------------------------------------+

NOW(), SYSDAT E(), CURRENT _T IMEST AMP()


Returns the current date and time in fo rmat 'YYYY-MM-DD HH:MM:SS' if used in the co ntext o f string. If it is
used in the co ntext o f an integer, this fo rmat is returned: YYYYMMDDHHMMSS.

INTERACTIVE SESSION:

mysql> select now(), sysdate() + '0', current_timestamp();


+---------------------+-----------------+---------------------+
| now() | sysdate() + '0' | current_timestamp() |
+---------------------+-----------------+---------------------+
| 2014-11-03 16:42:48 | 20141103164248 | 2014-11-03 16:42:48 |
+---------------------+-----------------+---------------------+

UNIX_T IMEST AMP(), UNIX_T IMEST AMP(date)


Returns the Unix timestamp. If a dat e parameter is pro vided, that date is returned as a Unix timestamp.

INTERACTIVE SESSION:

mysql> select unix_timestamp(), unix_timestamp(now());


+------------------+-----------------------+
| unix_timestamp() | unix_timestamp(now()) |
+------------------+-----------------------+
| 1415054660 | 1415054660 |
+------------------+-----------------------+

FROM_UNIXT IME(unix_timestamp), FROM_UNIXT IME(unix_timestamp,


format)
Co nverts the unix_timestamp back to no rmal time fo rmat 'YYYY-MM-DD HH:MM:SS' o r
YYYYMMDDHHMMSS. If a fo rmat was specified (using specifiers mentio ned in DATE_FORMAT), the
date/time is returned in that fo rmat.
INTERACTIVE SESSION:

mysql> select from_unixtime(unix_timestamp()), from_unixtime('1415054660');


+---------------------------------+-----------------------------+
| from_unixtime(unix_timestamp()) | from_unixtime('1415054660') |
+---------------------------------+-----------------------------+
| 2014-11-03 16:46:12 | 2014-11-03 16:44:20 |
+---------------------------------+-----------------------------+

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Advanced SQL Syntax, Part 2

Math Functions
We'll explain each o f these functio ns in detail with samples o f its usage, and we'll explain the parameters and o utput o f
the functio ns. Yo u sho uld explo re each o f them o n yo ur o wn in o rder to fully understand them.

Yo u can use this lesso n as a reference. We'll co ver these functio ns in this lesso n (x and y are numbers (int o r flo at)):

Ge ne ral Funct io ns Ro unding Funct io ns


MOD(x,y) TRUNCATE(x,y)
ABS(x) FLOOR(x)
SIGN(x) CEILING(x)
LEAST(x,y,...) ROUND(x)
GREATEST(x,y,...) ROUND(x,y)

Wave Funct io ns Expo ne nt ial Funct io ns


SIN(x) EXP(x)
COS(x) LOG(x)
TAN(x) LOG10 (x)
ASIN(x) SQRT(x)
ACOS(x) POW(x,y)
ATAN(x) POWER(x,y)
ATAN2(x,y) COT(x)
PI() DEGREES(x)
RADIANS(x)

MOD(x,y)
Returns the remainder o f x divided by y. The return is an integer. If bo th parameters are o f the flo ating type, the
remainder o f the divisio n will be ro unded to the nearest integer.

INTERACTIVE SESSION:

mysql> select mod(10.5,6), mod(10.45,6);


+-------------+--------------+
| mod(10.5,6) | mod(10.45,6) |
+-------------+--------------+
| 4.5 | 4.45 |
+-------------+--------------+
1 row in set (0.00 sec)

ABS(x)
Returns the abso lute value o f x.
INTERACTIVE SESSION:

mysql> select abs(-7), abs(7), abs(-3.45);


+---------+--------+------------+
| abs(-7) | abs(7) | abs(-3.45) |
+---------+--------+------------+
| 7 | 7 | 3.45 |
+---------+--------+------------+

SIGN(x)
Returns o ne o f o nly three kinds o f returns: If x is a negative number, returns -1. If x is po sitive, returns 1. If x is
ze ro , returns ze ro .

INTERACTIVE SESSION:

mysql> select sign(-5.3), sign(0.0), sign(3.4);


+------------+-----------+-----------+
| sign(-5.3) | sign(0.0) | sign(3.4) |
+------------+-----------+-----------+
| -1 | 0 | 1 |
+------------+-----------+-----------+

LEAST (x,y,...)
Requires at least two parameters. This functio n searches the list o f entries and returns the smallest value
within the list. This includes strings as well—fo r characters and strings, lo wercase letters have a higher value
than uppercase letters.

INTERACTIVE SESSION:

mysql> select least(1, 9.2, -1.4), least('A','a','B','b','C','c');


+---------------------+--------------------------------+
| least(1, 9.2, -1.4) | least('A','a','B','b','C','c') |
+---------------------+--------------------------------+
| -1.4 | A |
+---------------------+--------------------------------+

GREAT EST (x,y,...)


Requires at least two parameters. This functio n searches the list o f entries and returns the largest value within
the list. This includes strings as well—fo r characters and strings, uppercase letters have a higher value than
lo wercase letters.

INTERACTIVE SESSION:

mysql> select greatest(1, 9.2, -1.4), greatest('A','a','B','b','C','c');


+------------------------+-----------------------------------+
| greatest(1, 9.2, -1.4) | greatest('A','a','B','b','C','c') |
+------------------------+-----------------------------------+
| 9.2 | C |
+------------------------+-----------------------------------+

T RUNCAT E(x,y)
Cho ps o ff the decimal numbers that co me after the yth decimal and returns the result. Ho wever, the yth
decimal is ro unded do wn if the x value is negative.
INTERACTIVE SESSION:

mysql> select truncate(1.123, 2), truncate(5.345,1), truncate(-5.345,1);


+--------------------+-------------------+--------------------+
| truncate(1.123, 2) | truncate(5.345,1) | truncate(-5.345,1) |
+--------------------+-------------------+--------------------+
| 1.12 | 5.3 | -5.3 |
+--------------------+-------------------+--------------------+

FLOOR(x)
Ro unds x do wn to the nearest integer.

INTERACTIVE SESSION:

mysql> select floor(1.60), floor(-3.78);


+-------------+--------------+
| floor(1.60) | floor(-3.78) |
+-------------+--------------+
| 1 | -4 |
+-------------+--------------+

CEILING(x)
Ro unds x up to the nearest integer.

INTERACTIVE SESSION:

mysql> select ceiling(1.20), ceiling(-3.78);


+---------------+----------------+
| ceiling(1.20) | ceiling(-3.78) |
+---------------+----------------+
| 2 | -3 |
+---------------+----------------+

ROUND(x), ROUND(x,y)
Ro unds x to the nearest integer. Ho wever, if a seco nd parameter y is entered, this functio n ro unds x to the
nearest yth decimal. Yo u can even use negative values fo r y, so as to ro und by tens (1 to the right o f the
decimal, thus y as -1).

INTERACTIVE SESSION:

mysql> select round(2.34), round(-3.76), round(5.379,2), round(34.56, -1);


+-------------+--------------+----------------+------------------+
| round(2.34) | round(-3.76) | round(5.379,2) | round(34.56, -1) |
+-------------+--------------+----------------+------------------+
| 2 | -4 | 5.38 | 30 |
+-------------+--------------+----------------+------------------+
1 row in set (0.00 sec)

SIN(x)
Returns the sine o f x in radians. The x value sho uld be in radians.
INTERACTIVE SESSION:

mysql> select sin(3.14);


+-----------+
| sin(3.14) |
+-----------+
| 0.001593 |
+-----------+

COS(x)
Returns the co sine o f x in radians. The x value sho uld be in radians.

INTERACTIVE SESSION:

mysql> select cos(5.20);


+-----------+
| cos(5.20) |
+-----------+
| 0.468517 |
+-----------+

T AN(x)
Returns the tangent o f x in radians. The x value sho uld be in radians.

INTERACTIVE SESSION:

mysql> select tan(-2.49);


+------------+
| tan(-2.49) |
+------------+
| 0.762721 |
+------------+

ASIN(x)
Returns the arc sine o f x in radians. Ho wever, a NULL is returned if x is no t within the range o f -1 and 1.

INTERACTIVE SESSION:

mysql> select asin(-1), asin(0), asin(1), asin(1.1);


+-----------+----------+----------+-----------+
| asin(-1) | asin(0) | asin(1) | asin(1.1) |
+-----------+----------+----------+-----------+
| -1.570796 | 0.000000 | 1.570796 | NULL |
+-----------+----------+----------+-----------+

ACOS(x)
Returns the arc co sine o f x in radians. Ho wever, a NULL is returned if x is no t within the range o f -1 and 1.
INTERACTIVE SESSION:

mysql> select acos(-1), acos(0), acos(1), acos(1.1);


+----------+----------+----------+-----------+
| acos(-1) | acos(0) | acos(1) | acos(1.1) |
+----------+----------+----------+-----------+
| 3.141593 | 1.570796 | 0.000000 | NULL |
+----------+----------+----------+-----------+

AT AN(x)
Returns the arc tangent o f x in radians.

INTERACTIVE SESSION:

mysql> select atan(-1), atan(0), atan(1), atan(1.1);


+-------------------+---------+------------------+------------------+
| atan(-1) | atan(0) | atan(1) | atan(1.1) |
+-------------------+---------+------------------+------------------+
| -0.78539816339745 | 0 | 0.78539816339745 | 0.83298126667443 |
+-------------------+---------+------------------+------------------+

AT AN2(x,y)
Returns the arc tangent o f y/x in radians, but the signs o f x and y are used to determine the quadrant.

INTERACTIVE SESSION:

mysql> select atan(-3,1), atan(2,-4);


+------------+------------+
| atan(-3,1) | atan(2,-4) |
+------------+------------+
| -1.249046 | 2.677945 |
+------------+------------+

COT (x)
Returns the co tangent o f x in radians. If the value returned is o ut o f bo unds, a NULL is returned instead.

INTERACTIVE SESSION:

mysql> select cot(2.3), cot(0);


+-------------+--------+
| cot(2.3) | cot(0) |
+-------------+--------+
| -0.89348446 | NULL |
+-------------+--------+

PI()
Returns the co nstant pi.
INTERACTIVE SESSION:

mysql> select pi();


+----------+
| PI() |
+----------+
| 3.141593 |
+----------+

DEGREES(x)
Co nverts x fro m radians into degrees and returns the value.

INTERACTIVE SESSION:

mysql> select degrees(pi());


+---------------+
| degrees(pi()) |
+---------------+
| 180.000000 |
+---------------+

RADIANS(x)
Co nverts the value x fro m degrees into radians and returns the value.

INTERACTIVE SESSION:

mysql> select radians(270);


+--------------+
| radians(270) |
+--------------+
| 4.712389 |
+--------------+

EXP(x)
Returns natural lo garithms e to the po wer o f x.

INTERACTIVE SESSION:

mysql> select exp(2), exp(-3);


+----------+----------+
| exp(2) | exp(-3) |
+----------+----------+
| 7.389056 | 0.049787 |
+----------+----------+

LOG(x)
Returns natural lo garithm o f x.
INTERACTIVE SESSION:

mysql> select log(3), log(-2.3);


+----------+-----------+
| log(3) | log(-2.3) |
+----------+-----------+
| 1.098612 | NULL |
+----------+-----------+

LOG10(x)
Returns natural lo garithm base 10 o f x.

INTERACTIVE SESSION:

mysql> select log10(4), log10(100), log10(-10);


+----------+------------+------------+
| log10(4) | log10(100) | log10(-10) |
+----------+------------+------------+
| 0.602060 | 2.000000 | NULL |
+----------+------------+------------+

SQRT (x)
Returns square ro o t o f x.

INTERACTIVE SESSION:

mysql> select sqrt(4), sqrt(9), sqrt(-25);


+----------+----------+-----------+
| sqrt(4) | sqrt(9) | sqrt(-25) |
+----------+----------+-----------+
| 2.000000 | 3.000000 | NULL |
+----------+----------+-----------+

POW(x,y), POWER(x,y)
Po w and Po wer are identical functio ns. Yo u can use either o ne. This functio n returns x to the po wer o f y.

INTERACTIVE SESSION:

mysql> select pow(2,3), power(3,-4);


+----------+-------------+
| pow(2,3) | power(3,-4) |
+----------+-------------+
| 8.000000 | 0.012346 |
+----------+-------------+

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Advanced SQL Syntax, Part 3

String and Character Functions


Yo u can refer back to this lesso n later as a reference. We will co ver these functio ns:

Charact e r Manipulat ing Funct io ns


ASCII(str) OCT(x)
CONV(x,y,z) HEX(x)
BIN(x) CHAR(x,y,z,...)

St ring Inf o Funct io ns


LENGTH(str) CHAR_LENGTH(str)
OCTET_LENGTH(str) CHARACTER_LENGTH(str)
LOCATE(str1,str2) INSTR(str1,str2)
POSITION(str1 IN str2) SOUNDEX(str)
LOCATE(str1,str2,x)

St ring Manipulat ing Funct io ns


CONCAT(str1,str2,...) SUBSTRING(str,x)
LPAD(str1,x,str2) SUBSTRING(str FROM x)
RPAD(str1,x,str2) SUBSTRING(str,x,y)
LEFT(str,x) SUBSTRING(str FROM x FOR y)
RIGHT(str,x) MID(str,x,y)
LTRIM(str) SUBSTRING_INDEX(str1,str2,x)
RTRIM(str) LCASE(str)
LOAD_FILE(filen) LOWER(str)
SPACE(str) UCASE(str)
REPLACE(str1,str2,str3) UPPER(str)
REPEAT(str,x) MAKE_SET(bit,str)
REVERSE(str) EXPORT_SET(bit,str1,str2,[str3,[x]])
INSERT(str1,x,y,str2) FIND_IN_SET(str1,strlist)
ELT(x,str1,str2,str3,...) FIELD(str1,str2,str3,str4,...)
TRIM([[BOTH | LEADING | TRAILING] [str2] FROM] str1)

f ile n represents a filename including path to the file, st r represents string, st rlist represents a list string, bit
represents bits, and x, y, and z represent numbers.

We'll explain each o f these in detail, with examples o f usage. We'll also explain the parameters and o utput.

ASCII(str)
Returns the ASCII co de value o f the leftmo st character o f string str.
INTERACTIVE SESSION:

mysql> select ascii('2'), ascii(2), ascii(20), ascii('blah');


+------------+----------+-----------+---------------+
| ascii('2') | ascii(2) | ascii(20) | ascii('blah') |
+------------+----------+-----------+---------------+
| 50 | 50 | 50 | 98 |
+------------+----------+-----------+---------------+

CONV(x,y,z)
This functio n co nverts numbers between different bases, such as hexadecimal to decimal, and binary to o ctal.
x is the number being co nverted fro m base y to base z. The bases y and z can range fro m 2 to 36 . If the base
has a preceding negative sign, x is treated as an unsigned number. x can also be a string. co nv() wo rks with
6 4-bit precisio n.

INTERACTIVE SESSION:

mysql> select conv("a",16,2), conv("6E",18,8);


+----------------+-----------------+
| conv("a",16,2) | conv("6E",18,8) |
+----------------+-----------------+
| 1010 | 172 |
+----------------+-----------------+
mysql> select conv(-17,10,-18), conv(10+"10"+'10'+0xa,10,10);
+------------------+------------------------------+
| conv(-17,10,-18) | conv(10+"10"+'10'+0xa,10,10) |
+------------------+------------------------------+
| -H | 40 |
+------------------+------------------------------

BIN(x)
Returns the binary o f x, where x is in base 10 . This is identical to co nv(x,10 ,2).

INTERACTIVE SESSION:

mysql> select bin(184), conv(184,10,2);


+----------+----------------+
| bin(184) | conv(184,10,2) |
+----------+----------------+
| 10111000 | 10111000 |
+----------+----------------+

OCT (x)
Returns the o ctal value o f x, where x is a decimal number. This is identical to co nv(x,10 ,8 ).

INTERACTIVE SESSION:

mysql> select oct(43), conv(43,10,8);


+---------+---------------+
| oct(43) | conv(43,10,8) |
+---------+---------------+
| 53 | 53 |
+---------+---------------+
HEX(x)
Returns the hexadecimal value o f x, where x is a decimal number. This is identical to co nv(x,10 ,16 ).

INTERACTIVE SESSION:

mysql> select hex(123), conv(123,10,16);


+----------+-----------------+
| hex(123) | conv(123,10,16) |
+----------+-----------------+
| 7B | 7B |
+----------+-----------------+

CHAR(x,y,z,...)
Co nverts x, y, z, etc., to ASCII characters. x, y, z, etc. are decimal ASCII co des. If any o f the parameters are
flo at values, they are truncated to integers.

INTERACTIVE SESSION:

mysql> select char(72, 79, 89.3, '79.9', 85, 76);


+------------------------------------+
| char(72, 79, 89.3, '79.9', 85, 76) |
+------------------------------------+
| HOYOUL |
+------------------------------------+

LENGT H(str), CHAR_LENGT H(str), OCT ET _LENGT H(str),


CHARACT ER_LENGT H(str)
These functio ns are all identical. They return the length o f the string st r.

INTERACTIVE SESSION:

mysql> select length('this'), char_length('is');


+----------------+-------------------+
| length('this') | char_length('is') |
+----------------+-------------------+
| 4 | 2 |
+----------------+-------------------+
mysql> octet_length('really'), character_length('cool');
+------------------------+--------------------------+
| octet_length('really') | character_length('cool') |
+------------------------+--------------------------+
| 6 | 4 |
+------------------------+--------------------------+

LOCAT E(str1,str2), POSIT ION(str1 IN str2)


Returns the po sitio n o f the first o ccurrence o f substring st r1 in the string st r2.
INTERACTIVE SESSION:

mysql> select locate('hak','what'), position('ssy' in 'missy');


+----------------------+----------------------------+
| locate('hak','what') | position('ssy' in 'missy') |
+----------------------+----------------------------+
| 0 | 3 |
+----------------------+----------------------------+

LOCAT E(str1,str2,x)
Returns the po sitio n o f the first o ccurrence o f substring st r1 in the string st r2, starting at po sitio n x. If st r2 is
no t fo und, returns a zero .

INTERACTIVE SESSION:

mysql> select locate('ufo','didyoufocus?',2);


+--------------------------------+
| locate('ufo','didyoufocus?',2) |
+--------------------------------+
| 6 |
+--------------------------------+
mysql> select locate('ufo','didyoufocus?',9);
+--------------------------------+
| locate('ufo','didyoufucus?',9) |
+--------------------------------+
| 0 |
+--------------------------------+

INST R(str1, str2)


Returns the po sitio n o f the first o ccurrence o f substring st r2 in the string st r1. This is identical to lo cat e and
po sit io n, except that the substring is the seco nd argument in instr.

INTERACTIVE SESSION:

mysql> select instr('missy','ssy');


+----------------------+
| instr('missy','ssy') |
+----------------------+
| 3 |
+----------------------+

SOUNDEX(str)
This is an interesting functio n. Returns the so undex o f the string st r. Similar-so unding strings sho uld have
the same so undex value. Treats no n-alphabet strings as vo wels.

INTERACTIVE SESSION:

mysql> select soundex('greetings'), soundex('meeting'), soundex('mayor');


+----------------------+--------------------+------------------+
| soundex('greetings') | soundex('meeting') | soundex('mayor') |
+----------------------+--------------------+------------------+
| G6352 | M352 | M600 |
+----------------------+--------------------+------------------+
CONCAT (str1,str2,...)
Returns a string co mpo sed o f st r1, st r2, etc. If the parameters are integers, flo at o r o ther no n-string values,
they are co nverted to a string.

INTERACTIVE SESSION:

mysql> select concat('po', 'ke', 'm', 'on');


+-------------------------------+
| concat('po', 'ke', 'm', 'on') |
+-------------------------------+
| pokemon |
+-------------------------------+

LPAD(str1,x,str2)
The string st r2 is added to the left side o f string st r1 until the length o f the string is x.

INTERACTIVE SESSION:

mysql> select lpad('h no!', 8, 'oo');


+------------------------+
| lpad('h no!', 8, 'oo') |
+------------------------+
| oooh no! |
+------------------------+

RPAD(str1,x,str2)
The string st r2 is added to the right side o f string st r1 until the length o f the string is x.

INTERACTIVE SESSION:

mysql> select rpad('a ghost said b', 18, 'oo');


+----------------------------------+
| rpad('a ghost said b', 18, 'oo') |
+----------------------------------+
| a ghost said boooo |
+----------------------------------+

LEFT (str,x)
Returns part o f the st r string o f length x, starting fro m the beginning o f the string.

INTERACTIVE SESSION:

mysql> select left('jimmythecricket', 5);


+----------------------------+
| left('jimmythecricket', 5) |
+----------------------------+
| jimmy |
+----------------------------+

RIGHT (str,x)
Returns part o f the st r string o f length x, starting fro m the right side o f the string.
INTERACTIVE SESSION:

mysql> select right('jimmythecricket', 7);


+-----------------------------+
| right('jimmythecricket', 7) |
+-----------------------------+0
| cricket |
+-----------------------------+

LT RIM(str)
Trims the space characters o ff o f the string st r fro m the left side o f the string and returns it.

INTERACTIVE SESSION:

mysql> select ltrim(' whoopy');


+--------------------+
| ltrim(' whoopy') |
+--------------------+
| whoopy |
+--------------------+

RT RIM(str)
Trims the space characters o ff the right side o f the string st r and returns it.

INTERACTIVE SESSION:

mysql> select rtrim('snoopy ');


+--------------------+
| rtrim('snoopy ') |
+--------------------+
| snoopy |
+--------------------+

LOAD_FILE(filen)
Reads the file indicated by the string f ile n (with full path) and returns the co ntents o f the file as a string. No te
that mo st servers—including OST's—do no t grant MySQL users file access thro ugh MySQL, so this functio n
usually wo n't wo rk.

INTERACTIVE SESSION:

mysql> update table_name set some_column = load_file("/tmp/blah");

SPACE(x)
Returns a string o f spaces x characters lo ng.
INTERACTIVE SESSION:

mysql> select concat('front', space(7), 'end');


+----------------------------------+
| concat('front', space(7), 'end') |
+----------------------------------+
| front end |
+----------------------------------+

REPLACE(str1,str2,str3)
Replaces all o ccurrences o f st r2 to st r3 in string st r1.

INTERACTIVE SESSION:

mysql> select replace('u am a chump', 'u', 'i');


+-----------------------------------+
| replace('u am a chump', 'u', 'i') |
+-----------------------------------+
| i am a chimp |
+-----------------------------------+

REPEAT (str,x)
Returns a string co mpo sed o f string st r x times.

INTERACTIVE SESSION:

mysql> select repeat('super ', 3);


+---------------------+
| repeat('super ', 3) |
+---------------------+
| super super super |

REVERSE(str)
Returns the reverse string o f st r.

INTERACTIVE SESSION:

mysql> select reverse('evian');


+------------------+
| reverse('evian') |
+------------------+
| naive |
+------------------+

INSERT (str1,x,y,str2)
Inserts the string st r2 into the string st r1 at po sitio n x and replaces y characters fro m po sitio n x.

WARNING Be careful! This is different fro m the inse rt co mmand used to insert into a database.
INTERACTIVE SESSION:

mysql> select insert('Powerful HeMan', 6, 3, 'less');


+----------------------------------------+
| insert('Powerful HeMan', 6, 3, 'less') |
+----------------------------------------+
| Powerless HeMan |
+----------------------------------------+

ELT (x,str1,str2,str3,...)
Returns string st r1 if x is 1, st r2 if x is 2, st r3 if x is 3 and so o n. If the index value is o ut o f range, returns
NULL.

INTERACTIVE SESSION:

mysql> select elt(2, 'abc', 'def', 'ghi', 'jkl');


+------------------------------------+
| elt(2, 'abc', 'def', 'ghi', 'jkl') |
+------------------------------------+
| def |
+------------------------------------+
mysql> select elt(4, 'abc', 'def', 'ghi', 'jkl');
+------------------------------------+
| elt(4, 'abc', 'def', 'ghi', 'jkl') |
+------------------------------------+
| jkl |
+------------------------------------+

FIELD(str1,str2,str3,str4,...)
this functio n searches thro ugh string parameters fro m st r2 to the end fo r string st r1. If fo und, the index o f the
string parameter is returned. Fo r instance, 1 is returned if st r2 is equal to st r1, 2 is returned if st r3 is equal to
st r1 and so o n. If st r1 is no t fo und, a zero is returned.

INTERACTIVE SESSION:

mysql> select field('abc', 'abc', 'def', 'ghi', 'jkl');


+------------------------------------------+
| field('abc', 'abc', 'def', 'ghi', 'jkl') |
+------------------------------------------+
| 1 |
+------------------------------------------+
mysql> select field('blah', 'abc', 'def', 'ghi', 'jkl');
+-------------------------------------------+
| field('blah', 'abc', 'def', 'ghi', 'jkl') |
+-------------------------------------------+
| 0 |
+-------------------------------------------+

T RIM([[BOT H | LEADING | T RAILING] [str2] FROM] str1)


This o ne is easier to explain with so me examples than in text.
INTERACTIVE SESSION:

mysql> select trim(' ab cd ');


+----------------------+
| trim(' ab cd ') |
+----------------------+
| ab cd |
+----------------------+
mysql> select trim(both ' ' from ' ab cd ');
+------------------------------------+
| trim(both ' ' from ' ab cd ') |
+------------------------------------+
| ab cd |
+------------------------------------+
mysql> select trim(both '?!' from '?!?!ab cd?!?!');
+---------------------------------------+
| trim(both '?!' from '?!?!ab cd?!?!') |
+---------------------------------------+
| ab cd |
+---------------------------------------+
mysql> select trim(leading '?!' from '?!?!ab cd?!?!');
+------------------------------------------+
| trim(leading '?!' from '?!?!ab cd?!?!') |
+------------------------------------------+
| ab cd?!?! |
+------------------------------------------+
mysql> select trim(trailing '?!' from '?!?!ab cd?!?!');
+-------------------------------------------+
| trim(trailing '?!' from '?!?!ab cd?!?!') |
+-------------------------------------------+
| ?!?!ab cd |
+-------------------------------------------+

SUBST RING(str,x), SUBST RING(str FROM x)


These functio ns are identical. Bo th return a substring o f st r fro m po sitio n x to the end o f the string.

INTERACTIVE SESSION:

mysql> select substring('beginning to the end', 11);


+---------------------------------------+
| substring('beginning to the end', 11) |
+---------------------------------------+
| to the end |
+---------------------------------------+
mysql> select substring('beginning to the end' from 11);
+-------------------------------------------+
| substring('beginning to the end' from 11) |
+-------------------------------------------+
| to the end |
+-------------------------------------------+

SUBST RING(str,x,y), SUBST RING(str FROM x FOR y), MID(str,x,y)


Same as the substring functio n, with an extra parameter. Here the functio n returns the substring o f string st r
fro m po sitio n x with a length o f y characters.
INTERACTIVE SESSION:

mysql> select substring('Which one is it going to be?', 7, 3);


+-------------------------------------------------+
| substring('Which one is it going to be?', 7, 3) |
+-------------------------------------------------+
| one |
+-------------------------------------------------+
mysql> select substring('Which one is it going to be?' from 7 for 3);
+--------------------------------------------------------+
| substring('Which one is it going to be?' from 7 for 3) |
+--------------------------------------------------------+
| one |
+--------------------------------------------------------+

SUBST RING_INDEX(str1,str2,x)
The string st r2 acts as the delimiter and splits the string st r1. Integer x will determine which delimiter to use
to split the string st r1. The sign o f x will determine whether to select the po rtio n o f the string to the left o r to the
right o f the delimiter.

INTERACTIVE SESSION:

mysql> select substring_index('this/is/weird/.', '/', 2);


+--------------------------------------------+
| substring_index('this/is/weird/.', '/', 2) |
+--------------------------------------------+
| this/is |
+--------------------------------------------+
mysql> select substring_index('this/is/weird/.', '/', 3);
+--------------------------------------------+
| substring_index('this/is/weird/.', '/', 3) |
+--------------------------------------------+
| this/is/weird |
+--------------------------------------------+
mysql> select substring_index('this/is/weird/.', '/', -2);
+---------------------------------------------+
| substring_index('this/is/weird/.', '/', -2) |
+---------------------------------------------+
| weird/. |
+---------------------------------------------+
mysql> select substring_index('this/is/weird/.', '/', -1);
+---------------------------------------------+
| substring_index('this/is/weird/.', '/', -1) |
+---------------------------------------------+
| . |
+---------------------------------------------+

LCASE(str), LOWER(str)
Bo th o f these functio ns return a lo wercase versio n o f string st r.
INTERACTIVE SESSION:

mysql> select lcase('WhAt Is GoInG oN?');


+----------------------------+
| lcase('WhAt Is GoInG oN?') |
+----------------------------+
| what is going on? |
+----------------------------+
mysql> select lower('WhAt Is GoInG oN?');
+----------------------------+
| lower('WhAt Is GoInG oN?') |
+----------------------------+
| what is going on? |
+----------------------------+

UCASE(str), UPPER(str)
Bo th o f these functio ns return an uppercase versio n o f string st r.

INTERACTIVE SESSION:

mysql> select ucase('WhAt Is GoInG oN?');


+----------------------------+
| ucase('WhAt Is GoInG oN?') |
+----------------------------+
| WHAT IS GOING ON? |
+----------------------------+
mysql> select upper('WhAt Is GoInG oN?');
+----------------------------+
| upper('WhAt Is GoInG oN?') |
+----------------------------+
| WHAT IS GOING ON? |
+----------------------------+

MAKE_SET (bit,str1,str2,...)
Returns a set (a string co ntaining substrings separated by co mmas(',')) co nsisting o f the strings that have the
co rrespo nding bit in bits set. st r1 co rrespo nds to bit 0 , st r2 to bit 1, etc. NULL strings in st r1, st r2, and so
o n, are no t appended to the result.

INTERACTIVE SESSION:

mysql> select make_set(1,'a','b','c');


+-------------------------+
| make_set(1,'a','b','c') |
+-------------------------+
| a |
+-------------------------+
mysql> select make_set(1 | 4,'hello','nice','world');
+----------------------------------------+
| make_set(1 | 4,'hello','nice','world') |
+----------------------------------------+
| hello,world |
+----------------------------------------+
mysql> select make_set(0,'a','b','c');
+-------------------------+
| make_set(0,'a','b','c') |
+-------------------------+
| |
+-------------------------+
EXPORT _SET (bit,str1,str2,[str3,[x]])
Returns a string where fo r every bit set in 'bit', yo u get an 'o n' string and fo r every reset bit, yo u get an 'o ff'
string. Each string is separated with 'separato r' (default ',') and o nly 'number_o f_bits' (default 6 4) o f 'bits' is
used.

INTERACTIVE SESSION:

mysql> select export_set(5,'Y','N',',',4);


+-----------------------------+
| export_set(5,'Y','N',',',4) |
+-----------------------------+
| Y,N,Y,N |
+-----------------------------+

FIND_IN_SET (str1,strlist)
The st rlist is a list o f strings separated by co mmas. This functio n searches fo r st r1 in the string list and
returns the index/po sitio n relative to the st rlist .

INTERACTIVE SESSION:

mysql> select find_in_set('ogre', 'wild,gandolf,ogre,blah');


+-----------------------------------------------+
| find_in_set('ogre', 'wild,gandolf,ogre,blah') |
+-----------------------------------------------+
| 3 |
+-----------------------------------------------+

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Final Project
The go al o f this pro ject is to expand o n the sho pping cart yo u created in the Intro ductio n to PHP co urse. In case yo u didn't take
that co urse, yo u can create a simple versio n o f this cart fro m scratch. The new sho pping cart will no t o nly have pro ducts, prices,
registratio n, and a checko ut area, but it will also have a managers' area in which pro ducts, custo mers, and purchases can be
viewed, and new pro ducts can be entered. Yo u can make this sho pping cart any way yo u wish.

Final Project, Part 1


Fo r the first part o f this pro ject, yo u will need to design and create yo ur SQL tables fo r the cart's pro ducts, registered
custo mers, and purchases. Be sure to think carefully abo ut ho w the tables will relate to o ne ano ther fo r the purpo ses
o f yo ur cart. When yo u are finished creating yo ur tables, hand them in.

Final Project, Part 2


No w it's time to create yo ur sho pping cart and managers' area. Altho ugh ho w yo u implement this is up to yo u, yo u
sho uo ld include these elements:

Fo r the sho pping cart:

A way fo r the custo mers to view the pro ducts fro m the database, alo ng with prices.
A way to add each pro duct to the custo mer's sho pping cart.
A way to view the sho pping cart.
A way to register and checko ut.

Fo r the managers' area:

A way to view, update, and add pro ducts and prices.


A way to view custo mers and their purchases.

Fo r the sake o f evaluatio n, try to include as many o f the elements discussed in this co urse as yo u can. Yo u sho uld
also o bserve go o d pro gramming practices, with co mments, co de reusability, and readability.

Hand in two files: The first file sho uld be the starting po int fo r yo ur custo mers. The seco nd file sho uld be the starting
po int fo r managers.

Be creative and have fun! Yo u want to present yo urself in a pro fessio nal yet friendly way, so feel free to express
yo urself!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.

You might also like