Insert a comment line is easy: you only have to add -- before your comment.
-- This is a comment line**From **
When having logical noun/verb language separations, component names will
be separated by the underscore character to indicate the separation.
e.g. A column storing a user’s date of birth would be named date_of_birth and
a column storing time elapsed in seconds would be named time_elapsed_in_seconds.
Table names will be defined in the plural. This is because a table is itself
a collection of 1 or more row entities (plural), and this naming convention
is also better understood in the object oriented world.e.g. A table storing records of customer location addresses
would be named customer_location_addresses (rather than customer_location_address).
RQ: The name of a table can begin with a capital letter.
Format
CONSTRAINT pk_table_name PRIMARY KEY (column_name)Example:
CREATE TABLE IF NOT EXISTS Clients (
...,
CONSTRAINT pk_Clients PRIMARY KEY (numéro_client),
...
);Format
The source is the source table, column is the column which will be the fk and target is the target table.
CONSTRAINT fk_source_column_target FOREIGN KEY (column_name) REFERENCES target_table(column_name)Example:
CREATE TABLE IF NOT EXISTS Commandes (
...,
CONSTRAINT fk_commandes_numéro_client_clients FOREIGN KEY (numéro_client) REFERENCES Clients(numéro_client),
...
);Format
CONSTRAINT ck_column_name CHECK(column_name condition)Example:
CREATE TABLE IF NOT EXISTS Produits (
...,
CONSTRAINT ck_quantité_stock CHECK(quantité_stock >= 0),
...
);CREATE DATABASE [IF NOT EXISTS] db_name
[DEFAULT] CHARACTER SET [=] charset
[DEFAULT] COLLATE [=] collation;CREATE DATABASE IF NOT EXISTS Parc
CHARACTER SET utf8
COLLATE utf8_general_ci;CREATE TABLE [IF NOT EXISTS] tbl_name (
create definition…
) [table_options] [partition_options];CREATE TABLE IF NOT EXISTS Clients (
numéro_client VARCHAR(4),
nom VARCHAR(15),
localité VARCHAR(15),
catégorie VARCHAR(2),
compte INT(7),
CONSTRAINT pk_Clients PRIMARY KEY(numéro_client)
)
ENGINE = INNODB;SELECT column_name, function(column_name)
FROM table_name
WHERE condition;SELECT numéro_client, nom
FROM Clients
WHERE localité <=> 'TOULOUSE';| numéro_client | nom |
|---|---|
| B512 | GILLET |
| C003 | AVRON |
| D063 | MERCIER |
| F011 | PONCELET |
| K729 | NEUMAN |
SELECT *
FROM Clients
WHERE localité <=> 'TOULOUSE';| numéro_client | nom | localité | catégorie | compte |
|---|---|---|---|---|
| B512 | GILLET | Toulouse | B1 | -8700.00 |
| C003 | AVRON | Toulouse | B1 | -1700.00 |
| D063 | MERCIER | Toulouse | NULL | -2250.00 |
| F011 | PONCELET | Toulouse | B2 | 0.00 |
| K729 | NEUMAN | Toulouse | NULL | 0.00 |
| Operator | Use |
|---|---|
| = | Equal (can't be used with NULL) |
| <=> or is | Equal (also with NULL) |
| != | Different (can't be used with NULL) |
| <> or is not | Different (also with NULL) |
| < | Smaller |
| <= | Smaller or equal |
| > | Greater |
| >= | Greater or equal |
| AND | AND |
| OR | OR |
| NOT | Opposite |
⇒ We'll use <=> instead of =.
This condition is used for a search into a list.
RQ: When the search item isn't in the list, week-end can use NOT IN.
Format
SELECT numéro_client
FROM Clients
WHERE catégorie IN ('C1', 'C2', 'C3');This condition is used for a search in a range, instead of using <= and >=.
RQ: To exclude a range, use NOT BETWEEN.
SELECT numéro_client
FROM Clients
WHERE compte BETWEEN 1000 AND 4000;How to search for strings ?
Using LIKE is the solution, there are two jokers:
As always, you can exclude a string with NOT LIKE.
Format
SELECT column_name
FROM table_name
WHERE column_name LIKE 'name%';EXAMPLES
SELECT numéro_client
FROM Clients
WHERE catégorie LIKE 'B_';The results could be: B1 or Bd.
They couldn't be: xB, B or B12.
SELECT numéro_produit
FROM Produits
WHERE Libelle LIKE '%SAPIN%';The results could be: Boite en SAPIN or SAPIN verni.
They couldn't be: Boite en Sapin or S A P I N verni.
RQ: Le mot clé doit se trouver à l'intérieur de la fonction.
SELECT DISTINCT column_name, function(DISTINCT column_name)
FROM table_name
WHERE condition;SELECT localité
FROM Clients
WHERE catégorie <=> 'C1';| localité |
|---|
| Poitiers |
| Namur |
| Poitiers |
| Namur |
| Namur |
SELECT DISTINCT localité
FROM Clients
WHERE catégorie <=> 'C1';| localité |
|---|
| Namur |
| Poitiers |
Example
SELECT numéro_produit AS Produit, 0.21*prix*quantité_stock AS Valeur_TVA
FROM Produits
WHERE quantité_stock > 50000; | Produit | Valeur_TVA |
|---|---|
| CS264 | 67788 |
| PH222 | 37770.6 |
To group several results from a same column and use it with an aggregation function.
An advantage of using GROUP BY is the automatic sorting of the values.
Format
SELECT column_name, func(column_name)
FROM table_name
GROUP BY column_name;Example:
SELECT localité, COUNT(*) AS nombre_clients
FROM Clients;| localité | nombreClients |
|---|---|
| Bruxelles | 16 |
Displays the first alpha-numerical value and count all values.
SELECT localité, COUNT(*) AS nombre_clients
FROM Clients
GROUP BY localité;| localité | nombreClients |
|---|---|
| Bruxelles | 1 |
| Geneve | 1 |
| Lille | 1 |
| Namur | 4 |
| Paris | 1 |
| Poitiers | 3 |
| Toulouse | 5 |
Displays the sorted grouped values and the linked count values.
To sort the result table after one or several columns in ascending (ASC) or descending (DESC) order.
RQ: The default order is ascending but it's better to use it.
Format
SELECT column_name
FROM table_name
ORDER BY column_name;Example:
SELECT *
FROM Produits
ORDER BY prix;| numéro_produit | prix | quantité_stock |
|---|---|---|
| CS262 | 75 | 45 |
| PA60 | 95 | 134 |
| PA45 | 105 | 580 |
| CS264 | 120 | 2690 |
| PS222 | 185 | 1220 |
| CS464 | 220 | 450 |
| PH222 | 230 | 782 |
HAVING is like WHERE but it filters using functions like SUM, COUNT, AVG,….
It allows to select the chosen column, by grouping the identical values of the column, and to respect the condition.Because the command groups the values, it isn't necessary to use GROUP BY whith it.
Format
SELECT column_name, func(column_name)
FROM table_name
GROUP BY column_name
HAVING condition;Example: See the GROUP BY example
SELECT localité, COUNT(*) AS nombre_clients
FROM Clients
GROUP BY localité
HAVING COUNT(*) >= 3;| localité | nombreClients |
|---|---|
| Namur | 4 |
| Poitiers | 3 |
| Toulouse | 5 |
In addition to working with functions, there is another difference between WHERE and HAVING:
This is an example of the reading order of a more complex query:
7: SELECT column_name
1: FROM table_name
2: WHERE condition
3: AND otherCondition
4: GROUP BY column_name
5: HAVING condition
6: ORDER BY column_nameAn SQL JOIN clause is used to combine rows from two or more tables, based on a common field between them.
The most common type of join is: SQL INNER JOIN (simple join). An SQL INNER JOIN returns all rows from multiple tables where the join condition is met.
Imagine you have 2 tables (T1 and T2):
| T1 | T2 | |
|---|---|---|
| Num | Num | |
| 12 | 93 | |
| 34 | 12 | |
| 27 | 34 | |
| 12 | 12 | |
| 12 | 49 |
The UNION operator is used to combine the result-set of two or more SELECT statements.
Notice that each SELECT statement within the UNION must have the same number of columns. The columns must also have similar data types.
The mathematical notation is: T1 ∪ T2
The MySQL code will be:
SELECT Num FROM T1
UNION
SELECT Num FROM T2;The result is:
| T1 ∪ T2 |
|---|
| 12 |
| 34 |
| 27 |
| 93 |
| 49 |
The intersection is used to return the results of two or more SELECT statements.
Each SQL statement must have the same number of fields in the result sets with similar data types.
The mathematical notation is: T1 ∩ T2
The MySQL code will be:
SELECT DISTINCT Num
FROM T1
WHERE T1.Num IN
(SELECT T2.Num
FROM T2);The result is:
| T1 ∩ T2 |
|---|
| 12 |
| 34 |
The difference is used to return all rows in the first SELECT statement that are not returned by the second SELECT statement.
Each SELECT statement must have the same number of fields in the result sets with similar data types.
The mathematical notation is: T1 − T2
The MySQL code will be:
SELECT DISTINCT Num
FROM T1
WHERE T1.Num NOT IN
(SELECT T2.Num
FROM T2);The result is:
| T1 − T2 |
|---|
| 27 |
Returns the Cartesian product of the sets of records from the two or more joined tables.
Thus, it equates to an inner join where the join-condition always evaluates to True or where the join-condition is absent from the statement.The mathematical notation is: T1 × T2

The MySQL code will be:
SELECT T1.Num, T2.Num
FROM T1, T2;The result is:
| T1 × T2 |
|---|
| 12 ⏤ 93 |
| 12 ⏤ 12 |
| 12 ⏤ 34 |
| 12 ⏤ 12 |
| 12 ⏤ 49 |
| 34 ⏤ 93 |
| 34 ⏤ 12 |
| … |
| 12 ⏤ 49 |
We use subqueries when we want a response from several tables.
For instance, we want the numéro_commande from the Clients living in Namur.
⇒ numéro_commande is from Commande and Namur is from Client.
The query will be:
SELECT numéro_commande, date_commande
FROM Commandes
WHERE numéro_client in (SELECT numéro_client
FROM Clients
WHERE localité <=> 'Namur');Where the inner query is named subquery.
RQ: The reading direction is bottom-up.
There a five functions:
AVG(): calculates the average of a set of records
COUNT(): the number of records on a table or column
MAX(): the maximum value (numeric or alphanumeric) of a column
MIN(): the minimum value (numeric or alphanumeric) of a column
SUM(): calculates the sum of a set of records
RQ: _The strings can be values from a column as **catégorie
A stored procedure is actually a series of SQL statements identified by a name.
When a stored procedure is created, it is stored in the database that is being used, in the same way as a table for example.Once the procedure is created, it can be called by name. The instructions of the procedure are then executed.
DELIMITER |
CREATE PROCEDURE my_procedure([parameter1 [, parameter2,…]])
BEGIN
SELECT column_name, function(column_name)
FROM table_name
WHERE condition;
END|
DELIMITER ;CALL my_procedure([parameter1 [, parameter2,…]);DROP PROCEDURE IF EXISTS my_procedure;ALTER PROCEDURE IF EXISTS my_procedure;The delimiter has to be change by the DELIMITER command.
Indeed, the default delimiter is ; but, in the stored procedure, the delimiter has to be ;.
In that case, there'll be an error when arriving to the inside ;.
Thus the delimiter is replaced by |, // or $ for the stored procedure.
DELIMITER |In this case, the delimiter is now |. That means that ; has no meaning anymore.
These two keywords are used to delimit one instruction block which can contain more than one instruction.
DELIMITER |
CREATE PROCEDURE name()
BEGIN
instructions;
END|RQ: The name of a parameter has to begin by p_.
Example: p_client.
CREATE PROCEDURE my_procedure(SENSE p_param_name TYPE)
...There're three senses of parameters:
It is an incoming parameter.
That is to say that it is a parameter whose value is supplied to the stored procedure. This value will be used during the procedure (for a calculation or a selection for example).RQ: It is the default sense. That means that if no sense is given, it'll be this one who will be used.
It is an outgoing parameter whose value will be established during the procedure and which can then be used outside of this procedure.
Such a parameter will be used during the procedure, may see its value changed by it, and will then be usable outside.
DELIMITER |
CREATE PROCEDURE get_nb_clients_by_location (IN p_nb_min_clients INT)
BEGIN
SELECT localité, COUNT(*) AS nombre_clients
FROM Clients
GROUP BY localité
HAVING COUNT(*) >= p_nb_min_clients;
END |
DELIMITER ;CALL get_nb_clients_by_location (3);| localité | nombreClients |
|---|---|
| Namur | 4 |
| Poitiers | 3 |
| Toulouse | 5 |
CREATE TRIGGER trigger_name {BEFORE|AFTER} {INSERT|UPDATE|DELETE}
ON table_name FOR EACH ROW
trigger_body;The body of a trigger has the same format as a stored procedure.
There are three different events which can trigger the execution of the instructions of a trigger:
A trigger is activated by only one of the three events.
But there can be several different triggers (one for each event).
When a trigger is activated, its instructions can be executed at two different times:
There can be only one trigger per combination.
That means that it can be only one BEFORE UPDATE per table.RQ: Since there are two possibilities for the execution time, and three for the trigger event, we have a maximum of six triggers per table.
A trigger has an execution time, an event and a table name.
Thus, a trigger is unique and it can have an unique name:
trigger_name = time_event_table_name
DELIMITER |
CREATE TRIGGER after_insert_clients AFTER INSERT
ON Clients FOR EACH ROW
-- BEGIN
SET NEW.nom = UPPER(NEW.nom);
-- END|
DELIMITER ;| numéro_client | nom | localité | catégorie | compte |
|---|---|---|---|---|
| B062 | GOFFIN | Namur | B2 | -3200.00 |
| B112 | HANSENNE | Poitiers | C1 | 1250.00 |
| B332 | MONTI | Geneve | B2 | 0.00 |
| B512 | GILLET | Toulouse | B1 | -8700.00 |
| C003 | AVRON | Toulouse | B1 | -1700.00 |
| C123 | MERCIER | Namur | C1 | -2300.00 |
| C400 | FERARD | Poitiers | B2 | 350.00 |
| D063 | MERCIER | Toulouse | NULL | -2250.00 |
| F010 | TOUSSAINT | Poitiers | C1 | 0.00 |
| F011 | PONCELET | Toulouse | B2 | 0.00 |
| F400 | JACOB | Bruxelles | C2 | 0.00 |
| K111 | VANBIST | Lille | B1 | 720.00 |
| K729 | NEUMAN | Toulouse | NULL | 0.00 |
| L422 | FRANCK | Namur | C1 | 0.00 |
| S127 | VANDERKA | Namur | C1 | -4580.00 |
| S712 | GUILLAUME | Paris | B1 | 0.00 |
| numéro_commande | numéro_client | date_commande |
|---|---|---|
| 30178 | K111 | 2008-08-22 |
| 30179 | C400 | 2008-08-22 |
| 30182 | S127 | 2008-08-23 |
| 30184 | C400 | 2008-08-23 |
| 30185 | F011 | 2009-01-02 |
| 30186 | C400 | 2009-01-02 |
| 30188 | B512 | 2009-01-02 |
| numéro_produit | prix | quantité_stock |
|---|---|---|
| CS262 | 75 | 45 |
| CS264 | 120 | 2690 |
| CS464 | 220 | 450 |
| PA45 | 105 | 580 |
| PA60 | 95 | 134 |
| PH222 | 230 | 782 |
| PS222 | 185 | 1220 |
| numéro_commande | numéro_produit | quantité_commande |
|---|---|---|
| 30178 | CS464 | 25 |
| 30179 | CS262 | 60 |
| 30179 | PA60 | 20 |
| 30182 | PA60 | 30 |
| 30184 | CS464 | 120 |
| 30184 | PA45 | 20 |
| 30185 | CS464 | 260 |
| 30185 | PA60 | 15 |
| 30185 | PS222 | 600 |
| 30186 | PA45 | 3 |
| 30188 | CS464 | 180 |
| 30188 | PA45 | 22 |
| 30188 | PA60 | 70 |
| 30188 | PH222 | 92 |