SQL statements can be categorized into five types:
Category | Purpose |
---|---|
1. Query statements |
They make the search of the information possible
|
2. Data manipulation statements |
Allow you to change the contents of the tables
|
3. Data definition statements |
Allow you to change the design of the database
|
4. Transaction control statements |
They make the saving or cancelling of the change in the contents of records possible
|
5. Data control statements) |
Allow you to change the user priviledges
|
Usually all products(except Access) interpret the line as comment if it begins with "--". In other words so:
-- Commentline
Also the following comment is possible in most of the products:
/* comment begins
and comment ends */
In MySQL the # sign at the beginning of the line also will signify the comment.
Tables are created with the CREATE TABLE statement. After that there will be the name of the new table end inside brackets the field names and their types.
ExampleCREATE TABLE person( id_person SMALLINT PRIMARY KEY, firstname CHAR(15) NOT NULL, lastname CHAR(15) NOT NULL, city CHAR(10), birthyear SMALLINT, salary DOUBLE) ENGINE=InnoDB;
CREATE TABLE person( id_person SMALLINT primary key ...The same is achieved also as follows:
CREATE TABLE person( id_person SMALLINT, ... PRIMARY KEY(id_person) ...
PRIMARY KEY (id_project, id_person)
Index in sql is created to tables to retrieve the rows quickly. When there are thousands of records in a table, retrieving information will take a long time. Therefore indexes are created on columns which are accessed frequently, so that the information can be retrieved quickly. Indexes can be created on a single column or a group of columns. When a index is created, it first sorts the data and then it assigns a ROWID for each row.
When you create an index on the index defines whether duplicates or not. If duplicate values are allowed, the index is created with keyword INDEX.
ExampleCREATE TABLE person( id_person SMALLINT PRIMARY KEY, firstname CHAR(15) NOT NULL, lastname CHAR(15) NOT NULL, city CHAR(10), birthyear SMALLINT, salary DOUBLE, INDEX lastnameIndex (lastname));And if you want to disallow duplicates on the index fields, use Unique
CREATE TABLE person( id_person SMALLINT PRIMARY KEY, firstname CHAR(15) NOT NULL, lastname CHAR(15) NOT NULL, city CHAR(10), birthyear SMALLINT, salary DOUBLE, UNIQUE lastnameIndex (lastname) );Also you can make an index which includes several fields:
CREATE TABLE person( id_person SMALLINT PRIMARY KEY, firstname CHAR(15) NOT NULL, lastname CHAR(15) NOT NULL, city CHAR(10), birthyear SMALLINT, salary DOUBLE, INDEX nameIndex (firstname,lastname) );
If you don't give any name to the index,
MySQL names the index according to the first index field.
Example INDEX (fi,si) -> index will be named fi.
You can also add indexes later, when the table already exists. Then you can use below code:
CREATE INDEX lastnameIndex ON person(lastname);
You can check what indexes the table has with below command:
show indexes from person\G
You can delete indexes with below command:
DROP INDEX lastnameIndex ON person;
Data types vary slightly in different systems, so you should check the product manual. Most products has below types:
The purpose of referential integrity is to take care that all rows in child-table has a parent row in parent table.
In order to create table named hour to MySQL, you can use below code
CREATE TABLE hour ( id_project CHAR(5) NOT NULL, id_person SMALLINT NOT NULL, workhour INT, PRIMARY KEY (id_project,id_person), CONSTRAINT project_hour FOREIGN KEY (id_project) REFERENCES project (id_project) ON DELETE RESTRICT ON UPDATE CASCADE) Engine=InnoDB;In order to execute above code, you have to first create a table named project which has field id_project. And now if you update some value of id_project int the project table(parent-table), the same changes will be made automatically to hour table(child table). And you can not delete rows from project table if there is child rows in hour table.
The SQL ALTER TABLE command is used to modify the definition (structure) of a table by modifying the definition of its columns. The ALTER command is used to perform the following functions.
ALTER TABLE person ADD COLUMN test CHAR(20);
ALTER TABLE person MODIFY COLUMN test CHAR(40);
ALTER TABLE person DROP COLUMN test;
ALTER TABLE person ADD INDEX ind_name (lastname);
DROP TABLE hour;
DROP TABLE hour,person;
Select Queries will produce a view (return data).
Select queries consists of The following elements :
SELECT
which columns will be retrieved
FROM
from what table/tables or a view/views is it searched for
WHERE
which rows will be included in view
GROUP BY
how is it grouped
HAVING
what of the lines which have been created as a result of the grouping are shown
ORDER BY
how is it sorted
Examples
--this will return id_person and lastname SELECT id_person, lastname FROM person;
--this will return all fields from the table SELECT * FROM person;
You can use DISTINCT statement in the SELECT query to return only those lines as a result which have differences.
SELECT DISTINCT city FROM person;prints all city-names only once.
You can use Limit statement in the SELECT query to return only those lines which are between the given values.
SELECT city LIMIT 3,5 FROM person;prints the 5 rows from the person table, starting from row 3.
There are several functions which you can use in the SELECT. Here are some examples, which works in MySQL.
SELECT DATE();Shows the date of today.
SELECT VERSION();Shows the version of your MySQL-server (in MySQL).
SELECT USER();Shows your username (in MySQL).
If you want to change the heading of the result set, you can use the AS keyword
ExampleSELECT lastname AS Name FROM person;In above example lastname is the field name in the database, but in the result set the heading is changed to Name. (Note: the code works also without the keyword AS, but the code is clearer, when you use it.)
SELECT name, 'Some text' FROM person;
You can concatenate several fields and literals together
ExampleSELECT CONCAT(firstname," ", lastname) AS Name FROM person;
SELECT SUBSTRING(lastname,2,4) FROM person;This will print 4 characters from name starting from the second character.
You can use Where statement to choose which rows will be included to the view.
ExamplesSELECT * FROM person WHERE city ='TURKU';
SELECT * FROM person WHERE NOT city='TURKU';
SELECT * FROM person WHERE city <>'TURKU';
SELECT * FROM person WHERE salary=5000;
If there is several option, it is shorter to use IN query
SELECT * FROM person WHERE city in ('Turku', 'Tampere', Oulu);
If you need to return values between some values, you can use below example
SELECT * FROM person WHERE salary between 4000 AND 5000;
Missing information can be found with below code:
SELECT * FROM person WHERE city IS NULL;
Example
WHERE city LIKE 'T%'So it shows those records in which the city begins with the letter, T
WHERE lastnameLIKE '_i%'shows those records which has i as a second letter in the name-field
_
: any character (only one character)
%
: any character or string (also several characters)
The Aggregate Functions are:
SELECT AVG(priorit) FROM project;
SELECT city, count(id_person) FROM person GROUP BY city;Example
SELECT city, GROUP_CONCAT(lastname) AS peoples FROM person GROUP BY city;the following result is obtained:
+----------+----------------------+ | city | peoples | +----------+----------------------+ | HELSINKI | River,Simpson | | TAMPERE | Daniels | | TURKU | Morrison,Smith,Jones | +----------+----------------------+
SELECT place, count(*) FROM project GROUP BY place HAVING COUNT (*) >= 2;
Difference between WHERE and HAVING: WHERE filters rows before grouping, and HAVING filters groups after grouping. And you can not use HAVING without GROUP BY.
SQL join clause combines records from two or more tables in a database. You can combine the parent and child table with JOIN and then return fields from both tables. MySQL has three kind of JOINS:
select project.id_project,pname,work_hour FROM project inner JOIN hour ON project.id_project = hour.id_project;And the result is this
+------------+-------------+-----------+ | id_project | pname | work_hour | +------------+-------------+-----------+ | 101 | Bookkeeping | 300 | | 101 | Bookkeeping | 200 | | 101 | Bookkeeping | 200 | | 101 | Bookkeeping | 100 | | 101 | Bookkeeping | 100 | | 101 | Bookkeeping | 400 | | 102 | Billing | 300 | | 102 | Billing | 400 | | 103 | Store | 200 | | 104 | Selling | 300 | | 104 | Selling | 200 | | 104 | Selling | 400 | +------------+-------------+-----------+
FROM Table1 LEFT OUTER JOIN Table2 ON Table1.id=Table2.idIs the same as:
FROM Table2 RIGHT OUTER JOIN Table1 ON Table2.id=Table1.idN.B.! The word OUTER is often omitted
select project.id_project,pname,work_hour FROM project left JOIN hour ON project.id_project = hour.id_project;And the result is this
+------------+-------------+-----------+ | id_project | pname | work_hour | +------------+-------------+-----------+ | 101 | Bookkeeping | 300 | | 101 | Bookkeeping | 200 | | 101 | Bookkeeping | 200 | | 101 | Bookkeeping | 100 | | 101 | Bookkeeping | 100 | | 101 | Bookkeeping | 400 | | 102 | Billing | 300 | | 102 | Billing | 400 | | 103 | Store | 200 | | 104 | Selling | 300 | | 104 | Selling | 200 | | 104 | Selling | 400 | | 105 | Customers | NULL | | 106 | Statistics | NULL | +------------+-------------+-----------+
FROM person INNER JOIN hour ON person.id_person=hour.id_person INNER JOIN project ON hour.id_project=project.id_project;
You can retrieve records from several tables using Union Query
Example
The persons which salary is over 40 and/or which belong to the project 102
SELECT lastname as Name,"Salary is over 40" FROM person WHERE salary>40 UNION SELECT lastname,"Belongs to 102" FROM person INNER JOIN hour ON person.id_person = hour.id_person WHERE id_project='102';The results are
+----------+-------------------+ | Name | Salary is over 40 | +----------+-------------------+ | Morrison | Salary is over 40 | | Jones | Salary is over 40 | | Morrison | Belongs to 102 | | River | Belongs to 102 | +----------+-------------------+You can also make Union queries like this:
SELECT lastname as Name,"Salary is over 40" FROM person WHERE salary>40 UNION SELECT lastname as Name,"Salary is not over 40" FROM person WHERE salary<=40;The results are
+----------+-----------------------+ | Name | Salary is over 40 | +----------+-----------------------+ | Morrison | Salary is over 40 | | Jones | Salary is over 40 | | Smith | Salary is not over 40 | | River | Salary is not over 40 | | Simpson | Salary is not over 40 | | Daniels | Salary is not over 40 | +----------+-----------------------+You can also replace previous Union with IF like this
SELECT lastname as Name, IF(salary>40, "Salary is over 40", "Salary is not over 40") as "Explanation" FROM person;
SELECT lastname,"Less than 39" FROM person WHERE salary<39 UNION SELECT lastname,"Over 39" FROM person WHERE salary>39 UNION SELECT lastname,"Exactly 39" FROM person WHERE salary=39 ORDER BY 2;And the result is
+----------+--------------+ | lastname | Less than 39 | +----------+--------------+ | Smith | Exactly 39 | | River | Exactly 39 | | Simpson | Less than 39 | | Daniels | Less than 39 | | Morrison | Over 39 | | Jones | Over 39 | +----------+--------------+
Example
SELECT column_name(s) FROM table1
UNION ALL
SELECT column_name(s) FROM table2
You can use also IF in SELECT statement. The syntax is IF(condition, Option1, Option2). So, if the condition is true, Option1 will be executed otherwise Option2.
Example
SELECT pname, IF(priorit<2, "Very Important", "Normal priorit") as Cathegory FROM project;
Subquery or Inner query or Nested query is a query inside a query. A subquery is usually added in the WHERE Clause of the sql statement.
Most of the time, a subquery is used when you know how to search for a value using a SELECT statement, but do not know the exact value.
Example
All the person are fetched who were born in the same year as Morrison
SELECT lastname FROM person WHERE birth_year= ( SELECT birth_year FROM person WHERE lastname='Morrison');Example
SELECT lastname, salary FROM person WHERE salary > ( SELECT min(salary)*2 FROM person);If a subquery returns more than one records, there is a need for an IN subquery
SELECT lastname FROM person WHERE id_person IN ( SELECT id_person FROM hour WHERE work_hour>=400);
If we use word ANY like this
WHERE salary > ANY ("SubQuery")In this case, the condition is fulfilled when the salary is greater than any of the return values of the subquery.
and if we use word ALL, like this
WHERE salary > ALL ("SubQuery")In this case, the condition is fulfilled when the salary is greater than all of the return values of the subquery.
Example, we have this data
+----------+--------+ | city | salary | +----------+--------+ | HELSINKI | 39 | | HELSINKI | 36 | | TAMPERE | 34 | | TURKU | 44 | | TURKU | 39 | | TURKU | 44 | +----------+--------+Then with this query
select city, salary from person where salary < any(select salary from person where city='Turku');we will get this data (all rows where salary < 44)
+----------+--------+ | city | salary | +----------+--------+ | TURKU | 39 | | HELSINKI | 39 | | HELSINKI | 36 | | TAMPERE | 34 | +----------+--------+And with this query
select city, salary from person where salary < all(select salary from person where city='Turku');we will get this data (all rows where salary < 39)
+----------+--------+ | city | salary | +----------+--------+ | HELSINKI | 36 | | TAMPERE | 34 | +----------+--------+
Delete records, which meets on a condition
DELETE FROM project WHERE id_project=2145;
UPDATE person SET salary=salary*1.2 WHERE city='TURKU';
INSERT INTO test VALUES(101,'Matt',180);or like this:
INSERT INTO test VALUES(102,'Liisa',NULL);In the previous examples the information must be given in that order as the fields are in the table and to every field a value must be fed(at least NULL.)
INSERT INTO test (name,id) VALUES('Liisa',103);
You can also read data from one table and insert that data to a new table which does not already exist.
The new table gets the same field definitions as in that table at which the data is picked up.
Example
Below code will read data from project-table and create a new table named helsinki with that data.
CREATE TABLE helsinki SELECT * FROM project WHERE place='Helsinki';If you already have table named helsinki and you want to insert data from project, you can use below code
INSERT INTO helsinki SELECT * FROM project WHERE place ='Helsinki';
Stored Procedures are SQL-scipts which will be stored in the database. Every RDBMS has they own syntax for procedures.
Below examples are only for MySQL.
Next example will create an procedure named searchPerson:DELIMITER // CREATE PROCEDURE searchPerson(IN sname CHAR(50)) BEGIN SELECT * FROM person WHERE lastname=sname; END // DELIMITER ;Then we can call this procedure with this command:
CALL searchPerson('Morrison');We can check what procedures we have in a certain database:
SHOW PROCEDURE STATUS WHERE db='database' \GWe can check the procedure syntax:
SHOW CREATE PROCEDURE searhPerson \GWe can delete the procedure:
DROP PROCEDURE searhPerson;
NOTE : In above example the query was so simple that it is not reasonable to save it as a procedure.
In the parameter list you will create variables (like sname in previous example ), but you can also save the results from SQL to variables. You can create two kind of variables :
Another difference between local variables and user-defined variable is that local variable is reinitialized with NULL value each time whenever stored procedure is called while user-defined variable is not reinitialized with NULL.
Example about User-defined variableSELECT firstname INTO @chosenFname FROM person WHERE lastname=sname; SELECT * FROM person WHERE firstname = @chosenFname;Example about local variable
DECLARE chosenFname VARCHAR(50); SELECT firstname INTO chosenFname FROM person WHERE lastname=sname; SELECT * FROM person WHERE firstname = chosenFname;
Lets assume that you want to check, if some rows exists. So, you can do it like this
DECLARE test INT DEFAULT 0; SET test = (SELECT COUNT(*) ...);Then you can use the test variable in IF ELSE like this
IF test THEN ... ELSE END IF;
Stored Procedures have several benefits:
Delimiter is the "string" that tells to mysql-client that you want to execute your script. The default is ;
. When you write procedures, you need to add ;
inside your procedure code. So, before you start to write the procedure, you should change the delimiter to something else (typically // or $$), so that your client does not execute it immediatelly. And when your procedure is ready, you can change the delimiter back to default.
Transaction means a subset of several operations to database. If one operation fails, the whole transaction will be cancelled.
COMMIT makes the changes (caused by transaction) permanent. And Rollback will cancel them (if they are not committed yet).
Create a table with below code
CREATE TABLE bank_account( idaccount INT PRIMARY KEY, balance double, credit_limit double );And another table with below code
CREATE TABLE action ( idaction int PRIMARY KEY AUTO_INCREMENT, idaccount int, action varchar(45), action_time timestamp, amount double );Then we will create two accounts, which both have balance 500.
INSERT INTO bank_account VALUES(1,500,1000); INSERT INTO bank_account VALUES(2,500,2000);Then we will create an Procedure which will move money from one account to another account
DELIMITER // CREATE PROCEDURE debit_transfer(IN first_id INT, IN second_id INT, IN amount DOUBLE ) BEGIN DECLARE test1,test2 INT DEFAULT 0; START TRANSACTION; UPDATE bank_account SET balance=balance-amount WHERE idaccount=first_id AND balance >= amount; SET test1=ROW_COUNT(); UPDATE bank_account SET balance=balance+amount WHERE idaccount=second_id; SET test2=ROW_COUNT(); IF (test1 > 0 AND test2 >0) THEN COMMIT; INSERT INTO action(idaccount,action,amount,action_time) VALUES(first_id,'withdrawal',amount,NOW()); INSERT INTO action(idaccount,action,amount,action_time) VALUES(second_id,'deposit',amount,NOW()); ELSE ROLLBACK; END IF; END // DELIMITER ;Explanation:
CALL debit_transfer(1,2,100); SELECT * FROM bank_account; and CALL debit_transfer(1,3,100); SELECT * FROM bank_account; and CALL debit_transfer(3,2,2000); SELECT * FROM bank_account;Above transaction is suitable for bank_accounts where is not allowed that the balance is negative.
DELIMITER // CREATE PROCEDURE credit_transfer(IN first_id INT, IN second_id INT, IN amount DOUBLE ) BEGIN DECLARE test1, test2 INT DEFAULT 0; START TRANSACTION; UPDATE bank_account SET balance=balance-amount WHERE idaccount=first_id AND balance + credit_limit >= amount; SET test1=ROW_COUNT(); UPDATE bank_account SET balance=balance+amount WHERE idaccount=second_id; SET test2=ROW_COUNT(); IF (test1 > 0 AND test2 >0) THEN COMMIT; INSERT INTO action(idaccount,action,amount,action_time) VALUES(first_id,'withdrawal',amount, NOW()); INSERT INTO action(idaccount,action,amount,action_time) VALUES(second_id,'deposit',amount, NOW()); ELSE ROLLBACK; END IF; END // DELIMITER ;
Triggers are little modules stored on database. These modules are executed automatically, when certain SQL-commands are executed. We can define the triggers start when UPDATE-, INSERT-, or DELETE-command is executed.
ExampleCREATE TABLE Customers( idCustomers INT primary key auto_increment, customerName VARCHAR(20) ); CREATE TABLE Logs( idLogs INT primary key auto_increment, customerName VARCHAR(20), idCustomers INT, updateType VARCHAR(50) DEFAULT NULL, updateTime TIMESTAMP );Then we will create an trigger, which will add the previous name of the Customer to the Customer-table, when we update the name. Also we will add the time and explanation "update".
DELIMITER $$ CREATE TRIGGER updateCustomer BEFORE UPDATE ON Customers FOR EACH ROW BEGIN INSERT INTO Logs SET updateType = 'update', idCustomers = OLD.idCustomers, customerName = OLD.customerName, updateTime = NOW(); END$$ DELIMITER ;Also we can create trigger, which will save the name of the Customer, to Logs-table, if we delete the Customer. Also the time and explanation "delete" will be saved.
DELIMITER $$ CREATE TRIGGER deleteCustomer BEFORE DELETE ON Customers FOR EACH ROW BEGIN INSERT INTO Logs SET updateType = 'delete', idCustomers = OLD.idCustomers, customerName = OLD.customerName, updateTime = NOW(); END$$ DELIMITER ;
You can also schedule some actions in MySQL Server, using events. Here is one simple example which will update the value in database after 1 minute.
Create a test database and a table with below code
create database eventtest; use eventtest; create table atest( id_atest int primary key auto_increment, amount int); insert into atest(amount) values(5);And create the event with below code
CREATE EVENT myevent ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MINUTE DO UPDATE atest SET amount=amount + 1;If you check the data after in a minute, you should see that the value om amount has been updated.
You can check what kind of event your database has with below command
SHOW events;Note! above event will be deleted after it has been executed. If you want to make an event which will be executed every 1 minute, you can use below code
DELIMITER // CREATE EVENT permanent_event ON SCHEDULE EVERY 1 MINUTE DO BEGIN UPDATE atest SET amount=amount + 1; END // DELIMITER ;If you now check the data once in a minute, you should see that the value om amount will be updated. You can remove the event with the command
DROP EVENT permanent_event;
If you are going to make an application (web-application, Java-application etc), you should take care that there is no risk for sql-injection.
Example here is a dangerous php-code
$sql = 'SELECT * FROM person WHERE person_id='.$_POST['id'] ;