Mysql Workshop

197
Using MySQL - Introducing SQL This is the first in a series of MySQL workshops designed to introduce MySQL and SQL statements to a novice developer. What is MySQL and why are we using it? MySQL is a powerful Relational Database Management System (RDBMS) which we will use to learn the basic principles of database and data manipulation using Structured Query Language (SQL) statements. SQL is a database language that is used to retrieve, insert, delete and update stored data. This is achieved by constructing conditional statements that conform to a specific syntax (i.e. the strict order required of elements for a statement to work). Although it is assumed that most people reading this know what a database and SQL are (if not necessarily how to use them), there follows a little recap that it does no harm ;-) How does MySQL work? MySQL is a database server program and as such is installed on one machine, but can 'serve' the database to a variety of locations. To explain look at the following diagram. The MySQL Server is installed on a Server and can be accessed directly via various client interfaces, which send SQL statements to the server and then display the results to a user. Some of these are: A Local Client - a program on the same machine as the server . An example of this is the command line MySQL client software we will be using in the rest of the MySQL workshops (although there are other programs including graphical interfaces).

Transcript of Mysql Workshop

Page 1: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 1/197

Using MySQL - Introducing SQL

This is the first in a series of MySQL workshops designed to introduce MySQL andSQL statements to a novice developer.

What is MySQL and why are we using it?MySQL is a powerful Relational Database Management System (RDBMS) which wewill use to learn the basic principles of database and data manipulation usingStructured Query Language (SQL) statements. SQL is a database language that isused to retrieve, insert, delete and update stored data. This is achieved byconstructing conditional statements that conform to a specific syntax (i.e. thestrict order required of elements for a statement to work).

Although it is assumed that most people reading this know what a database andSQL are (if not necessarily how to use them), there follows a little recap that itdoes no harm ;-)

How does MySQL work?

MySQL is a database server program and as such is installed on one machine, butcan 'serve' the database to a variety of locations. To explain look at the followingdiagram.

The MySQL Server is installed on a Server and can be accessed directly viavarious client interfaces, which send SQL statements to the server and thendisplay the results to a user. Some of these are:

A Local Client - a program on the same machine as the server. An example of thisis the command line MySQL client software we will be using in the rest of theMySQL workshops (although there are other programs including graphicalinterfaces).

Page 2: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 2/197

A Scripting Language - can pass SQL queries to the server and display the result.

A Remote Client - a programme on a different machine that can connect to theserver and run SQL statements.

You can also use two more indirect methods.

Remote Login - You may be able to connect to the Server Machine to run one of 

its local clients.

Web Browser - you can use a web browser and scripts that someone has written(we're going to use this method for the rest of the workshop).

A bit about SQL

Structured Query Langauge is cross between a math-like language and anEnglish-like language that allows us to ask a database questions or tell it do dothings. There is a structure to this language: it uses English phrases to define anaction, but uses math-like symbols to make comparisons. For example:

SELECT * FROM table;

Where 'SELECT', 'FROM' and 'table' are in English, but '*' is a symbol that meansall.

It is important to learn SQL as it is common to almost all database programs andwas developed specifically as a language used to retrieve, add and manipulatedata in databases. You will find it not only here in MySQL, but underlying MSAccess, MS SQL Server, and in every web-based database application. While it

may seem confusing at first it is almost like telling a story or asking a questiononce you become comfortable with the syntax.

A Bit About Database Structure

Databases can be as complicated as you wish to make them... so lets start withsimple and work out way up from there. A database can have many TABLEsholding data. Imagine a simple table of car information:

CarID Manufacturer Year Car Model AirCon CDMulti

1094 Subaru 91 Legacy 2000 FALSE FALSE

1095 Suzuki 95 Vitatra 1600 FALSE FALSE

1096 Toyota 97 Corolla 1300 FALSE FALSE

1097 Volkswagen 95 Golf3 1600 FALSE FALSE

Page 3: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 3/197

If you look at the blue Cell we call this a 'FIELD' and it has a value of 'Suzuki'.

This FIELD exists in the COLUMN named 'Manufacturer'. The 'Model' COLUMN isgreen in this example. All the FIELDs in the 'Model' COLUMN contain the sametype of data (i.e. the model of the car).

Whereas a ROW (in this case red) contains a series of FIELDs, one in each

COLUMN, together comprising a record about one car. This record represents thereal world uniqueness of each thing we are recording (in this case a car) and thusis given a unique number (in database language the 'Primary Key') with which toidentify it. In our simple table each unique number is stored as a FIELD in the'carID' COLUMN.

Creating a First SQL Statement

As we have yet to create a database it would be difficult to construct some simpleSQL statements to explain the above without first getting involved in someMySQL server administration. However as we saw above there are many ways to

interact with a database and thus I have created a database and a 'cars' tablefilled with car info and provided a web browser interface to accept SQLstatements and return the results for you to experiment with.

So open the web interface in a new browser window and switch between the two orprint this out and work from it.

The first SQL statement we will look at is the SELECT statement. The basicSELECT statement has the following syntax.

SELECT columns FROM table [WHERE (condition)]

The WHERE condition is in square brackets as it is optional. So using our 'cars'table we can start issuing commands and you should see the actual data beingdisplayed.

Note: As an SQL statement can span many lines of a script or when typing it in ata command line (this virtual workshop will 'format' the SQL statements overmultiple lines to avoid overlapping and to aid readability). When using MySQL thestatement is only deemed 'complete' when a semi-colon is typed at the end tosignify that you have finished constructing your statement. So ensure you include

a semi-colon.......To display all the data from the 'cars' table we would issue the followingcommand (where '*' is the wildcard symbol for all).

SELECT *

Page 4: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 4/197

 FROM cars;

The result should be a large amount of data displayed (due to the quantity it maytake a few moments to display). This is not very useful, but we can begin torestrict the output by including WHERE conditions. For example to display onlythe records that contain the data '95-98' in the 'Year' field, try the following

command:

SELECT *

FROM cars

WHERE (Year = '95-98');

There are a couple of items of good practice that make life easier at this point.The first is that our conditions (the bit after WHERE) should be enclosed bybrackets. This 'forces' the condition to be evaluated and is needed when you havenested conditions in complex queries, so you should to get into the habit of doingthis from the beginning. Secondly, it is likely that you will at some point wish todisplay data from different tables using the same query - making it a good idea toalso get into the habit of using a the full TABLE.COLUMN reference (as differenttables sometimes have COLUMNs of the same name).

For example if we use another select statement, perhaps all records that have'Volvo' as 'Manufacturer', we are explicit that we mean the ManufacturerCOLUMN in the cars TABLE.

SELECT *

FROM cars

WHERE (cars.Manufacturer = 'Volvo');

As hinted at above, conditions can be combined to achieve better filtering of results, the simplist being to use the 'AND' operator

Page 5: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 5/197

SELECT *

FROM cars

WHERE ((cars.Year = '95-98')

AND (cars.Manufacturer = 'Volvo'));

This last statement should produce only one result and you can begin to see howusing conditions can be useful in finding individual records.

A Tiny Bit about Operators

Operators are another tool that you can use within your SQL statement to refineyour search for specific records.

SELECT *

FROM cars

WHERE ((cars.Year = '95-98')

AND (cars.Manufacturer = 'Volvo'));

The above statement uses the 'AND' operator (it can also be expressed as '&& ')

to combine two conditions. Both conditions have to be met in order for the recordto be displayed. We can also use the 'OR' operator (can be expressed as '||' ) toask for a record to be displayed if either condition is met.

SELECT *

Page 6: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 6/197

 FROM cars

WHERE ((cars.Year = '95-98')

OR (cars.Manufacturer = 'Volvo'));

The final operator we'll discuss here is the 'NOT' operator ('!' in case you werewondering), which is a bit more complicated. Rather than joining conditionstogether it becomes part of the condition, turning a positive into a negative. Thefollowing statement retrieves all records that do not  contain 'Volvo' as'Manufacturer'.

SELECT *

FROM cars

WHERE (cars.Manufacturer != 'Volvo');

As the 'NOT' operator has become part of the condition it can be used withanother operator to combine positive and negative conditions. For example toretrieve the records that contain the data '95-98' in the 'Year' field but do notcontain 'Volvo' as 'Manufacturer' enter the following.

SELECT *

FROM cars

WHERE ((cars.Year = '95-98')

AND (cars.Manufacturer != 'Volvo'));

Page 7: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 7/197

There are also other operators, but they will be discussed in a later part of theMySQL Virtual Workshop series.

Restricting Columns

Before leaving our initial encounter with the SELECT statement we need to

address one final component. In all the examples we have used so far thewildcard '*' has been used to retrieve all the COLUMNs. While this may be okayfor a table that only has 7 COLUMNs, it would not work quite so well for a tablewith 20 COLUMNs. Thus it may be desirable to sometimes restrict whichCOLUMNs are returned.

If we look again at the seven fields that make up the 'cars' table

+-------+--------------+-------+------+-----------+--------+---------+

| CarID | Manufacturer | Year | Car | Model | AirCon | CDMulti |

+-------+--------------+-------+------+-----------+--------+---------+

We may only be interested in seeing the 'Manufacturer','Year','Car' and'Model' fields and thus we would construct a statement like so:

SELECT cars.Manufacturer, cars.Year, cars.Car, cars.Model

FROM cars

WHERE (cars.Year = '95-98');

Which, as you can see, asks for only certain columns to be returned - each fieldseparated by a comma.

Page 8: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 8/197

Using MySQL - Data and Structures

Workshop Requirements

You should have completed the first workshop in this series.You should also have access to the MySQL command line client software. You caneither ask your systems adminstrator for access to this client, alternatively youcould install a local copy of MySQL - see Setting Up a Server for details.

You should also have full permissions on a database (or the ability to create anew one), again check with your administrator if necessary.

Finally you should have printed out and filled in the Data Collection Form........ fromthe experience of others it IS easier than doing this 'on the fly'.

Important information to understand before beginning.A common problem when learning how to the MySQL Command Line Client isgetting the syntax exactly right. There are several conventions which are usedthroughout the MySQL virtual workshops when displaying commands that you willhave to type.

  $ - This preceding a command signifies that the command should betyped at the command line of your system. The '$' should not beincluded in any statement you type.

mysql> - This preceding a command signifies the command should be

typed at the MySQL client Command Line Interface. Again ignore thisand only type what follows.

There are also several other command prompts that you may encounter withinthe mysql client.

 -> This is a continuation line allowing you to enter a long statementover several lines. A statement is never executed until you issue a semicolon at the end of it.

You may at some point require to type either an apostrophe (') or a double quote

(") as part of your data entry. However as these are used as part of the SQLsyntax the statement would fail. This is signified by either:

 '> MySQL is asking you for another apostrophe Or

"> MySQL is asking you for another double quote.

To successsfully execute a statement containing either of these characters theymust be entered in pairs.

Page 9: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 9/197

Page 10: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 10/197

However is it a REALLY bad idea to ever enter a password anywhere in plaintext, so if we omit the password but still leave the password flag (-p), you will beprompted for it (again do not try this yet).

$ mysql -u vworks -p vworksDB

Enter password:

You could also omit the name of the database as well (wait 'til I say so).

$ mysql -u vworks -p

Enter password:

...and once logged in elect to 'use' a specific database. You could choose to dothis if your user has privileges on different databases.

mysql> use vworksDB

Database changed

...but we wont do that either. Okay, you can now log in to the database using thesecond example above.

$ mysql -u vworks -p examples

Enter password:

You should now be looking at the MySQL Command Line Interface that is awaitingany statement you wish to type.

mysql>

Page 11: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 11/197

In the previous MySQL Virtual Workshop we looked at issuing SQL SELECTstatements containing conditions to retrieve data from a table. The naturalprogression is to start constructing other statements which INSERT, UPDATE andDELETE records from the table. However, before we attempt this we need tocreate a table in our database.

Creating a Table

Datatypes

Creating a table requires you to have an understanding of MySQL datatypes(similar if not identical to other database datatypes) so that you can define thefields in the table. The datatypes below are some of the basic datatypes and aremeant as a simple introduction. If you are planning a production database youshould investigate the datatypes thoroughly.

Datatype Description Example:

INT Numeric entry id INT

VARCHAR(n)

Text string of characters up to n witha maximim of 255 characters

nameVARCHAR(20)

CHAR(n) Text string with specific number (n)of characters. If the number of characters is less than 'n' then ispadded by spaces (spaces areremoved when data is retrieved).255 Maximum.

addressCHAR(30)

TEXT Holds between 255 - 65535characters philosophy TEXT

DATE The date stored in the format YYYY-MM-DD

dob DATE

TIME The time stored in the formatHH:MM:SS

tob TIME

The syntax for defining a field and datatype (as used in the examples) is'fieldname datatype'.

So lets get started with making a database table. You should have completedthe Data Collection form so we will create a table and begin to enter some of the data

into your database.

CREATE TABLE......

The syntax for creating a table is as follows:

mysql> CREATE TABLE <table_name> (

Page 12: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 12/197

  field1 datatype,

field2 datatype,

etc......

  );

When split over multiple lines within the MySQL command line client thecontinuation indictor will be used.

mysql> CREATE TABLE <table_name> (

  -> field1 datatype,

  -> field2 datatype,

  -> etc......);

REMINDER: the command statement will not be executed until you use a semi-colon. Thus for the command to create a table based on the information in thedata collection form you should enter the following (omitting the 'No. of Tracks'which we will add later):

mysql> CREATE TABLE cds (

  -> cdID INT(3) auto_increment primary key,

  -> artist VARCHAR(20),

Page 13: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 13/197

  -> title VARCHAR(30),

  -> year INT(4),

  -> label VARCHAR(20),

  -> bought DATE );

Query OK, 0 rows affected (0.00 sec)

When entering these commands over several lines it is possible you may make amistake and would want to cancel the command. This can be done by typing the'\c' command:

mysql> CREATE TABLE cds (

  -> cdID IN(3)

  -> \c

mysql>

You can check that you have created the table correctly by issuing a 'describe'command.

mysql> describe cds;

Page 14: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 14/197

+--------+-------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+--------+-------------+------+-----+---------+----------------+

| cdID | int(3) | | PRI | NULL | auto_increment |

| artist | varchar(20) | YES | | NULL | |

| title | varchar(30) | YES | | NULL | |

| year | int(4) | YES | | NULL | |

| label | varchar(20) | YES | | NULL | |

| bought | date | YES | | NULL | |

+--------+-------------+------+-----+---------+----------------+

6 rows in set (0.01 sec)

You will have noticed that when we created the first 'cdID' field we added a fewother instuctions. These were 'auto_increment' and 'primary key'. These areused in the context of relational databases to identify the unique COLUMN in theTABLE (primary key) and to ensure that there cannot be duplicate numbers inthe COLUMN by automatically numbering this FIELD (auto_increment).

Now that the table has been created we are ready to start inserting data.

Page 15: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 15/197

INSERTing data

The SQL statement to INSERT data is again fairly straight forward once you getused to the syntax. The basic syntax for the INSERT statement is as follows.

INSERT INTO <table_name>

VALUES (

value1,

value2,

etc......

)

Which will work fine if you are inserting data into every field in a row. However if 

you only want to insert data into certain fields (columns) you will need to specifyonly these fields as part of the statement otherwise the number of data items willnot match the number of available fields and MySQL will return an error.

INSERT INTO <table_name> (

column1,

column2,

....

Page 16: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 16/197

) VALUES (

value1,

value2,

....

)

 

To illustrate this point we will try to insert the first example from the Data Collection

form into the 'cds' table.

mysql> INSERT INTO cds

-> VALUES (

-> 'jamiroquai',

  -> 'A Funk Odyssey',

  -> '2001',

  -> 'Sony Soho2',

Page 17: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 17/197

  -> '2001-09-13');

ERROR 1136: Column count doesn't match value count at row 1

As you can see we get an error telling us that the number of values we have triedto insert (5) does that match the number of columns that there are (6). This isbecause we have omitted the 'cdID' field which is used as the unique indentiferand thus gets generated automatically. In order for this to work we we wouldhave to specify which 5 fields we want to insert our values into.

mysql> INSERT INTO cds (

-> artist, title, year, label, bought

  -> ) VALUES (

  -> 'jamiroquai',

  -> 'A Funk Odyssey',

  -> '2001',

  -> 'Sony Soho2',

  -> '2001-09-01');

Query OK, 1 row affected (0.02 sec)

Page 18: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 18/197

Although MySQL tells us that this has worked, we can check for ourselves byissuing a SELECT query.

mysql> SELECT * FROM cds;

+------+------------+----------------+------+------------+------------+

| cdID | artist | title | year | label | bought |

+------+------------+----------------+------+------------+------------+

| 1 | jamiroquai | A Funk Odyssey | 2001 | Sony Soho2 | 2001-09-01 |

+------+------------+----------------+------+------------+------------+

1 row in set (0.00 sec)

Also notice that the 'cdID' field has a value of '1' that has been generatedautomatically by the 'auto_increment' property.

Although we could enter all our data by explicitly declaring the fields then thevalues, there is another way we could do it. Our first attempt at the INSERT SQLstatement failed because we were trying to add 5 values to a database that has 6fields (columns) and we couldn't specify a 6th value for the 'cdID' field as thatvalue is an automatically generated number. What we can do in the statement isacknowledge that a field exists, but admit we don't know what the value will be.This is done by substituting a question mark for a real value. If we enter thestatement again.

 

mysql> INSERT INTO cds VALUES (

Page 19: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 19/197

  -> '?',

  -> 'jamiroquai',

  -> 'A Funk Odyssey',

  -> '2001',

  -> 'Sony Soho2',

  -> '2001-09-01');

Query OK, 1 row affected (0.00 sec)

Page 20: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 20/197

This time the INSERT statement succeeds. Another SELECT statement confirmsthis.

mysql> SELECT * FROM cds;

+------+------------+----------------+------+------------+------------+

| cdID | artist | title | year | label | bought |

+------+------------+----------------+------+------------+------------+

| 1 | jamiroquai | A Funk Odyssey | 2001 | Sony Soho2 | 2001-09-01 |

| 2 | jamiroquai | A Funk Odyssey | 2001 | Sony Soho2 | 2001-09-01 |

+------+------------+----------------+------+------------+------------+

1 row in set (0.00 sec)

Page 21: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 21/197

Using MySQL - Manipulating Data

Workshop Requirements

You should have completed Parts One and Two of this series.

You should also have access to the MySQL command line client software.

You should also have full permissions on a database.

Introduction

In the previous MySQL Virtual Workshops we have looked at logging into MySQL,creating tables, adding and selecting data using SQL statements. In thisWorkshop we will continue to look at other SQL commands, specifically updatingand deleting, and revisit the SELECT command to examine different operatorsand options.

UPDATE-ing RecordsThe UPDATE SQL statement is similar to the SELECT statement as there must bea WHERE condition to specify which record(s) to change.

UPDATE <table_name>

SET <column_name> = 'new_value'

WHERE (<column_name> = 'some_value');

So to change the 'title' in the first row of our 'cds' table from:

| 1 | jamiroquai | A Funk Odyssey | 2001 | Sony Soho2 | 2001-09-01 |

to:

| 1 | jamiroquai | Wrong Title | 2001 | Sony Soho2 | 2001-09-01 |

We would use the following statement:

mysql> UPDATE cds

Page 22: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 22/197

  -> SET cds.title = 'Wrong Title'

  -> WHERE (cds.cdID = '1');

Query OK, 1 row affected (0.06 sec)

Rows matched: 1 Changed: 1 Warnings: 0

The value '1' in the 'cdID' column is the unique identifier that allows us tochange values. You can issue a SELECT statement if you want to check thechanges.

mysql> SELECT * FROM cds;

+------+------------+----------------+------+------------+------------+

| cdID | artist | title | year | label | bought |

+------+------------+----------------+------+------------+------------+

| 1 | jamiroquai | Wrong Title | 2001 | Sony Soho2 | 2001-09-01 |

| 2 | jamiroquai | A Funk Odyssey | 2001 | Sony Soho2 | 2001-09-01 |

We could also change multiple columns using one statement

Page 23: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 23/197

mysql> UPDATE cds SET cds.title = 'Other Title',

  -> cds.artist = 'artist'

  -> WHERE (cds.cdID = '1');

Query OK, 1 row affected (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0

 The DELETE statement

By using the UPDATE statement we have altered the 'cds' table so that there areno longer duplicate records in rows 1 and 2. However we do have an incorrectrecord in row 1 and need to DELETE it. The syntax for deleting rows is:

DELETE FROM <table_name>

WHERE (<column_name> = 'some_value');

Thus to remove our incorrect record

mysql> DELETE FROM cds

-> WHERE (cds.cdID = '1');

Page 24: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 24/197

Query OK, 1 row affected (0.00 sec)

NOTE: When a record is deleted all the fields are deleted INCLUDING the uniqueidentifier, and the database does not renumber this auto_increment COLUMN. Soit is important to remember that the ID is not the same as the row number, e.g.in our example row 2 has a cdID of 3, row 3 - cdID of 4 etc.

SELECT Revisited

In the first MySQL Virtual Workshop we looked at using the SELECT SQLstatement to retrieve data from a table. This was fairly limited in scope as wecould only retrieve data which matched a specific text string. In this section wewill look at retrieving data based on other criteria.

The first of these we will look at is Selecting a Number Range. We havecreated two numeric COLUMNs in our 'cds' TABLE: the 'cdID' and 'Year'COLUMNs. As each 'cdID' entry is unique, we will use the 'Year' COLUMN in the

following examples. It is also important to note that while we may recognise anentry in the 'Year' COLUMN as an actual year MySQL only recognises it as anumber.

Simple stuff first to select all from one year

mysql> SELECT * FROM cds

-> WHERE (cds.year = 2001);

Note that as the 'year' COLUMN is numeric rather than a text string we do notneed to enclose our search term in apostrophes (although if we didit would treat the number '2001' as a text string and find it anyway). If wewanted to expand our search term to include other years (as well as 2001) weneed to use numeric operators.

Numeric Operators

Numeric operators are used to compare two numbers under several conditions.

Operator Condition

= Equal to

<> Not equal to

> Greater than

Page 25: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 25/197

< Less than

>= Greater than or equal to

<= Less than or equal to

Thus to display all cds that were released before 2001:

mysql> SELECT * FROM cds

-> WHERE (cds.year < 2001);

Or all cds in / after 1990:

mysql> SELECT * FROM cds

-> WHERE (cds.year >= 1990);

So we are able to select records by a column's numeric content.

Other Operators

There are two other operators so far unmentioned, the LIKE and BETWEENoperators.

The LIKE operator is used when we want to match part of the data in a field byusing the '%' wildcard. So if we wanted to search the 'title' field for all albumsbeginning with 'A' we would use the following statement.

mysql> SELECT * FROM cds

-> WHERE (cds.title LIKE 'A%');

Page 26: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 26/197

The 'A' in the search string is followed by our wildcard character. To match theword 'the' in any title we would put a wildcard character before and afterwards inthe SQL statement.

mysql> SELECT * FROM cds

-> WHERE (cds.title LIKE '%the%');

The BETWEEN statement is used to add more functionality to a condition, allowingus to select a range of values from a column.

SELECT <column_name> FROM <table_name>

WHERE (<column_name> BETWEEN value1 AND value2)

Thus we could select a numeric range

mysql> SELECT * FROM cds

-> WHERE (cds.year BETWEEN 1995 AND 1998);

Or we could select an alphanumeric range. To select all artists alphabeticallybetween 'Elvis' and 'Michael Jackson'

mysql> SELECT * FROM cds

-> WHERE (cds.artist BETWEEN 'Elvis' AND 'Michael Jackson');

Which might return 'Frank Sinatra' or 'Led Zeppelin'.

Working With Dates

A typical entry for a date might look something like this.

Page 27: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 27/197

mysql> SELECT cds.bought FROM cds;

+------------+

| bought |

+------------+

| 2001-09-01 |

+------------+

1 row in set (0.01 sec)

You could imagine trying to SELECT dates using 'Less Than' or 'More Than'would be difficult as a date is not a sequential decimal number. However that is

why we specify the 'DATE' datatype when creating the field in the table, as thisallows comparisons of this type. What actually happens is that the MySQL DBMSconverts any date into the number of days since year '0' before doing anycomparison.

Try SELECTing cds that you bought prior to the year 2000

mysql> SELECT * FROM cds

-> WHERE (cds.bought < '2001-01-01');

And cds that were bought this century.

mysql> SELECT * FROM cds

Page 28: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 28/197

  -> WHERE (cds.bought >= '2001-01-01');

Other Tricks When Displaying Data

Before leaving the SELECT command alone again for a while, we should touchupon a few popular ways to control output.

DISTINCT

The DISTINCT qualifier is used to return unique results and is included as part of the SELECT statement (i.e. before any conditions are applied). Let us image thatour 'cds' table contained over 2000 rows. If we wanted to look at all the artistswhose name started with 'E' we might construct a statement like so.

mysql> SELECT artist FROM cds

-> WHERE cds.artist LIKE 'E%';

This would return each row that had an artist whose name started with 'E'. If thatartist has 10 cds in the database his name will be returned 10 times (once foreach cd). We could avoid this by using the DISTINCT qualifier, which wouldensure that each artist was returned only once.

mysql> SELECT DISTINCT cds.artist FROM cds

-> WHERE cds.artist LIKE 'E%';

Hierarchy of Conditions

The conditions that control the filtering of the query exist in a rough (if not quiteexact) hierarchal order:

  WHERE

  |

Page 29: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 29/197

  GROUP BY

  | |

HAVING ORDER BY

  | |

  LIMIT

If more than one of these conditions are to used in a query then it isrecommended that this order be used, so that GROUP BY cannot go before theWHERE condition and LIMIT cannot go before HAVING etc. Notice that HAVINGand ORDER BY are at the same level - this is because either one can go beforethe other. Breaking this hierarchy will generally result in errors.

We have already looked at the WHERE condition extensively, so lets have a closerlook at these conditions.

GROUP BY

When we issue a SELECT command we are shown the results in the order that therecords were entered. We can change this by using the 'GROUP BY' directive,allowing us to display the data grouped by field. To return the results ordered byartist:

mysql> SELECT * FROM cds

-> GROUP BY cds.artist;

ORDER BY

Similar to GROUP BY, this condition further allows control over the result set.ORDER BY controls the sequence of results. For example to display all the datafrom the 'cds' table ordered alphabetically by artist we would issue this command.

Page 30: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 30/197

mysql> SELECT * FROM cds ORDER BY cds.artist;

You can also choose to sort the results in reverse by appending DESC to thecondition

mysql> SELECT * FROM cds ORDER BY cds.artist DESC;

We can also use two or more ORDER BY conditions, for example if we wanted tolist by artist then the date bought in descending order we could enter.

mysql> SELECT * FROM cds ORDER BY cds.artist, cds.bought DESC;

HAVING

The HAVING condition is really just another WHERE condition that acts as a'secondary constraint' on the result set. This works best when you are trying toapply a restrictive condition after a grouping has taken place. So for example:

mysql> SELECT * FROM cds

-> GROUP BY cds.artist

-> HAVING cds.title LIKE 'A%';

You should try if at possible to write queries using the WHERE condition ratherthan the HAVING condition as HAVING is un-optimised. Most people use HAVINGto work out summaries of datareturned - such as the number or rows etc.

LIMIT

There will be times that you create a query that produces a large result set thatyou don't want to view or handle all at once. In these situations it is useful to usethe LIMIT condition to restrict the number or records returned. For example todisplay the first 5 records that meet a query:

mysql> SELECT * FROM cds LIMIT 5;

Page 31: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 31/197

To retrieve the rest of the records in batches we can also specify a starting pointbefore the number or rows to return.

SELECT <fields> FROM <TABLE> LIMIT <starting_point>, <number_of_rows>

So to return rows 6-10 we would specify the start point of 5 and then ask toreturn 5 records.

mysql> SELECT * FROM cds LIMIT 5, 5

Or to start at rows 3-7:

mysql> SELECT * FROM cds LIMIT 2, 4

Page 32: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 32/197

Using MySQL - Manipulating Structures

Workshop Requirements

You should have completed Parts One,  Two and Three of this series.You should also have access to the MySQL command line client software.

You should also have full permissions on a database.

Introduction

By this point you should be very familiar with SQL statements and manipulatingdata within database TABLEs. In this part of the Using MySQL series we will lookat manipulating database tables rather than just the data within. Beforebeginning, ensure that you have opened your own MySQL database where you

entered all the CD data.

ADDing a Column

When we created the 'cds' TABLE, based on the Data Collection Form, we omitted the

'tracks' field. It is time to correct this by adding a 'tracks' COLUMN to our 'cds'TABLE. This is done by using the ALTER statement. With the ALTER statement youcan add, remove or change a table's columns with a general syntax of:

ALTER TABLE <table_name>

ADD/DROP <column_name> [datatype];

As we want to add a new COLUMN called 'tracks' to our 'cds' table we shouldenter this:

mysql> ALTER TABLE cds

-> ADD tracks INT(2);

Using the SELECT command we can confirm that there is now an empty or NULL'tracks' column in every row.

mysql> SELECT cdID, artist, title, tracks

Page 33: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 33/197

  -> FROM cds;

+------+------------+----------------+--------+

| cdID | artist | title | tracks |

+------+------------+----------------+--------+

| 2 | jamiroquai | A Funk Odyssey | NULL |

Mini Exercise

Using the UPDATE command learned in Part3 you can now add all the 'tracks' datato your 'cds' table.

MODIFYing a TABLE

As well as ADDing new COLUMNs we could also change an existing one by usingMODIFY in the statement.

ALTER TABLE <table>

MODIFY <column> <new_definition>

So to change the newly added track COLUMN to hold 3 figure values we wouldenter:

mysql> ALTER TABLE cds

-> MODIFY tracks INT(3);

And to change this back to hold 2 figure values:

Page 34: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 34/197

mysql> ALTER TABLE cds

-> MODIFY tracks INT(2);

Copying Tables

Before we look at the other table manipulation commands it will be useful tomake a copy of our 'cds' table (in fact we'll make several to illsutrate the process)so that we can mess about and still have all the data we have input. Copyingtables in MySQL can sometimes be done in one statement, but some columnattributes cannot be copied so it is usually necessary to use at least twostatements. To gain a good understanding of what is going on let's break thisprocess down into its parts.

 The Long WayThe really long 'manual' way to copy a table is to create a new table indentical tothe first, THEN copy all our inputted data into the new table and finally modify thenew table to create the 'auto increment' and 'primary key' attributes on the 'cdID'field.

So first we should double check the structure of the 'cds' table usingthe describe command.

mysql> DESCRIBE cds;

+--------+-------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+--------+-------------+------+-----+---------+----------------+

| cdID | int(3) | | PRI | NULL | auto_increment |

| artist | varchar(20) | YES | | NULL | |

Page 35: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 35/197

| title | varchar(30) | YES | | NULL | |

| year | int(4) | YES | | NULL | |

| label | varchar(20) | YES | | NULL | |

| bought | date | YES | | NULL | |

| tracks | int(2) | YES | | NULL | |

+--------+-------------+------+-----+---------+----------------+

7 rows in set (0.00 sec)

We now need to make the new 'cds2' table that matches exactly.

mysql> CREATE TABLE cds2 (

  -> cdID INT(3) auto_increment primary key,

  -> artist VARCHAR(20),

  -> title VARCHAR(30),

  -> year INT(4),

Page 36: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 36/197

  -> label VARCHAR(20),

  -> bought DATE,

  -> tracks INT(2));

Query OK, 0 rows affected (0.00 sec)

Use the DESCRIBE command again, this time to check that the 'cds2' tablematches the 'cds' table. Once that is complete, we now have to copy the datafrom one table to the other. This is done by mixing the INSERT and SELECT

statements so that you are inserting into one table the selection from the other.

mysql> INSERT INTO cds2

-> SELECT * FROM cds;

Check that this has worked by issuing a select command on the 'cds2' table .

mysql> SELECT cds2.cdID, cds2.artist, cds2.title

-> FROM cds2;

+------+------------+----------------+

| cdID | artist | title |

+------+------------+----------------+

Page 37: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 37/197

| 2 | jamiroquai | A Funk Odyssey |

There is a problem however. As can be seen in the DESCRIBE statement,the 'cdID' COLUMN in the new TABLE has been created withoutthe auto_increment and primary key properties. We can use the ALTERTABLE.....MODIFY statement we learned above to add

theauto_increment and primary key properties:

mysql> ALTER TABLE cds2

-> MODIFY cdID INT(3) auto_increment primary key;

 The Short Way

There is another way to achieve the same result. Rather than creating the newtable theninserting the data from the original we can CREATE another tablecalled 'cds3' with a SELECT statement:

mysql> CREATE TABLE cds3

-> SELECT * from cds;

A SELECT statement will confirm that this has worked.

mysql> SELECT cds3.cdID, cds3.artist, cds3.title

-> FROM cds3;

+------+------------+----------------+

| cdID | artist | title |

Page 38: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 38/197

+------+------------+----------------+

| 2 | jamiroquai | A Funk Odyssey |

We still have to add the structural constraints.

mysql> ALTER TABLE cds3

-> MODIFY cdID INT(3) auto_increment primary key;

All in one statement

We can make copy of the table in one statement if we first create the cdID field(with auto_increment and primary key) then insert the other fields as specified inthe INSERT statement, which is a combination of boths methods.

mysql> CREATE TABLE cds4 (cdID INT(3) auto_increment primary key)

-> SELECT

-> cds.artist,

-> cds.title,

-> cds.year,

-> cds.label,

-> cds.bought,

Page 39: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 39/197

  -> cds.tracks

  -> FROM cds;

DROP-ing Columns and Tables

As we saw in a previous Virtual Workshop we can delete data from a table by usingthe DELETE command. This will leave the table structure intact and simplyremove the data. If we want to delete a structural element of the database (acolumn or table) we have to use the DROPcommand.

DROP <element> <name>

So to remove a column from our 'cds2' table - lets say the newly added 'tracks'column - we would use the DROP and ALTER TABLE commands together (as weare altering a table).

mysql> ALTER TABLE cds2

-> DROP tracks;

Similarly if we wanted to remove the whole table we would issue the following:

mysql> DROP TABLE cds2;

It is important to be sure that you know exactly what want to do before you issuea DROP Command. If you created another 'cds3' table in the previous sectionremove it as well. You can check that a table has in fact gone by asking MySQL todisplay all the tables.

mysql> show tables;

+------------------+

Page 40: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 40/197

| Tables_in_kbrown |

+------------------+

| cds |

| cds3 |

| cds4 |

In order to tidy things up - you should also delete tables 'cds3' and 'cds4'.

mysql> DROP TABLE cds3;

mysql> DROP TABLE cds4;

Exporting and Importing Data

The final thing that we will look at in this workshop is the exporting and importingof data. You may want to export data so that it can be imported into anotherpackage, or similarly we may wish to import data from a different package.

IMPORTANT: In newer versions of MySQL these methods may be disabled. You shouldbe able to turn this feature on by issuing the command:

mysql> --local-infile=1

Otherwise contact your systems administrator for advice. The version of MySQLthat comes with the FoxSev distribution discussed in Setting Up a Server does allowthis.

Page 41: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 41/197

Exporting Data

When we are exporting files from MySQL we need an area that the 'MySQL'package can write to AND that you can access to get your data. You may have tocontact your systems administrator for advice on a directory. For the purpose of this section we will use Unix commands and the example directory '/tmp/vworks'.If you are a Windows users you will have to substitute Windows commands (i.e.

'dir' for 'ls' and 'type' for 'cat') and directory strucures (e.g. 'C:\temp\vworks' for'/tmp/vworks').

The command to export data to a text file is similar to the standard SELECTcommand except instead of displaying the data on screen it goes into a file.

SELECT <columns>

FROM <table_name>

INTO OUTFILE <file_name>

IMPORTANT: We do not want to output the 'cdID' column as this is only usefulwithin the database and so we need to specify the other columns explicitly.

mysql> SELECT

-> cds.artist,

-> cds.title,

-> cds.year,

-> cds.label,

-> cds.bought,

Page 42: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 42/197

  -> cds.tracks

  -> FROM cds INTO OUTFILE '/tmp/vworks/cds.txt';

In order to check that this has worked we need to exit MySQL to your system'scommand line (or you could open another 'shell' window). First Change Directoryto '/tmp/vworks''.

$ cd /tmp/vworks

Then issue a 'list short' command.

$ ls

And you should see that your file is there, so far so good. Next we want to viewthe contents of the file and to do this we will use a 'cat' command.

$ cat cds.txt

You should see something like this..... (Thanks to Mark for these).

Jamiroquai A Funk Odyssey 2001 Sony soho2 2001-09-01 11

Abba Abbas Greatest Hits 1998 demon 2001-09-10 23

Various Now 49 2001 virgin 2001-09-10 40

westlife westlife 2000 jive 2000-06-09 13

Various Eurovision Song contest 2001 2001 EMI 2000-09-08 20

Page 43: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 43/197

The space between each column is a 'tab'. This is because MySQL creates a 'tabdelimited' file by default. It is important to know this if you are going to importthe file to another database as it will likely ask for the delimited format todetermine the differences between fields.

Importing data

Importing data is a very simliar process to exporting. The syntax for importing afile is:

LOAD DATA INFILE 'file_name.txt'

INTO TABLE tbl_name (field1, field2...etc)

For a quick example we will import our exported data back into the cds TABLE. Itis important to specify the field names as we are not importing data into everycolumn - the first column 'cdID' is automatically numbered by MySQL. So to do itfor real:

mysql> LOAD DATA INFILE '/tmp/vworks/cds.txt'

-> INTO TABLE cds (artist, title, year, label, bought, tracks);

You can now check that this has worked by issuing a SELECT command, whereyou should see duplicate entries in your table.

mysql> SELECT *

-> FROM cds;

Using MySQL, Joins

Workshop Requirements

You should have completed Parts One, Two, Three and Four of this series.

Page 44: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 44/197

You should also have access to the MySQL command line client software.

You should also have full permissions on a database.

Introduction

In this Virtual Workshop we will look at retrieving data from a relational database

structure, i.e. with multiple tables, using the SQL JOIN Syntax. Most databaseshave multiple tables to avoid repeating data. i.e. why enter the details of acustomer over and over again.

NOTE: For brevity I will only show 5 records in the examples in this page.

Creating Another Table

In order to see how JOINs work we need to create another table and populate itwith data. So let's create a new table called 'genres' with the followingproperties.

genreID Unique Identifier 01

genre Music Genre Heavy Metal

boughtbyType of personthat buys thismusic

Greasy HairedBikers

mysql> CREATE TABLE genres (

  -> genreID INT(2) auto_increment primary key,

  -> genre VARCHAR(20),

  -> boughtby VARCHAR(30)

  ->);

Insert the following genres into your genres table. The descriptions for the peoplethat buy the music (boughtby) - I'll leave to you. You could also add othergenres that are perhaps more relevant to your music collection.

Pop Example INSERT:

Page 45: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 45/197

mysql> INSERT INTO genres VALUES (

  -> '?',

  -> 'Heavy Metal',

  -> 'Greasy Haired Bikers'

  -> );

Easy Listening

'Classic' Rock

Heavy Metal

Soul

Seventies

Eighties

Hip Hop

Jazz

Guitar Bands

This could (depending on what you enter as descriptions) result in a table likethis:

mysql> SELECT *

-> FROM genres;

+---------+----------------+------------------------------------------------+

| genreID | genre | boughtby |

+---------+----------------+------------------------------------------------+

| 1 | Pop | Little girls and adults who should know better |

Page 46: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 46/197

| 2 | Easy Listening | Crushed velvet wearing lounge lizards |

| 3 | "Classic" Rock | Middle-aged men reliving their youth |

| 4 | Heavy Metal | Wannabe Bikers - who work PT at safeway |

| 5 | Soul | White Boys in thin leather ties |

| 6 | Seventies | Those not born til 1980 |

| 7 | Eighties | Those born in the '70's |

| 8 | Hip Hop | Middle-class Ghetto wannabes |

| 9 | Jazz | Those that *think* they are better |

| 10 | Guitar Bands | Those stuck in 1996 |

+---------+----------------+------------------------------------------------+

10 rows in set (0.00 sec)

Adding a genre to the 'cds' table

Next we need to add a 'genreID' column to our 'cds' table so we can storeinformation about the genre of each cd. This will be an Integer (numeric) field asit will correspond to the unique identifier ('genreID') from the genres table.

Page 47: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 47/197

mysql> ALTER TABLE cds

-> ADD genreID INT(2);

Check this has worked by using the describe command.

mysql> DESCRIBE cds;

+--------+-------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+--------+-------------+------+-----+---------+----------------+

| cdID | int(3) | | PRI | NULL | auto_increment |

| artist | varchar(20) | YES | | NULL | |

| title | varchar(30) | YES | | NULL | |

| year | int(4) | YES | | NULL | |

| label | varchar(20) | YES | | NULL | |

| bought | date | YES | | NULL | |

Page 48: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 48/197

| tracks | int(2) | YES | | NULL | |

| genreID| int(2) | YES | | NULL | |

+--------+-------------+------+-----+---------+----------------+

8 rows in set (0.00 sec)

IMPORTANT: As we now have a column called 'genreID' in both tables we needto distinguish which we are talking about. This is why we have been prefixing thecolumn name with the table name to ensure we can tell the difference. For

example 'cds.genreID' and 'genres.genreID' are easily distinguishable in ourexample.

We are now ready to enter the genre type for each cd into our CDs table.

If we decide that our 'Jamiroquai' album is a soul album we need the'genres.genreID' number from our 'genres' table for the soul entry, i.e. '5'. Wemust UPDATE the Jamiroquai record in the CDs table so that the 'cds.genreID'column also has a value of '5'.

mysql> UPDATE cds

-> SET cds.genreID = 5

-> WHERE (cds.cdID = 2);

If we issue a SELECT all command we can see the effect this has.

mysql> select * from cds;

+------+-------------------+------------------+------+---------+

Page 49: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 49/197

| cdid | artist | title | year | genreID |

+------+-------------------+------------------+------+---------+

| 2 | Jamiroquai | A Funk Odyssey | 2001 | 5 |

Continue and enter the rest of the genres into the CDs table.

Beginning with Joins

Before starting with joins we should say a little about what exactly a join is.Basically it is the combining of two rows based on the comparative values inselected columns. This 'super-row' exists only for the duration of the query thatcreates it. We need to use joins to temporarily create 'complete' records from adatabase which may split related data across several tables (perhaps as a resultof normalisation).

Cross-Join

Syntax:

SELECT <column_name>

FROM <table1>, <table2>

A cross-join between two tables takes the data from each row in table1 and joinsit to the data from each row in table2. To give an example lets look at two verysimple tables.

id Food

1 Milk

2 Bone

3 Grass

A cross-join on these tables would produce the following result.

1 Cat 1 Milk

id animal

1 Cat

2 Dog

3 Cow

Page 50: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 50/197

1 Cat 2 Bone

1 Cat 3 Grass

2 Dog 1 Milk

2 Dog 2 Bone

2 Dog 3 Grass

3 Cow 1 Milk

3 Cow 2 Bone

3 Cow 3 Grass

Where every row from one table is joined to every row in the other table. We canalso see the effect of this by using an SQL cross-join on our tables (although inthis example we are asking only to display one column from each table).

mysql> SELECT cds.artist, genres.genre

-> FROM cds, genres;

You should see every artist associated with every genre. This is obviously not avery useful join, but does specify the need for a join that uses some kind of comparison between the two tables.

 The Equi-Join or Inner Join

Syntax:

SELECT <column_name>

FROM <Table1>, <Table2>

WHERE (Table1.column = Table2.column)

In the equi-join the comparison we are making between two columns is that theymatch the same value. We can use this method to select certain fields from bothtables and only the correct rows will be joined together. So if we were to use this join on the cds and genres tables in our own database (using the CDsthat Mark provided in the last virtual workshop as an example).

Page 51: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 51/197

mysql> SELECT cds.artist, cds.title, genres.genre

-> FROM cds, genres

-> WHERE (cds.genreID = genres.genreID);

+------------+------------------------------+----------------+

| artist | title | genre |

+------------+------------------------------+----------------+

| Jamiroquai | A Funk Odyssey | Soul |

| Abba | Abbas Greatest Hits | Seventies |

| Various | Now 49 | Pop |

| westlife | westlife | Pop |

| Various | Eurovision Song contest 2001 | Easy Listening |

+------------+------------------------------+----------------+

5 rows in set (0.00 sec)

Page 52: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 52/197

Obviously your data will be different as you should have different CDs anddifferent genres. If we compare the cross-join and equi-join we can see that theequi-join is just the cross join with a very restrictive WHERE condition, that forcesonly the rows in the second table RELEVANT to the rows in the first table to beretrieved. This method is fine if all we want to do is look at normalised data in atemporarily flat database view. However if we want to filter this data, we have to

start adding more conditions to our WHERE clause and it seems rather redundantto have to specify joining conditions as part of the WHERE condition every time.

 The Left Join

The left join is a mechanism used to join tables before we add other conditionssuch as WHERE etc.

Syntax:

SELECT <column_name>

FROM <Table1>

LEFT JOIN <Table2>

ON Table1.column = Table2.column

Without adding a WHERE clause the Left Join produces the same results as theequi-join example above.

mysql> SELECT cds.artist, cds.title, genres.genre

-> FROM cds

-> LEFT JOIN genres

-> ON cds.genreID = genres.genreID;

Page 53: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 53/197

+-------------------+------------------------------+----------------+

| artist | title | genre |

+-------------------+------------------------------+----------------+

| Jamiroquai | A Funk Odyssey | Soul |

| Abba | Abbas Greatest Hits | Seventies |

| Various | Now 49 | Pop |

| westlife | westlife | Pop |

| Various | Eurovision Song contest 2001 | Easy Listening |

+-------------------+------------------------------+----------------+

5 rows in set (0.00 sec)

An important thing to note with this particular join is that even if there are norecords in the second table (in this case 'genres') data will still be displayed fromthe first table. Or in other words data from the LEFT of the join will be displayedand is where the term LEFT JOIN comes from. To demonstrate this, UPDATE agenreID from row four (cdID of 5, because we deleted one row in  part three) of thecds table (in this case westlife) to a value that doesn't exist in the genres table.

mysql> UPDATE cds

Page 54: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 54/197

SET cds.genreID = 100

WHERE (cds.cdID = 5);

...and run the query again....

mysql> SELECT cds.artist, cds.title, genres.genre

-> FROM cds

-> LEFT JOIN genres

-> ON cds.genreID = genres.genreID;

+-------------------+------------------------------+----------------+

| artist | title | genre |

+-------------------+------------------------------+----------------+

| Jamiroquai | A Funk Odyssey | Soul |

| Abba | Abbas Greatest Hits | Seventies |

| Various | Now 49 | Pop |

Page 55: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 55/197

| westlife | westlife | NULL |

| Various | Eurovision Song contest 2001 | Easy Listening |

+-------------------+------------------------------+----------------+

5 rows in set (0.00 sec)

The artist and title are still displayed even though there is no data in the genre(and thus NULL is shown). To further illustrate this we can issue a RIGHT JOINwhich is a variation where all the data on the RIGHT side of the join (the second

table) is returned regardless of the presence of data from the first table.Reset row four of the cds table to have the correct genreID value.

mysql> UPDATE cds

-> SET cds.genreID = 1

-> WHERE (cds.cdID = 5);

And run the RIGHT JOIN query including genres.genreID.

mysql> SELECT cds.artist, cds.title, genres.genreID, genres.genre

-> FROM cds

  -> RIGHT JOIN genres

-> ON cds.genreID = genres.genreID;

Page 56: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 56/197

+--------------------+------------------------------+---------+----------------+

| artist | title | genreID | genre |

+--------------------+------------------------------+---------+----------------+

| Various | Now 49 | 1 | Pop |

| westlife | westlife | 1 | Pop |

| Various | Eurovision Song contest 2001 | 2 | Easy Listening |

| NULL | NULL | 3 | "Classic" Rock |

| NULL | NULL | 4 | Heavy Metal |

| Jamiroquai | A Funk Odyssey | 6 | Soul |

| Abba | Abbas Greatest Hits | 6 | Seventies |

| NULL | NULL | 7 | Eighties |

| NULL | NULL | 8 | Hip Hop |

| NULL | NULL | 9 | Jazz |

Page 57: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 57/197

| NULL | NULL | 10 | Guitar Bands |

+--------------------+------------------------------+---------+----------------+

19 rows in set (0.00 sec)

Note that where there aren't any cds in a genre then a NULL value is returned.This is because every record of the RIGHT side must be returned at least once bythe RIGHT JOIN.

Adding a WHERE Clause to our Join

Now we have the join occurring out with the WHERE clause, we can begin to add

other conditions. For example if we want to select only the pop CDs

mysql> SELECT cds.artist, cds.title, genres.genre

-> FROM cds

-> LEFT JOIN genres

-> ON cds.genreID = genres.genreID

-> WHERE genres.genre = 'pop';

+----------+----------+-------+

| artist | title | genre |

Page 58: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 58/197

+----------+----------+-------+

| Various | Now 49 | Pop |

| westlife | westlife | Pop |

+----------+----------+-------+

2 rows in set (0.00 sec)

 The USING Clause

A variation on the Left Join is the 'USING' clause. You can use this if the columnsyou are carrying out the join on have the same name.

Syntax:

SELECT <column_name>

FROM <Table1>

LEFT JOIN <Table2>

USING (<column_name>)

In our example we are joining the tables where cds.genreID is the sameas genres.genreIDthus genreID is the name of a column in BOTH of tables weare using for the join.

mysql> SELECT cds.artist, cds.title, genres.genre

Page 59: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 59/197

  -> FROM cds

-> LEFT JOIN genres

-> USING (genreID);

+-------------------+------------------------------+----------------+

| artist | title | genre |

+-------------------+------------------------------+----------------+

| Jamiroquai | A Funk Odyssey | Soul |

| Abba | Abbas Greatest Hits | Seventies |

| Various | Now 49 | Pop |

| westlife | westlife | Pop |

| Various | Eurovision Song contest 2001 | Easy Listening |

+-------------------+------------------------------+----------------+

5 rows in set (0.00 sec)

Page 60: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 60/197

Mini Exercise

Practice joining the 'CDs' and 'genre' tables to retrieve different data about theCDs, e.g.

mysql> SELECT cds.artist, genres.boughtby

-> FROM cds

-> LEFT JOIN genres

-> USING (genreID);

+-------------------+------------------------------------------------+

| artist | boughtby |

+-------------------+------------------------------------------------+

| Jamiroquai | White Boys in thin leather ties |

| Abba | Those not born til 1980 |

| Various | Little girls and adults who should know better |

| westlife | Little girls and adults who should know better |

Page 61: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 61/197

| Various | Crushed velvet wearing lounge lizards |

+-------------------+------------------------------------------------+

5 rows in set (0.00 sec)

Preparing to Join more than two tables

It is also possible to join more than two tables. In order to do this, however, wewill need to make a third table - this time an 'artist' table containing the artistIDand name. This will use a lot of the techniques we've used in the previousworkshops, so you may have to refer back to refresh your memory as to whatyou are doing, which will serve as more good revision. We are going to create ournew table using a five stage process

• CREATE the new table

• INSERT our artist data using a SELECT DISTINCT query

• ALTER TABLE to add a new 'artistID' COLUMN to the cds TABLE

• UPDATE the cds.artistID fields to match the values assigned to an artist inthe new table

• DROP the artist column from the cds TABLE

We'll go through each step in more detail

CREATE the new table

A simple enough revision of what we've done before.

mysql> CREATE TABLE artists (

  -> artistID int(3) auto_increment primary key,

-> Artist varchar(20)

  -> );

Page 62: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 62/197

INSERT our artist data using a SELECT DISTINCT query

This uses similar syntax to that in Workshop Four . We are going to insert the artistsfrom the cds table into the artist.Artist column.

mysql> INSERT INTO artists (artists.Artist)

-> SELECT DISTINCT cds.artist

-> FROM cds;

You can check this has worked by using a (by now) standard SELECT statement.

mysql> SELECT *

-> FROM artists;

ALTER TABLE to add a new 'artistID' COLUMN to the cds TABLE

As we are going to refer to the artist by their artistID rather than their name, weneed to create a column in the cds table to hold that ID.

mysql> ALTER TABLE cds

-> ADD artistID int(3);

Check this has worked with a describe statement.

mysql> DESCRIBE cds;

+----------+-------------+------+-----+---------+----------------+

Page 63: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 63/197

| Field | Type | Null | Key | Default | Extra |

+----------+-------------+------+-----+---------+----------------+

| cdID | int(3) | | PRI | NULL | auto_increment |

| artist | varchar(20) | YES | | NULL | |

| title | varchar(30) | YES | | NULL | |

| year | int(4) | YES | | NULL | |

| label | varchar(20) | YES | | NULL | |

| bought | date | YES | | NULL | |

| tracks | int(2) | YES | | NULL | |

| genreID | int(2) | YES | | NULL | |

| artistID | int(3) | YES | | NULL | |

+----------+-------------+------+-----+---------+----------------+

9 rows in set (0.00 sec)

Page 64: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 64/197

UPDATE the cds.artistID fields without Joins

For those with access to older versions of MySQL this will have to be done byhand. If you are lucky enough to have MySQL 4.0 installed, then you could useUPDATE joins to speed up this stage, but for consistency between versions MySQLI will demonstrate the method common to older and newer versions of MySQL.

mysql> UPDATE cds

-> SET cds.artistID = 1

-> WHERE (cds.artist = 'Jamiroquai');

......etc usng all the artistIDs from the artists table. Check that this has workedwith a few joins between the cds and artists TABLEs eg

mysql> SELECT artists.Artist, cds.title

-> FROM artists

-> LEFT JOIN cds

-> USING (artistID)

-> WHERE (cds.artistID = 1);

+------------+----------------+

| name | title |

Page 65: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 65/197

Page 66: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 66/197

Page 67: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 67/197

The problem with this is, once more, that we already have a fairly complexWHERE clause just to join ALL the records properly. Ideally what we want is tohave a LEFT / RIGHT JOIN, but this is a problem as we cannot compare just twotables (Right vs Left). The solution to this is to use a series of joins. This is whereone join is made, but rather than being used to evaluate and display the datafrom it, the result is passed to a second join and THEN the data can be displayed.

A good way to think of this is that the first JOIN creates a virtual table (from joining tables one and two) which can then be joined to the third table.

So let us first make a LEFT JOIN between the 'cds' and 'genres' tables.

mysql> SELECT cds.title, genres.genre

-> FROM cds

  -> LEFT JOIN genres

-> ON cds.genreID = genres.genreID;

+------------------------------+----------------+

| title | genre |

+------------------------------+----------------+

| A Funk Odyssey | Soul |

| Abbas Greatest Hits | Seventies |

| Now 49 | Pop |

Page 68: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 68/197

| westlife | Pop |

| Eurovision Song contest 2001 | Easy Listening |

+------------------------------+----------------+

5 rows in set (0.02 sec)

Next we add another JOIN and SELECT the artists.Artist as well. The order inwhich you SELECT COLUMNs determines how your results will look, so we shouldplace artists.Artist first.

mysql> SELECT artists.Artist, cds.title, genres.genre

-> FROM cds

  -> LEFT JOIN genres

-> ON cds.genreID = genres.genreID

-> LEFT JOIN artists

-> ON cds.artistID = artists.artistID;

+------------+------------------------------+----------------+

| name | title | genre |

Page 69: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 69/197

+------------+------------------------------+----------------+

| Jamiroquai | A Funk Odyssey | Soul |

| Various | Now 49 | Pop |

| westlife | westlife | Pop |

| Various | Eurovision Song contest 2001 | Easy Listening |

| Abba | Abbas Greatest Hits | Seventies |

+------------+------------------------------+----------------+

5 rows in set (0.01 sec)

We can now add a WHERE clause to restrict the output.

mysql> SELECT artists.Artist, cds.title, genres.genre

-> FROM cds

  -> LEFT JOIN genres

-> ON cds.genreID = genres.genreID

Page 70: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 70/197

  -> LEFT JOIN artists

-> ON cds.artistID = artists.artistID

-> WHERE (genres.genre = 'Pop');

+----------+----------+-------+

| name | title | genre |

+----------+----------+-------+

| Various | Now 49 | Pop |

| westlife | westlife | Pop |

+----------+----------+-------+

2 rows in set (0.01 sec)

We could also join a fourth table, imagine we were to repeat the steps above to

create a 'label' table. We could issue the a statement to join all four tables anddisplay the results.

mysql> SELECT artists.Artist, cds.title, label.Label, genres.genre

-> FROM cds

Page 71: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 71/197

  -> LEFT JOIN genres

-> ON cds.genreID = genres.genreID

-> LEFT JOIN artists

-> ON cds.artistID = artists.artistID

  -> LEFT JOIN label

-> ON cds.labelID = label.labelID;

+------------+------------------------------+------------+----------------+

| Artist | title | Label | genre |

+------------+------------------------------+------------+----------------+

| Jamiroquai | A Funk Odyssey | Sony soho2 | Soul |

| Various | Now 49 | virgin | Pop |

| westlife | westlife | jive | Pop |

| Various | Eurovision Song contest 2001 | EMI | Easy Listening |

Page 72: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 72/197

| Abba | Abbas Greatest Hits | EMI | Seventies |

+------------+------------------------------+------------+----------------+

5 rows in set (0.01 sec)

This method of adding tables and performing JOINS will work only if one TABLEhas all the foreign keys. Joins CAN be more complex mixing types etc, but I don'tthink it is necessary to go into that here.

UPDATE and DELETE Joins

Requires MySQL 4.0 or later.

As MySQL 4.0 has been deemed to be stable enough for production use it is worthmentioning some of the functionality that has been added and significantly thisincludes UPDATE and DELETE joins. To find out the version of MySQL that youhave access to you are usually told when you login at the command-line:

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

Your MySQL connection id is 2471 to server version: 4.0.12

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

But you can also check from the command-line using a 'STATUS' command:

Page 73: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 73/197

mysql> STATUS

--------------

mysql Ver 12.18 Distrib 4.0.12, for pc-linux (i586)

Connection id: 2563

Current database:

Current user: kbrown@localhost

SSL: Not in use

Current pager: stdout

Using outfile: ''

Server version: 4.0.12

If you do indeed have access to MySQL 4.0 then you can continue with thisworkshop.

UPDATE Joins

Before looking at the syntax let's pause for a moment and think why we wouldwant a to perform a Join as part of a UPDATE statement? Well the answer is to

Page 74: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 74/197

update more than one table using only one statement or indeed to insert thevalues from one table into another.

The syntax for UPDATE joins is very similar to a normal UPDATE statement onlyincluding one of the Joins specified above in much the same way as the selectstatement did. Thus to use an Equi-Join in the statement, we specify the tablestogether, what we want to SET and then use a WHERE condition to apply theconstraint.

UPDATE <table1>, <table2>

SET <column_name> = 'new_value'

WHERE <conditions>

For Example let's temporarily change the values of the 'A Funk Odyssey' album sothat it was recorded by 'George Clinton' (see  bio if you're confused), and called'The Funkship Odyssey' (one of the lesser known works ;-). Thus we have toupdate the 'cds' (to change the title) and the 'artists' table, use one condition toconstrain the join (cds.artistID =artists.artistID) and then a final condition to onlyeffect that row (and not all rows).

mysql> UPDATE cds, artists

  -> SET

-> cds.title = 'The Funkship Odyssey',

-> artists.Artist = 'George Clinton'

  -> WHERE (artists.artistID = cds.artistID)

Page 75: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 75/197

  -> AND (cds.cdID = '2');

Query OK, 2 rows affected (0.00 sec)

Rows matched: 2 Changed: 2 Warnings: 0

You can use a SELECT join described above to view how this has changed thevalues.

mysql> SELECT artists.Artist, cds.title

-> FROM artists

-> LEFT JOIN cds

-> USING (artistID)

-> WHERE (cds.artistID = 1);

+----------------+----------------------+

| name | title |

+----------------+----------------------+

| George Clinton | The Funkship Odyssey |

Page 76: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 76/197

+----------------+----------------------+

1 row in set (0.00 sec)

Of course by replacing 'Jamiroquai' in the 'artists' table it now means that Georgehas recorded all their albums and since George didn't record 'The FunkshipOdyssey' we'd better put things back the way they were. This time we will use aLEFT JOIN to UPDATE the values. In a SELECT statement the LEFT JOIN allowedus to join the tables before applying any constraints and in an UPDATE join this isno different. First we make the LEFT JOIN, then use SET to provide new andfinally use the WHERE condition to restrict which rows this effects.

mysql> UPDATE cds->LEFT JOIN artists

-> ON cds.artistID = artists.artistID

  -> SET

-> cds.title = 'A Funk Odyssey',

-> artists.name = 'Jamiroquai'

  -> WHERE (cds.cdID = '2');

Query OK, 2 rows affected (0.00 sec)

Rows matched: 2 Changed: 2 Warnings: 0

The other purpose of the UPDATE join is to set the value of a column in one tableto that of a column in another table. This isn't particularly spectacular as any

Page 77: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 77/197

column value in a table can be set to the value of another column in the samerow and as any join results in a 'big virtual table' this can be done also.

To illustrate let's recreate the artist field in the cds table that we deleted aboveand repopulate the column using an UPDATE join. First modify the cds table:

mysql> ALTER TABLE cds

-> ADD artist VARCHAR(20);

Next set a value of 'Unknown' for each row.

mysql> UPDATE cds

-> SET artist = 'Unknown';

Query OK, 9 rows affected (0.00 sec)

Rows matched: 9 Changed: 9 Warnings: 0

 

mysql> SELECT cds.artist, cds.title

-> FROM cds;

+---------+------------------------------+

| artists | title |

Page 78: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 78/197

+---------+------------------------------+

| Unknown | A Funk Odyssey |

| Unknown | Now 49 |

| Unknown | westlife |

| Unknown | Eurovision Song contest 2001 |

| Unknown | Abbas Greatest Hits |

+---------+------------------------------+

5 rows in set (0.01 sec)

Next we will use an UPDATE Join to merge with the 'artists' table and SET thevalue of the ofcds.artist = artists.Artist. Let's only do one artist(Jamiroquai again) to see how this works.

mysql> UPDATE cds

-> LEFT JOIN artists

-> USING (artistID)

  -> SET cds.artists = artists.Artist

Page 79: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 79/197

  -> WHERE (cds.cdID = '2');

Query OK, 1 row affected (0.02 sec)

Rows matched: 1 Changed: 1 Warnings: 0

 

mysql> SELECT cds.artists, cds.title

-> FROM cds;

+------------+------------------------------+

| artists | title |

+------------+------------------------------+

| Jamiroquai | A Funk Odyssey |

| Unknown | Now 49 |

| Unknown | westlife |

| Unknown | Eurovision Song contest 2001 |

Page 80: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 80/197

| Unknown | Abbas Greatest Hits |

+------------+------------------------------+

5 rows in set (0.01 sec)

We can rerun the query without the final WHERE condition that constrains therow and all the artists will be correctly identified by the join.

mysql> UPDATE cds

-> LEFT JOIN artists

-> USING (artistID)

  -> SET cds.artists = artists.name;

Query OK, 8 rows affected (0.02 sec)

Rows matched: 9 Changed: 8 Warnings: 0

 

mysql> SELECT cds.artists, cds.title

-> FROM cds;

Page 81: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 81/197

+-------------+------------------------------+

| artists | title |

+-------------+------------------------------+

| Jamiroquai | A Funk Odyssey |

| Various | Now 49 |

| westlife | westlife |

| Various | Eurovision Song contest 2001 |

| Abba | Abbas Greatest Hits |

+-------------+------------------------------+

5 rows in set (0.01 sec)

Notice: These last two examples have included a USING clause as part of theJoin.

DELETE Joins

The final Join that I am going to discuss in this workshop is the DELETE Join. Thisis pretty much a case of 'same again' so I'll only give a quick examples in whichI'll delete Westlife who have an artistID = '3' (if only it were that easy ;->.

To DELETE from just the 'cds' table include only the 'cds' table between DELETEand FROM (the join is made after FROM so both tables are needed there).

Page 82: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 82/197

mysql> DELETE cds

-> FROM cds, artists

-> WHERE (cds.artistID = artists.artistID)

-> AND (cds.artistID = '3');

To DELETE from both tables:

mysql> DELETE cds, artist

-> FROM cds, artist

  -> WHERE (cds.artistID = artists.artistID)

-> AND (cds.artistID = '3');

Phew.. I bet you're glad that's over. ;-)

Using MySQL, Administration

Workshop RequirementsYou should have access to the MySQL command line client software.

Various different PRIVILEGES on the MySQL Server

Introduction

In the other MySQL Virtual Workshops we have used commands that are prettymuch applicable to anyone. This part of the MySQL series is aimed at giving a

Page 83: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 83/197

rudimentary understanding of managing a MySQL database server. As such thetask covered here are not really about manipulating data or database structures,but the actual databases themselves.

Creating a Database

In order to create a database you need to have the PRIVILEGES- this may bebecause you are the root user or you (or you systems administrator) has createdan admin user that has ALL PRIVILEGES over all databases. In these examples auser called 'admin' has been created precisely for this purpose. Creating adatabase is fairly straightforward.

Logging In

A reminder of how to start the MySQL Client Software, and as we are notconcerned with manipulating just one database we don't have to specify adatabase as part of our startup command.

$ mysql -u <username> -p

Enter password:

Create database command

Next we are ready to enter the very simple command to create a database which

is:

mysql> CREATE DATABASE <database>;

Let's imagine that we are going to create a 'vworks' database (those wishing tocreate a database for use with the VWs should use this). We would enter thecommand:

mysql> CREATE DATABASE vworks;

We can now check for the presence of this database by typing:

mysql> SHOW DATABASES;

Page 84: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 84/197

+-----------+

| Database |

+-----------+

| mysql |

| vworks |

+-----------+

2 rows in set (0.06 sec)

The other database listed ('mysql') is the internal database which MySQL uses tomanage users, permissions etc.

NOTE: Deleting or DROPing a database is similar to the DROP TABLE commandissued in Part 4. e.g.

DROP DATABASE <database>

Granting Privileges on the new database

Now that we have created a database, we need to decide who gets to use it. Thisis done by granting permissions for a user to use the database. This has a

simplified syntax of:

GRANT <privileges>

ON <database>

Page 85: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 85/197

TO <user>

[IDENTIFIED BY <password>]

[WITH GRANT OPTION]

Where the items in square brackets are optional. The most common use is to giveALL PRIVILEGES on a database to a local user who has to use a password toaccess the database (in this case vworks).

mysql> GRANT ALL PRIVILEGES

-> ON vworks.*

-> TO newuser@localhost

-> IDENTIFIED BY 'newpassword';

If you are creating a database for use with the rest of the Virtual Workshops youshould use this statement, substituting your username and password of choice.There are some other options we will look at. To restrict the user to manipulatingdata (rather than table or database structures) the statement would be alteredto:

mysql> GRANT SELECT,INSERT,UPDATE,DELETE

-> ON vworks.*

-> TO newuser@localhost

Page 86: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 86/197

  -> IDENTIFIED BY 'newpassword';

So that the user can only change the data using SELECT,INSERT,UPDATE orDELETE statements. If you wished to give a non-local user permissions on thedatabase (for use with remote clients) then you could designate an IP or hostaddress from which the user can connect:

mysql> GRANT ALL PRIVILEGES

-> ON vworks.*

-> TO [email protected]

-> IDENTIFIED BY 'newpassword';

Now a user on the machine '192.168.0.2' can connect to the database. To allow auser to connect from anywhere you would use a wildcard '%'

mysql> GRANT ALL PRIVILEGES

-> ON vworks.*

-> TO newuser@'%'

-> IDENTIFIED BY 'newpassword';

You could even decide that a user doesn't need a password if connecting from acertain machine.

mysql> GRANT ALL PRIVILEGES

Page 87: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 87/197

  -> ON vworks.*

-> TO [email protected]

But I think it is sometimes good to provide a password anyway. Finally we'll lookat the WITH GRANT OPTION condition. This allows the user to give othersprivileges to that database:

mysql> GRANT ALL PRIVILEGES

-> ON vworks.*

-> TO newuser@localhost

-> IDENTIFIED BY 'newpassword'

-> WITH GRANT OPTION;

This would allow the user 'newuser' to log into the database and give their friendprivileges to SELECT,INSERT,UPDATE or DELETE from the database.

mysql> GRANT SELECT,INSERT,UPDATE,DELETE

-> ON vworks.*

-> TO friend@localhost

-> IDENTIFIED BY 'friendpass';

Page 88: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 88/197

The WITH GRANT OPTION usually signifies ownership although it is worth notingthat no user can GRANT more privileges that they themselves possess.

Revoking privileges

Revoking privileges is almost identical to granting them as you simply substitute

RE VOKE.... FROM for GRANT....TO and omit any passwords or other options.For example to REVOKE the privileges assigned to a user called 'badvworks':

mysql> REVOKE ALL PRIVILEGES

-> ON vworks.*

-> FROM badvworks@localhost;

Or just to remove UPDATE, INSERT and DELETE privileges to that data cannot bechanged.

mysql> REVOKE INSERT,UPDATE,DELETE

-> ON vworks.*

-> FROM badvworks@localhost;

Backing Up Data

There are several methods we can use to backup data. We are going to look at a

couple of utilities that come with MySQL: mysqlhotcopy and mysqldump.

mysqlhotcopy

mysqlhotcopy is a command line utility written in Perl that backs up (to a locationyou specify) the files which make up a database. You could do this manually, butmysqlhotcopy has the advantage of combining several different commands thatlock the tables etc to prevent data corruption. The syntax (as ever) first.

Page 89: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 89/197

$ mysqlhotcopy -u <username> -p <database> /backup/location/

Which SHOULD copy all the tables (*.frm, *.MYI, *.MYD) into the new directory -the script does require the DBI perl module though. To restore these backup filessimply copy them back into your MySQL data directory.

mysqldump

This is my preferred method of backing up. This outputs the table structure anddata in series of SQL commands stored in a text file. The simplified syntax is

$ mysqldump -u <username> -p <database> [<table>] > file.sql

So for example to back up a 'vworks' database which may have been created bycompleting the workshops:

$ mysqldump -u admin -p vworks > vworks.sql

After entering the password a 'vworks.sql' file should be created. When you lookat this file you can actually see that the data and structures are stored as a seriesof SQL statements. e.g.:

-- MySQL dump 8.22

--

-- Host: localhost Database: vworks

---------------------------------------------------------

-- Server version 3.23.52

Page 90: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 90/197

--

-- Table structure for table 'artist'

--

CREATE TABLE artist (

  artistID int(3) NOT NULL auto _increment,

  name varchar(20) default NULL,

  PRIMARY KEY (artistID)

) TYPE=MyISAM;

--

-- Dumping data for table 'artist'

--

Page 91: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 91/197

INSERT INTO artist VALUES (1,'Jamiroquai');

INSERT INTO artist VALUES (2,'Various');

INSERT INTO artist VALUES (3,'westlife');

INSERT INTO artist VALUES (4,'Various');

INSERT INTO artist VALUES (5,'Abba');

And so on for the other tables.

We could also have chosen to output just one table from the database, for

example the artist table:

$ mysqldump -u admin -p vworks artist > artist.sql

We could even dump all the databases out (providing we have the permissions).

$ mysqldump -u admin -p --all-databases > alldb.sql

Restoring a Dump

Restoring a dump depends on what you have actually dumped. For example torestore a database to a blank database (perhaps having transferred the sql file toanother machine) it is fairly simple.

$ mysql -u admin -p vworks < vworks.sql

Page 92: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 92/197

...or to add a non-existent table to a database...

$ mysql -u admin -p vworks < artist.sql

However, what happens if we want to restore data to an existing database

(perhaps a nightly backup) ? Well we would have to add other options:

The equivalent of overwriting the existing tables would be telling the dump toautomatically drop any tables that exist before restoring the stored tables. This isdone with the ' --add-drop-table ' option added to our statement.

$ mysqldump -u admin -p --add-drop-table vworks > vworks.sql

Then restore like normal:

$ mysql -u admin -p vworks < vworks.sql

The reverse might also be true. We may wish to create the database if it doesn'talready exist. To do this we use the '--databases' option to specify the databasewe wish to back up (you can specify more than one).

$ mysqldump -u admin -p --databases vworks > vworksDB.sql

This will create additional SQL statements at the start of each database thatCREATEs the dumped database (checking first to see if it does indeed exist) thenUSEing that database to import the table data into.

-- Current Database: vworks

--

CREATE DATABASE /*!32312 IF NOT EXISTS*/ vworks;

Page 93: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 93/197

USE vworks;

Again we can resort like normal, but of course this time we can omit the databasename.

$ mysql -u admin -p < vworksDB.sql

Optimising a dump

There are a couple of options that are sometimes worth including when backingup and restoring large databases.

The first option is '--opt', this is used override the mysql server's normal methodof reading the whole result set into memory giving a faster dump. Example:

$ mysqldump -u admin -p --opt vworks > vworks.sql

The second option is '-a' or '-all' (either will do). Which also optimises the dumpby creating mysql specific CREATE statements that speeds up the restore:

$ mysqldump -u admin -p --all vworks > vworks.sql

Using mysqldump to copy databases.

It is possible to combine a dump and a restore on one line by using a pipe '|' topass the output of the dump directly to mysql basically bypassing the file. Thismay initially seem a bit redundant, but we can use this method to copy adatabase to another server or even create a duplicate copy.

For example to copy the 'vworks' database to a mysql server called'remote.server.com':

$ mysqldump -u admin -p --databases vworks | \

> mysql -u backup -p MyPassword -h remote.server.com

Page 94: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 94/197

Note: the"\" at the end of the first line means you wish to contine the commandon another line before executing it.

You may, in certain circumstances, wish to make a copy of live data so that youcan test new scripts and 'real world' data. To do this you would need to duplicatea local database. First create the duplicate database:

mysql> CREATE DATABASE vworks2;

Then once appropriate privileges have been assigned we can copy the tables fromthe first table into the second.

$ mysqldump -u admin -p vworks | mysql -u backup -p MyPassword vworks2

Notice in both these examples the second half of the line (after the pipe) passes

the password as part of the connection statement. This is because asking for twoseparate passwords at the same time breaks most shells. That is why I have useda 'backup' user who can be granted permissions and have them revoked asnecessary.

Miscellaneous Leftovers

This final bit includes a few brief tricks that weren't really appropriate to includeelsewhere, but are still worth noting.

Remote Client Connection

If you have set the privileges to allow remote connections to a database, you canconnect from a remote command line client by using the -h flag:

$ mysql -u <username> -p -h <host>

For example to connect to a fictional vworks.keithjbrown.co.uk server:

$ mysql -u admin -p -h vworks.keithjbrown.co.uk 

Non-Interactive Commands

Sometimes you may wish to just do a quick look up on a table without the hassleof logging into the client, running the query then logging back out again. You caninstead just type one line using the ' -e ' flag. For example:

Page 95: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 95/197

$ mysql -u admin -p vworks -e 'SELECT cds.artist, cds.title FROM cds'

Enter password:

+------------+------------------------------+

| artist | title |

+------------+------------------------------+

| Jamiroquai | A Funk Odyssey |

| Various | Now 49 |

| westlife | westlife |

| Various | Eurovision Song contest 2001 |

| Abba | Abbas Greatest Hits |

+------------+------------------------------+

Page 96: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 96/197

Using MySQL, Normalisation

Workshop Requirements

You should have experience of using databases and be familiar with retrievingdata from multiple tables using SQL joins. It is also advised that you haveundertaken parts 1 -5 of this MySQL series so that you are familiar with theexamples used so far.

Page 97: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 97/197

Page 98: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 98/197

Before we begin looking at the stages of normalisation it is worth having a brief look at some of the relational database concepts that inform the process.

Relational Databases

Relational databases, such as MySQL, are so called as they rely on a series of 

relationships to connect data stored in different tables. For example in Workshop5 we looked at joining tables based on a common ID number. This ID number wasstored as the uniquely valued field (Primary Key) in one table (for example in theartists table), but was also present in another table (the cds table) acting as areference (Foreign Key) that allowed data to be retrieved from both tables whenthe values matched. For ease of understanding we used unique numbers, but akey can have any value provided it conforms to a few rules.

 Terminology

When were we were looking at the physical database in the other workshops we

used certain terms such as TABLE, COLUMN, ROW and FIELD. Discussion of database theory uses different terms:

Relation/ Entity - These are the same as a table.

Attributes - These are similar to columns in that they describe the type of datastored.

Domain - This is values within the same attribute (a collection of fields that existin the same column).

Tuple - This is a record similar to a row.

As I'm trying to tie the theoretical discussion to the practical database experience

that the first Virtual Workshops provide, I will use both sets of terms in thisworkshops for clarity and to reinforce their meanings.

Different Keys

The Primary Key is frequently used to identify a specific row (although other keysmay exist) and all the other values are dependent on that value to bemeaningfully identified. A primary key is usually one attribute (column) in arelation (table), but can be a combination of attributes (Composite Key). If weconsider the following attributes some cds may have.

CatalogueNo.

Artist Title

The obvious Primary Key for a CDs table would be the Catalogue No. as each cdhas already been given a unique identifier. But consider if we knew for a FACTthat each artist could only release one CD per year (perhaps something a coldwar communist five year plan would envisage ;-).

CDs

Page 99: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 99/197

CatalogueNo.

Artist Year Title

By adding the Year attribute we could also use the combination of Artist and Yearto identify the row, as together they form a Composite Key. Thus we have twopotential or Candidate Keys.We would probably still choose the Catalogue No. asit is simpler to use one column. Consider a Radio station wishing to record howmany times a day they played a CD. The combination of Catalogue No. and thedate would be sufficient to identify that record in a new Play History table.

 

Play History

CatalogueNo.

DateTimesPlayed

In this situation the Catalogue No. number is a Primary Key in the CDs table butonly part of the Composite Key in the Play History table as the date is required toform the whole key. An alternative could have been to create a new unique

single-attribute Primary Key for the table. As we still need to know the cataloguenumber in order to work out how many times a DJ has played Britney, Christinaor Pink (BBC Radio One is just rubbish isn't it? ;-). The catalogue number wouldbecome the Foreign Key in the Play History table, i.e. a Foreign Key is a attribute(column) in a table that refers to a Primary Key in another table.

Play History

HistoryIDCatalogueNo.

DateTimesPlayed

During the Normalisation process we will look at the rules that determine how

tables (and thus Keys) are formed.

NULLs

NULLs are used in databases to signify that no value exists, but are not reallyvalues themselves. Instead they are just an indictor that a particular field has novalue. Some argue this is better that leaving a blank value or having a defaultvalue. I personally see little value in a blank field, but default values (such asinserting the current date if no date is offered) can be useful. The interestingpoint about NULLs is that no Primary Key can contain a NULL and thus it's usefulwhen comparing Candidate Keys to see if one could potentially contain a NULL,

thus disqualifying that key.

Functional Dependency

This is another important concept and describes the relationship that columnshave to the Primary Key. If the value of a column can be determined by knowingthe value of the Primary Key and no other, then that column is said to befunctionally dependent. Or more simply, if we know the value of Primary Key we

Page 100: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 100/197

can find out the value of any other dependent column. This dependency is oftenwritten as follows (where A is the Primary Key and B is the dependent column):

A B→

So for the CDs table above we could express the dependency of the title columnas either:

Catalogue No Title→ or

(Artist, Year) Title→

This is important as we will see later as having a column that is NOT whollydependent on the Primary Key causes redundancy. Having introduced some of theterminology of Normalisation we can begin to look at the stages.

Describing relations (tables)

When describing tables there is a way of expressing their structure that we willfollow here. This includes the name of the relation, the attributes within therelation and which attributes are key. The format of this is:

RELATION (attribute one, attribute two, attribute three etc)

NOTE: The key attribute is underlined to signify its status and the relation isalways UPPERCASE.

For example consider how we might express the CDs table above:

CDS (Catalogue No, Artist, Year, Title)

Stages of Normalisation

There are several stages of normalisation that a database structure can besubject to, each with rules that constrain the database further and each creatingwhat is called a Normal Form. These are, in order:

• First Normal Form (1NF)

• Second Normal Form (2NF)

• Third Normal Form (3NF)

• Boyce Codd Normal Form (BCNF)

• Fourth Normal Form (4NF)

Fifth Normal Form (5FN)As the database goes through each stage of normalisation it is said to be in thenormal form of that stage, i.e. my database is 2NF and I need it to be 3NF. Weare not going to take a detailed look at all of these Normal Forms as BCNF, 4NFand 5NF are probably overkill for small to medium databases, with the first 3normal forms usually being sufficient. There is also one other stage - that of theUn-normalised Normal Form (UNF) which is the starting point for Normalisation.To begin our examination we must first create this Un-normalised data.

Page 101: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 101/197

Our Scenario

In order to look at database normalisation we are going to use a fictional CDlibrary (quaint in the post-napster internet age I know). Monitoring who haswhich CD is done by logging the CDs in and out of a loans logbook that containsthe following information (with sample data):

DateBorrowed

DueBack

Borrower Artist Title

1st Dec 8thDec

DavidFindlay

BritneySpearsPinkChristinaAguilera

BritneyCant Take MeHomeStripped

8th Dec 15thDec

IainBrown

DariusChristina

AguileraWill Young

Dive InStripped

From Now On

Loans Log

Information is also stored about each borrower in a separate register:

Borrower AddressTelephoneNo.

E-mail

DavidFindlay

DaviesLodge23 DrivenStEdinburghEH5 APE

0131 5555579

[email protected]

Iain Brown 54 HomeSt,Edinburgh,EH23 8TF

0131 5555580

[email protected]

Borrower Log

Finally there is a ledger that stores information about the CDs:

Artist Title Year LabelNo. of Tracks

Copy

BritneySpears

Britney 2001 Jive 14 1

PinkCant TakeMe Home

2002 LaFace 15 3

Page 102: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 102/197

ChristinaAguilera

Stripped 2002 RCA 20 1

Darius Dive In 2002 Mercury 13 2

Will YoungFrom NowOn

2002 RCA 13 2

CDs Log

We can see that by keeping the information in different places there has beensome common sense organisation to avoid repeatedly entering the same data.This is quite common, but doesn't really help up as we need to use thenormalisation rules to determine our structure. Thus to begin with we'll merge thefields (attributes) into a one-table structure along with the same sample data(figure one).

We have also created a column called 'Transaction No' which we use as a primarykey to uniquely identify each lending transaction. We do this as there is no other

simple method of identifying the row, as the obvious Composite Key is prettycomplex (date borrowed, name, artist, title ), and thus assigning a unique'Transaction No' is sensible at this time.

Note: As I mentioned above, a modeling tool like Entity Relationship diagrammingis good to use before normalisation. This would be essential on larger databaseprojects as it would be pretty impossible to create one big flat database to beginnormalising. It is also worth noting that although we have included sample data,we are normalising the database structure and not the data itself. It can be easierhowever to spot potential problems when using example data.

So to begin the normalisation process, we use the Un-normalised data and applyour first rules.

First Normal Form (1NF)

For a relation (table) to conform be 1NF, it must obey the following rules:

To ensure that all attributes (columns) are atomic - what this means is that anysingle field should only have a value for ONE thing. For example in a 'cars'database a field in a car may have a value 'Blue Ford Focus'. This field is notatomic as it contains more than one piece of information (colour, manufacturerand model). To demostrate the problem with this, try to imagine constructing a

query to select all Ford cars. This would be difficult as the value 'Ford' is trappedin the middle of the field. We must therefore split this column into three (colour,manufacturer, model).

There must be no repeating groups. This is perhaps most easily understood asthere cannot be repeating columns (that which contain the same type of information). For example a cars field may contain a list of Ford cars (Focus,Mondeo, Puma). As we know we must also make this field atomic, but splittingthe column into three (cars1, cars2, cars3) to hold these values isn't an option

Page 103: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 103/197

this time as that would create three domains that contain similar data. In practicethis would make querying the databases difficult as we would have to create astatement to match potential values in 3 columns (or four, or five or a hundred if there was a list of a hundred). Splitting the field so that each value was in aseparate row would require the other values in the rows to be repeated. Thesolution is to change the structure of the database by extracting the repeating

groups into a new relation.

1NF in practice

Looking at the Un-normalised data we can see that there are non-atomic attributesin the following columns:

• Borrower

• Address

• The elements that make up the CD information (Artist, Title, Year, Label,No_of_Tracks and Copy)

All of these attributes will have to be normalised so the domain contains onlyatomic values. To begin, let's look at the Borrower attribute. If you look at asection of the table in figure one, the borrower contains a forename and a surname

expressed as a single borrower. Thus we should split this attribute in two. Thefollowing excerpt from the table illustrates how this would be implemented:

TransactionNo. Forename Surname Address TeleNo

1 David Findlay DaviesLodge23 Driven

StEdinburghEH5 APE

01315555579

2 Iain Brown 54 HomeStEdinburghEH23 8TF

01315555580

 

Similarly the address should be broken down into different attributes. Anyone that

has filled out an application form will be familiar with this structure.• Address Line One

• Address Line Two (for the purposes of this workshop we'll stop at twoaddress lines - in reality you may need more)

• City

• Postcode

Once more we can see the effect that this has on an excerpt of the table:

Page 104: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 104/197

TransactionNo. Forename SurnameAddress_ One

Address_ Two

City Postco

1 David Findlay DaviesLodge

23 DrivenSt

Edinburgh EH5 AP

2 Iain Brown 54 HomeSt

  Edinburgh EH23 8

 The Repeating Group

If we have a look at the remaining non-atomic attributes we can see that they aresimilar informational attributes about a CD. In order to make these attributesatomic we cannot repeat the trick of creating additional columns as each repeatedcolumn would hold values of a similar type. If we take the artist field for example:

TransactionNo.(OtherAttributes)

Artist_ One

Artist_Two

Artist_Three

1 ... BritneySpears

Pink ChristinaAguilera

2 ... Darius ChristinaAguilera

Will Young

If we split each original field into 3 we can see the value 'Christina Aguilera'appears twice, once in Artist_Two and once in Artist_Three. If we were searchingto see who had borrowed CDs by Christina we'd have to create a query to searchALL the artist fields. Also if someone borrowed a 4th CD as part of a transactionwe would have to create a fourth Artist column and so on. The other reason that

repeating groups are not allowed to be split into columns is that we MUST knowthe number of columns required in order to create the database.

The alternative, for someone who knew nothing about normalisation, would be to just create extra rows and copy the values in non-repeating attributes - that waywe could make sure that each field contained atomic values as seen in figure two.

This is a trap that we could fall into by looking at only the data. We have notactually changed the structure of the database and thus the problem of repeatinggroups still exists. This can be seen by the fact that the Primary Key is no longerunique. The correct solution is to remove the repeating groups (Artist, Title, Year,

Label, No_of_Tracks and Copy) into a new 'Borrowed CDs' relation .

TransactionNo Artist Title Year LabelNo_of  _Tracks

Copy

1 BritneySpears

Britney 2001 Jive 14 1

1 Pink Cant 2002 LaFace 15 3

Page 105: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 105/197

Take MeHome

1 ChristinaAguilera

Stripped 2002 RCA 20 1

2 Darius Dive In 2002 Mercury 13 2

2 WillYoung

FromNow On

2002 RCA 13 2

2 ChristinaAguilera

Stripped 2002 RCA 20 1

Because we need to be able to join this data back with that left in the originaltable we also need to include the TransactionNo in this Borrowed CDs relationwhich will act (along with a qualifying value) as Key for this relation. Thequalifying value, allowing us to identify each CD in the library, combined with thetransaction number will be able to tell us the specific CD borrowed pertransaction. Thus we next need to define the qualifying value which will be theleast number of attributes required to uniquely identify the CD. This could be(Artist, Title) if we were sure that this was a unique indentifer for a CD, but wealready can see that there are different copies of the same CD. We could tryadding Copy to the Key (Artist, Title, Copy), but in practice having a single uniquevalue for each CD is preferable. Thus we will also create a cdID attribute in thisrelation and use that to represent the uniqueness of a CD.

After achieving First Normal Form our database has two relations as can be seenin figure threeor can be expressed as follows:

LOANS (TransactionNo, Forename, Surname, AddressOne, AddressTwo, City,Postcode, TeleNo, E-mail, Date_Borrowed, Due_Back)BORROWED CDS (TransactionNo, cdID, Artist, Title, Year, Label, No_of_Tracks,Copy)

Second Normal Form (2NF)

The second normal form has one rule that must be followed:

All non-key attributes must be dependant ON THE WHOLE KEY and not just oneattribute of the key. This obviously only applies to Composite Keys and meansthat attributes in the relation that only contain information (and have no role inthe structure of the database) must be functionally dependent on all parts of theKey. Another way of thinking about this is that if there are some attributes thatare not dependent on all parts of the Key this means that they are in the wrongrelation.

For example: Imagine we have a cars_bought table where each row (record)contains information about the car that a customer bought, which has a PrimaryKey of (CustomerID, Model). Information about the car (such as engine size, yearetc) could be derived from just one part of the Key (Model) and thus isn't

Page 106: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 106/197

dependent on the whole key. Whereas if we wanted to find out the colour of thecar the customer bought then we could search for the customer and this wouldgive us the colour - assuming he has only bought one car. BUT what if thecustomer has ordered two cars, of different models and different colours. In orderto find the colour of a specific car we would need to know the CustomerID ANDthe model number. Thus colour is dependent on the WHOLE Primary Key and not

 just a part of it. What this tells us is that colour is in the correct relation as it isspecific to the customer and the model, whereas information about the car, whichis dependent upon the Model alone, should be in a different table.

2NF in practice

When removing the partial dependencies from our database we can only look attables that have a Composite Key and not a sole attribute as the Primary Key. Asthe loans Relation has a Primary Key of 'TransactionNo' this table doesn't requireto be changed in this Normal Form. The second relation (Borrowed CDs) DOEShave a Composite Key so we must examine the attributes of this table to see if 

they are all dependent on the whole Key.

We can see that ALL the CD information attributes are dependent on the cdIDattribute rather than the whole Key. This is because they aren't really about theCDs borrowed and more about just the CDs bought and thus belong on their ownrelation - CDs Bought.

cdID Artist Title Year LabelNo_of_ Tracks

Copy

1 BritneySpears

Britney 2001 Jive 14 1

2 Pink Cant TakeMe Home

2002 LaFace 15 3

3 ChristinaAguilera

Stripped 2002 RCA 20 1

4 Darius Dive In 2002 Mercury 13 2

5 WillYoung

From NowOn

2002 RCA 13 2

CDs BoughtAnd that means that we can remove all the rest of CD attributes fromthe Borrowed CDs table.

TransactionNo cdID

1 1

1 2

Page 107: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 107/197

1 3

2 4

2 5

2 3

Borrowed CDs

The database in the second normal form will now have the relations as shownin figure four and is expressed as:

LOANS (TransactionNo, Forename, Surname, AddressOne, AddressTwo, City,Postcode, TeleNo, E-mail, Date_Borrowed, Due_Back)BORROWED CDS(TransactionNo, cdID, Artist, Title, Year, Label, No_of_Tracks,Copy)CDS BOUGHT(cdID, Artist, Title, Year, Label, No_of_Tracks, Copy)

 Third Normal Form (3NF)To achieve Third Normal Form no attribute must be dependent on a non-keyattribute. This means that every informational attribute must be DIRECTLYdependent on the Primary Key and not on another column. If we again look at animagined cars database, a customer table contains information such as address,city, postcode and also a column called shipping cost. The value of shipping costchanges in relation to where the car should be delivered, and thus is not directlydependent on the customer, but the city. Thus we would need to create anotherseparate relation to hold the information about cities and shipping costs.

3NF in practice

As is good practice we should examine every table in turn to see if the non-keyattributes are indeed directly dependent on the Primary Key.

If we look at the loans relation we can see that the columns AddressOne,AddressTwo, City, Postcode, and E-mail are not dependent on the TransactionNo,but rather a Composite Key of Forename and Surname. Thus they should beremoved from this table into a new relationBorrowers. As there is a possibilitythat there could be more that one David Findlay or Iain Brown, this CompositeKey isn't very effective so once more we will replace it with a unique numericreference (BorrowerID). This will become the new Primary Key of Borrowers anda foreign Key in the loans relation.

The effect that this has on the tables can be seen in figure five.

The Borrowed CDs relation only has two attributes, which together make up thePrimary Key and thus is not required to be normalised. The final table CDsBought can however be nornailised further. Year, Label and No of Tracks aredependent on a Composite Key of Artist + Title. Copy is dependent on the cdIDi.e. that which relates a particular physical CD that has been purchased, rather

Page 108: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 108/197

Page 109: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 109/197

cdID releaseID Copy

6 6 12/12/2002

CDs Bought Relation

Whereas we would only need to add information about the Christina Aguilera

album to the CDs Bought relation, as its release information has already beenentered into the CD Releasesrelation.

cdID releaseID Copy

7 3 12/12/2002

CDs Bought Relation

Thus after three levels of normalisation we have a table structure as shownin figure six and is expressed as so:

LOANS (TransactionNo, BorrowerID, Date_Borrowed, Due_Back)

BORROWER (BorrowerID, Forename, Surname, AddressOne, AddressTwo, City,Postcode, TeleNo, E-mail)BORROWED CDS (TransactionNo, cdID, Artist, Title, Year, Label, No_of_Tracks,Copy)CDS BOUGHT (cdID, releaseID, Copy)CD RELEASES (releaseID, Artist, Title, Year, Label, No_of_Tracks)

Other Normal Forms

As mentioned above there are more Normal Forms that we could use to normalise

our database further. We are not going to do this, because in practice the

anomalies that they are designed to remove are rare. We will however have abrief look at BCNF so that there is at least some understanding of that normshould you come across it. If you are confused or struggling with the above, itwould perhaps be worth skipping past this section until you are more confidentabout your understanding of the first three Normal Forms.

Boyce-Codd Normal Form (BCNF)

This often referred to as a strong 3NF and states that each determinant must bea Candidate Key. In a relation there may be more than just the Primary Key fromwhich we can derive the values of other attributes, i.e. from another attribute or

combination of attributes. These are known as Candidate Keys and in 3NF it ispossible to have only some of the attributes functionally dependent on them. InBCNF all attributes must depend on all Candidate Keys.

Variations

While the rules of Normalisation stay the same the practical implementation of them differs. The method I've used above is the one that I think is easiest tounderstand for the beginner, but there are a couple of others worth mentioning in

Page 110: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 110/197

case you see them discussed elsewhere. It doesn't really matter which you use asthe derived data structure is the same.

Composite Key in the First Relation

In the above example we had 1NF of :

LOANS (TransactionNo, Forename, Surname, AddressOne, AddressTwo, City,Postcode, TeleNo, E-mail, Date_Borrowed, Due_Back)BORROWED CDS(TransactionNo, cdID, Artist, Title, Year, Label, No_of_Tracks,Copy)

We are reminded that there was a Composite Key in the second relation(Borrowed CDs). We could have just as easily created the Composite Key in thefirst relation, where we remove (Artist, Title, Year, Label, No_of_Tracks, Copy) toa new relation called CDs Bought, create the Primary Key cdID for that relationand create a new attribute in the Loans relation that is a Foreign Key and thequalifying value for the TransactionNo. This would have duplicated the data in the

non-repeating groups, which doesn't matter as we're normalising the databasestructure not the actual data, and that repetition is removed by the later NormalForms. This would leave a 1NF of:

LOANS (cdID, TransactionNo, Forename, Surname, AddressOne, AddressTwo,City, Postcode, TeleNo, E-mail, Date_Borrowed, Due_Back)CDS BOUGHT (cdID, Artist, Title, Year, Label, No_of_Tracks, Copy)

This means that in to achieve 2NF we no longer look at the second relation, butinstead the first relation to determine if the attributes are functionally dependenton the whole Composite Key. All the attributes are functionally dependent on theTransactionNo. not the whole Key, so we remove them to a new relation called

Transaction Info. 2NF is thus expressed:

LOANS (cdID, TransactionNo)TRANSACTION INFO (TransactionNo, Forename, Surname, AddressOne,AddressTwo, City, Postcode, TeleNo, E-mail, Date_Borrowed, Due_Back)CDS BOUGHT (cdID, Artist, Title, Year, Label, No_of_Tracks, Copy)

We can see that this is the same data structure as the original method at 2NF, butwe've just chosen different names due to the order in which a relation was firstestablished.

1NF with only one relationThis is another method that is quite popular. If we recall the rules for 1NF theyare:

• To ensure that all attributes (columns) contain only atomic values

• There must be no repeating groups

This says nothing about not repeating data or having to create new relations toresolve the problems. If we look at figure two, we can see that the data in the non-

Page 111: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 111/197

repeating attributes has indeed been repeated. The problem we had with this isthat there was no longer a Primary Key. We can however make a Composite Keyby using the same cdID as we did above to represent the uniqueness, except thistime in just one relation. So 1NF would be:

LOANS (cdID, TransactionNo, Forename, Surname, AddressOne, AddressTwo,City, Postcode, TeleNo, E-mail, Date_Borrowed, Due_Back, Artist, Title, Year,Label, No_of_Tracks, Copy)

The consequence of this is that to achieve 2NF would be a longer stage. Initiallywe can see (similar to previous examples) that the attributes (Artist, Title, Year,Label, No_of_Tracks, Copy) are dependant on only the cdID part of the key andthus can be removed to a new relation:

LOANS (cdID, TransactionNo, Forename, Surname, AddressOne, AddressTwo,City, Postcode, TeleNo, E-mail, Date_Borrowed, Due_Back)CDS BOUGHT (cdID, Artist, Title, Year, Label, No_of_Tracks, Copy)

This creates a structure identical to that of the 'Composite Key in the First

Relation' example in 1NF, where the loan information attributes are onlydependent on the Transaction No, and thus we have to split the relation again:

LOANS (cdID, TransactionNo)TRANSACTION INFO (TransactionNo, Forename, Surname, AddressOne,AddressTwo, City, Postcode, TeleNo, E-mail, Date_Borrowed, Due_Back)CDS BOUGHT (cdID, Artist, Title, Year, Label, No_of_Tracks, Copy)

The database structure is now 2NF.

Without A Joining Table and cdID

This produces the only truly normalised database schema in this workshop - andI'll explain why in a moment. But first what is a 'Joining Table'? This is a table thatis an entirely Composite Key of attributes which are Foreign Keys that contain noinformational data and thus its function is to join the Primary Keys of other tablestogether.

For example: in each of the database structures we have produced so far therehas been a relation with two attributes (cdID, TransactionNo) so that if we look upa Transaction No we can retrieve the cds by the corresponding cdIDs. In strictnormalisation this table should not exist in this form, it has come into existencebecause we created an artificial key (cdID) to represent the Composite Key

(Artist, Title, Copy). This is something that is done quite frequently in practice(why I've done so above), but is theoretically wrong. To explain let's normalisethe structure again.

Because we cannot replace the Composite Key elements with cdID in 1NF, we areleft with a structure like so:

LOANS (TransactionNo, Forename, Surname, AddressOne, AddressTwo, City,Postcode, TeleNo, E-mail, Date_Borrowed, Due_Back)BORROWED CDS (TransactionNo, Artist, Title, Copy, Year, Label, No_of_Tracks)

Page 112: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 112/197

As we can see, the Composite Key for the Borrowed CDs relation is now a lotmore complicated. When we achieve 2NF we would need to create a structure likeso:

LOANS (TransactionNo, Forename, Surname, AddressOne, AddressTwo, City,Postcode, TeleNo, E-mail, Date_Borrowed, Due_Back)BORROWED CDS (TransactionNo, Artist, Title, Copy)CDS BOUGHT (Artist, Title, Copy, Year, Label, No_of_Tracks)

This has meant that any join we perform using SQL becomes much morecomplicated, as we are having to match more fields. Consider the followingsample MySQL Inner Join to retrieve all the information about a bought cd.

With cdID:

SELECT *

FROM cds_bought, cds_released

WHERE (cds_bought.cdID = cds_released.cdID);

Without cdID:

SELECT *

FROM cds_bought, cds_released

WHERE (cds_bought.Artist = cds_released.Artist)

AND (cds_bought.Title = cds_released.Title)

AND (cds_bought.Copy = cds_released.Copy);

As we observe, joining tables on three fields is more complicated than on onefield.

Page 113: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 113/197

NOTE: The names of tables and columns are slightly different as the physicalimplementation of any database is best done without spaces in the names,whereas in the theoretical design stage spaces aid readability.

Thus to summarise, we have replaced the 'true' Composite Key with an artificialPrimary Key, in order to make things easier in the physical implementation, BUTTHERE IS NO RULE IN NORMALISATION THAT SAYS YOU SHOULD.

Conclusion

This has hopefully been a pretty straightforward guide to a complicated (for thenovice anyway) subject. I first got into this whole web design game from a mediastandpoint rather than a technical computer standpoint. When I started usingdatabases on the web, I had to become familiar with concepts that are secondnature to those from a formal technical background, which was tricky at first dueto the target audience of the literature. Thus I hope that this VW can be of someuse to those coming to normalisation from other backgrounds as well as those inIT seeking a little clarification.

Using MySQL, Advanced Queries

Workshop Requirements

You should have completed Parts One, Two, Three,  Four and Five of this series.

You should also have access to the MySQL command line client software.

You should also have full permissions on a database.

Page 114: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 114/197

Introduction

Earlier in this series when we looked at SQL statements we were primarilyconcerned with either retrieving, changing or deleting values within the databaseand also manipulating the database structures. SQL is more powerful than thatand in this workshop I aim to introduce some of the advanced functions andqueries that can be useful when building more complex applications.

As

One of the simplest manipulations is to define a new structural element (table orcolumn) by aliasing an existing value. A common use for this is to create ashorthand reference to elements with long names to make the SQL statementsshorter and reduce the chance of typos in the longer names.

SELECT <columns>

FROM <existing_table_name>

AS <new_table_name>

It is important to remember that the table hasn't actually been renamed, butinstead the<new_table_name> is simply a reference that exists for the duration

of the SQL statement. For example to see this working lets create a simpleSELECT statement that retrieves the name column from the artists table (that wecreated in Part 5) using a reference 't1'.

mysql> SELECT t1.name

-> FROM artists

-> AS t1;

+----------------------+

Page 115: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 115/197

| name |

+----------------------+

| Jamiroquai |

| Various |

| westlife |

| Various |

| Abba |

As we can see t1 is a lot easier to type that artists. To see the full benefit of thislet's revisit one of the join statements from  part 5.

The existing statement is:

mysql> SELECT artists.Artist, cds.title, genres.genre FROM cds

  -> LEFT JOIN genres ON cds.genreID = genres.genreID

-> LEFT JOIN artists ON cds.artistID = artists.artistID

-> WHERE (genres.genre = 'Pop');

Whereas our modified statement would look like so:

Page 116: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 116/197

mysql> SELECT t2.Artist, t1.title, t3.genre FROM cds AS t1

  -> LEFT JOIN genres AS t3 ON t1.genreID = t3.genreID

-> LEFT JOIN artists AS t2 ON t1.artistID = t2.artistID

-> WHERE (t3.genre = 'Pop');

Using aliases also has few other advantages including:

• Avoiding any reserved (used by MySQL) words.

Allowing Multiple Joins to the same table• Allowing Self-Joins

• Assigning the result of MySQL function to a temporary column name.

While there is not much more to be said about MySQL reserved words and MySQLfunctions are covered in Part 9 of this Virtual Workshop series, we will take a lookat Self-Joins next.

Practical Uses of As

In the earlier Virtual Workshop on joins we looked at joining different tables together,we are going to extend the use of joins using AS to in allow multiple joins on thesame table and Self-Joins.

To illustrate how these work we will create a new 'producer' column in the cdstable (the reasons for which will become apparent later) that we last modifiedin  part 5. This will again hold a foreign key reference to a table holding detailsabout the producer, but rather than creating a 'producer' table, we can just reusethe artist table as producers are artists too.

Altering the database structures and adding data

In order to include this new producer column (and include meaningful data) we

need to alter the structure of the cds table.

mysql> ALTER TABLE cds

-> ADD producerID INT(3);

Page 117: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 117/197

At this point you can if you want you can enter the appropriate producerinformation for your existing CDs entered. For use in this workshop we also needto enter the details of an album produced by the artist and an album produced bya outside party. In this case the famously self reliant Prince (or whatever he iscalling himself this week) and The Beatles with and their producer the '5th Beatle'Sir George Martin.

Artist Title Year Label Bought Tracks Genre Producer

PrinceSign of theTimes

1987WarnerBrothers

1987-11-07

16 Soul Prince

TheBeatles

TheWhiteAlbum

1990 Capitol1994-07-20

30ClassicRock

GeorgeMartin

This data has to be entered into the artists table first:

mysql> INSERT INTO artists

-> VALUES ('?','The Beatles');

Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO artists

-> VALUES ('?','Prince');

Query OK, 1 row affected (0.00 sec)

Page 118: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 118/197

mysql> INSERT INTO artists

-> VALUES ('?','George Martin');

Query OK, 1 row affected (0.00 sec)

Then the get the artistIDs using a SELECT statement

mysql> SELECT *

-> FROM artists;

+----------+----------------------+

| artistID | name |

+----------+----------------------+

  -- snip --

| 17 | The Beatles |

| 18 | Prince |

| 19 | George Martin |

Page 119: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 119/197

+----------+----------------------+

19 rows in set (0.00 sec)

Next enter the label details in the label table.

mysql> INSERT INTO label

-> VALUES ('?','Warner Brothers');

Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO label

-> VALUES ('?','Capitol');

Query OK, 1 row affected (0.00 sec)

And getting those newly created label IDs as well.

mysql> SELECT *

-> FROM label;

+---------+-----------------+

Page 120: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 120/197

| labelID | name |

+---------+-----------------+

  -- snip --

| 5 | Warner Brothers |

| 6 | Capitol |

+---------+-----------------+

6 rows in set (0.02 sec)

We should also know the genreIDs as well (Classic Rock = 3; Soul = 5) and wecan enter the cd details into the cds table (you can see why it is better to have

a scripted interface to MySQL).

mysql> INSERT INTO cds (

  -> title, year, bought, tracks, genreID, artistID, labelID, producerID

 -> ) VALUES (

  -> 'Sign of the Times','1987','1987-11-07','16','5','18','5','18'

  -> );

Page 121: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 121/197

Query OK, 1 row affected (0.08 sec)

mysql> INSERT INTO cds (

  -> title, year, bought, tracks, genreID, artistID, labelID, producerID

  -> ) VALUES (

  -> 'The White Album','1990','1994-07-20','30','3','17','6','19'

  -> );

Query OK, 1 row affected (0.01 sec)

This will now allow us to see some of the good things that you can do with AS.

Multiple Joins to One Table.

Consider the following SQL statement and resulting output.

mysql> SELECT cds.title, artists.name

-> FROM cds

  -> LEFT JOIN artists

Page 122: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 122/197

  -> USING (artistID)

  -> WHERE artists.artistID = 17;

+-----------------+-------------+

| title | name |

+-----------------+-------------+

| The White Album | The Beatles |

+-----------------+-------------+

1 row in set (0.00 sec)

This is fine, but if we wanted to include the producer details we need to join to aproducer table, which we don't have because we decided that producers areartists and this creates a problem. We solve this problem by making ANOTHER join to the artists table only this time calling it the producers table using AS tocreate this alias.

LEFT JOIN artists AS producers ....etc

There is another small consideration. In order to complete the join to the newlyaliased producers tale we have to construct the join without the USING clause.This is because we need to join the cds.producerID field on the producers.artistIDfield which obviously aren't the same name that USING requires. SO to constructthe whole query.

mysql> SELECT cds.title, artists.name AS Artist, producers.name AS Producer 

Page 123: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 123/197

  -> FROM cds

  -> LEFT JOIN artists

-> USING (artistID)

  -> LEFT JOIN artists AS producers

-> ON cds.producerID = producers.artistId

-> WHERE artists.artistID = 17;

+-----------------+-------------+---------------+

| title | Artist | Producer |

+-----------------+-------------+---------------+

| The White Album | The Beatles | George Martin |

+-----------------+-------------+---------------+

1 row in set (0.01 sec)

NOTE: The artists.name and producers.name field has also been aliased todifferentiate them in the output.

Page 124: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 124/197

We can also use this method of aliasing tables to to join a table to itself orperform a Self-Join as it is known.

 The Self-Join

A Self-Join (as the name suggests) is when a table is joined to itself and is made

possible by aliasing the original table. The main reasons for using a Self-Join arisewhen you need to either compare the values in differ net rows in the same table.

Unfortunately in the CDs examples we have used so far there is no obviouscandidate to demonstrate the Self-Join correctly so I will use a different examplethis one time only. The classic example given when explaining Self-Joins (I readthis in many different books when learning SQL) involves an 'Employees' tablethat stores the details of their supervisor as well.

EmployeeID Name Salary ManagerID

023452 Ken Smith 45000 NULL

087652 Linda Jones 25000 023452Employees Table

In order to get the name of the Linda's manager you would have to join the tableto itself (using an alias to create a 'Manager' table). The join would occur ONEmployees.ManagerID = Manager.EmployeeID. Thus we can construct the SQLstatement using AS like so:

SELECT

Employees.EmployeeID, Employees.Name, Employees.Salary, Manager.Name AS Manager 

FROM Employees

LEFT JOIN Employees AS Manager 

ON Employees.ManagerID = Manager.EmployeeID

WHERE (Employees.EmployeeID = '087652';

Page 125: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 125/197

This would result in the following being output.

EmployeeID Name Salary Manager

087652 Linda Jones 25000 Ken Smith

Aliasing Function output

Using AS with built in functions is discussed in more depth in Part 9 of thisworkshop series, but worth covering quickly here. Consider a quick query to findthe average number of tracks.

mysql> SELECT AVG(tracks)

-> FROM cds;

+-------------+

| AVG(tracks) |

+-------------+

| 22.1667 |

+-------------+

1 row in set (0.00 sec)

AVG(tracks) does tell us certain information, but this field would be difficult touse as part of a script and therefore we can use AS to give a more meaningfulname.

mysql> SELECT AVG(tracks) AS AverageTracks

Page 126: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 126/197

  -> FROM cds;

+---------------+

| AverageTracks |

+---------------+

| 22.1667 |

+---------------+

1 row in set (0.03 sec

UNION Joins

Union Joins allow the results of two queries to be combined into one outputtedresult set. This is done by having the 2 (or more) queries glued together by theUNION operator.

SELECT <fields>

FROM <table>

WHERE <condition>

UNION

Page 127: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 127/197

SELECT <fields>

FROM <table>

WHERE <condition>

For example if you wanted to search for artist beginning with either P or G youwould construct two statements that searched each phrase and use the UNIONstatement.

mysql> SELECT artists.name

-> FROM artists

-> WHERE (artists.name LIKE 'P%')

-> UNION

  -> SELECT artists.name

-> FROM artists

-> WHERE (artists.name LIKE 'G%');

+-----------------+

| name |

Page 128: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 128/197

+-----------------+

| pop goes the 80 |

| Prince |

| George Martin |

+-----------------+

3 rows in set (0.03 sec)

By now with the knowledge you possess you will have worked out that this could just have easily been done by using two where conditions.

mysql> SELECT artists.name

-> FROM artists

  -> WHERE ((artists.name LIKE 'P%') || (artists.name LIKE 'G%'));

+-----------------+

| name |

+-----------------+

Page 129: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 129/197

| pop goes the 80 |

| Prince |

| George Martin |

+-----------------+

3 rows in set (0.00 sec)

However UNION also allows you to combine the results from different tables not just the same one. To give a practical, but somewhat unrealistic in a 'real world'sense lets return to our CDs database and select all the genres and all the labelsthat start with letters A to M.

mysql> SELECT label.name

-> FROM label

-> WHERE (label.name BETWEEN 'A%' AND 'M%')

  -> UNION

  -> SELECT genres.genre

-> FROM genres

Page 130: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 130/197

  -> WHERE (genres.genre BETWEEN 'A%' AND 'M%');

+----------------+

| name |

+----------------+

| jive |

| EMI |

| Capitol |

| Easy Listening |

| Heavy Metal |

| Eighties |

| Hip Hop |

| Jazz |

| Guitar Bands |

Page 131: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 131/197

+----------------+

9 rows in set (0.04 sec)

A more practical example would be to imagine if we had in fact made a separateproducers table rather than just alias the artists table. We could query both tablesusing UNION to produce a result set.

 Temporary Tables

As there name suggests, temporary tables are fleeting in nature lasting only forthe length of the MySQL session. Some of the reasons that you may wish to dothis include.

• A large, busy site may create a temporary table copies (which are issuedand die with a session for example) for each client to use, thus easingcongestion in on the original table.

• MySQL does not yet support subselects. Using temporary tables can, insome instances, overcome that problem.

• Storing data during structural database changes.

There are many other reasons that I could go into but let's just look at one cooltrick.

Creating the Temporary Table.

The syntax for creating temporary tables is almost identical that used for creating

a normal table. Except that there is an extra TEMPORARY clause.

CREATE TEMPORARY TABLE <table> (

  field definitions

  )

This will work by using a query to create the table as well, like so.

CREATE TEMPORARY TABLE <newtable>

Page 132: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 132/197

SELECT * FROM <oldtable>

And it is here that the 'cool trick' comes in. I received an e-mail asking for help(as I often do) and I was able to provide a solution using a temporary table. Theproblem was related to how to remove duplicate rows from a database. This cameabout from a web form that fed into a database and users were submitting it

multiple times, thus creating duplicated data. The correspondent wished toremove any duplicate entries. We can replicate this problem by creating a copy of the cds table with all the data duplicated.

First make the duplicate cds table:

mysql> CREATE TABLE cdsdupe

-> SELECT * FROM cds;

Apply the same structural constraints to the table:

mysql> ALTER TABLE cdsdupe MODIFY cdID INT(3) auto_increment primary key;

Next insert the same data again only omitting the cdID which would cause aconflict with the existing cdIDs (this means using the longer method of specifyingwhich fields to insert into and select from).

mysql> INSERT INTO cdsdupe

-> (title, year, bought, tracks, genreID, artistID, labelID, producerID)

-> SELECT cds.title, cds.year, cds.bought, cds.tracks, cds.genreID,

-> cds.artistID, cds.labelID, cds.producerID

-> FROM cds;

Page 133: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 133/197

Query OK, 8 rows affected (0.00 sec)

Records: 8 Duplicates: 0 Warnings: 0

You can check that there are indeed duplicate entries using a standard selectstatement. So how do we solve this problem? We saw in an earlier workshop thatthe DISTINCT qualifier can be used to only output records one if there areduplicates - which is what we want. Thus if we create a temporary table using aDISTINCT qualifier in a SELECT statement we can filter out the duplicates.

mysql> CREATE TEMPORARY TABLE cdstemp

-> SELECT DISTINCT cdsdupe.title, cdsdupe.year, cdsdupe.bought,

  -> cdsdupe.tracks, cdsdupe.genreID, cdsdupe.artistID,

-> cds.labelID, cds.producerID

-> FROM cdsdupe;

Query OK, 8 rows affected (0.03 sec)

Records: 8 Duplicates: 0 Warnings: 0

Again you can check this with a select statement. We next need to remove thedata from the original table using a TRUNCATE statement

TRUNCATE TABLE <table_name>

Page 134: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 134/197

This is better than a delete statement as it drops then recreates the table. Thismeans that it is faster on large tables and more importantly can be used as partof a transaction.

mysql> TRUNCATE TABLE cdsdupe;

Query OK, 0 rows affected (0.03 sec)

We then use the temporary table to repopulate the cdsdupe table.

mysql> INSERT INTO cdsdupe

-> (title, year, bought, tracks, genreID, artistID, labelID, producerID)

  -> SELECT cdstemp.title, cdstemp.year, cdstemp.bought, cdstemp.tracks,

-> cdstemp.genreID, cdstemp.artistID, cdstemp.labelID, cdstemp.producerID

-> FROM cdstemp;

Thus we have removed the duplicates from the cdsdupe table.

Using Full Text Searches

Full Text searches allow you to search for a phrase that can appear ANYWHERE infields that you specify. This is a kind of 'super-wildcard' approach. To do this you

first have to alter any table nominating fields to be searchable within brackets aspart of a FULL TEXT defination.

ALTER TABLE <table> ADD FULLTEXT (fields)

To illustrate lets make our title field of the cds table searchable.

Page 135: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 135/197

mysql> ALTER TABLE cds ADD FULLTEXT (title);

Query OK, 8 rows affected (0.36 sec)

Records: 8 Duplicates: 0 Warnings: 0

This done we could query the database using the MATCH() and AGAINST()functions, where the field is matched against the search term.

SELECT * FROM cds WHERE MATCH(fields) AGAINST ('search term')

So if we wanted to see all the cds with 'funk' in the title (just because there are

bound to be some).

mysql> SELECT cdID, title, year, tracks

-> FROM cds

-> WHERE

-> MATCH(title) AGAINST ('hits');

+------+---------------------+------+--------+

| cdID | title | year | tracks |

+------+---------------------+------+--------+

Page 136: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 136/197

| 5 | Abbas Greatest Hits | 1998 | 24 |

+------+---------------------+------+--------+

1 row in set (0.02 sec)

The MATCH function also sorts multiple results be relevance with the first resultbeing the most relevant. To demonstrate lets add another cds with hits in the title(The Hits by Prince).

mysql> INSERT INTO cds (

  -> title, year, bought, tracks, genreID, artistID, labelID, producerID

  -> ) VALUES (

  -> 'The Hits','1993','1993-10-07','58','5','18','5','18'

  -> );

Query OK, 1 row affected (0.08 sec)

Running the FULL TEXT query again will put the newly added CD top.

mysql> SELECT cdID, title, year, tracks

-> FROM cds

Page 137: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 137/197

  -> WHERE

-> MATCH(title) AGAINST ('hits');

+------+---------------------+------+--------+

| cdID | title | year | tracks |

+------+---------------------+------+--------+

| 9 | The Hits | 1993 | 58 |

| 5 | Abbas Greatest Hits | 1998 | 24 |

+------+---------------------+------+--------+

2 rows in set (0.00 sec)

We can ask MySQL to show us the rating as well by SELECTing the result of thematch().

mysql> SELECT title, MATCH(title) AGAINST ('hits') AS Rating

-> FROM cds

-> WHERE MATCH(title) AGAINST ('hits');

Page 138: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 138/197

Page 139: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 139/197

Using MySQL, Built-In Functions

Workshop Requirements

You should have completed Parts One, Two, Three,  Four and Five of this series.

You should also have access to the MySQL command line client software.

You should also have full permissions on a database.

Introduction

Thus far when retrieving stored data we have simply displayed the results of anyquery. MySQL can do more that this and has many built in functions that cantransform data to meet our requirements. These include:

• Date Functions - used to manipulate the display format of a date as well ascalculate time.

• String Functions - can manipulate a text string

• Numeric Functions - can manipulate figures

• Summarising Functions - output meta results from a query

There are also Control Functions that can be used to give conditionality toqueries.

Date Functions

Before looking at the date functions in detail it is worth revisiting the variousdate datatypes to gain a better understanding of the limitations of date formatting.

Date Datatypes

There are 5 MySQL date datatypes these are:

Datatype Format Info

DATETIMEYYYY-MM-DDHH:MM:SS

This stores both date andtime.

DATE YYYY-MM-DD This only stores the date

TIMESTAMP(length)

Varies See Below

TIME HH:MM:SS This stores only the timeYEAR YYYY Stores only the year

The timestamp datatype is somewhat different as it stores the time that a rowwas last changed. The format also varies according to the length. For example tostore the same information as DATETIME, you would specify a length of 14whereas to store the DATE you would specify a length of 8.

Timestamp Format

Page 140: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 140/197

Definition

TIMESTAMP(2) YY

TIMESTAMP(4) YYYY

TIMESTAMP(6) YYMMDD

TIMESTAMP(8) YYYYMMDD

TIMESTAMP(10) YYMMDDHHMM

TIMESTAMP(12) YYMMDDHHMMSS

TIMESTAMP(14) YYYYMMDDHHMMSS

In the 'cds' table we have used the DATE for the 'bought' field.

mysql> SELECT cds.title, cds.bought

-> FROM cds;

+------------------------------+------------+

| title | bought |

+------------------------------+------------+

| A Funk Odyssey | 2001-10-10 |

| Now 49 | 2001-10-15 |

| Eurovision Song contest 2001 | 2000-09-08 |

| Abbas Greatest Hits | 2000-11-05 |

Page 141: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 141/197

| Space Cowboy | 2001-10-10 |

| Sign of the times | 1987-11-07 |

| The White Album | 1994-07-20 |

| The Hits | 1993-10-07 |

| westlife | 2000-06-09 |

+------------------------------+------------+

9 rows in set (0.02 sec)

So to begin with let's look at how we can manipulate these dates using MySQL'sdate functions.

DATE_FORMAT()

This function allows the developer to format the date anyway that they wish byspecifying a sequence of format strings. A string is composed of the percentagesymbol '%' followed by a letter that signifies how you wish to display part of thedate. These are some of the more common strings to use:

String Displays Example

%dThe numeric day of themonth

01....10....17....24 etc

%D The day of the month witha suffix

1st, 2nd, 3rd.... etc

%m The numeric month 01....04....08....11 etc

%M The Month nameJanuary....April....Augustetc

%bThe Abbreviated MonthName

Jan....Apr....Aug....Novetc

Page 142: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 142/197

%y Two digit year98, 99, 00, 01, 02, 03etc

%Y Four digit year1998, 2000, 2002, 2003etc

%W Weekday nameMonday....

Wednesday....Friday etc

%aAbbreviated Weekdayname

Mon....Wed....Fri etc

%H Hour (24 hour clock) 07....11....16....23 etc

%h Hour (12 hour clock) 07....11....04....11 etc

%p AM or PM AM....PM

%i Minutes 01....16....36....49 etc

%s Seconds 01....16....36....49 etc

There are more, but that should be enough for now. There are a couple of things

to note. Upper and Lowercase letters in the string make a difference and also thatwhen arranging these strings into a sequence you can intersperse 'normal'characters. For example:

The sequence '%d/%m/%y', with forward slashes separating the strings, wouldbe displayed as 01/06/03.

The next stage is to use the function DATE_FORMAT() to convert a stored time toa format we want.

Syntax:

DATE_FORMAT(date, sequence)

Thus to change the format of the cds.bought field to DD-MM-YYYY we specify thefield as the date and the sequence as '%d-%m-%Y'.

DATE_FORMAT(cds.bought, '%d-%m-%Y')

This function is then incorporated into our SQL statement in place of the exiting

cds.bought field.

mysql> SELECT cds.title, DATE_FORMAT(cds.bought, '%d-%m-%Y')

-> FROM cds;

Page 143: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 143/197

+------------------------------+-------------------------------------+

| title | DATE_FORMAT(cds.bought, '%d-%m-%Y') |

+------------------------------+-------------------------------------+

| A Funk Odyssey | 10-10-2001 |

| Now 49 | 15-10-2001 |

| Eurovision Song contest 2001 | 08-09-2000 |

| Abbas Greatest Hits | 05-11-2000 |

| Space Cowboy | 10-10-2001 |

| Sign of the times | 07-11-1987 |

| The White Album | 20-07-1994 |

| The Hits | 07-10-1993 |

| westlife | 09-06-2000 |

+------------------------------+-------------------------------------+

Page 144: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 144/197

9 rows in set (0.00 sec)

Dates can also be formatted in 'plain english'.

mysql> SELECT cds.title, DATE_FORMAT(cds.bought, '%W the %D of %M %Y')

-> FROM cds;

+------------------------------+-----------------------------------------------+

| title | DATE_FORMAT(cds.bought, '%W the %D of %M %Y') |

+------------------------------+-----------------------------------------------+

| A Funk Odyssey | Wednesday the 10th of October 2001 |

| Now 49 | Monday the 15th of October 2001 |

| Eurovision Song contest 2001 | Friday the 8th of September 2000 |

| Abbas Greatest Hits | Sunday the 5th of November 2000 |

| Space Cowboy | Wednesday the 10th of October 2001 |

| Sign of the times | Saturday the 7th of November 1987 |

Page 145: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 145/197

| The White Album | Wednesday the 20th of July 1994 |

| The Hits | Thursday the 7th of October 1993 |

| westlife | Friday the 9th of June 2000 |

+------------------------------+-----------------------------------------------+

9 rows in set (0.01 sec)

Note: DATE_FORMAT() only works with datatypes that include the date. Thismeans DATE, DATETIME and TIMESTAMP. There is a similar function calledTIME_FORMAT() that works with TIME as well as DATETIME and TIMESTAMP.

Extraction Functions

As well as using DATE_FORMAT() there are other functions that allow you toextract specific information about a date (year, month, day etc). These include:

Function Displays Example

DAYOFMONTH(date) The numeric day of the month 01....10....17....24 etc

DAYNAME(date) The Name of the dayMonday....Wednesday....Friday etc

MONTH(date) The numeric month 01....04....08....11 etc

MONTHNAME(date)

The Month nameJanuary....April....Augustetc

YEAR(date) Four digit year1998, 2000, 2002, 2003etc

HOUR(time) Hour (24 hour clock) 07....11....16....23 etc

MINUTE(time) Minutes 01....16....36....49 etc

SECOND(time) Seconds 01....16....36....49 etc

DAYOFYEAR(date)

Numeric day of theyear

1.....366

To give an example of one of these you can use DAYNAME() to work out whichday you were born on. To do this you can specify the date directly to the functionwithout referring to any tables or field. So for my birthday (20th July 1973):

Page 146: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 146/197

mysql> SELECT DAYNAME('1973-07-20');

+-----------------------+

| DAYNAME('1973-07-20') |

+-----------------------+

| Friday |

+-----------------------+

1 row in set (0.00 sec)

Or you could even SELECT two or three date items.

mysql> SELECT DAYNAME('1973-07-20'), MONTHNAME('1973-07-20'), YEAR('1973-07-20');

+-----------------------+-------------------------+--------------------+

| DAYNAME('1973-07-20') | MONTHNAME('1973-07-20') | YEAR('1973-07-20') |

+-----------------------+-------------------------+--------------------+

| Friday | July | 1973 |

Page 147: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 147/197

+-----------------------+-------------------------+--------------------+

1 row in set (0.02 sec)

Getting the Current Date and Time

There are three functions that you can use to get the current date and time.NOW() - which gets both date and time, CURDATE() which works with only thedate and CURTIME() for the time.

mysql> SELECT NOW(), CURTIME(), CURDATE();

+---------------------+-----------+------------+

| NOW() | CURTIME() | CURDATE() |

+---------------------+-----------+------------+

| 2003-06-02 19:44:51 | 19:44:51 | 2003-06-02 |

+---------------------+-----------+------------+

1 row in set (0.01 sec)

Changing Date Values

There are two functions that allow you to add and subtract time to a date. Theseare DATE_ADD() and DATE_SUB().

Syntax:

DATE_ADD(date,INTERVAL expr type)

Page 148: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 148/197

DATE_SUB(date,INTERVAL expr type)

The date - is a standard DATE or DATETIME value, next come thecommand INTERVALfollowed by the time period (expr) and finally what typeperiod it is (Month, Day, Year etc). Therefore to work out the date 60 days in thefuture:

mysql> SELECT DATE_ADD(CURDATE(), INTERVAL 60 DAY);

+--------------------------------------+

| DATE_ADD(CURDATE(), INTERVAL 60 DAY) |

+--------------------------------------+

| 2003-08-01 |

+--------------------------------------+

1 row in set (0.00 sec)

Or 6 months in the past:

mysql> SELECT DATE_SUB(CURDATE(), INTERVAL 6 MONTH);

+---------------------------------------+

| DATE_SUB(CURDATE(), INTERVAL 6 MONTH) |

Page 149: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 149/197

+---------------------------------------+

| 2002-12-02 |

+---------------------------------------+

1 row in set (0.00 sec)

We can also format this result as well using DATE_FORMAT() and using an alias totidy up the title:

mysql> SELECT

-> DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 6 MONTH), '%W the %D of %M %Y')

-> AS 'Six Months Ago';

+---------------------------------+

| Six Months Ago |

+---------------------------------+

| Monday the 2nd of December 2002 |

+---------------------------------+

Page 150: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 150/197

1 row in set (0.01 sec)

By now you should have the idea and thus I'm not going to carry on andextensively cover all the functions, the MySQL manual is probably the best place tolook to see all the date functions.

String Functions

String values are can be explained as 'bits of text' and much like the datefunctions, the string functions allow us to manipulate these values before they aredisplayed. Although there are once more many different functions, I'm going toconcentrate on the functions that fall into a few broad categories.

• Adding text to an existing value

• Changing Part of a String

• Extracting Text from a String

• Finding a piece of text in a string

Adding text to an existing value

There are two simple ways to add more text to an existing value - either at thestart or end of the text. Placing the text at either end is best achieved with theCONCAT() function.

Syntax:

CONCAT(string1,string2,...)

Thus we can take an existing value (say string2) and place a new value (string1)at the beginning to get string1string2. To see this in action let's retrieve the titleof The Beatles 'The White Album' (which was entered in  part 8).

mysql> SELECT cds.title

-> FROM cds WHERE cdID='20';

+-----------------+

| title |

Page 151: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 151/197

+-----------------+

| The White Album |

+-----------------+

1 row in set (0.00 sec)

If we wanted to add the text "The Beatles' " at the beginning.

+-----------------------------------+

| CONCAT("The Beatles' ",cds.title) |

+-----------------------------------+

| The Beatles' The White Album |

+-----------------------------------+

1 row in set (0.04 sec)

Or if we wanted to say "By The Beatles" at the end.

mysql> SELECT CONCAT(cds.title," By The Beatles")

-> FROM cds WHERE cdID='20';

Page 152: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 152/197

+-------------------------------------+

| CONCAT(cds.title," By The Beatles") |

+-------------------------------------+

| The White Album By The Beatles |

+-------------------------------------+

1 row in set (0.00 sec)

Changing Part of a String

As well as add text we can replace it or overwrite it completely. To replace aninstance of text within a string we can use the REPLACE() function.

Syntax:

REPLACE(whole_string,to_be_replaced,replacement)

Therefore if we wanted to replace the word 'White' with the word 'Black' inthe cds.title:

mysql> SELECT REPLACE(cds.title,'White','Black')

-> FROM cds WHERE cdID='20';

+------------------------------------+

Page 153: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 153/197

| REPLACE(cds.title,'White','Black') |

+------------------------------------+

| The Black Album |

+------------------------------------+

1 row in set (0.02 sec)

Or just to be silly (and to demonstrate that each occurrence in the string ischanged) let's swap the 'e' for an 'a'.

mysql> SELECT REPLACE(cds.title,'e','a')

-> FROM cds WHERE cdID='20';

+----------------------------+

| REPLACE(cds.title,'e','a') |

+----------------------------+

| Tha Whita Album |

+----------------------------+

Page 154: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 154/197

1 row in set (0.00 sec)

Another Function we can use to add text is the INSERT() function that overwritesany text in the string from a start point for a certain length.

Syntax:

INSERT(string,start_position,length,newstring)

In this case the crucial bits of information are the position to start (how manycharacters from the begriming) and the length. So again to replace 'White' (whichstarts at character 5 in the string) with 'Black' in the title we need to start atposition 5 for a length of 5.

mysql> SELECT INSERT(cds.title,5,5,'Black')

-> FROM cds WHERE cdID='20';

+-------------------------------+

| INSERT(cds.title,5,5,'Black') |

+-------------------------------+

| The Black Album |

+-------------------------------+

1 row in set (0.01 sec)

If we alter the position (say to 3) you can see that the exchange doesn't workproperly.

Page 155: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 155/197

mysql> SELECT INSERT(cds.title,3,5,'Black')

-> FROM cds WHERE cdID='20';

+-------------------------------+

| INSERT(cds.title,3,5,'Black') |

+-------------------------------+

| ThBlackte Album |

+-------------------------------+

1 row in set (0.00 sec)

Similarly if we were to shorten the length to 3 (resetting the position to 5) not allof the word 'White' gets overwritten.

mysql> SELECT INSERT(cds.title,5,3,'Black')

-> FROM cds WHERE cdID='20';

+-------------------------------+

| INSERT(cds.title,5,3,'Black') |

Page 156: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 156/197

+-------------------------------+

| The Blackte Album |

+-------------------------------+

1 row in set (0.00 sec)

Thus using this knowledge we can insert text into the middle of a string by settingthe length to '0' (so it doesn't overwrite anything). Let's make the title 'Black andWhite':

mysql> SELECT INSERT(cds.title,5,0,'Black and ')

-> FROM cds WHERE cdID='20';

+------------------------------------+

| INSERT(cds.title,5,0,'Black and ') |

+------------------------------------+

| The Black and White Album |

+------------------------------------+

1 row in set (0.00 sec)

Page 157: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 157/197

Extracting Text from a String.

As well as adding text to a string we can also use functions to extract specificdata from a string. To begin with lets look at three LEFT(), RIGHT() and MID().

Syntax:

LEFT(string,length)

RIGHT(string,length)

MID(string,start_position,length)

The first two, LEFT() and RIGHT(), are fairly straight forward. You specify thestring and the length of the string to keep, relative to either the left or rightdepending on which function you are using. So to keep the words 'The' (whichoccupies 3 characters on the left) and 'Album' (5characters on the right) wewould specify:

mysql> SELECT LEFT(cds.title,3), RIGHT(cds.title,5)

-> FROM cds WHERE cdID='20';

+-------------------+--------------------+

| LEFT(cds.title,3) | RIGHT(cds.title,5) |

+-------------------+--------------------+

| The | Album |

Page 158: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 158/197

+-------------------+--------------------+

1 row in set (0.00 sec)

The MID() function is only slightly complex. You still specify the length, but also astarting position. So to keep the work 'White', you would start at position 5 andhave a length of 5.

mysql> SELECT MID(cds.title,5,5)

-> FROM cds WHERE cdID='20';

+--------------------+

| MID(cds.title,5,5) |

+--------------------+

| White |

+--------------------+

1 row in set (0.03 sec)

There is also another extraction function that is is worthmentioning; SUBSTRING().

Syntax:

SUBSTRING(string,position)

Page 159: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 159/197

This returns all of the string after the position. Thus to return 'White Album' youwould start at '5'.

mysql> SELECT SUBSTRING(cds.title,5)

-> FROM cds WHERE cdID='20';

+------------------------+

| SUBSTRING(cds.title,5) |

+------------------------+

| White Album |

+------------------------+

1 row in set (0.00 sec)

Finding a piece of text in a string.

In some of the string functions we have seen so far it has been necessary toprovide a starting position as part of the function This position can be found usingthe LOCATE() function specifying the text to find (substring) as well as

the string to search in.

Syntax:

LOCATE(substring,string)

So to find the location of 'White':

Page 160: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 160/197

mysql> SELECT LOCATE('White',cds.title)

-> FROM cds WHERE cdID='20';

+---------------------------+

| LOCATE('White',cds.title) |

+---------------------------+

| 5 |

+---------------------------+

1 row in set (0.06 sec)

If a substring is not present then '0' is returned.

mysql> SELECT LOCATE('Black',cds.title)

-> FROM cds WHERE cdID='20';

+---------------------------+

| LOCATE('Black',cds.title) |

Page 161: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 161/197

+---------------------------+

| 0 |

+---------------------------+

1 row in set (0.00 sec)

It is also possible to automatically calculate the length of a piece of textusing LENGTH().

Syntax:

LENGTH(string)

So with the word 'White'.

mysql> SELECT LENGTH('White');

+-----------------+

| LENGTH('White') |

+-----------------+

| 5 |

+-----------------+

Page 162: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 162/197

1 row in set (0.03 sec)

Therefore with these results who these can be combined with one of the otherfunctions. For example with the MID() function.

mysql> SELECT MID(cds.title,LOCATE('White',cds.title),LENGTH('White'))

-> FROM cds WHERE cdID='20';

+----------------------------------------------------------+

| MID(cds.title,LOCATE('White',cds.title),LENGTH('White')) |

+----------------------------------------------------------+

| White |

+----------------------------------------------------------+

1 row in set (0.01 sec)

The LENGTH() of 'White' is worked out, the position of 'White' is worked out usingLOCATE() and these values are included within the MID() function. The result isthat White is returned.

 Transforming Strings

The final group of string functions this workshop will look at are those thattransform the string in some way. The first two change the case of the string toeither uppercase - UCASE() - or to lowercase - LCASE().

Syntax:

Page 163: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 163/197

LCASE(string)

UCASE(string)

As you can imagine the usage of these are fairly straightforward.

mysql> SELECT LCASE(cds.title), UCASE(cds.title)

-> FROM cds WHERE cdID='20';

+------------------+------------------+

| LCASE(cds.title) | UCASE(cds.title) |

+------------------+------------------+

| the white album | THE WHITE ALBUM |

+------------------+------------------+

1 row in set (0.01 sec)

The last string function this workshop will examine is REVERSE().Syntax:

REVERSE(string)

This rather obviously reverses the order of the letters. For example the alphabet.

Page 164: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 164/197

mysql> SELECT REVERSE('abcdefghijklmnopqrstuvwxyz');

+---------------------------------------+

| REVERSE('abcdefghijklmnopqrstuvwxyz') |

+---------------------------------------+

| zyxwvutsrqponmlkjihgfedcba |

+---------------------------------------+

1 row in set (0.00 sec)

Once more there are more string functions that the MySQL Manual documents.

Numeric Functions

Before talking about the specific numeric functions, it is probably worthmentioning that MySQL can perform simple math functions using mathematicaloperators.

Operator Function

+ Add

- Subtract

* Multiply

 / DivideExamples:

mysql> SELECT 6+3;

+-----+

Page 165: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 165/197

| 6+3 |

+-----+

| 9 |

+-----+

1 row in set (0.00 sec)

mysql> SELECT 6-3;

+-----+

| 6-3 |

+-----+

| 3 |

+-----+

1 row in set (0.01 sec)

Page 166: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 166/197

mysql> SELECT 6*3;

+-----+

| 6*3 |

+-----+

| 18 |

+-----+

1 row in set (0.00 sec)

mysql> SELECT 6/3;

+------+

| 6/3 |

+------+

Page 167: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 167/197

| 2.00 |

+------+

1 row in set (0.22 sec)

There are also other functions that serve a more specific math function and weshall have a look at a few of these.

FLOOR()

This reduces any number containing decimals to the lowest whole number.

Syntax:

SELECT FLOOR(number)

Example:

mysql> SELECT FLOOR(4.84);

+-------------+

| FLOOR(4.84) |

+-------------+

| 4 |

+-------------+

Page 168: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 168/197

1 row in set (0.00 sec)

CEILING()

Raises a number containing decimals to the highest whole number.

Syntax:

SELECT CEILING(number)

Example:

mysql> SELECT CEILING(4.84);

+---------------+

| CEILING(4.84) |

+---------------+

| 5 |

+---------------+

1 row in set (0.01 sec)

ROUND()

This function, as you may have guessed, rounds the figures up or down to thenearest whole number (or to a specified number of decimal places).

Syntax:

Page 169: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 169/197

ROUND(number,[Decimal Places])

'Decimal Places' is optional and omitting it will mean that the figure is rounded toa whole number.

Examples:

mysql> SELECT ROUND(14.537);

+---------------+

| ROUND(14.537) |

+---------------+

| 15 |

+---------------+

1 row in set (0.01 sec)

mysql> SELECT ROUND(14.537,2);

+-----------------+

| ROUND(14.537,2) |

Page 170: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 170/197

+-----------------+

| 14.54 |

+-----------------+

1 row in set (0.00 sec)

 TRUNCATE()

This function, rather than rounding, simply shortens the number to a required

decimal place.

Syntax:

TRUNCATE(number,places)

Example:

mysql> SELECT TRUNCATE(14.537,2);

+--------------------+

| TRUNCATE(14.537,2) |

+--------------------+

| 14.53 |

+--------------------+

Page 171: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 171/197

1 row in set (0.00 sec)

The interesting thing about truncate is that if you specify a negative number forthe 'places', it replaces the existing numbers in those places with zeros. So forexample 545 to '-2' becomes500.

mysql> SELECT TRUNCATE(545,-2);

+------------------+

| TRUNCATE(545,-2) |

+------------------+

| 500 |

+------------------+

1 row in set (0.00 sec)

Summary Functions

The MySQL manual describes this group of functions as ' Functions for Use with

GROUP BY Clauses' which I think is a little misleading as they can be used inqueries where there are no GROUP BY clauses (see Part 3 for a refresher on

GROUP BY). Thus is it is perhaps better (if probably not strictly correct) to thinkof them as functions that report information about a query (for example thenumber of rows), rather than simply display or manipulate directly the dataretrieved.

COUNT()

This counts the number of times a row (or field) is returned.

Syntax:

Page 172: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 172/197

COUNT(field)

The most common usage for this is just to specify an asterisks as the field tocount the number of rows (or in this case cds).

mysql> SELECT COUNT(*) as 'Number of Cds'

-> FROM cds;

+---------------+

| Number of Cds |

+---------------+

| 9 |

+---------------+

1 row in set (0.00 sec)

You could also choose to count just one field:

mysql> SELECT COUNT(cds.title) as 'Number of Cds'

-> FROM cds;

+---------------+

Page 173: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 173/197

| Number of Cds |

+---------------+

| 9 |

+---------------+

1 row in set (0.00 sec)

There may be occasions that we would want to count the DISTINCT occurrencesin a field. Let's look at the artist ID field to demonstrate.

mysql> SELECT COUNT(cds.artistID)

-> FROM cds;

+-----------------+

| COUNT(artist ID) |

+-----------------+

| 9 |

+-----------------+

Page 174: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 174/197

1 row in set (0.00 sec)

Now my database contain two artists that have 2 cds in the database(Various and Prince) each of whom have been counted twice. Thus we could tryusing DISTINCT as part of the query to find out how many artists have cds in thedatabase.

mysql> SELECT DISTINCT COUNT(cds.artistID)

-> FROM cds;

+-----------------+

| COUNT(artist ID) |

+-----------------+

| 9 |

+-----------------+

1 row in set (0.00 sec)

As we can see this doesn't work as each row is indeed unique and thus returns

the total of cds again. However if we include DISTINCT as part of the COUNT()function it does work.

mysql> SELECT COUNT(DISTINCT cds.artistID)

-> FROM cds;

Page 175: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 175/197

+--------------------------+

| COUNT(DISTINCT artist ID) |

+--------------------------+

| 7 |

+--------------------------+

1 row in set (0.00 sec)

AVG()

The next function we are going to look at is the AVG() which unsurprisingly is theaverage function.

Syntax:

AVG(field)

Lets look that the tracks field and work out the average number of tracks per CD.

mysql> SELECT AVG(cds.tracks)

-> FROM cds;

+-------------+

| AVG(tracks) |

Page 176: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 176/197

+-------------+

| 25.6667 |

+-------------+

1 row in set (0.01 sec)

As that is simply but AVG() can work out more that one value at a time whenused with a GROUP BY clause.

mysql> SELECT cds.artistID,AVG(cds.tracks)

-> FROM cds

-> GROUP BY cds.artistID;

+----------+-------------+

| artist ID | AVG(tracks) |

+----------+-------------+

| 1 | 11.5000 |

| 2 | 40.0000 |

Page 177: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 177/197

| 3 | 17.0000 |

| 4 | 23.0000 |

| 5 | 24.0000 |

| 17 | 30.0000 |

| 18 | 37.0000 |

+----------+-------------+

7 rows in set (0.01 sec)

As you can see an average is produced for each artist (not that we know whothey are yet) when the artist ID is specified in the GROUP BY clause. Although

AVG() is fairly straight forward, lets take this opportunity to 'tidy things up' andsee how it can work with other functions and also with a join. So first left's roundthe averages to one decimal place:

mysql> SELECT cds.artistID, ROUND(AVG(cds.tracks),1)

-> FROM cds

-> GROUP BY cds.artistID;

+----------+----------------------+

Page 178: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 178/197

| artist ID | ROUND(AVG(tracks),1) |

+----------+----------------------+

| 1 | 11.5 |

| 2 | 40.0 |

| 3 | 17.0 |

| 4 | 23.0 |

| 5 | 24.0 |

| 17 | 30.0 |

| 18 | 37.0 |

+----------+----------------------+

7 rows in set (0.04 sec)

...then perform a join on the artists table to retrieve and display the artists'names in place of the artist ID:

mysql> SELECT artists.Artist, ROUND(AVG(cds.tracks),1)

Page 179: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 179/197

  -> FROM cds

  -> LEFT JOIN artists

-> USING (artist ID)

-> GROUP BY artists.Artist;

+-------------+--------------------------+

| Artist | ROUND(AVG(cds.tracks),1) |

+-------------+--------------------------+

| Abba | 24.0 |

| Jamiroquai | 11.5 |

| Prince | 37.0 |

| The Beatles | 30.0 |

| Various | 31.5 |

| westlife | 17.0 |

Page 180: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 180/197

+-------------+--------------------------+

6 rows in set (0.01 sec)

MIN() and MAX()

These functions are very similar and select the lowest and highest figurerespectively from a result set.

Syntax:

MIN(field)

MAX(field)

So a simple example would be to display the least number and most number of tracks that any cd in the database has.

mysql> SELECT MIN(cds.tracks), MAX(cds.tracks)

-> FROM cds;

+-----------------+-----------------+

| MIN(cds.tracks) | MAX(cds.tracks) |

+-----------------+-----------------+

| 11 | 58 |

Page 181: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 181/197

+-----------------+-----------------+

1 row in set (0.00 sec)

SUM()

The final summary function that we will look at is the SUM() function which addsrows of one field in the results set together.

Syntax:

SUM(field)

So another simple example would be to add the total number of tracks in the CD

collection.

mysql> SELECT SUM(tracks)

-> FROM cds;

+-------------+

| SUM(tracks) |

+-------------+

| 231 |

+-------------+

Page 182: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 182/197

1 row in set (0.03 sec)

Control Functions

The final set of functions that this workshop will look at are the control functions

that allow us a degree of conditionality when returning result sets.

IF()

The IF() function is fairly straight forward and consists of 3 elements. A conditionand values for the condition being evaluated either true or false.

Syntax:

IF(condition,true_value,false_value)

So using a simple comparison (is a number greater than 10) to return either 'yup'or 'nope'.

mysql> SELECT IF(15>10,'Yup','Nope');

+------------------------+

| IF(15>10,'Yup','Nope') |

+------------------------+

| Yup |

+------------------------+

1 row in set (0.03 sec)

Page 183: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 183/197

mysql> SELECT IF(5>10,'Yup','Nope');

+-----------------------+

| IF(5>10,'Yup','Nope') |

+-----------------------+

| Nope |

+-----------------------+

1 row in set (0.01 sec)

As well as returned a string value, a number can also be returned. Thus if wewanted to count how many cds had more that 15 tracks we could return '1' for atrue match and a NULL value for a false match.

mysql> SELECT IF(cds.tracks>15,1,NULL)

-> FROM cds;

+--------------------------+

| IF(cds.tracks>15,1,NULL) |

Page 184: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 184/197

+--------------------------+

| NULL |

| 1 |

| 1 |

| 1 |

| NULL |

| 1 |

| 1 |

| 1 |

| 1 |

+--------------------------+

9 rows in set (0.00 sec)

We can then use COUNT() to give us a total as it ignores NULL values.

Page 185: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 185/197

mysql> SELECT COUNT(IF(cds.tracks>15,1,NULL))

-> FROM cds;

+---------------------------------+

| COUNT(IF(cds.tracks>15,1,NULL)) |

+---------------------------------+

| 7 |

+---------------------------------+

1 row in set (0.01 sec)

CASE

Slightly more advanced from IF() is the CASE function that allows for than onecomparison to be made. It is slightly different as the actual value is specified first,then a series of comparisons are made for a potential match that then returns avalue.

Syntax:

CASE actual_value

WHEN potential_value1 THEN return_value1

WHEN potential_value2 THEN return_value2...

Page 186: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 186/197

etc

END

Thus if we were to evaluate numeric values and return their string values.

mysql> SELECT CASE 2

-> WHEN 1 THEN 'One'

-> WHEN 2 THEN 'Two'

-> WHEN 3 THEN 'Three'

-> END;

+--------------------------------------------------------------------+

| CASE 2 WHEN 1 THEN 'One' WHEN 2 THEN 'Two' WHEN 3 THEN 'Three' END |

+--------------------------------------------------------------------+

| Two |

+--------------------------------------------------------------------+

Page 187: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 187/197

1 row in set (0.01 sec)

mysql> SELECT CASE 1

-> WHEN 1 THEN 'One'

-> WHEN 2 THEN 'Two'

-> WHEN 3 THEN 'Three'

-> END;

+--------------------------------------------------------------------+

| CASE 1 WHEN 1 THEN 'One' WHEN 2 THEN 'Two' WHEN 3 THEN 'Three' END |

+--------------------------------------------------------------------+

| One |

+--------------------------------------------------------------------+

1 row in set (0.00 sec)

Page 188: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 188/197

mysql> SELECT CASE 3

-> WHEN 1 THEN 'One'

-> WHEN 2 THEN 'Two'

-> WHEN 3 THEN 'Three'

-> END;

+--------------------------------------------------------------------+

| CASE 3 WHEN 1 THEN 'One' WHEN 2 THEN 'Two' WHEN 3 THEN 'Three' END |

+--------------------------------------------------------------------+

| Three |

+--------------------------------------------------------------------+

1 row in set (0.01 sec)

Notice that the actual_value is the only thing that changes in the statement.Again you could also return numeric values. Consider the following short example

Page 189: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 189/197

in which I have competed in various competitions around Scotland (sportundetermined ;-).

mysql> SELECT * FROM comp;

+------+-----------+----------+

| id | location | position |

+------+-----------+----------+

| 1 | Aberdeen | 2 |

| 2 | Edinburgh | 1 |

| 3 | Glasgow | 1 |

| 4 | Dundee | 3 |

+------+-----------+----------+

4 rows in set (0.00 sec)

I know that 10 points are awarded for 1st, 7 points for second and 5 points forthird. I can use the case statement to work out the total points I have.

mysql> SELECT CASE comp.position

Page 190: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 190/197

Page 191: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 191/197

+--------+

4 rows in set (0.00 sec)

A SUM() function can be added to this statement to give us the total.

mysql> SELECT SUM(CASE comp.position

-> WHEN 1 THEN 10

-> WHEN 2 THEN 7

-> WHEN 3 THEN 5

-> END)

-> AS points

-> FROM comp;

+--------+

| points |

+--------+

Page 192: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 192/197

| 32 |

+--------+

1 row in set (0.00 sec)

IFNULL()

The Final function we will look at is IFNULL and unsurprisingly this is a verysimple syntax that is similar to IF(). The difference is that that instead of therebeing TRUE and FALSE return values based on a condition, the original value isreturned if it is not NULL and a different new value is returned if it is NULL.

Syntax:

IFNULL(original_value, new_value)

To quickly demonstrate test one query with a NULL value and another with a realvalue.

mysql> SELECT IFNULL(NULL,'The value is Null');

+----------------------------------+

| IFNULL(NULL,'The value is Null') |

+----------------------------------+

| The value is Null |

+----------------------------------+

Page 193: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 193/197

1 row in set (0.00 sec)

mysql> SELECT IFNULL(10,'The value is Null');

+--------------------------------+

| IFNULL(10,'The value is Null') |

+--------------------------------+

| 10 |

+--------------------------------+

1 row in set (0.00 sec)

This is particularly useful for converting NULL values to actual numeric zeros. Toillustrate let's set the track value from 'The White Album' to NULL.

mysql> UPDATE cds

-> SET cds.tracks = NULL

-> WHERE (cdID = "20");

Page 194: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 194/197

Query OK, 1 row affected (0.03 sec)

Rows matched: 1 Changed: 1 Warnings: 0

mysql> SELECT cds.title, cds.tracks

-> FROM cds;

+------------------------------+--------+

| title | tracks |

+------------------------------+--------+

| A Funk Odyssey | 11 |

| Now 49 | 40 |

| Eurovision Song contest 2001 | 23 |

| Abbas Greatest Hits | 24 |

| Space Cowboy | 12 |

Page 195: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 195/197

| Sign of the times | 16 |

| The White Album | NULL |

| The Hits | 58 |

| westlife | 17 |

+------------------------------+--------+

9 rows in set (0.00 sec)

So we can use the IFNULL() function to specify a zero in place of the NULL figure.

mysql> SELECT cds.title, IFNULL(cds.tracks,0)

-> FROM cds;

+------------------------------+----------------------+

| title | IFNULL(cds.tracks,0) |

+------------------------------+----------------------+

| A Funk Odyssey | 11 |

Page 196: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 196/197

| Now 49 | 40 |

| Eurovision Song contest 2001 | 23 |

| Abbas Greatest Hits | 24 |

| Space Cowboy | 12 |

| Sign of the times | 16 |

| The White Album | 0 |

| The Hits | 58 |

| westlife | 17 |

+------------------------------+----------------------+

9 rows in set (0.00 sec)

Conclusion

I have by no means covered all the functions that MySQL possesses and evensome of those discussed above have additional syntax elements that have beenexcluded from this workshop for reasons of brevity and 'keeping things simple'.That said I would wager that what has been covered would be enough 99% of thetime. The final thing I would like to mention about functions is that if you wantyou can define your own to some degree using 'User Defined Functions', but I don'tthink these workshops are the correct place to discuss that either.

Page 197: Mysql Workshop

8/3/2019 Mysql Workshop

http://slidepdf.com/reader/full/mysql-workshop 197/197