Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
44 views

MySQL Notes

MySQL

Uploaded by

sirilkanuri01
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views

MySQL Notes

MySQL

Uploaded by

sirilkanuri01
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 120

MySQL

Chapter 1: Getting started with MySQL


Section 1.1: Getting Started
Chapter 2: Data Types
Section 2.1: CHAR(n)
Section 2.2: DATE, DATETIME, TIMESTAMP, YEAR, and TIME
Section 2.3: VARCHAR(255) -- or not
Section 2.4: INT as AUTO_INCREMENT
Section 2.5: Others
Section 2.6: Implicit / automatic casting
Section 2.7: Introduction (numeric)
Section 2.8: Integer Types
Section 2.9: Fixed Point Types
Section 2.10: Floating Point Types
Section 2.11: Bit Value Type
Chapter 3: SELECT
Section 3.1: SELECT with DISTINCT
Section 3.2: SELECT all columns (*)
Section 3.3: SELECT by column name
Section 3.4: SELECT with LIKE (%)
Section 3.5: SELECT with CASE or IF
Section 3.6: SELECT with Alias (AS)
Section 3.7: SELECT with a LIMIT clause
Section 3.8: SELECT with BETWEEN
Section 3.9: SELECT with WHERE
Section 3.10: SELECT with LIKE(_)
Section 3.11: SELECT with date range
Chapter 4: NULL
Section 4.1: Uses for NULL Testing NULLs
Chapter 5: Limit and Offset
Section 6.1: Limit and Offset relationship
Chapter 6: Creating databases
Section 7.1: Create database, users, and grants
Section 7.2: Creating and Selecting a Database
Section 7.3: MyDatabase
Section 7.4: System Databases

Chapter 7: Using Variables


Section 8.1: Setting Variables
Section 8.2: Row Number and Group By using variables in Select Statement
Chapter 8: Comment MySQL
Section 9.1: Adding comments
Section 9.2: Commenting table definitions
Chapter 9: INSERT
Section 10.1: INSERT, ON DUPLICATE KEY UPDATE
Section 10.2: Inserting multiple rows
Section 10.3: Basic Insert
Section 10.4: INSERT with AUTO_INCREMENT + LAST_INSERT_ID()
Section 10.5: INSERT SELECT (Inserting data from another Table)
Section 10.6: Lost AUTO_INCREMENT ids
Chapter 10: DELETE
Section 11.1: Multi-Table Deletes
Section 11.2: DELETE vs TRUNCATE
Section 11.3: Multi-table DELETE
Section 11.4: Basic delete
Section 11.5: Delete with Where clause
Section 11.6: Delete all rows from a table
Section 11.7: LIMITing deletes
Chapter 11: UPDATE
Section 12.1: Update with Join Pattern
Section 12.2: Basic Update
Section 12.3: Bulk UPDATE
Section 12.4: UPDATE with ORDER BY and LIMIT
Section 12.5: Multiple Table UPDATE
Chapter 12: ORDER BY
Section 13.1: Contexts
Section 13.2: Basic
Section 13.3: ASCending / DESCending
Section 13.4: Some tricks
Chapter 13: Group By
Section 14.1: GROUP BY using HAVING
Section 14.2: Group By using Group Concat
Section 14.3: Group By Using MIN function
Section 14.4: GROUP BY with AGGREGATE functions
Chapter 14: Joins
Section 16.1: Joins visualized
Section 16.2: JOIN with subquery ("Derived" table)
Section 16.3: Full Outer Join
Section 16.4: Retrieve customers with orders -- variations on a theme
Section 16.5: Joining Examples
Chapter 16: UNION

Section18.1: Combining SELECT statements with UNION


Section18.2: Combining data with di?erent columns
Section18.3: ORDER BY
Section18.4: Pagination via OFFSET
Section18.5: Combining and merging data on different MySQL tables
with the same columns into unique rows and running
query
Section 18.6: UNION ALL and UNION
Chapter 17: Arithmetic
Section 19.1: Arithmetic Operators
Section 19.2: Mathematical Constants
Section 19.3: Trigonometry (SIN, COS)
Section 19.4: Rounding (ROUND, FLOOR, CEIL)
Section 19.5: Raise a number to a power (POW)
Section 19.6: Square Root (SQRT)
Section 19.7: Random Numbers (RAND)
Section 19.8: Absolute Value and Sign (ABS, SIGN)
Chapter 18: String operations
Section 20.1: LENGTH()
Section 20.2: CHAR_LENGTH()
Section 20.3: HEX(str)
Section 20.4: SUBSTRING()
Section 20.5: UPPER() / UCASE()
Section 20.6: STR_TO_DATE - Convert string to date
Section 20.7: LOWER() / LCASE()
Section 20.8: REPLACE()
Section 20.9: Find element in comma separated list
Chapter 19: Date and Time Operations
Section 21.1: Date arithmetic
Section 21.2: SYSDATE(), NOW(), CURDATE()
Section 21.3: Testing against a date range
Section 21.4: Extract Date from Given Date or DateTime Expression
Section 21.5: Using an index for a date and time lookup
Section 21.6: Now()
Chapter 20: Handling Time Zones
Section 22.1: Retrieve the current date and time in a particular time zone
Section 22.2: Convert a stored `DATE` or `DATETIME` value to another time zone
Section 22.3: Retrieve stored `TIMESTAMP` values in a particular time zone
Section 22.4: What is my server's local time zone setting?
Section 22.5: What time_zone values are available in my server?
Chapter 21: Regular Expressions
Section 23.1: REGEXP / RLIKE
Chapter 22: VIEW
Section 24.1: Create a View
Section 24.2: A view from two tables
Section 24.3: DROPPING A VIEW
Section 24.4: Updating a table via a VIEW
Chapter 23: Table Creation
Section 25.1: Table creation with Primary Key
Section 25.2: Basic table creation
Section 25.3: Table creation with Foreign Key
Section 25.6: Table Create With TimeStamp Column To Show Last Update
Section 25.7: CREATE TABLE FROM SELECT
Chapter 24: ALTER TABLE
Section 26.1: Changing storage engine; rebuild table; change file_per_table
Section 26.2: ALTER COLUMN OF TABLE
Section 26.3: Change auto-increment value
Section 26.4: Renaming a MySQL table
Section 26.5: ALTER table add INDEX
Section 26.6: Changing the type of a primary key column
Section 26.7: Change column definition
Section 26.8: Renaming a MySQL database
Section 26.9: Swapping the names of two MySQL databases
Section 26.10: Renaming a column in a MySQL table
Chapter 25: Drop Table
Section 27.1: Drop Table
Section 27.2: Drop tables from database
Chapter 26: MySQL LOCK TABLE
Section 28.1: Row Level Locking
Section 28.2: Mysql Locks
Chapter 27: Stored routines (procedures and functions)
Section 30.1: Stored procedure with IN, OUT, INOUT parameters
Section 30.2: Create a Function
Section 30.3: Cursors
Section 30.4: Multiple ResultSets
Section 30.5: Create a function
Chapter 28: Indexes and Keys
Section 31.1: Create index
Section 31.2: Create unique index
Section 31.3: AUTO_INCREMENT key
Section 31.4: Create composite index
Section 31.5: Drop index
Chapter 29: Full-Text search
Section 32.1: Simple FULLTEXT search
Section 32.2: Simple BOOLEAN search
Section 32.3: Multi-column FULLTEXT search
Chapter 30: PREPARE Statements
Section 33.1: PREPARE, EXECUTE and DEALLOCATE PREPARE Statements
Section 33.2: Alter table with add column
Chapter 31: MySQL Admin

Section 34.1: Atomic RENAME & Table Reload


Section 34.2: Change root password
Section 34.3: Drop database
Chapter 32: TRIGGERS
Section 35.1: Basic Trigger
Section 35.2: Types of triggers
Chapter 33: Events
Section 36.1: Create an Event
Chapter 34: ENUM
Section 37.1: Why ENUM?
Section 37.2: VARCHAR as an alternative
Section 37.3: Adding a new option
Section 37.4: NULL vs NOT NULL
Chapter 35: Clustering
Section 38.1: Disambiguation

Chapter 36: Partitioning


Section 39.1: RANGE Partitioning
Section 39.2: LIST Partitioning
Section 39.3: HASH Partitioning
Chapter 1: Getting started with MySQL
What is a Database?
A database is a separate application that stores a collection of data. Each database
has one or more distinct APIs for creating, accessing, managing, searching and
replicating the data it holds.
Other kinds of data stores can also be used, such as files on the file system or large
hash tables in memory but data fetching and writing would not be so fast and easy
with those type of systems.
Nowadays, we use relational database management systems (RDBMS) to store and
manage huge volume of data. This is called relational database because all the data
is stored into different tables and relations are established using primary keys or
other keys known as Foreign Keys.

MySQL Database
MySQL is a fast, easy-to-use RDBMS being used for many small and big businesses.
MySQL is developed, marketed and supported by MySQL AB, which is a Swedish
company. MySQL is becoming so popular because of many good reasons −
 MySQL is released under an open-source license. So you have nothing to pay to
use it.
 MySQL is a very powerful program in its own right. It handles a large subset of
the functionality of the most expensive and powerful database packages.
 MySQL uses a standard form of the well-known SQL data language.
 MySQL works on many operating systems and with many languages including
PHP, PERL, C, C++, JAVA, etc.
 MySQL works very quickly and works well even with large data sets.
 MySQL is very friendly to PHP, the most appreciated language for web
development.
 MySQL supports large databases, up to 50 million rows or more in a table. The
default file size limit for a table is 4GB, but you can increase this (if your
operating system can handle it) to a theoretical limit of 8 million terabytes (TB).
 MySQL is customizable. The open-source GPL license allows programmers to
modify the MySQL software to fit their own specific environments.

Creating a database in MySQL


CREATE DATABASE mydb;

Show list of existing databases


show database;

select the database mydb


USE mydb;

Creating a table in MySQL


CREATE TABLE mytable
(
id int NOT NULL auto_increment,
username varchar(100) NOT NULL,
email varchar(100) NOT NULL,
PRIMARY KEY (id)
);

CREATE TABLE will create a new table called mytable.

Create tables from another database.


create table isandb.items select * from stores.items;

Practice Tables
create table suppliers(supplier_id int,supplier_name varchar(40),
contact_name varchar(40), city varchar(40));

create table customers(customer_id int, customer_name varchar(40),


address varchar(40),city varchar(40));

create table products(product_id int, product_name varchar(40),


supplier_id int);

create table items(item_id int, item_name varchar(40), supplier_id int,qty


int, price int);

create table orders(order_id int, supplier_id int,order_date varchar(40),


customer_id int, item_id int);
Inserting a row into a table
INSERT INTO mytable ( username, email ) VALUES("myuser",
"myuser@example.com" );

insert into test_tbl select * from stores.items where supplier_id = 105;

Updating a row into a table


UPDATE mytable SET username="myuser" WHERE id=8

Deleting a row into a MySQL table


DELETE FROM mytable WHERE id=8

Selecting rows based on conditions in MySQL


SELECT * FROM mytable WHERE username = "myuser";

Show list of existing databases


SHOW databases;

Output:

We can think of "information_schema" as a "master database" that provides access to


database metadata.
Show tables in an existing database
SHOW tables;

Show all the fields of a table


DESCRIBE databaseName.tableName;

or, if already using a database:

DESCRIBE tableName;
Desc table name;
Chapter 2: Data Types
A data type is a set of representable values. Each value belongs to one data type.
Items that can be referenced by a name, such as SQL parameters, columns, fields,
attributes, and variables, also have declared types.

MySQL supports these groups of data types:


 Numeric

 Date & time


 String
Choosing the right data types for columns is a part of the initial design of the
database. Data types make sure the accuracy of the data provided. They make sure
that the data is used in a meaningful way. This is important when we do comparisons,
ordering of data. For example dates are compared differently than numbers. Other
developers using our tables will know what data to expect from the database schema.
Data types enable MySQL to do validation on the data inserted. Finally, with correct
data types for table columns, we allow MySQL to optimize the queries and use less
disk space.

Numbers
Numeric types can be either integers or floating point numbers.
1. Integers
1. TINYINT
2. SMALLINT
3. MEDIUMINT
4. INTEGER
5. BIGINT
2. Floating points
1. FLOAT
2. DOUBLE
3. DECIMAL

Integers
Integers are a subset of the real numbers. They are written without a fraction or a
decimal component. Integers fall within a set Z = {..., -2, -1, 0, 1, 2, ...} Integers are
infinite. Computers can practically work only with a subset of integer values, because
computers have finite capacity. Integers are used to count discrete entities. We can
have 3, 4, 6 cars, but we cannot have 3.33 cars. We can have 3.33 kilograms.

The following is a table of integer types

Table 1: Signed integer types

Byte
Data type Minimum value Maximum value
s

TINYINT 1 -128 127


SMALLINT 2 -32768 32767
MEDIUMINT 3 -8388608 8388607
INTEGER 4 -2147483648 2147483647
- 922337203685477580
BIGINT 8
9223372036854775808 7

The integer types differ in their storage. We can choose values that fit our
requirements.

CREATE TABLE Ages(Id SMALLINT, Age TINYINT);

We have created a temporary Ages table. This will be only a temporary testing table,
so there will be only a few rows. The SMALLINT will suffice. We do not know anyone
older than 130 years, so TINYINT will be OK for the Age column.

mysql> INSERT INTO Ages VALUES(1, 43);

Output:

We insert a row into the table.

mysql> INSERT INTO Ages VALUES (2, 128);


ERROR 1264 (22003): Out of range value for column 'Age' at row 1

Trying to insert a value outside the range of the column type leads to an error.

When we are dealing with ages, we do not need negative integer values. MySQL
supports unsigned integers.

Table 2: Unsigned integer types

Byte Minimum
Data type Maximum value
s value

TINYINT 1 0 255
SMALLINT 2 0 65535
MEDIUMINT 3 0 16777215
INTEGER 4 0 4294967295
1844674407370955161
BIGINT 8 0
5

We use the SQL statement to change the Age column to have a TINYINT
UNSIGNED data type.

mysql> ALTER TABLE Ages MODIFY Age TINYINT UNSIGNED;

Now we can insert values from 0 to 255.

mysql> INSERT INTO Ages VALUES(2, 128);

output
mysql> SELECT * FROM Ages;
output:

We have inserted a hypothetical age 128. Now the column accepts it.

Floating point values

Floating point numbers represent real numbers in computing. Real numbers measure
continuous quantities, like weight, height or speed.

MySQL has floating point types for approximate values: FLOAT and DOUBLE and fixed-
point types for exact values: DECIMAL and NUMERIC.

FLOAT is a single precision floating point number. MySQL uses four bytes to store
a FLOAT value.

DOUBLE is a double precision floating point number. MySQL uses eight bytes to store
a DOUBLE value.

DECIMAL and NUMERIC types store exact numeric data values. These types are used
when it is important to preserve exact precision, for example with financial data. In
MySQL, NUMERIC is a synonym for DECIMAL.

Floats, doubles, and decimals may have specified their precision and scale.

In DECIMAL[M, D]

The M is the maximum number of digits, the precision.

The D is the number of digits to the right of the decimal point.

A column with DECIMAL(3, 1), we can insert numbers with maximum of three digits:
before and one after the decimal point.

mysql> CREATE TABLE Numbers (Id TINYINT, Floats FLOAT, Decimals DECIMAL(3, 2));

We create a table in which we are going to store a few floats and decimals.

mysql> INSERT INTO Numbers VALUES (1, 1.1, 1.1), (2, 1.1, 1.1), (3, 1.1, 1.1);

We insert three rows into the newly created table.

mysql> SELECT * FROM Numbers;

output:

This is how the table looks.

mysql> SELECT SUM(Floats), SUM(Decimals) FROM Numbers;

output:

The two results differ. The decimal calculation is more precise. Due to some internal
rounding, the sum of floats is not accurate.
Date & time values

MySQL has data types for storing dates and times: DATE, TIME, DATETIME, YEAR,
and TIMESTAMP. MySQL tries to interpret date and time values in several formats but
the date parts must always be given in year/month/day order. MySQL automatically
converts a date or time value to a number if the value is used in a numeric context
and vice versa.

Date

The DATE is used to store dates. MySQL retrieves and displays date values in YYYY-
MM-DD format. The supported range is from 1000-01-01 to 9999-12-31.

mysql> SELECT CURDATE();


output:

mysql> SELECT DATE('2019-01-31 12:01:00');


output

The DATE() function returns the date part of the date and time value.

mysql> SELECT ADDDATE('2017-01-20', 8);


ouput

The ADDDATE() function adds days to a date. It returns the calculated date.

mysql> CREATE TABLE Dates(Id TINYINT, Dates DATE);


mysql> INSERT INTO Dates VALUES(1, '2017-01-24');
mysql> INSERT INTO Dates VALUES(2, '2017/01/25');
mysql> INSERT INTO Dates VALUES(3, '20170126');
mysql> INSERT INTO Dates VALUES(4, '170127');
mysql> INSERT INTO Dates VALUES(5, '2017+01+28');

Dates are displayed in MySQL in one format, but we can use various date formats in
our SQL statements. The YYYY-MM-DD is the standard format. It is possible to use any
punctuation character between the date parts.

mysql> SELECT * FROM Dates;


output:

We have used multiple formats to insert dates into the table. MySQL uses one format
to display the dates.

mysql> INSERT INTO Dates VALUES (6, '10000-01-01');


ERROR 1292 (22007): Incorrect date value: '10000-01-01' for column 'Dates' at row 1

In case we go beyond the range of supported date values an error occurs.

Time
The TIME data type is used to display time in MySQL. It shows values
in HH:MM:SS format.

MySQL retrieves and displays TIME values in 'HH:MM:SS' format or 'HHH:MM:SS'


format for large hours values. The range is from -838:59:59 to 838:59:59. The hours
part of the time format may be greater than 24.

It is because TIME data type can be used to denote time intervals. This is also why we
can have negative time values.
mysql> SELECT CURTIME();
Output

The CURTIME() function returns the current time.

mysql> SELECT TIMEDIFF('23:34:32', '22:00:00');


Output:

The TIMEDIFF() function is used to subtract two time values in timestamp format.

mysql> SELECT TIMEDIFF('211344', 201123);

We can use the TIME() function to extract the time part of the date and time value.

mysql> SELECT TIME('2017-01-31 11:06:43');

We can write time values in different formats too. The first parameter is a time value
in a string format without delimiters. The second is a time value specified as a
number.

Datetime

The DATETIME values contain both date and time. MySQL retrieves and displays
values in YYYY-MM-DD HH:MM:SS format. The supported range is from 1000-01-01
00:00:00 to 9999-12-31 23:59:59.

mysql> SELECT NOW();

The NOW() function returns current datetime.

mysql> SELECT DAYNAME('2017@01@31 11@12@12');

‘2017@01@31 Date
11@12@12' Time

MySQL displays date and time in only one format. But in our SQL statements, we can
use different formats. Any punctuation character may be used as the delimiter
between date parts or time parts. In our case, we have used the @ character.

Year

The YEAR is a data type used for representing years. MySQL displays YEAR values
in YYYY format. It allows us to assign values to YEAR columns using either strings or
numbers. The allowable range is from 1901 to 2155, or 0000. Illegal year values are
converted to 0000.

mysql> SELECT YEAR(CURDATE()) AS 'Current year';

In the above SQL statement, we have retrieved the current year.

Timestamp

A timestamp is a sequence of characters, denoting the date and/or time at which a


certain event occurred. Timestamps are typically used for logging events. In MySQL
we have a TIMESTAMP data type for creating timestamps. A TIMESTAMP column is
useful for recording the date and time of an INSERT or UPDATE operation. It
automatically sets to the date and time of the most recent operation if you do not give
it a value yourself. The TIMESTAMP data type has a range of 1970-01-01 00:00:01 UTC
to 2038-01-19 03:14:07 UTC.

The following table summarizes the supported TIMESTAMP formats.

Data type Format

TIMESTAMP(14) YYYYMMDDHHMMSS
TIMESTAMP(12) YYMMDDHHMMSS
TIMESTAMP(10) YYMMDDHHMM
TIMESTAMP(8) YYYYMMDD
TIMESTAMP(6) YYMMDD
TIMESTAMP(4) YYMM
TIMESTAMP(2) YY

The TIMESTAMP data type offers automatic initialisation and updating. We can restrict
this data type to have only automatic initialisation or automatic update only.

The TIMESTAMP value has a range from ‘1970-01-01-00:00:01’ UTC to ‘2038-01-19-


03:14:07’ UTC.

When we insert a TIMESTAMP value into a table, MySQL converts it from your
connection’s time zone to UTC for storing.

mysql> CREATE TABLE Prices(Id TINYINT PRIMARY KEY, Price DECIMAL(8, 2), Stamp
TIMESTAMP);
mysql> INSERT INTO Prices VALUES(1, 234.34,'2019-10-01- 00:00:01');
mysql> INSERT INTO Prices VALUES(2, 144.34,'2019-01-01- 00:00:01');

We create a table with a TIMESTAMP column. We insert two rows into the table. The
Stamp column is not included in the SQL statements. MySQL automatically fills the
column.

mysql> SELECT * FROM Prices;


The timestamps for the two rows were created. This is the auto-initialisation of
the TIMESTAMP data type. This can be turned off by Stamp TIMESTAMP DEFAULT 0 ON
UPDATE CURRENT_TIMESTAMPSQL code when creating the table.

mysql> UPDATE Prices SET Price=250.50 WHERE Id=1;

We execute the SQL statement to update the Price column in the first row.

mysql> SELECT * FROM Prices;

The timestamp of the first column was updated. If we wanted to turn off the auto-
update of the TIMESTAMP, we could use the Stamp TIMESTAMP DEFAULT
CURRENT_TIMESTAMP SQL code when creating the table.

Strings

MySQL has the following string data types:

 CHAR
 VARCHAR
 BINARY
 VARBINARY
 BLOB
 TEXT
 ENUM
 SET

Char

A CHAR is a fixed length character data type. It is declared with a length, CHAR(x),
where x can be between 0 to 255. CHAR always uses the same amount of storage
space per entry.

mysql> CREATE TABLE Chars(Id TINYINT PRIMARY KEY, Chars CHAR(3));


mysql> INSERT INTO Chars VALUES (1, 'a'), (2, 'ab'), (3, 'abc'), (4, 'abb');

In the above SQL code, we have created a Chars table which has one column of
the CHAR data type. The maximum length is set to three characters.

mysql> INSERT INTO Chars VALUES (5, 'abcd');


ERROR 1406 (22001): Data too long for column 'Chars' at row 1

Trying to insert a larger string than specified leads to an error.

mysql> SELECT * FROM Chars;

This is what we have in the table.

mysql> SELECT Id, LENGTH(Chars) AS Length FROM Chars;


We have retrieved Ids and the length of the characters that we have inserted.
Previously we have stated that chars are stored at fixed size. Why do we have
different size values for the rows now? We would expect each row to have exactly 3
characters. The reason is that MySQL trims spaces for chars at the data retrieval.

By setting the sql_mode to PAD_CHAR_TO_FULL_LENGTH the spaces are also trimmed.

mysql> SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';

mysql> SELECT Id, LENGTH(Chars) AS Length FROM Chars;

By changing the sql_mode, we get the expected results.

varchar

VARCHAR data types stores variable-length strings. The length of the string can be
from 0 to 65535. VARCHAR values are not padded when they are stored. Trailing
spaces are retained when values are stored and retrieved. Most shorter string data
types are stored in this data type; for example emails, names of people, of
merchandise, or addresses.

mysql> CREATE TABLE FirstNames(Id TINYINT, Firstname VARCHAR(20));


mysql> INSERT INTO FirstNames VALUES (1, 'Tom'), (2, 'Lucy'), (3, 'Alice'),
-> (4, 'Robert'), (5, 'Timothy'), (6, 'Alexander');

We create a FirstNames table in which we store six first names.

mysql> SELECT Id, LENGTH(FirstName) AS Length FROM FirstNames;

We can see that names in a VARCHAR column type are stored in variable length. This
saves disk space.

Binary and varbinary

BINARY and VARBINARY are binary byte data types. They contain byte strings rather
than character strings. They have no character sets. Sorting and comparison are
based on the numeric values of the bytes in the values. The range of the BINARY data
types is from 0 to 255. It stores values in fixed length. The range of the VARBINARY is
from 0 to 65535.

Blob

A BLOB is a binary large object data type. It can hold a variable amount of binary
data. It can be used to store binary data like images or documents. BLOB has four
types:

Range in
Blob type
bytes

TINYBLOB 0 – 255
BLOB 0 - 65535
MEDIUMBLOB 0 - 16777215
LONGBLOB 0 - 4294967295

Next, we are going to read and write an image.

mysql> CREATE TABLE Images(Id INT PRIMARY KEY, Img LONGBLOB);

A table with a LONGBLOB column is created.

mysql> SHOW VARIABLES LIKE "secure_file_priv";

MySQL has security restrictions on loading and dumping data.


The secure_file_priv shows a directory path where such operations are allowed.

mysql> INSERT INTO Images VALUES (1, LOAD_FILE('e:\python_batch7\images.jpg'));

With the help of the LOAD_FILE() function, we insert an image into the Images table.

mysql> SELECT Img FROM Images WHERE Id=1 INTO DUMPFILE 'C:\ProgramData\
MySQL\MySQL Server 8.0\Uploads/image_bck.jpg';

Text

A TEXT datatype is used for storing large textual data. For example articles, blogs, or
pages. TEXT values are best used when VARCHAR and other string-based data objects
are insufficient to handle storing the desired amount of information.

Range in
Blog type
bytes

TINYTEXT 0 - 255
TEXT 0 - 65535
MEDIUMTEXT 0 - 16777215
LONGTEXT 0 - 4294967295

There is no padding on insert and no bytes are stripped on select.

Enum

The ENUM is a string object with a value chosen from a permitted list of values. They
are enumerated explicitly in the column specification. We can insert only one value
from the list.

mysql> CREATE TABLE Sizes(Size ENUM('S', 'M', 'L', 'XL', 'XXL'));


We create a table, which has one column of the ENUM type. The list of permitted
values is explicitly stated.
mysql> INSERT INTO Sizes VALUES ('S'), ('L');
We insert two rows in the table.

mysql> INSERT INTO Sizes VALUES ('Large');


ERROR 1265 (01000): Data truncated for column 'Size' at row 1

Since 'Large' was not mentioned in the list, we get an error message.
mysql> SELECT * FROM Sizes;
We have two regular values in the table.

Example:

mysql> create table Rollno(s_no ENUM('101','201','301','401'),stu_name varchar(40));

mysql> insert into Rollno values('101','rama'),('201','krishna');

mysql> select * from Rollno;

Set
A SET is a string object that can have zero or more values, each of which must be
chosen from a list of permitted values. It is similar to the ENUM data type. The
difference is that it can contain zero or more values from the list of permitted values.
mysql> CREATE TABLE Letters(Let SET('a', 'b', 'c', 'd', 'e'));

We create a table that allows a set of letters on a column.

mysql> INSERT INTO Letters VALUES ('a');


mysql> INSERT INTO Letters VALUES ('b');
mysql> INSERT INTO Letters VALUES ('b,a');
mysql> INSERT INTO Letters VALUES ('');
mysql> INSERT INTO Letters VALUES ('a,b,c');

mysql> SELECT * FROM Letters;

Example:

mysql> CREATE TABLE Letters(Let SET('a', 'b', 'c', 'd', 'e'),stu_no int);

mysql> INSERT INTO Letter VALUES ('a,b,c',101);

mysql> select * from Letter;


Let stu_no
a,b,c 101
a,b,c 101
a,b 202
a,b,c 303

We have added various combinations of letters allowed by SET.


Chapter 3: SELECT
SELECT is used to retrieve rows selected from one or more tables.
Section 3.1: SELECT with DISTINCT
The DISTINCT clause after SELECT eliminates duplicate rows from the result set.
create table car(car_id int unsigned not null primary key,name
varchar(20),price decimal(8,2));

INSERT INTO CAR (`car_id`, `name`, `price`) VALUES (1, 'Audi A1', '20000');
INSERT INTO CAR (`car_id`, `name`, `price`) VALUES (2, 'Audi A1', '15000');
INSERT INTO CAR (`car_id`, `name`, `price`) VALUES (3, 'Audi A2', '40000');
INSERT INTO CAR (`car_id`, `name`, `price`) VALUES (4, 'Audi A2', '40000');
SELECT DISTINCT `name`, `price` FROM CAR;

DISTINCT works across all columns to deliver the results, not individual columns. The
latter is often a misconception of new SQL developers. In short, it is the distinctness at
the row-level of the result set that matters, not distinctness at the column-level. To
visualize this, look at "Audi A1" in the above result set.

Section 3.2: SELECT all columns (*)


Query
SELECT * FROM stack;
Result

SELECT stack.* FROM stack JOIN Overflow ON stack.id = Overflow.id;

Section 3.3: SELECT by column name


CREATE TABLE stack( id INT, username VARCHAR(30) NOT NULL, password
VARCHAR(30) NOT NULL );

INSERT INTO stack (`id`, `username`, `password`) VALUES (1, 'Foo', 'hiddenGem');
INSERT INTO stack (`id`, `username`, `password`) VALUES (2, 'Baa', 'verySecret');
Query
SELECT id FROM stack;
Result

SELECT with LIKE (%)


CREATE TABLE stack( id int AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(100) NOT NULL);
INSERT stack(username) VALUES ('admin'),('k admin'),('adm'),('a adm b'),('b XadmY
c'), ('adm now'), ('not here');
"adm" anywhere:
SELECT * FROM stack WHERE username LIKE "%adm%";

Output:

SELECT * FROM stack WHERE username LIKE "adm%";


Output:

Ends with "adm":

SELECT * FROM stack WHERE username LIKE "%adm";


Output:
Just as the % character in a LIKE clause matches any number of characters,
the _ character matches just one character. For example,
SELECT * FROM stack WHERE username LIKE "adm_n";
Output:

Performance Notes If there is an index on username, then


 LIKE 'adm' performs the same as `= 'adm'
 LIKE 'adm% is a "range", similar to BETWEEN..AND.. It can make good use of
an index on the column.
 LIKE '%adm' (or any variant with a leading wildcard) cannot use any index.
Therefore it will be slow. On tables with many rows, it is likely to be so slow it is
useless.
 RLIKE (REGEXP) tends to be slower than LIKE, but has more capabilities.
 While MySQL offers FULLTEXT indexing on many types of table and column,
those FULLTEXT indexes are not used to fulfill queries using LIKE.

Section 3.5: SELECT with CASE or IF

mysql> create table student(name varchar(40),percentage int);


Query OK, 0 rows affected (0.74 sec)

mysql> insert into student values('Sou',99),('Sat',98),('Ram',35),('Sam',30);


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

mysql> select * from student;

SELECT st.name, st.percentage, CASE WHEN st.percentage >= 35 THEN 'Pass'


ELSE 'Fail' END AS `Remark` FROM student AS st ;
Output:

Or with IF
SELECT st.name, st.percentage, IF(st.percentage >= 35, 'Pass', 'Fail') AS `Remark`
FROM student AS st ;

N.B
IF(st.percentage >= 35, 'Pass', 'Fail')
This means : IF st.percentage >= 35 is TRUE then return 'Pass' ELSE return 'Fail'

Section 3.6: SELECT with Alias (AS)


SQL aliases are used to temporarily rename a table or a column.
mysql> select supplier_name as sup_name from suppliers;

Section 3.7: SELECT with a LIMIT clause


Query:
SELECT * FROM Customers ORDER BY customer_id LIMIT 3;

mysql> SELECT * from items limit 5,4;

mysql> select * from items order by item_id desc limit 3;

When a LIMIT clause contains two numbers, it is interpreted as LIMIT offset, count.
So, in this example the query skips two records and returns one.
Output:

Note:
The values in LIMIT clauses must be constants; they may not be column values.

Section 3.8: SELECT with BETWEEN


You can use BETWEEN clause to replace a combination of "greater than equal AND
less than equal" conditions.
Query with operators
select * from items where price >=400 and price <=1000;
Similar query with BETWEEN
mysql> select *from items where item_id between 306 and 312;

Note
BETWEEN uses >= and <=, not > and <.

Using NOT BETWEEN


If you want to use the negative you can use NOT. For example :
mysql> select *from items where item_id not between 306 and 312;
Output:

Section 3.9: SELECT with WHERE


mysql> select * from suppliers where supplier_id = 102 and city='Vijayawada';
Result

Query with a nested SELECT in the WHERE clause


The WHERE clause can contain any valid SELECT statement to write more complex
queries. This is a 'nested' query

Query
mysql> select supplier_id,supplier_name from suppliers where supplier_id in(select
supplier_id from items where item_name = 'Keyboard' and price >=400);
Chapter 4: NULL
We have seen the SQL SELECT command along with the WHERE clause to fetch
data from a MySQL table, but when we try to give a condition, which compares the
field or the column value to NULL, it does not work properly.
To handle such a situation, MySQL provides three operators −
 IS NULL − This operator returns true, if the column value is NULL.
 IS NOT NULL − This operator returns true, if the column value is not NULL.
 <=> − This operator compares values, which (unlike the = operator) is true
even for two NULL values.
The conditions involving NULL are special. You cannot use = NULL or != NULL to
look for NULL values in columns. Such comparisons always fail because it is
impossible to tell whether they are true or not. Sometimes, even NULL = NULL fails.
To look for columns that are or are not NULL, use IS NULL or IS NOT NULL.

Using NULL values at the Command Prompt


create table stu_tbl (stu_name varchar(40) NOT NULL, stu_no INT);

INSERT INTO stu_tbl(stu_name,stu_no) values ('mahran', 20);

INSERT INTO stu_tbl(stu_name,stu_no) values ('mahnaz', NULL);

INSERT INTO stu_tbl(stu_name,stu_no) values ('Jen', NULL);

INSERT INTO stu_tbl(stu_name,stu_no) values ('Gill', 20);

SELECT * from stu_tbl;

To find the records where the stu_no column is or is not NULL, the queries should be
written as shown in the following program.

SELECT * FROM tcount_tbl WHERE tutorial_count IS NULL;

SELECT * from stu_tbl WHERE stu_no IS NOT NULL;


Chapter 6: Limit and Offset
What is the LIMIT keyword?

The limit keyword is used to limit the number of rows returned in a query result.

It can be used in conjunction with the SELECT, UPDATE OR DELETE commands LIMIT
keyword syntax

The syntax for the LIMIT keyword is as follows

SELECT {fieldname(s) | *} FROM tableName(s) [WHERE condition] LIMIT N;

HERE

 "SELECT {fieldname(s) | *} FROM tableName(s)" is the SELECT statement


containing the fields that we would like to return in our query.
 "[WHERE condition]" is optional but when supplied, can be used to specify a
filter on the result set.
 "LIMIT N" is the keyword and N is any number starting from 0, putting 0 as the
limit does not return any records in the query. Putting a number say 5 will
return five records. If the records in the specified table are less than N, then all
the records from the queried table are returned in the result set.
Example:
SELECT * FROM stu_tbl LIMIT 2;

Using the OFF SET in the LIMIT query


The OFF SET value is also most often used together with the LIMIT keyword. The OFF
SET value allows us to specify which row to start from retrieving data

Let's suppose that we want to get a limited number of members starting from the
middle of the rows, we can use the LIMIT keyword together with the offset value to
achieve that.

SELECT * FROM stu_tbl LIMIT 1, 3;

LIMIT clause with one argument


When one argument is used, the result set will only be constrained to the number
specified in the following
manner:

SELECT * FROM stu_tbl ORDER BY stu_no ASC LIMIT 2;

Also notice that the ORDER BY clause may be important in order to specify the first
rows of the result set that will be presented (when ordering by another column).

LIMIT clause with two arguments


When two arguments are used in a LIMIT clause:

The first argument represents the row from which the result set rows will be
presented – this number is often mentioned as an offset, since it represents the row
previous to the initial row of the constrained result
set. This allows the argument to receive 0 as value and thus taking into consideration
the first row of the nonconstrained
result set.

the second argument specifies the maximum number of rows to be returned in the
result set (similarly to the one argument's example).
Example:
SELECT * FROM stu_tbl ORDER BY stu_no ASC LIMIT 2, 3

select * from items order by item_name asc limit 2,3;

Notice that when the offset argument is 0, the result set will be equivalent to a one
argument LIMIT clause. This means that the following 2 queries:

SELECT * FROM Customers ORDER BY Customer_id LIMIT 2,3;

SELECT * FROM stu_tbl ORDER BY stu_no ASC LIMIT 2

OFFSET keyword: alternative syntax


An alternative syntax for the LIMIT clause with two arguments consists in the usage
of the OFFSET keyword after the first argument in the following manner:

SELECT * FROM stu_tbl ORDER BY stu_no ASC LIMIT 2 OFFSET 3

Notice that in this alternative syntax the arguments have their positions switched:
the first argument represents the number of rows to be returned in the result set;
the second argument represents the offset.
Chapter 7: Creating databases
CREATE DATABASE Creates a database with the given name CREATE SCHEMA This is
a synonym for CREATE DATABASE IF NOT EXISTS Used to avoid execution error, if
specified database already exists create_specification options specify database
characteristics such as CHARACTER SET and COLLATE(database collation)

Section 7.1: Create database, users, and grants


Create Database

CREATE DATABASE is the SQL command for creating a database.


Imagine you need to create a database with name "movies". You can do it by
executing following SQL command.

Example:
CREATE DATABASE movies;

Note: you can also use the command CREATE SCHEMA instead of CREATE DATABASE

Now let's improve our SQL query adding more parameters and specifications.
IF NOT EXISTS
A single MySQL server could have multiple databases. If you are not the only one
accessing the same MySQL server or if you have to deal with multiple databases there
is a probability of attempting to create a new database with name of an existing
database.

When IF NOT EXISTS is used, database is created only if given name does not clash
with an existing database's name. Without the use of IF NOT EXISTS MySQL throws
an error.

CREATE DATABASE IF NOT EXISTS movies;

Collation and Character Set

Collation is set of rules used in comparison. Many people use MySQL to store data
other than English. Data is stored in MySQL using a specific character set. The
character set can be defined at different levels in server , database , table and
columns.

You need to select the rules of collation which in turn depend on the character set
chosen.
For instance, the Latine1 character set uses the latin1_swedish_ci collation which is
the Swedish case insensitive order.

CREATE DATABASE IF NOT EXISTS movies CHARACTER SET latin1 COLLATE


latin1_swedish_ci

The best practice while using local languages like Arabic , Chinese etc is to select
Unicode (utf-8) character set which has several collations or just stick to default
collation utf8-general-ci.
You can find the list of all collations and character sets
SHOW CHARACTER SET;

You can see list of existing databases by running following SQL command.
SHOW DATABASES

Create a new user


How to Create MySQL User and Grant Permission.
For the good security implementation, make sure to create separate user account
rather than root to access database for each application. This will ensure that
application can’t access other application’s database. You need MySQL administrator
(root) privileges To create user accounts and assign privileges to the database. For
your information MySQL root account is different than system root account, there are
no relations between them.

1. Create New User in MySQL

Login to the MySQL server with root user with shell access and create a new user
named “rahul”. Below command will allow accessing MySQL server to user rahul from
localhost system only.

mysql> CREATE USER 'rahul'@'localhost' IDENTIFIED BY 'password';

Now assign the privileges to the specific database. Below command will allow all
privileges on database “mydb” to user rahul.

mysql> GRANT ALL ON mydb.* TO 'rahul'@'localhost';

After creating user and assigning proper privileges, make sure to reload privileges.

mysql> FLUSH PRIVILEGES;

C:\Users\sathish>mysql -u sow1 -p
Enter password: ********

 How to Reset MySQL root User Password

MySQL is an open source database software widely used for data storage. Sometimes
we forgot MySQL root password. So don’t be panic, This tutorial will help you to reset
MySQL root password with simple steps.

Step 1 – Start MySQL in Safemode

First of all, you are required to stop running MySQL server. Use one of the following
commands to stop MySQL server on your Linux system.

# service mysql stop

# systemctl stop mysql.service


Now start MySQL server in safe mode using withe the --skip-grant-tables option. Use
the following command to start MySQL in safe mode. In safe mode, MySQL does not
prompt for login password.
# mysqld_safe --skip-grant-tables &

Step 2 – Reset MySQL root Password


Now login to MySQL server as root user and change password using the following set
of commands. This will reset MySQL root password on your system.
For MySQL 5.6 or Below
# mysql -u root

mysql> USE mysql;


mysql> UPDATE user SET password=PASSWORD("NEW-PASSWORD") WHERE
User='root';
mysql> FLUSH PRIVILEGES;
mysql> quit
For MySQL 5.7 or Above
# mysql -u root

mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD("NEW-PASSWORD");

mysql> FLUSH PRIVILEGES;

mysql> quit

Step 3 – Restart MySQL Server


After changing password stop the MySQL (running in safe mode) service and start it
again with the commands below.
# service mysql stop
# service mysql start

# systemctl stop mysql.service


# systemctl start mysql.service
Step 4 – Verify New Password
After resetting MySQL root account password and restarting, just verify new password
by login.

# mysql -u root -p

Enter password: **********


Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 29
Server version: 5.5.57 MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its


affiliates. Other names may be trademarks of their respective
owners.

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

mysql>

2. Create MySQL User Remote Accessible


To allow any user to connect MySQL server from the remote system. You need to
specify hostname or IP address of the remote system. You can also use % to allow any
host

mysql> CREATE USER 'rahul'@'123.45.67.89' IDENTIFIED BY 'password';

mysql> CREATE USER 'rahul'@'%' IDENTIFIED BY 'password';

mysql> FLUSH PRIVILEGES;


3. Grant Specific User Permissions in MySQL
Please find below list of frequently used privileges in MySQL user. Visit here to get full
list of privileges for MySQL user.
 ALL [PRIVILEGES] – Grant all privileges to user.
 CREATE – Grant user to create new databases and tables.
 DROP – Grant user to delete (drop) databases and tables.
 DELETE – Grant user to delete rows from tables.
 ALTER – Grant user to modify table structure.
 INSERT – Grant user to insert (add) rows into tables.
 SELECT – Grant user to run select command to read data from tables.
 UPDATE – Grant user to update data in tables.
 EXECUTE – Grant user to execute stored routines.
 FILE – Grant user to access file on server host.
 GRANT OPTION – Grant user to grant or remove other users’ privileges.
Here, you can specify privileges separated by a comma in place of ALL. For example
to allow CREATE, DELETE, INSERT, UPDATE access to ‘rahul’@’localhost’ on database
mydb.

mysql> GRANT CREATE,DELETE,INSERT,UPDATE ON mydb.* TO 'rahul'@'localhost';

mysql> FLUSH PRIVILEGES;


4. Revoke User Permissions in MySQL
Use REVOKE command to remove any specific privilege from the user. For example to
remove DELETE privilege from user ‘rahul’@’localhost’ on mydb database.

mysql> REVOKE DELETE ON mydb.* TO 'rahul'@'localhost';

mysql> FLUSH PRIVILEGES;


5. Drop User in MySQL
You can simply drop any user from MySQL using DROP command. For example to
delete user ‘rahul’@’localhost’, use following command.

mysql> DROP USER 'rahul'@'localhost';

mysql> FLUSH PRIVILEGES;

For checking users in mysql


select user from mysql.user;
Section 7.2: Creating and Selecting a Database
If the administrator creates your database for you when setting up your permissions,
you can begin using it. Otherwise, you need to create it yourself:
mysql> CREATE DATABASE menagerie;
Database changing
mysql> USE menagerie

Alternatively, you can select the database on the command line when we invoke
mysql.
Just specify its name after any connection parameters that you might
need to provide. For example:
shell> mysql -h host -u user -p menagerie
Enter password: ********
Chapter 8: Using Variables
Introduction to MySQL user-defined variables
Sometimes, you want to pass a value from an SQL statement to another SQL statement.
To do this, you store the value in a MySQL user-defined variable in the first statement and
refer to it in the subsequent statements.

To create a user-defined variable, you use the format @variable_name, where


the variable_name consists of alphanumeric characters. The maximum length of the user-
defined variable is 64 characters.

The user-defined variables are not case-sensitive. It means that the @id and @ID are the
same.

You can assign the user-defined variable to a certain data types such as integer, floating
point, decimal, string or NULL.

A user-defined variable defined by one client is not visible by other clients. In other words,
an user-defined variable is session-specific.

Note that the user-defined variables are the MySQL-specific extension to SQL standard.
They may not be available in other database systems.

create table items1(item_no int,item_name varchar(40),qty int, price int);

insert into items values(101,'Keyboard',5,500);

insert into items values(102,'Monitor',10,1000);

MySQL variable assignment


There are two ways to assign a value to a user-defined variable.

The first way is to use the SET statement as follows:


SET @variable_name := value;

You can use either := or = as the assignment operator in the SET statement.
SET @counter := 100;

The second way to assign a value to a variable is to use the SELECT statement.
In this case, you must use the := assignment operator because, within the
SELECT statement, MySQL treats the = operator as the equal operator.
SELECT @variable_name := value;
After the assignment, you can use the variable in the subsequent statement
where an expression is permitted e.g.,
in WHERE clause, INSERT or UPDATE statement.

MySQL variable examples


The following statement gets the most expensive product in the products table and
assigns the price to the user-defined variable @msrp:
SELECT @msrp:=MAX(qty) FROM items;

The following statement uses the @msrp variable to query the information of the most
expensive product.

SELECT item_id, item_name, qty, price FROM items WHERE qty = @msrp;
SELECT item_id, item_name, qty, price FROM items WHERE price < @msrp;

Sometimes, you want to insert a row into a table, get the last insert id, and use it for
inserting data into another table. In this case, you can use the user-defined variable to
store the most recent id generated by an AUTO_INCREMENT column as follows.

SELECT @id:=LAST_INSERT_ID();
A user-defined variable can hold a single value only. If the SELECT statement returns
multiple values, the variable will take the value of the last row in the result.

SELECT @buyPrice:=buyprice FROM products WHERE buyprice > 95 ORDER BY buyprice;


Chapter 9: Comment MySQL
Section 9.1: Adding comments
There are three types of comment:
# This comment continues to the end of line

-- This comment continues to the end of line

/* This is an in-line comment */

/*
This is a
multiple-line comment
*/
Example:
SELECT * FROM t1; -- this is comment

CREATE TABLE stack(/*id_user int,username varchar(30),password varchar(30)*/id


int );

The -- method requires that a space follows the -- before the comment begins,
otherwise it will be interpreted as a command and usually cause an error.
#This comment works
/*This comment works.*/
--This comment does not.
Chapter 10: INSERT
Section 10.1: INSERT, ON DUPLICATE KEY UPDATE

When you insert a new row into a table if the row causes a duplicate in UNIQUE index
or PRIMARY KEY , MySQL will issue an error.
Syntax:

INSERT INTO table (column_list) VALUES (value_list) ON DUPLICATE KEY UPDATE


c1 = v1,
c2 = v2,
...;

If we specify the ON DUPLICATE KEY UPDATE option in the INSERT statement, MySQL
will update the existing row with the new values instead.

First, create a table named devices to store the network devices.

CREATE TABLE devices (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100));

Next, insert rows into the devices table.

INSERT INTO devices(name)VALUES('Router F1'),('Switch 1'),('Switch 2');


SELECT id, name FROM devices;

Then, query the data from the devices table to verify the insert:

SELECT id, name FROM devices;

Now, we have three rows in the devices table.


After that, insert one more row into the devices table.

INSERT INTO devices(name) VALUES ('Printer') ON DUPLICATE KEY UPDATE name =


'Printer';

Because there is no duplicate, MySQL inserts a new row into the devices table. The
statement above has the same effect as the following statement:

INSERT INTO devices(name) VALUES ('Printer');

Finally, insert a row with a duplicate value in the id column.


INSERT INTO devices(id,name) VALUES (4,'Printer') ON DUPLICATE KEY UPDATE name
= 'Central Printer';

Section 10.2: Inserting multiple rows


create table mytable(field_1 varchar(40),field_2 varchar(40));

INSERT INTO mytable (field_1, field_2) VALUES ('data_1', 'data_2'), ('data_1', 'data_3'),
('data_4', 'data_5');

This is an easy way to add several rows at once with one INSERT statement.
This kind of 'batch' insert is much faster than inserting rows one by one. Typically,
inserting 100 rows in a single batch insert this way is 10 times as fast as inserting
them all individually.

Ignoring existing rows


When we use the INSERT statement to add multiple rows to a table and if an error
occurs during the processing, MySQL terminates the statement and returns an error.
As the result, no rows are inserted into the table.

However, if you use the INSERT IGNORE statement, the rows with invalid data that
cause the error are ignored and the rows with valid data are inserted into the table.

The syntax of the INSERT IGNORE statement is as follows:


INSERT IGNORE INTO table(column_list) VALUES( value_list), ( value_list), ...

MySQL INSERT IGNORE example

create a new table called subscribers


create table subscribers(email varchar(40) UNIQUE);

insert into values in subscribers.


INSERT INTO subscribers(email)VALUES('john.doe@gmail.com');

Let’s execute another statement that inserts two rows into the subscribers table:
INSERT INTO subscribers(email) VALUES('john.doe@gmail.com'),
('jane.smith@ibm.com');

error. Error Code: 1062. Duplicate entry 'john.doe@gmail.com' for key 'email'
As indicated in the error message, the email john.doe@gmail.com violates the
UNIQUE constraint.
If we use the INSERT IGNORE statement instead.
INSERT IGNORE INTO subscribers(email) VALUES('john.doe@gmail.com'),
('jane.smith@ibm.com');

Basic Insert
INSERT INTO subscribers(email)VALUES('john.doe@gmail.com');

INSERT with AUTO_INCREMENT + LAST_INSERT_ID()

For more information on how to set the AUTO_INCREMENT attribute for a column,
check it out the MySQL sequence tutorial.

You can obtain the generated sequence number using the


MySQL LAST_INSERT_ID function and use the number for the next statements e.g.,
inserting a new row into a correlated table.

First, create a new table named tbl for testing. In the tbl table, you set the
AUTO_INCREMENT attribute for the id column.

CREATE TABLE tbl (id INT AUTO_INCREMENT PRIMARY KEY, description VARCHAR(250)
NOT NULL);
Second, insert a new row into the tbl table.
INSERT INTO tbl(description)VALUES('MySQL last_insert_id');

Third, use the MySQL LAST_INSERT_ID function to get the last insert id that MySQL has
been generated.

SELECT LAST_INSERT_ID();

It’s important to note that if you insert multiple rows into a table using a single INSERT
statement, the LAST_INSERT_ID function returns the last insert id of the first row.

Suppose the AUTO_INCREMENT column has current value as 1 and you insert 3 rows
into the table. When you use the LAST_INSERT_ID function to get the last insert id, you
will get 2 instead of 4.

The following statement inserts 3 rows into the tbl table and gets the last insert id
using the LAST_INSERT_ID function.

INSERT INTO tbl(description)VALUES('record 1'),('record 2'),('record 3');

SELECT LAST_INSERT_ID();

Check the data of the tbl table:


SELECT * FROM tbl;

INSERT SELECT (Inserting data from another Table)


This is the basic way to insert data from another table with the SELECT statement.
INSERT INTO `tableA` (`field_one`, `field_two`) SELECT `tableB`.`field_one`,
`tableB`.`field_two` FROM `tableB` WHERE `tableB`.clmn <> 'someValue'
ORDER BY `tableB`.`sorting_clmn`;

You can SELECT * FROM, but then tableA and tableB must have matching column
count and corresponding datatypes.

create table sup(supplier_id int,supplier_name varchar(40));

insert into sup(supplier_id,supplier_name)select supplier_id,supplier_name from


suppliers;
Columns with AUTO_INCREMENT are treated as in the INSERT with VALUES clause.
This syntax makes it easy to fill (temporary) tables with data from other tables, even
more so when the data is to be filtered on the insert.

Lost AUTO_INCREMENT ids


Several 'insert' functions can "burn" ids. Here is an example.
CREATE TABLE Burn ( id SMALLINT AUTO_INCREMENT NOT NULL, name VARCHAR(99)
NOT NULL, PRIMARY KEY(id), UNIQUE(name));

INSERT IGNORE INTO Burn (name) VALUES ('first'), ('second');


SELECT LAST_INSERT_ID(); -- 1
SELECT * FROM Burn ORDER BY id;
+----+--------+
| 1 | first |
| 2 | second |
+----+--------+
INSERT IGNORE INTO Burn (name) VALUES ('second'); -- dup 'IGNORE', but id=3 is
burned
SELECT LAST_INSERT_ID(); -- Still "1" -- can't trust in this situation
SELECT * FROM Burn ORDER BY id;
+----+--------+
| 1 | first |
| 2 | second |
+----+--------+
INSERT IGNORE INTO Burn (name) VALUES ('third');
SELECT LAST_INSERT_ID(); -- now "4"
SELECT * FROM Burn ORDER BY id; -- note that id=3 was skipped over
+----+--------+
| 1 | first |
| 2 | second |
Chapter 11: DELETE
Parameter Details

LOW_PRIORITY If LOW_PRIORITY is provided, the delete will be delayed until there


are no processes reading from the table IGNORE If IGNORE is provided, all errors
encountered during the delete are ignored table.

The table from which you are going to delete records WHERE conditions. The
conditions that must be met for the records to be deleted.

If no conditions are provided, then all records from the table will be deleted.
ORDER BY expression If ORDER BY is provided, records will be deleted in the given
order LIMIT. It controls the maximum number of records to delete from the table.
Given number_rows will be deleted.

Multi-Table Deletes

MySQL's DELETE statement can use the JOIN construct, allowing also to specify which
tables to delete from. This is useful to avoid nested queries. Given the schema:

create table people ( id int primary key, name varchar(100) not null, gender char(1)
not null );

insert people (id,name,gender) values (1,'Kathy','f'),(2,'John','m'),(3,'Paul','m'),


(4,'Kim','f');

create table pets ( id int auto_increment primary key, ownerId int not null, name
varchar(100) not null, color varchar(100) not null);

insert pets(ownerId,name,color) values (1,'Rover','beige'),(2,'Bubbles','purple'),


(3,'Spot','black and white'), (1,'Rover2','white');

If we want to remove Paul's pets, the statement


DELETE p2 FROM pets p2 WHERE p2.ownerId in (SELECT p1.id FROM people p1
WHERE p1.name = 'Paul');
can be rewritten as:
DELETE p2 -- remove only rows from pets
FROM people p1
JOIN pets p2
ON p2.ownerId = p1.id
WHERE p1.name = 'Paul';
1 row deleted

Spot is deleted from Pets


p1 and p2 are aliases for the table names, especially useful for long table names and
ease of readability.
To remove both the person and the pet:
DELETE p1, p2 -- remove rows from both tables
FROM people p1
JOIN pets p2
ON p2.ownerId = p1.id
WHERE p1.name = 'Paul';
2 rows deleted
Spot is deleted from Pets
Paul is deleted from People

DELETE vs TRUNCATE

The TRUNCATE TABLE statement is used when you want to delete the complete data
from a table without removing the table structure.

Syntax: TRUNCATE TABLE table_name;

Step1:
CREATE TABLE books(id int auto_increment primary key, title varchar(255) not null);

Step 2:
insert into books(title)values('java'),('C++'),('Python');

Step 3:
SELECT * FROM books;

Step 4:
TRUNCATE TABLE books;
Step 5:
SELECT * FROM books;

Multi-table DELETE
MySQL allows to specify from which table the matching rows must be deleted
Step 1:

CREATE TABLE t1(id INT PRIMARY KEY AUTO_INCREMENT);

CREATE TABLE t2 (id VARCHAR(20) PRIMARY KEY,ref INT NOT NULL);

INSERT INTO t1 VALUES (1),(2),(3);

INSERT INTO t2(id,ref) VALUES('A',1),('B',2),('C',3);

DROP TABLE IF EXISTS t1, t2;

MySQL DELETE JOIN with INNER JOIN example

The following statement deletes the row with id 1 in the t1 table and also row
with ref 1 in the t2 table using DELETE...INNER JOIN statement:

CREATE TABLE t1(id INT PRIMARY KEY AUTO_INCREMENT);

CREATE TABLE t2 (id VARCHAR(20) PRIMARY KEY,ref INT NOT NULL);

INSERT INTO t1 VALUES (1),(2),(3);

INSERT INTO t2(id,ref) VALUES('A',1),('B',2),('C',3);

DELETE t1,t2 FROM t1 INNER JOIN t2 ON t2.ref = t1.id WHERE t1.id = 1;


create table sup(supplier_id int, supplier_name varchar(40));

insert into sup values(101,'IBM'),(102,'Samsung'),(103,'TVS'),(104,'DELL'),(105,'HP');

create table pro(product_id int, product_name varchar(40),supplier_id int);

insert into pro values(401,'Keyboard',101),(402,'Monitor',102),(403,'Monitor',104),


(404,'Monitor',104);

-- remove only the sup


delete e from sup e join pro d on e.supplier_id = d.supplier_id where d.product_name
= 'Keyboard';

select * from sup;

-- remove sup and pro


delete e,d from sup e join pro d on e.supplier_id = d.supplier_id where
d.product_name = 'Monitor';

select * from sup;


select * from pro;

Delete with Where clause


DELETE FROM `table_name` WHERE `field_one` = 'value_one'

This will delete all rows from the table where the contents of the field_one for that row
match 'value_one'.
The WHERE clause works in the same way as a select, so things like >, <, <> or
LIKE can be used.
delete from items where qty <20;
delete from items where qty >20;
delete from items where qty <> 25;
delete from products where product_name like 'Keyboard';

Notice: It is necessary to use conditional clauses (WHERE, LIKE) in delete query. If


you do not use any conditional clauses then all data from that table will be deleted.

Delete all rows from a table


DELETE FROM table_name ;
delete from products;

This will delete everything, all rows from the table. It is the most basic example of the
syntax. It also shows that DELETE statements should really be used with extra care
as they may empty a table, if the WHERE clause is omitted.

LIMITing deletes
DELETE FROM `table_name` WHERE `field_one` = 'value_one' LIMIT 1
delete from items where qty = 25 limit 1;

This works in the same way as the 'Delete with Where clause' example, but it will stop
the deletion once the limited number of rows have been removed.
Chapter 12: UPDATE
Update with Join Pattern

CREATE TABLE merits (performance INT(11) NOT NULL,percentage FLOAT NOT


NULL,PRIMARY KEY (performance));

CREATE TABLE employees( emp_id INT(11) NOT NULL AUTO_INCREMENT, emp_name


VARCHAR(255) NOT NULL, performance INT(11) DEFAULT NULL, salary FLOAT
DEFAULT NULL,PRIMARY KEY (emp_id), CONSTRAINT fk_performance FOREIGN KEY
(performance) REFERENCES merits (performance));

INSERT INTO merits(performance,percentage)VALUES(1,0),(2,0.01),(3,0.03),(4,0.05),


(5,0.08);

INSERT INTO employees(emp_name,performance,salary) VALUES('Mary Doe', 1,


50000),('Cindy Smith', 3, 65000),('Sue Greenspan', 4, 75000),('Grace Dell', 5,
125000),('Nancy Johnson', 3, 85000),('John Doe', 2, 45000),('Lily Bush', 3, 5000);

UPDATE employees INNER JOIN merits ON employees.performance =


merits.performance SET salary = salary + salary * percentage;

Basic Update
Updating one row
update customers set customer_name = 'Sitaraju' where customer_id = 204;
This query updates the content of email in the customers table to the string luke_smith@email.com where
the value of id is equal to 1. The old and new contents of the database table are illustrated below on the
left and right respectively:

Updating all rows


update products set product_name = 'Keyboard';
This query update the content of product_name for every entry in the products table. The old and new
contents of the database table are illustrated below on the left and right respectively:

Bulk UPDATE
When updating multiple rows with different values it is much quicker to use a bulk update.
update items set item_name = (CASE item_id when 307 then 'Keyboard' when 310
then 'Mouse' when 315 then 'Monitor'end)where item_id in(307,310,315);

By bulk updating only one query can be sent to the server instead of one query for
each row to update. The cases should contain all possible parameters looked up in the
WHERE clause.

UPDATE with ORDER BY and LIMIT


If the ORDER BY clause is specified in your update SQL statement, the rows are
updated in the order that is specified.
If LIMIT clause is specified in your SQL statement, that places a limit on the number
of rows that can be updated.

There is no limit, if LIMIT clause not specified.


ORDER BY and LIMIT cannot be used for multi table update.
Syntax for the MySQL UPDATE with ORDER BY and LIMIT is,

UPDATE tableName
SET column1 = expression1,
column2 = expression2,
...
[WHERE conditions]
[ORDER BY expression [ ASC | DESC ]]
[LIMIT row_count];

update items set qty=qty+10 order by item_name limit 5;


In the above example, 5 rows will be updated according to the order of employees
joining Date.

Multiple Table UPDATE


In multiple table UPDATE, it updates rows in each specified tables that satisfy the
conditions. Each matching row is updated once, even if it matches the conditions
multiple times.

In multiple table UPDATE, ORDER BY and LIMIT cannot be used.


Syntax for multi table UPDATE is,
UPDATE table1, table2, ...
SET column1 = expression1,
column2 = expression2,
...
[WHERE conditions]

CREATE TABLE Books(BookID SMALLINT NOT NULL PRIMARY KEY,BookName


VARCHAR(40) NOT NULL, InStock SMALLINT NOT NULL);

CREATE TABLE B_Orders(OrderID SMALLINT NOT NULL PRIMARY KEY,BookID SMALLINT


NOT NULL,Quantity TINYINT (40) NOT NULL DEFAULT 1,DateOrdered
TIMESTAMP,FOREIGN KEY (BookID) REFERENCES Books (BookID))

INSERT INTO Books VALUES (101, 'Java', 12),(102, 'PHP', 17),(103, 'MySQL', 23),(104,
'Perl', 32),(105, 'Pyton', 6),(106, 'www.java2s.com', 28);

INSERT INTO B_Orders VALUES (1001, 103, 1, '2001-11-12 12:30:00'),(1002, 101, 1,


'2002-10-16 12:31:00'),(1003, 103, 2, '2003-02-11 12:34:00'),(1004, 104, 3, '2004-01-
19 12:36:00'),(1005, 102, 1, '2005-12-17 12:41:00'),(1006, 103, 2, '2006-10-18
12:59:00'),(1007, 101, 1, '2004-11-21 13:01:00'),(1008, 103, 1, '2014-10-16
13:02:00'),(1009, 102, 4, '1994-09-02 13:22:00'),(1010, 101, 2, '1995-10-04
13:30:00'),(1011, 103, 1, '1996-08-12 13:32:00'),(1012, 105, 1, '2004-10-03
13:40:00'),(1013, 106, 2, '2002-05-12 13:44:00'),(1014, 103, 1, '2001-10-01
14:01:00'),(1015, 106, 1, '1997-05-05 14:05:00'),(1016, 104, 2, '1998-10-07
14:28:00'),(1017, 105, 1, '2004-03-12 14:31:00'),(1018, 102, 1, '2004-10-21
14:32:00'),(1019, 106, 3, '1991-01-30 14:49:00'),(1020, 103, 1, '1990-10-12
14:51:00');

select * from Books;

select * from B_Orders;

UPDATE Books, B_Orders SET


B_Orders.Quantity=B_Orders.Quantity+2,Books.InStock=Books.InStock-2 WHERE
Books.BookID=B_Orders.BookID AND B_Orders.OrderID = 1002;
select * from Books;

select * from Orders;


Chapter 13: ORDER BY
MySQL: ORDER BY Clause
This MySQL tutorial explains how to use the MySQL ORDER BY clause with syntax
and examples.

The MySQL ORDER BY clause is used to sort the records in your result set.
Syntax

The syntax for the ORDER BY clause in MySQL is:


SELECT expressions FROM tables WHERE conditions] ORDER BY expression [ ASC |
DESC ];

Parameters or Arguments
Expressions : The columns or calculations that you wish to retrieve.
Tables: The tables that you wish to retrieve records from. There must be
at least one table listed in the FROM clause.
WHERE conditions: Optional. The conditions that must be met for the records to be
selected.
ASC: Optional. It sorts the result set in ascending order
by expression (default, if no modifier is provider).
DESC: Optional. It sorts the result set in descending order
by expression.

Note
 If the ASC or DESC modifier is not provided in the ORDER BY clause, the results
will be sorted by expression in ascending order. This is equivalent to ORDER
BY expression ASC.
 The ORDER BY clause can be used in a SELECT statement, SELECT LIMIT
statement, and DELETE LIMIT statement in MySQL.

Sorting without using ASC/DESC attribute


The MySQL ORDER BY clause can be used without specifying the ASC or DESC
modifier. When this attribute is omitted from the ORDER BY clause, the sort order is
defaulted to ASC or ascending order.

SELECT city FROM customers WHERE customer_name = 'Somesh' ORDER BY city;


This MySQL ORDER BY example would return all records sorted by the cityfield in
ascending order and would be equivalent to the following ORDER BY clause:

Sorting using with ASC attribute


SELECT city FROM customers WHERE customer_name = 'Somesh' ORDER BY city ASC;

Sorting in descending order


When sorting your result set in descending order, you use the DESC attribute in your
ORDER BY clause as follows:
SELECT supplier_name, contact_name, city FROM suppliers WHERE city = 'kakinada'
ORDER BY supplier_name DESC;
Sorting by relative position
You can also use the MySQL ORDER BY clause to sort by relative position in the result
set, where the first field in the result set is 1. The next field is 2, and so on.
For example:

SELECT supplier_name, contact_name, city FROM suppliers WHERE city = 'kakinada'


ORDER BY 2 DESC;

Using both ASC and DESC attributes


When sorting your result set using the MySQL ORDER BY clause, you can use the ASC
and DESC attributes in a single SELECT statement.
For example:
select item_name,qty from items where supplier_id = 105 order by item_name
desc,qty asc;

Some tricks
ORDER BY FIND_IN_SET(card_type, "MASTER-CARD,VISA,DISCOVER") -- sort 'MASTER-CARD' first.
ORDER BY x IS NULL, x -- order by `x`, but put `NULLs` last.
Custom ordering

select * from items where supplier_id in(101,104,102,105) order by field


(supplier_id,101,104,102,105);
Chapter 14: Group By
The expressions that are not summarize within an aggregate function and must be
included in the GROUP BY clause.

GROUP BY using HAVING

The HAVING clause is used in the SELECT statement to specify filter conditions for a
group of rows or aggregates.

The HAVING clause is often used with the GROUP BY clause to filter groups based on a
specified condition. If you omit the GROUP BY clause, the HAVING clause behaves like
the WHERE clause.

SELECT
select_list
FROM
table_name
WHERE
search_condition
GROUP BY
group_by_expression
HAVING
group_condition;

SELECT item_id,supplier_id, SUM(qty) AS itemsCount, SUM(price*qty) AS total FROM


items GROUP BY supplier_id;

Using GROUP BY ... HAVING to filter aggregate records for using SELECT ... WHERE
to filter individual records.

SELECT item_id,supplier_id, SUM(qty) AS itemsCount, SUM(price*qty) AS total FROM items


GROUP BY supplier_id HAVING total > 1000;

Group By using Group Concat


Group_Concat is used in MySQL to get concatenated values of expressions with more
than one result per column.

select customer_id, GROUP_CONCAT(supplier_id order by supplier_id desc)AS IDs from


orders group by customer_id;

Section 14.4: GROUP BY with AGGREGATE


functions
aggregate_function A function such as SUM, COUNT, MIN, MAX, or AVG functions
There must be at least one table listed in the FROM clause. WHERE conditions
Optional. The conditions that must be met for the records to be selected.
COUNT
Return the number of rows that satisfy a specific criteria in WHERE clause.
E.g.: Number of orders for each customer.
select item_name,count(*) as 'No of items' from items group by item_name order by
supplier_id;
SUM
Return the sum of the selected column.
E.g.: Sum of the total and items for each customer.
select item_name, sum(qty) as 'sum of items' from items group by item_name order
by supplier_id;
AVG
SELECT item_name, AVG(price) as avg_price FROM items GROUP BY item_name order
by item_name;
MAX
SELECT item_name, MAX(price) as max_price FROM items GROUP BY item_name order
by item_name;
MIN
SELECT item_name, min(price) as min_price FROM items GROUP BY item_name order
by item_name;

Chapter 15: Joins


Introduction to MySQL join statements

A MySQL join is a method of linking data between one or more tables based on values
of the common column between tables.

MySQL supports the following types of joins:

1. Cross join
2. Inner join
3. Left join
4. Right join

Notice that MySQL does not support full outer join.

To make easy for you to understand each type of join, we will use the t1 and t2 tables
with the following structures:

CREATE TABLE t1 (id INT PRIMARY KEY, pattern VARCHAR(50) NOT NULL);

CREATE TABLE t2 (id VARCHAR(50) PRIMARY KEY, pattern VARCHAR(50) NOT NULL);

Both t1 and t2 tables have the pattern column, which is also the common column
between tables.
The following statements insert data into both t1 and t2 tables:
INSERT INTO t1(id, pattern) VALUES(1,'Divot'), (2,'Brick'),(3,'Grid');

INSERT INTO t2(id, pattern) VALUES('A','Brick'), ('B','Grid'),('C','Diamond');

And the pictures below illustrate data from both t1 and t2 tables:
MySQL CROSS JOIN

The CROSS JOIN makes a product of rows from multiple tables.

Suppose, you join t1 and t2 tables using the CROSS JOIN, the result set will include the
combinations of rows from the t1 table with the rows in the t2 table.

To perform cross join, you use the CROSS JOIN clause as in the following statement:
SELECT t1.id, t2.id FROM t1 CROSS JOIN t2;
The following shows the result set of the query:

As you can see, each row in the t1 table combines with rows in the t2 table to form
the Cartesian product.
The following picture illustrates the CROSS JOIN between t1 and t2 tables.
MySQL INNER JOIN

To form anINNER JOIN, you need a condition which is known as a join-predicate.


An INNER JOIN requires rows in the two joined tables to have matching column values.

The following statement uses the INNER JOIN clause to join t1 and t2 tables:
SELECT t1.id, t2.id FROM t1 INNER JOIN t2 ON t1.pattern = t2.pattern;

select orders.supplier_id,suppliers.supplier_id from orders inner join


suppliers on orders.supplier_id = suppliers.supplier_id;

The following picture illustrates the INNER JOIN between t1 and t2 tables:

In this illustration, the rows in both tables must have the same pattern to be included
in the result set.
MySQL LEFT JOIN

Unlike an INNER JOIN, a LEFT JOIN returns all rows in the left table including rows that
satisfy join-predicate and rows that do not.

For the rows that do not match the join-predicate, NULLs appear in the columns of the
right table in the result set.

The following statement uses the LEFT JOIN clause to join t1 and t2 tables:
SELECT t1.id, t2.id FROM t1 LEFT JOIN t2 ON t1.pattern = t2.pattern ORDER BY
t1.id;

select orders.supplier_id,suppliers.supplier_id from orders left join suppliers on


orders.supplier_id = suppliers.supplier_id;

As you can see, all rows in the t1 table are included in the result set. For the rows in
the t1 table (left table) that do not have any matching row in the t2 table (right table),
NULLs are used for columns in t2 table.
The following picture illustrates the LEFT JOIN between t1 and t2 tables:

In this illustration, the following rows share the same pattern: (2 and A), (3 and B).
The row with id 1 in the t1 table has no matching row in the t2 table,
therefore, NULL are used for columns of the t2 table in the result set.
MySQL RIGHT JOIN

A RIGHT JOIN is similar to the LEFT JOIN except that the treatment of tables is
reversed. With a RIGHT JOIN, every row from the right table ( t2) will appear in the
result set. For the rows in the right table that do not have the matching rows in the
left table ( t1), NULLs appear for columns in the left table ( t1).
The following statement joins t1 and t2 tables using RIGHT JOIN:
SELECT t1.id, t2.id FROM t1 RIGHT JOIN t2 on t1.pattern = t2.pattern ORDER BY t2.id;

select orders.supplier_id,suppliers.supplier_id from orders right join suppliers on


orders.supplier_id = suppliers.supplier_id;
In this result, all rows from the right table ( t2) appear in the result set. For the rows in
the right table ( t2) that have no matching rows in the left table ( t1), NULL appears
for columns of the left table ( t1).
The following picture illustrates the RIGHT JOIN between t1 and t2 tables:

In this tutorial, you have learned various MySQL join statements including cross join,
inner join, left join and right join to query data from two or more tables.
Chapter 18: UNION
If you needed to keep duplicates in your query, you could use the ALL
keyword like so: UNION ALL.
Combining data with different columns
select supplier_id,supplier_name from suppliers
union
select supplier_id,product_name from products;

When combining 2 record sets with different columns then emulate the missing ones
with default values.

select supplier_id from suppliers union select supplier_id from orders;

select supplier_id from suppliers union all select supplier_id from orders;

ORDER BY
The MySQL UNION operator can use the ORDER BY clause to order the results of the
query.
( SELECT ... )
UNION
( SELECT ... )
ORDER BY

SELECT supplier_id, supplier_name FROM suppliers WHERE supplier_id <= 500


UNION
SELECT customer_id, customer_name FROM customers WHERE city = 'Vizag'
ORDER BY 2;

When adding a LIMIT to a UNION, this is the pattern to use:


(select supplier_id,supplier_name from suppliers limit 3) union all (select
customer_id,customer_name from customers limit 3)limit 4;

From the 2nd row of 3 items, this pattern is needed:


(select supplier_id,supplier_name from suppliers limit 3) union all (select
customer_id,customer_name from customers limit 3)limit 1,4;

Combining and merging data on different MySQL tables with the same
columns into unique rows and running query

select supplier_id,supplier_name from suppliers where supplier_id in (select


supplier_id from products where supplier_id = 104)
union
select item_id,item_name from items where supplier_id in (select supplier_id from
suppliers where supplier_name = 'IBM');

This UNION ALL combines data from multiple tables and serve as a table name alias
to use for your queries:

UNION ALL and UNION


select supplier_id from orders union select supplier_id from suppliers;
select supplier_id from orders union all select supplier_id from suppliers;
Chapter 19: Arithmetic
Section 19.1: Arithmetic Operators
MySQL provides the following arithmetic operators
Operator Name Example
+ Addition
SELECT 3+5; -> 8
SELECT 3.5+2.5; -> 6.0
SELECT 3.5+2; -> 5.5
- Subtraction SELECT 3-5; -> -2
* Multiplication SELECT 3 * 5; -> 15
/ Division
SELECT 20 / 4; -> 5
SELECT 355 / 113; -> 3.1416
SELECT 10.0 / 0; -> NULL
DIV Integer Division SELECT 5 DIV 2; -> 2
% or MOD Modulo
SELECT 7 % 3; -> 1
SELECT 15 MOD 4 -> 3
SELECT 15 MOD -4 -> 3
SELECT -15 MOD 4 -> -3
SELECT -15 MOD -4 -> -3
SELECT 3 MOD 2.5 -> 0.5
BIGINT
If the numbers in your arithmetic are all integers, MySQL uses the BIGINT (signed 64-
bit) integer data type to do its
work. For example:
select (1024 * 1024 * 1024 * 1024 *1024 * 1024) + 1 -> 1,152,921,504,606,846,977
and
select (1024 * 1024 * 1024 * 1024 *1024 * 1024 * 1024 -> BIGINT out of range error

DOUBLE
If any numbers in your arithmetic are fractional, MySQL uses 64-bit IEEE 754 floating
point arithmetic. You must be careful when using floating point arithmetic, because
many floating point numbers are, inherently, approximations rather than exact values.

Rounding (ROUND, FLOOR, CEIL)


Round a decimal number to an integer value
For exact numeric values (e.g. DECIMAL): If the first decimal place of a number is 5
or higher, this function will round a number to the next integer away from zero. If that
decimal place is 4 or lower, this function will round to the next integer value closest to
zero.

SELECT ROUND(4.51) -> 5


SELECT ROUND(4.49) -> 4
SELECT ROUND(-4.51) -> -5
For approximate numeric values (e.g. DOUBLE): The result of the ROUND() function
depends on the C library; on many systems, this means that ROUND() uses the round
to the nearest even rule:
SELECT ROUND(45e-1) -> 4 -- The nearest even value is 4
SELECT ROUND(55e-1) -> 6 -- The nearest even value is 6

Round up a number
To round up a number use either the CEIL() or CEILING() function
SELECT CEIL(1.23) -> 2
SELECT CEILING(4.83) -> 5

Round down a number


To round down a number, use the FLOOR() function
SELECT FLOOR(1.99) -> 1

FLOOR and CEIL go toward / away from -infinity:


SELECT FLOOR(-1.01), CEIL(-1.01) -> -2 and -1
SELECT FLOOR(-1.99), CEIL(-1.99) -> -2 and -1

Round a decimal number to a specified number of decimal places.


SELECT ROUND(1234.987, 2) -> 1234.99
SELECT ROUND(1234.987, -2) -> 1200
The discussion of up versus down and "5" applies, too.

Raise a number to a power (POW)


To raise a number x to a power y, use either the POW() or POWER() functions

SELECT POW(2,2); => 4


SELECT POW(4,2); => 16
Section 19.6: Square Root (SQRT)
Use the SQRT() function. If the number is negative, NULL will be returned
SELECT SQRT(16); -> 4
SELECT SQRT(-3); -> NULL

Random Numbers (RAND)


Generate a random number
To generate a pseudorandom floating point number between 0 and 1, use the RAND()
function Suppose you have the following query
SELECT i, RAND() FROM t;
This will return something like this
i RAND()
1 0.6191438870682
2 0.93845168309142
3 0.83482678498591
Random Number in a range
To generate a random number in the range a <= n <= b, you can use the following
formula
FLOOR(a + RAND() * (b - a + 1))
For example, this will generate a random number between 7 and 12
SELECT FLOOR(7 + (RAND() * 6));
A simple way to randomly return the rows in a table:
SELECT * FROM tbl ORDER BY RAND();
These are pseudorandom numbers.
The pseudorandom number generator in MySQL is not cryptographically secure. That
is, if you use MySQL to
generate random numbers to be used as secrets, a determined adversary who knows
you used MySQL will be able
to guess your secrets more easily than you might believe.
Chapter 20: String operations
String Functions in MySQL

ASCII (str)
In this function returns ASCII code value of the leftmost character of the String str and
returns 0 if str is the empty string.
Returns NULL if str is NULL.

Example : SELECT ASCII('0');


SELECT ASCII('d');

BIT_LENGTH (str)
In the BIT_LENGTH(str) function return the String str length in bits forms.

Example: SELECT BIT_LENGTH('a');

CHAR(N,... [USING charset_name] )

CHAR_LENGTH(str)
In this function returns String str lengths that is measured in characters. But in this
function a multi-byte character counts as single character such as a string contains 5
two-byte characters, then LENGTH() function returns 10, but the CHAR_LENGTH()
returns 5.

select char_length("ISAN");

CONCAT(str1, str2..)
The CONCAT(str1, str2?.) function can have one or more arguments and its returns a
string that is the result of concatenating the arguments. In this function all arguments
are non-binary strings then the result is also non-binary string but if any argument is
binary string then result is binary string. And a numeric argument is converted to its
equivalent binary string form. But if any argument is NULL then it also returns NULL.

Example: SELECT CONCAT('In', 'd', 'ia');


SELECT CONCAT('my', NULL, 'ql');
SELECT CONCAT(10.3);
CONCAT_WS(separator str1, str2,....)
CONCAT_WS() means CONCAT With Separator.

The first argument is treated as a separator for the rest of the arguments and it is
added between the strings for concatenating. If the separator is NULL then the result
is NULL.

Example: SELECT CONCAT_WS(',', ' Title', 'First name', 'Last Name');


SELECT CONCAT_WS(',', 'First name', NULL, 'Last Name');

FIELD(str,str1,str2,str3,...)
In the FIELD(str,str1,str2,str3,....) function is used to find the index position of str in
the arguments str1,str2,str3.

In other words it returns the index position of str in the arguments. It returns 0 if str is
not available in the arguments. If str is NULL then return value is 0 because NULL fails
equality comparison with any value.
Example: SELECT FIELD ('AA', 'BB', 'AA', 'CC');

FIND_IN_SET(str,strlist)
FIND_IN_SET(str, strlist) function returns a value in the range of 1 to N.

This function find the String str in the substring of String list strlist and return the
index value.

This String list have many substrings that is separated by ?,? characters. This function
returns 0 when str is not available in stringlist or string list is the empty string.

Example: SELECT FIND_IN_SET('2', '1,2,3,4');

FORMAT(X,D)
In the FORMAT(X,D) function formats the number X like #,###,###.## and rounded
the decimal places to D then returns the string as a result.

But if D is 0 then the result don’t have fractional part.

Example: SELECT FORMAT(1235.14687, 3);

HEX(N_or_S)
In HEX(N_or_S) function N_or_S is a number then this function returns a string that is
representation of hexadecimal value of N, where is a longlon(BIGINT) number. But if
N_or_S is a string, then it returns a string hexadecimal representation of N_or_S where
each character in N_or_S is converted to two hexadecimal digits.
Example: SELECT HEX(10);
SELECT HEX( 'abd');

INSERT(str,pos,len,newstr)
This function is used to replace some part or whole String of String str with String
newstr from beginning at position pos and len character long. This function returns
the String str if pos is not within the length of the string. It returns NULL if any
argument is NULL.

Example: SELECT INSERT('helloindia',2,3,'net');


SELECT INSERT('helloindia',-1,3,'net');

INSTR(str,substr)
This function is used to return the position of first occurrence of substr SubString in str
String.

Example: SELECT INSTR('helloindia','e');


SELECT INSTR('xe', 'helloindia');
LOWER(str)
The LOWER(str) function return the String str. And in this String all the characters are
changed in the lowercase.

Example: SELECT LOWER('HELLOINDIA');

LCASE(str)
The LCASE(str) function is same as LOWER() function

LEFT(str,len)
This function returns the leftmost len characters from the String str.

Example: SELECT LEFT('helloindia', 4);

LENGTH(str)
The LENGTH(str) function returns the length of the String str in bytes.

Example: SELECT LENGTH("helloindia");


LOAD_FILE(file_name)
This function is used to read the file and this function returns the content of file as a
string. For using it the file must be located on the server host., you must specify the
full path of the file. But for using this function you must have FILE privilege and the
file size is less than max_allowed_packet bytes.

Example: SELECT LOAD_FILE('C:/MySQL/MySQL Server 5.0/data');

LOCATE(substr,str), LOCATE(substr,str,pos)
The LOCATE(substr,str) function is same as INSTR(str, substr).

LOCATE(substr,str,pos) function is also same but its just start the to find first
occurrence of substr in String str from position pos.

These functions returns 0 if substr is not in String str.

Example: SELECT LOCATE('d','roseindia',4);

LPAD(str,len,padstr)
In the LPAD(str, len, padstr) function returns the string str that is left padded with
padstr string for length of len characters. But string str is longer than len characters
then return value is shortend to len characters.

Example: SELECT LPAD('hello',7,'??');


LTRIM(str)
LTRIM(str) function returns the string str with leading space characters removed.

Example: SELECT LTRIM(' helloindia');

MAKE_SET(bits,str1,str2,...)
The MAKE_SET(bits, str1, str2,..) function is returns a set value consisting of the
strings that have the corresponding bit in bits set. str1 corresponds to bit 0, str2 to bit
1, and so on. NULL values in str1, str2, ... are not appended to the result.

Example:
Select make_set(1, 'apple','mango','grapes');
Select make_set(1|3, 'apple','mango','grapes');
Select make_set(1|4, 'apple','mango','grapes');

MID(str,pos,len)
The MID(str, pos, len) function is same as SUBSTRING(str,pos,len)

Example:

SELECT MID('ISAN Computer Education', 1, 8) As SUBSTRING;

CREATE TABLE StudentDetails


(
Student_id INT AUTO_INCREMENT,
Student_name VARCHAR(100) NOT NULL,
Roll INT NOT NULL,
Department VARCHAR(10) NOT NULL,
PRIMARY KEY(Student_id )
);

INSERT INTO StudentDetails


(Student_name ,Roll, Department )
VALUES
('Anik Biswas ',10100,'CSE'),
('Bina Mallick', 11000,'ECE' ),
('Niket Sharma', 12000,'IT' ),
('Sayan Samanta',13000, 'ME' ),
('Riya Shah ', 14000,'EE' ),
('Bipin Kohli', 15000,'CE' );

SELECT Student_id , MID(Student_name,1,5 ) AS First_Name,


Student_name ,Roll,Department FROM StudentDetails;

REPEAT (str, count)


REPEAT (str, count) function returns a string that consist a String str repeated of count
times. But if count time is less than 1 than it returns an empty string.

Example: SELECT REPEAT('Hello', 3);

REPLACE (str, from_str, to_str)


In REPLACE (str, from_str, to_str) function returns the String str and in this String all
occurrences of the String from_str is replaced by the String to_str. This function can
perform a case-sensitive match when searching for from_str.

Example: SELECT REPLACE ('www.mcnsolutions.net', 'w', 'W');

REVERSE(str)
The REVERSE(str) function is used to return the reverse of String str.

Example: SELECT REVERSE('123');


RIGHT(str, len)
In the RIGET(str, len) function returns the rightmost len characters from the String str.
It return NULL if any argument is NULL.

Example : SELECT RIGHT ('Helloindia', 5);

RPAD(str, len, padstr)


RPAD(str, len, padstr) function returns the string str that is right padded with padstr
string for length of len characters. But string str is longer than len characters then
return value is shortend to len characters.

Example : SELECT RPAD ('hello', 7, '?');

RTRIM(str)
The RTRIM(str) function returns the String str with trailing space characters removed.

Example : SELECT RTRIM ('hello ');


SPACE(N)
In the SPACE(N) function returns a String that consist of N space characters.

Example :SELECT SPACE(5);

SUBSTRING(str,pos):
SUBSTRING (or equivalent: SUBSTR) returns the substring starting from the specified
position and, optionally, with the specified length
Syntax: SUBSTRING(str, start_position)

Example :SELECT SUBSTRING('HelloIndia',5);


SELECT SUBSTRING('HelloIndia' FROM 5);
SELECT SUBSTRING('HelloIndia',5,3);
UPPER(str)
UPPER(str) function return the String str. And in this string all the characters are
changed in the uppercase.

Example : SELECT UPPER('helloindia');


Chapter 21: Date and Time Operations
Introduction to MySQL DATE data type

MySQL DATE is one of the five temporal data types used for managing date values.
MySQL uses yyyy-mm-dd format for storing a date value. This format is fixed and it is
not possible to change it.

For example, we may prefer to use mm-dd-yyyy format but you can’t. Instead, you
follow the standard date format and use the DATE_FORMAT function to format the
date the way you want.

MySQL uses 3 bytes to store a DATE value. The DATE values range from 1000-01-
01 to 9999-12-31. If you want to store a date value that is out of this range, you need
to use a non-temporal data type like integer e.g., three columns, and each column for
the year, month, and day. You also need to create stored functions to simulate the
built-in date functions provided by MySQL, which is not recommended.

When strict mode is disabled, MySQL converts any invalid date e.g., 2015-02-30 to the
zero date value 0000-00-00.
MySQL Date values with two-digit years

MySQL stores the year of the date value using four digits. In case you use two-digit
year values, MySQL still accepts them with the following rules:

 Year values in the range 00-69 are converted to 2000-2069.


 Year values in the range 70-99 are converted to 1970 – 1999.
However, a date value with two digits is ambiguous therefore you should avoid using
it.

Let’s take a look at the following example.

First, create a table named people with birth date column with DATE data type.
CREATE TABLE people (id INT AUTO_INCREMENT PRIMARY KEY,first_name
VARCHAR(50) NOT NULL,last_name VARCHAR(50) NOT NULL,birth_date DATE NOT
NULL);

Next, insert a row into the people table.


INSERT INTO people(first_name,last_name,birth_date)VALUES('John','Doe','1990-09-
01');
Then, query the data from the people table.

SELECT first_name, last_name, birth_date FROM people;

After that, use the two-digit year format to insert data into the people table.
INSERT INTO people(first_name,last_name,birth_date)VALUES('Jack','Daniel','01-09-
01'),('Lily','Bush','80-09-01');

In the first row, we used 01 (range 00-69) as the year, so MySQL converted it to 2001.
In the second row, we used 80 (range 70-99) as the year, MySQL converted it to 1980.
Finally, we can query data from the people table to check whether data was
converted based on the conversion rules.
SELECT first_name, last_name, birth_date FROM people;

MySQL DATE functions


MySQL provides many useful date functions that allow you to manipulate date
effectively.

To get the current date and time, you use NOW() function.

SELECT NOW();
+---------------------+
| NOW() |
+---------------------+
| 2017-05-13 07:59:38 |
+---------------------+
1 row in set (0.02 sec)

To get only date part of a DATETIME value, you use the DATE() function.
SELECT DATE(NOW());
+-------------+
| DATE(NOW()) |
+-------------+
| 2015-07-13 |
+-------------+
1 row in set (0.01 sec)

In this example, we used the SLEEP() function to pause the query for 5 seconds.
SELECT NOW(), SLEEP(5), NOW();

To get the current system date, you use CURDATE() function as follows:
SELECT CURDATE();
+------------+
| CURDATE() |
+------------+
| 2015-07-13 |
+------------+
1 row in set (0.02 sec)

The SYSDATE() function returns the current date and time as a value in 'YYYY-MM-DD
HH:MM:SS' format if the function is used in a string context
or YYYYMMDDHHMMSS format in case the function is used in a numeric context.
The SYSDATE() function accepts an optional argument fsp that determines whether
the result should include a fractional seconds precision which ranges from 0 to 6.
See the following example.

SELECT SYSDATE();
+---------------------+
| SYSDATE() |
+---------------------+
| 2019-03-09 10:36:56 |
+---------------------+
1 row in set (0.00 sec)

If you pass the fsp argument, the result will include the fractional seconds precision as
shown in the following example:

SELECT SYSDATE(3);
+-------------------------+
| SYSDATE(3) |
+-------------------------+
| 2019-03-09 10:38:11.070 |
+-------------------------+
1 row in set (0.00 sec)
To format a date value, you use DATE_FORMAT function. The following statement
formats the date as mm/dd/yyyy using the date format pattern %m/%d/%Y :
SELECT DATE_FORMAT(CURDATE(), '%m/%d/%Y') today;
+------------+
| today |
+------------+
| 07/13/2015 |
+------------+
1 row in set (0.02 sec)

To calculate the number of days between two date values, you use the DATEDIFF
function as follows:
SELECT DATEDIFF('2015-11-04','2014-11-04') days;
+------+
| days |
+------+
| 365 |
+------+
1 row in set (0.02 sec)

To add a number of days, weeks, months, years, etc., to a date value, you use
the DATE_ADD function:

SELECT '2015-01-01' start, DATE_ADD('2015-01-01', INTERVAL 1 DAY) 'one day


later',DATE_ADD('2015-01-01', INTERVAL 1 WEEK) 'one week later',DATE_ADD('2015-
01-01', INTERVAL 1 MONTH) 'one month later',DATE_ADD('2015-01-01', INTERVAL 1
YEAR) 'one year later';

Similarly, you can subtract an interval from a date using the DATE_SUB function:

SELECT'2015-01-01' start,DATE_SUB('2015-01-01', INTERVAL 1 DAY) 'one day


before',DATE_SUB('2015-01-01', INTERVAL 1 WEEK) 'one week
before',DATE_SUB('2015-01-01', INTERVAL 1 MONTH) 'one month
before',DATE_SUB('2015-01-01', INTERVAL 1 YEAR) 'one year before';
If you want to get the day, month, quarter, and year of a date value, you can use the
corresponding function DAY, MONTH, QUARTER, and YEAR as follows:
SELECT DAY('2000-12-31') day, MONTH('2000-12-31') month, QUARTER('2000-12-31')
quarter, YEAR('2000-12-31') year;
+------+-------+---------+------+
| day | month | quarter | year |
+------+-------+---------+------+
| 31 | 12 | 4 | 2000 |
+------+-------+---------+------+
1 row in set (0.00 sec)

To get the week information week related functions. For example, WEEK function
returns the week number, WEEKDAY function returns the weekday index,
and WEEKOFYEAR function returns the calendar week.

SELECT WEEKDAY('2000-12-31') weekday, WEEK('2000-12-31')


week,WEEKOFYEAR('2000-12-31') weekofyear;

+---------+------+------------+
| weekday | week | weekofyear |
+---------+------+------------+
| 6 | 53 | 52 |
+---------+------+------------+
1 row in set (0.04 sec)

The week function returns the week number with the zero-based index if you don’t
pass the second argument or if you pass 0. If you pass 1, it will return week number
with 1-indexed.

SELECT WEEKDAY('2000-12-31') weekday, WEEK('2000-12-31',1) week,


WEEKOFYEAR('2000-12-31') weekofyear;
+---------+------+------------+
| weekday | week | weekofyear |
+---------+------+------------+
| 6 | 52 | 52 |
+---------+------+------------+
1 row in set (0.00 sec)
Chapter 22: Handling Time Zones
Retrieve the current date and time in a particular time zone
This fetches the value of NOW() in local time, in India Standard Time, and then again
in UTC.
SELECT NOW();

SELECT @@system_time_zone;
SELECT @@GLOBAL.time_zone, @@SESSION.time_zone;
SELECT @@time_zone;

Convert a stored `DATE` or `DATETIME` value to another time


zone
In MySQL the CONVERT_TZ() returns a resulting value after converting a datetime
value from a time zone specified as the second argument to the time zone specified
as the third argument. This function returns NULL when the arguments are invalid.

CONVERT_TZ (dt, from_tz,to_tz)

dt A datetime.
from_tz A time zone which will be converted to to_tz.
to_tz A time zone in which the from_tz will convert.

Coordinated Universal Time

The MySQL TIMESTAMP is a temporal data type that holds the combination of date
and time. The format of a TIMESTAMP is YYYY-MM-DD HH:MM:SS which is fixed at 19
characters. The TIMESTAMP value has a range from '1970-01-01 00:00:01' UTC to
'2038-01-19 03:14:07' UTC

SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;


SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','Asia/Kolkata');

Retrieve stored `TIMESTAMP` values in a particular time zone


This is really easy. All TIMESTAMP values are stored in universal time, and always
converted to the present time_zone setting whenever they are rendered.

CREATE TABLE `test` (`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON


UPDATE CURRENT_TIMESTAMP);

insert into `test` (`ts`) values (utc_timestamp()) ;


select * from test;

What is my server's local time zone setting?


Each server has a default global time_zone setting, configured by the owner of the
server machine. You can find out the current time zone setting this way:
SELECT @@time_zone

Unfortunately, that usually yields the value SYSTEM, meaning the MySQL time is
governed by the server OS's time zone setting.

CREATE TEMPORARY TABLE times (dt DATETIME, ts TIMESTAMP);


INSERT INTO times VALUES(NOW(), NOW());
SET time_zone = 'SYSTEM';
SELECT dt, ts, TIMESTAMPDIFF(MINUTE, dt, ts)offset FROM times;
DROP TEMPORARY TABLE times;
Chapter 23: Regular Expressions
A regular expression is a powerful way of specifying a pattern for a complex search.
REGEXP / RLIKE
The REGEXP (or its synonym, RLIKE) operator allows pattern matching based on
regular expressions.

Consider the following employee table:


EMPLOYEE_ID FIRST_NAME LAST_NAME Mobile SALARY
100 Steven King 515.123.4567 24000.00
101 Neena Kochhar 515.123.4568 17000.00
102 Lex De Haan 515.123.4569 17000.00
103 Alexander Hunold 590.423.4567 9000.00
104 Bruce Ernst 590.423.4568 6000.00
105 David Austin 590.423.4569 4800.00
106 Valli Pataballa 590.423.4560 4800.00
107 Diana Lorentz 590.423.5567 4200.00
108 Nancy Greenberg 515.124.4569 12000.00
109 Daniel Faviet 515.124.4169 9000.00
110 John Chen 515.124.4269 8200.00

Pattern ^
Select all emp whose FIRST_NAME starts with N.
Query
SELECT * FROM emp WHERE FIRST_NAME REGEXP '^N'
-- Pattern start with----------------------------^

Pattern $**
Select all emp whose PHONE_NUMBER ends with 4569.
Query
SELECT * FROM emp WHERE mobile REGEXP '4569$'
-- Pattern end with----------------------------------^

NOT REGEXP
Select all emp whose FIRST_NAME does not start with N.
Query
SELECT * FROM emp WHERE FIRST_NAME NOT REGEXP '^N'
-- Pattern does not start with---------------^

Regex Contain
Select all emp whose LAST_NAME contains in and whose FIRST_NAME contains a.
Query
SELECT * FROM emp WHERE FIRST_NAME REGEXP 'a' AND LAST_NAME REGEXP 'in'

Any character between [ ]


Select all emp whose FIRST_NAME starts with A or B or C.
Query
SELECT * FROM emp WHERE FIRST_NAME REGEXP '^[ABC]'

Pattern or |
Select all emp whose FIRST_NAME starts with A or B or C and ends with r, e, or i.
Query
SELECT * FROM emp WHERE FIRST_NAME REGEXP '^[ABC]|[rei]$'
Counting regular expression matches
Consider the following query:

SELECT FIRST_NAME, FIRST_NAME REGEXP '^N' as matching FROM emp


FIRST_NAME REGEXP '^N' is 1 or 0 depending on the fact that FIRST_NAME matches
^N.
To visualize it better:

SELECT FIRST_NAME, IF(FIRST_NAME REGEXP '^N', 'matches ^N', 'does not match
^N') as matching FROM emp;

Finally, count total number of matching and non-matching rows with:


SELECT IF(FIRST_NAME REGEXP '^N', 'matches ^N', 'does not match ^N') as
matching, COUNT(*) FROM emp GROUP BY matching;
Chapter 24: VIEW
Parameters Details
view_name Name of View SELECT statement SQL statements to be packed in the views. It can be a
SELECT statement to fetch data from one or more tables.
Create a View
Privileges
The CREATE VIEW statement requires the CREATE VIEW privilege for the view, and
some privilege for each column selected by the SELECT statement. For columns used
elsewhere in the SELECT statement, you must have the SELECT privilege. If the OR
REPLACE clause is present, you must also have the DROP privilege for the view.
CREATE VIEW might also require the SUPER privilege, depending on the DEFINER
value, as described later in this section.

A view belongs to a database. By default, a new view is created in the default


database. To create the view explicitly in a given database, use a fully qualified name.
Example:
db_name.view_name
CREATE VIEW test.v AS SELECT * FROM t;

mysql> create view v2 as select * from suppliers where city = 'Kakinada';


Query OK, 0 rows affected (0.17 sec)

mysql> select * from v2;


+-------------+---------------+--------------+----------+
| supplier_id | supplier_name | contact_name | city |
+-------------+---------------+--------------+----------+
| 102 | APPLE | Sou | kakinada |
+-------------+---------------+--------------+----------+
1 row in set (0.03 sec)

Within a database, base tables and views share the same namespace, so a base table
and a view cannot have the same name.

A VIEW can: be created from many kinds of SELECT statements refer to base tables or
other views use joins, UNION, and subqueries SELECT need not even refer to any
tables

Another Example
The following example defines a view that selects two columns from another table as
well as an expression calculated from those columns:

CREATE TABLE t (qty INT, price INT);


INSERT INTO t VALUES(3, 50);

CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;


SELECT * FROM v;
+------+-------+-------+
| qty | price | value |
+------+-------+-------+
| 3 | 50 | 150 |
+------+-------+-------+
CREATE VIEW suppformat AS SELECT CONCAT(UPPER(supplier_name), ' ', city) FROM
suppliers;

select * from suppformat;

A view from two tables


A view is most useful when it can be used to pull in data from more than one table.
create view v as SELECT product_id, product_name, supplier_name,city FROM
products, suppliers WHERE products.supplier_id = suppliers.supplier_id;

select * from v;

DROPPING A VIEW
-- Create and drop a view in the current database.
CREATE VIEW few_rows_from_t1 AS SELECT * FROM t1 LIMIT 10;
DROP VIEW few_rows_from_t1;

Updating a table via a VIEW


A VIEW acts very much like a table. Although you can UPDATE a table, you may or
may not be able to update a view into that table. In general, if the SELECT in the view
is complex enough to require a temp table, then UPDATE is not allowed.

ALTER VIEW view_name AS SELECT columns FROM table WHERE conditions;

ALTER VIEW v AS SELECT supplier_id, supplier_name, contact_name, city FROM


suppliers WHERE city = 'Kakinada'

Things like GROUP BY, UNION, HAVING, DISTINCT, and some subqueries prevent
the view from being updatable.
Chapter 25: Table Creation
Table creation with Primary Key
CREATE TABLE Person (PersonID INT UNSIGNED NOT NULL,LastName VARCHAR(66)
NOT NULL,FirstName VARCHAR(66),Address VARCHAR(255),City VARCHAR(66),
PRIMARY KEY (PersonID));

A primary key is a NOT NULL single or a multi-column identifier which uniquely


identifies a row of a table. An index is created, and if not explicitly declared as NOT
NULL, MySQL will declare them so silently and implicitly.

A table can have only one PRIMARY KEY, and each table is recommended to have
one. InnoDB will automatically create one in its absence, (as seen in MySQL
documentation) though this is less desirable.

Often, an AUTO_INCREMENT INT also known as "surrogate key", is used for thin
index optimization and relations with other tables. This value will (normally) increase
by 1 whenever a new record is added, starting from a default value of 1.

However, despite its name, it is not its purpose to guarantee that values are
incremental, merely that they are sequential and unique.

An auto-increment INT value will not reset to its default start value if all rows in the
table are deleted, unless the table is truncated using TRUNCATE TABLE statement.

Defining one column as Primary Key (inline definition)


If the primary key consists of a single column, the PRIMARY KEY clause can be
placed inline with the column definition:

CREATE TABLE Person ( PersonID INT UNSIGNED NOT NULL PRIMARY KEY,
LastName VARCHAR(66) NOT NULL, FirstName VARCHAR(66), Address
VARCHAR(255), City VARCHAR(66));

This form of the command is shorter and easier to read.

Defining a multiple-column Primary Key


It is also possible to define a primary key comprising more than one column. This
might be done e.g. on the child table of a foreign-key relationship. A multi-column
primary key is defined by listing the participating columns in a separate PRIMARY
KEY clause. Inline syntax is not permitted here, as only one column may be declared
PRIMARY KEY
inline. For example:

CREATE TABLE Person1 (PersonID INT UNSIGNED NOT NULL,LastName VARCHAR(66)


NOT NULL,FirstName VARCHAR(66),Address VARCHAR(255),City
VARCHAR(66),PRIMARY KEY (PersonID,LastName));
Query OK, 0 rows affected (0.46 sec)

Section 25.2: Basic table creation


The CREATE TABLE statement is used to create a table in a MySQL database.
CREATE TABLE Person (
`PersonID` INTEGER NOT NULL PRIMARY KEY,
`LastName` VARCHAR(80),
`FirstName` VARCHAR(80),
`Address` TEXT,
`City` VARCHAR(100)
) Engine=InnoDB;

Every field definition must have:


1. Field name: A valid field Name. Make sure to encolse the names in `-chars. This
ensures that you can use eg space-chars in the fieldname.

2. Data type [Length]: If the field is CHAR or VARCHAR, it is mandatory to specify a


field length.

3. Attributes NULL | NOT NULL: If NOT NULL is specified, then any attempt to store
a NULL value in that field will fail.

4. See more on data types and their attributes here.


Engine=... is an optional parameter used to specify the table's storage engine. If no
storage engine is specified, the
table will be created using the server's default table storage engine (usually InnoDB or
MyISAM).

Setting defaults
Additionally, where it makes sense you can set a default value for each field by using
DEFAULT:

CREATE TABLE Address (


`AddressID` INTEGER NOT NULL PRIMARY KEY,
`Street` VARCHAR(80),
`City` VARCHAR(80),
`Country` VARCHAR(80) DEFAULT "United States",
`Active` BOOLEAN DEFAULT 1,
);

If during inserts no Street is specified, that field will be NULL when retrieved. When
no Country is specified upon insert, it will default to "United States".

You can set default values for all column types, except for BLOB, TEXT, GEOMETRY,
and JSON fields.

Table creation with Foreign Key


CREATE TABLE Account (
AccountID INT UNSIGNED NOT NULL,
AccountNo INT UNSIGNED NOT NULL,
PersonID INT UNSIGNED,
PRIMARY KEY (AccountID),
FOREIGN KEY (PersonID) REFERENCES Person (PersonID)
);

Foreign key: A Foreign Key (FK) is either a single column, or multi-column composite
of columns, in a referencing table. This FK is confirmed to exist in the referenced
table. It is highly recommended that the referenced table key
confirming the FK be a Primary Key, but that is not enforced. It is used as a fast-
lookup into the referenced where it does not need to be unique, and in fact can be a
left-most index there.
MySQL creating table foreign key example
Syntax:

CREATE TABLE categories(cat_id int not null auto_increment primary key,cat_name


varchar(255) not null, cat_description text);

CREATE TABLE prod(prd_id int not null auto_increment primary key,prd_name


varchar(355) not null, prd_price decimal,cat_id int not null,FOREIGN KEY
fk_cat(cat_id)REFERENCES categories(cat_id) ON UPDATE CASCADE ON DELETE
RESTRICT)

mysql> insert into categories(cat_name,cat_description)values('ram','KKD'),


('sam','VSP'),('sou','CTC'),('sat','NRP');

mysql> insert into prod(prd_name,prd_price,cat_id)values('A_cat',1000.00,2);


Query OK, 1 row affected (0.08 sec)

mysql> insert into prod(prd_name,prd_price,cat_id)values('A_cat',1000.00,3);


Query OK, 1 row affected (0.10 sec)

mysql> insert into prod(prd_name,prd_price,cat_id)values('A_cat',1000.00,4);


Query OK, 1 row affected (0.08 sec)

mysql> insert into prod(prd_name,prd_price,cat_id)values('A_cat',1000.00,1);


Query OK, 1 row affected (0.06 sec)

Adding a foreign key to a table

mysql> update categories set cat_id = 8 where cat_id = 2;


Query OK, 1 row affected (0.08 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> delete from categories where cat_id = 8;


ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint
fails (`world`.`prod`, CONSTRAINT `fk_cat` FOREIGN KEY (`cat_id`) REFERENCES
`categories` (`cat_id`) ON DELETE RESTRICT ON UPDATE CASCADE)
Syntax;

ALTER table_name
ADD CONSTRAINT constraint_name
FOREIGN KEY foreign_key_name(columns)
REFERENCES parent_table(columns)
ON DELETE action
ON UPDATE action;

CREATE TABLE vendors(vdr_id int not null auto_increment primary key, vdr_name
varchar(255));

ALTER TABLE prod ADD COLUMN vdr_id int not null AFTER cat_id;

To add a foreign key to the products table, you use the following statement:
ALTER TABLE prod ADD FOREIGN KEY fk_vendor(vdr_id) REFERENCES vendors(vdr_id)
ON DELETE RESTRICT ON UPDATE CASCADE;

Dropping MySQL foreign key


ALTER TABLE table_name DROP FOREIGN KEY constraint_name;

In the statement above:

 First, you specify the table name from which you want to remove the foreign key.
 Second, you put the constraint name after the DROP FOREIGN KEY clause.

CREATE TABLE prod2 (


prd_id int(11) NOT NULL AUTO_INCREMENT,
prd_name varchar(355) NOT NULL,
prd_price decimal(10,0) DEFAULT NULL,
cat_id int(11) NOT NULL,
vdr_id int(11) NOT NULL,
PRIMARY KEY (prd_id),
KEY fk_cat (cat_id),
KEY fk_vendor(vdr_id),

CONSTRAINT products_ibfk_2
FOREIGN KEY (vdr_id)
REFERENCES vendors (vdr_id)
ON DELETE NO ACTION
ON UPDATE CASCADE,

CONSTRAINT products_ibfk_1
FOREIGN KEY (cat_id)
REFERENCES categories (cat_id)
ON UPDATE CASCADE
);

ALTER TABLE products


DROP FOREIGN KEY products_ibfk_1;

ALTER TABLE products


DROP FOREIGN KEY products_ibfk_2;

Show Table Structure


If you want to see the schema information of your table, you can use one of the
following:
SHOW CREATE TABLE child; -- Option 1
SHOW CREATE TABLE products;

Cloning an existing table


CREATE TABLE ClonedPersons SELECT * FROM Persons;

Table Create With TimeStamp Column To Show Last Update


The TIMESTAMP column will show when the row was last updated.
CREATE TABLE `TestLastUpdate` ( `ID` INT NULL,`Name` VARCHAR(50) NULL,
`Address` VARCHAR(50) NULL,`LastUpdate` TIMESTAMP NULL DEFAULT
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE FROM SELECT
You can create one table from another by adding a SELECT statement at the end of
the CREATE TABLE statement:
CREATE TABLE stack (
id_user INT,
username VARCHAR(30),
password VARCHAR(30)
);

Create a table in the same database:


-- create a table from another table in the same database with all attributes

CREATE TABLE stack2 AS SELECT * FROM stack;


-- create a table from another table in the same database with some attributes
CREATE TABLE stack3 AS SELECT username, password FROM stack;
Create tables from different databases:
-- create a table from another table from another database with all attributes
CREATE TABLE stack2 AS SELECT * FROM second_db.stack;
-- create a table from another table from another database with some attributes
CREATE TABLE stack3 AS SELECT username, password FROM second_db.stack;
Chapter 26: ALTER TABLE
ALTER TABLE stack ADD COLUMN submit date NOT NULL; -- add new column
ALTER TABLE stack DROP COLUMN submit; -- drop column
ALTER TABLE stack MODIFY submit DATETIME NOT NULL; -- modify type column
ALTER TABLE stack CHANGE submit submit_date DATETIME NOT NULL; -- change type and name of column
ALTER TABLE stack ADD COLUMN mod_id INT NOT NULL AFTER id_user; -- add new column after existing
column

Section 26.3: Change auto-increment value


Changing an auto-increment value is useful when you don't want a gap in an AUTO_INCREMENT column
after a massive deletion. For example, you got a lot of unwanted (advertisement) rows posted in your
table, you deleted them, and you want to fix the gap in auto-increment values. Assume the MAX value
of AUTO_INCREMENT column is 100 now. You can use the following to fix the auto-increment value.
ALTER TABLE your_table_name AUTO_INCREMENT = 101;

Section 26.4: Renaming a MySQL table


Renaming a table can be done in a single command:
RENAME TABLE `<old name>` TO `<new name>`;
The following syntax does exactly the same:
ALTER TABLE `<old name>` RENAME TO `<new name>`;
MySQL® Notes for Professionals
84
If renaming a temporary table, the ALTER TABLE version of the syntax must be used.
Steps:
1. Replace <old name> and <new name> in the line above with the relevant values. Note: If the table is
being
moved to a different database, the dbname.tablename syntax can be used for <old name> and/or <new
name>.
2. Execute it on the relevant database in the MySQL command line or a client such as MySQL
Workbench. Note:
The user must have ALTER and DROP privileges on the old table and CREATE and INSERT on the new
one.
Section 26.5: ALTER table add INDEX
To improve performance one might want to add indexes to columns
ALTER TABLE TABLE_NAME ADD INDEX `index_name` (`column_name`)
altering to add composite (multiple column) indexes
ALTER TABLE TABLE_NAME ADD INDEX `index_name` (`col1`,`col2`)

Section 26.6: Changing the type of a primary key


column
ALTER TABLE fish_data.fish DROP PRIMARY KEY;
ALTER TABLE fish_data.fish MODIFY COLUMN fish_id DECIMAL(20,0) NOT NULL PRIMARY KEY;
An attempt to modify the type of this column without first dropping the primary key would result in an
error.
Section 26.7: Change column definition
The change the definition of a db column, the query below can be used for example, if we have this db
schema
create table users (firstname varchar(20),lastname varchar(20),age char(2))

To change the type of age column from char to int, we use the query below:

ALTER TABLE users CHANGE age ages tinyint UNSIGNED NOT NULL;

General format is:


ALTER TABLE table_name CHANGE column_name new_column_definition

Section 26.10: Renaming a column in a MySQL


table
Renaming a column can be done in a single statement but as well as the new name, the "column
definition" (i.e. its
data type and other optional properties such as nullability, auto incrementing etc.) must also be
specified.
ALTER TABLE `<table name>` CHANGE `<old name>` `<new name>` <column definition>;
Steps:
1. Open the MySQL command line or a client such as MySQL Workbench.
2. Run the following statement: SHOW CREATE TABLE <table name>; (replacing <table name> with the
relevant
value).
3. Make a note of the entire column definition for the column to be renamed (i.e. everything that
appears after
the name of the column but before the comma separating it from the next column name).
4. Replace <old name>, <new name> and <column definition> in the line above with the relevant values
and
then execute it.
Chapter 27: Drop Table
Parameters Details
TEMPORARY Optional. It specifies that only temporary tables should be dropped by the DROP TABLE
statement.
IF EXISTS Optional. If specified, the DROP TABLE statement will not raise an error if one of the tables
does not
exist.
Section 27.1: Drop Table
Drop Table is used to delete the table from database.
Creating Table:
Creating a table named tbl and then deleting the created table
CREATE TABLE tbl(
id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(100) NOT NULL,
author VARCHAR(40) NOT NULL,
submission_date DATE,
PRIMARY KEY (id)
);
Dropping Table:
DROP TABLE tbl;
PLEASE NOTE
Dropping table will completely delete the table from the database and all its information, and it will not
be recovered.
Section 27.2: Drop tables from database
DROP TABLE Database.table_name
Chapter 28: MySQL LOCK TABLE
A lock is a flag associated with a table. MySQL allows a client session to explicitly
acquire a table lock for preventing other sessions from accessing the same table
during a specific period. A client session can acquire or release table locks only for
itself. It cannot acquire or release table locks for other sessions.
Before going into detail, we create a table named tbl for practicing the table locking
statements.

drop table tb;


CREATE TABLE tbl (id INT NOT NULL AUTO_INCREMENT,col INT NOT NULL, PRIMARY
KEY (id));

LOCK and UNLOCK TABLES syntax

The following statement explicitly acquires a table lock:


LOCK TABLES table_name [READ | WRITE]

To lock a table, you specify its name after the LOCK TABLES keywords. In addition,
you specify the type of lock, either READ or WRITE.
To release a lock for a table, you use the following statement:
UNLOCK TABLES;

Read Locks
A READ lock has the following features:
 A READ lock for a table can be acquired by multiple sessions at the same time.
In addition, other sessions can read data from the table without acquiring the
lock.
 The session that holds the READ lock can only read data from the table, but
cannot write. In addition, other sessions cannot write data to the table until
the READ lock is released. The write operations from another session will be put
into the waiting states until the READ lock is released.
 If the session is terminated, either normally or abnormally, MySQL will release
all the locks implicitly. This feature is also relevant for the WRITE lock.

Let’s take a look at how the READ lock works in the following scenario.
In the first session, first, connect to the sampledb database and use
the CONNECTION_ID() function to get the current connection id as follows:

SELECT CONNECTION_ID();

Then, insert a new row into the tbl table.


INSERT INTO tbl(col) VALUES(10);
Next, query the data the tbl table.
SELECT * FROM tbl;
After that, to acquire a lock, you use the LOCK TABLE statement.
LOCK TABLE tbl READ;
Finally, in the same session, if you try to insert a new row into the tbl table, you will
get an error message.
mysql> INSERT INTO tbl(col) VALUES(11);
ERROR 1099 (HY000): Table 'tbl' was locked with a READ lock and can't be updated
So the once READ lock is acquired, you cannot write data into the table within the
same session.
Write Locks
A WRITE lock has the following features:

 The only session that holds the lock of a table can read and write data from the
table.
 Other sessions cannot read data from and write data to the table until
the WRITE lock is released.

Let’s go into detail to see how the WRITE lock works.


First, acquire a WRITE lock from the first session.

LOCK TABLE tbl WRITE;

Then, insert a new row into the tbl table.

LOCK TABLE tbl WRITE;

Its working.
Next, read data from the tbl table.

SELECT * FROM tbl;


INSERT INTO tbl(col) VALUES(21);
SELECT * FROM tbl

MySQL puts these operations into a waiting state. You can check it using the SHOW
PROCESSLIST statement.

SHOW PROCESSLIST
UNLOCK TABLES;
You will see all pending operations from the second session executed and the
following picture illustrates the result:
Chapter 30: Stored routines (procedures
and functions)
A stored procedure is a segment of declarative SQL statements stored inside the
database catalog. A stored procedure can be invoked by triggers, other stored
procedures, and applications such as Java, Python, PHP.

A stored procedure that calls itself is known as a recursive stored procedure. Most
database management systems support recursive stored procedures. However,
MySQL does not support it very well. You should check your version of MySQL
database before implementing recursive stored procedures in MySQL.

Stored Procedures in MySQL

MySQL is known as the most popular open source RDBMS which is widely used by
both community and enterprise. However, during the first decade of its existence, it
did not support stored procedures, stored functions, triggers, and events. Since
MySQL version 5.0, those features were added to the MySQL database engine to make
it more flexible and powerful.

MySQL stored procedures advantages

 Typically, stored procedures help increase the performance of the applications.


Once created, stored procedures are compiled and stored in the database.
However, MySQL implements the stored procedures slightly different. MySQL
stored procedures are compiled on demand. After compiling a stored procedure,
MySQL puts it into a cache and maintains its own stored procedure cache for
every single connection. If an application uses a stored procedure multiple times
in a single connection, the compiled version is used, otherwise, the stored
procedure works like a query.
 Stored procedures help reduce the traffic between application and database
server because instead of sending multiple lengthy SQL statements, the
application has to send only the name and parameters of the stored procedure.
 Stored procedures are reusable and transparent to any applications. Stored
procedures expose the database interface to all applications so that developers
do not have to develop functions that are already supported in stored procedures.

Introduction to MySQL stored procedure parameters

Almost stored procedures that you develop require parameters. The parameters make
the stored procedure more flexible and useful. In MySQL, a parameter has one of
three modes: IN,OUT, or INOUT.

IN – is the default mode. When you define an IN parameter in a stored procedure, the
calling program has to pass an argument to the stored procedure. In addition, the
value of an IN parameter is protected. It means that even the value of
the IN parameter is changed inside the stored procedure, its original value is retained
after the stored procedure ends. In other words, the stored procedure only works on
the copy of the IN parameter.
The IN parameter example
DELIMITER //
CREATE PROCEDURE Getitem2(IN sup_id int)
BEGIN
SELECT * FROM items WHERE supplier_id = sup_id;
END //
DELIMITER ;

call Getitem1(101);

About the DELIMITER Command

In the above example, we added a couple of DELIMITER commands and we replaced a


semicolon with two forward slashes. What's going on here?

We did this to tell MySQL to use a different delimiter while it creates our stored
procedure.

The reason for this is that, MySQL already recognizes the semicolon as a delimiter for
marking the end of each SQL statement. Therefore, as soon as MySQL sees the first
semicolon, it will interpret the delimiter as such and our stored procedure would
break.
The DELIMITER command allows us to tell MySQL to use a different delimiter. In the
above example we set this to two forward slashes (//) but this could've been anything
(although, avoid using a backslash (\) as that is the escape character for MySQL). By
changing the delimiter, MySQL won't try to interpret our semicolons as the end of the
statement — it will wait until it sees the two forward slashes.

Once we've created the stored procedure, we can use DELIMITER ; to reset the
delimiter back to the semicolon.

OUT – the value of an OUT parameter can be changed inside the stored procedure and
its new value is passed back to the calling program. Notice that the stored procedure
cannot access the initial value of the OUT parameter when it starts.

The OUT parameter example

The following stored procedure returns the number of orders by order status. It has
two parameters:
 i_name : the IN parameter that is to read item_name from the items tabless.
 total : the OUT parameter that stores the number of items int items table.

DELIMITER $$
CREATE PROCEDURE itemCount1(IN i_name VARCHAR(25), OUT total INT)
BEGIN
SELECT count(item_name) INTO total FROM items WHERE item_name = i_name;
END$$
DELIMITER ;

call itemCount1('Keyboard',@total);

select @total;
INOUT – an INOUT parameter is a combination of IN and OUT parameters. It means
that the calling program may pass the argument, and the stored procedure can
modify the INOUT parameter, and pass the new value back to the calling program.

The INOUT parameter example


The following example demonstrates how to use an INOUT parameter in the stored
procedure.

DELIMITER //
CREATE PROCEDURE set_counter3(INOUT count INT(4),IN inc INT(4))
BEGIN
SET count = count + inc;
END$$;
DELIMITER;

mysql> DELIMITER ;
mysql> SET @counter = 1;
Query OK, 0 rows affected (0.00 sec)

mysql> CALL set_counter(@counter,1);


Query OK, 0 rows affected (0.00 sec)

mysql> CALL set_counter(@counter,1);


Query OK, 0 rows affected (0.00 sec)

mysql> CALL set_counter(@counter,5);


Query OK, 0 rows affected (0.00 sec)

mysql> select @counter;


+----------+
| @counter |
+----------+
| 8|
+----------+
1 row in set (0.00 sec)

Procedure with joins:


DELIMITER //
CREATE PROCEDURE spcheck(sup_id smallint)
begin
select items.item_name,items.qty,products.supplier_id from items inner join products
on items.supplier_id = products.supplier_id where products.supplier_id = sup_id;
end //
DELIMITER ;

CALL spcheck(101);

MySQL Loop in Stored Procedures


WHILE loop

The syntax of the WHILEstatement is as follows:


WHILE expression DO
statements
END WHILE

The WHILE loop checks the expression at the beginning of each iteration. If the
expression valuates to TRUE, MySQL will execute statements between WHILE and END
WHILE until the expression evaluates to FALSE. The WHILE loop is called pretest loop
because it checks the expression before the statements execute.

DELIMITER $$
DROP PROCEDURE IF EXISTS test_mysql_while_loop$$
CREATE PROCEDURE test_mysql_while_loop()
BEGIN
DECLARE x INT;
DECLARE str VARCHAR(255);

SET x = 1;
SET str = '';

WHILE x <= 5 DO
SET str = CONCAT(str,x,',');
SET x = x + 1;
END WHILE;

SELECT str;
END$$
DELIMITER ;

In the test_mysql_while_loopstored procedure above:

First, we build str string repeatedly until the value of the x variable is greater than 5.
Then, we display the final string using the SELECT statement.
Notice that if we don’t initialize the xvariable, its default value is NULL. Therefore, the
condition in the WHILEloop statement is always TRUE and you will have an indefinite
loop, which is not expected.

Let’s test the test_mysql_while_loopstored procedure:

CALL test_mysql_while_loop();

REPEAT loop
The syntax of the REPEAT loop statement is as follows:

REPEAT
statements;
UNTIL expression
END REPEAT

First, MySQL executes the statements, and then it evaluates the expression. If the
expression valuates to FALSE, MySQL executes the statements repeatedly until the
expression evaluates to TRUE.

Because the REPEAT loop statement checks the expression after the execution of
statements, the REPEAT loop statement is also known as the post-test loop.

The following flowchart illustrates the REPEAT loop statement:

We can rewrite the test_mysql_while_loopstored procedure that uses WHILE loop


statement above using the REPEAT loop statement:

DELIMITER $$
DROP PROCEDURE IF EXISTS mysql_test_repeat_loop$$
CREATE PROCEDURE mysql_test_repeat_loop()
BEGIN
DECLARE x INT;
DECLARE str VARCHAR(255);

SET x = 1;
SET str = '';

REPEAT
SET str = CONCAT(str,x,',');
SET x = x + 1;
UNTIL x > 5
END REPEAT;

SELECT str;
END$$
DELIMITER ;

CALL mysql_test_repeat_loop();

DROP PROCEDURE
Syntax
DROP PROCEDURE [IF EXISTS] sp_name

DROP PROCEDURE IF EXISTS set_counter;

Section 30.2: Create a Function


In MySQL, a function is a stored program that you can pass parameters into and then
return a value.

The syntax to create a function in MySQL is:


CREATE FUNCTION function_name [ (parameter datatype [, parameter datatype]) ]
RETURNS return_datatype

BEGIN
declaration_section
executable_section
END;

mysql> CREATE FUNCTION sample_fn_no_param ()


-> RETURNS INT
-> BEGIN
-> DECLARE count INT;
-> SELECT COUNT(*) INTO count FROM items;
-> RETURN count;
-> END
-> |
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS
SQL DATA in its declaration and binary logging is enabled (you *might* want to use
the less safe log_bin_trust_function_creators variable)
While running this function we will get this error. To fix this error
SET GLOBAL log_bin_trust_function_creators = 1;

DELIMITER |

CREATE FUNCTION sample_fn_no_param ()


RETURNS INT
BEGIN
DECLARE count INT;
SELECT COUNT(*) INTO count FROM items;
RETURN count;
END
|
DELIMITER ;

Execute and Verify Commands


select sample_fn_no_param ();

A Stored Function that Accept Parameters


DELIMITER |

CREATE FUNCTION sample_fn_with_params (itm_id INT UNSIGNED, newitem


VARCHAR(20))
RETURNS VARCHAR(20)

BEGIN
DECLARE olditem VARCHAR(20);
SELECT item_name into olditem FROM items where item_id = itm_Id;
UPDATE items SET item_name = newitem where item_id = itm_Id;
RETURN olditem;
END
|
DELIMITER ;

Execute and Verify Commands


select sample_fn_with_params(308,'Hardisk');
Basic MySQL CREATE FUNCTION statement
A very basic CREATE FUNCTION example which will produced the famed 'Hello World'
output:
DELIMITER $$
CREATE FUNCTION hello_world()
RETURNS TEXT
LANGUAGE SQL
BEGIN
RETURN 'Hello World';
END;
$$
DELIMITER ;

Execute this function as follows:


mysql> SELECT hello_world();

MySQL function with a parameter


Customize your 'Hello World' output with input from a parameter:
DROP FUNCTION IF EXISTS hello_world;
DELIMITER $$
CREATE FUNCTION hello_world(addressee TEXT)
RETURNS TEXT
LANGUAGE SQL -- This element is optional and will be omitted from subsequent
examples
BEGIN
RETURN CONCAT('Hello ', addressee);
END;
$$
DELIMITER ;

Execute as follows:
mysql> SELECT hello_world('Earth');

MySQL function with a local variable


Use a local variable to perform calculations inside your function:
DROP FUNCTION IF EXISTS hello_world;
DELIMITER $$
CREATE FUNCTION hello_world(addressee TEXT)
RETURNS TEXT
BEGIN
DECLARE strlen INT;
SET strlen = LENGTH(addressee);
RETURN CONCAT('Hello ', addressee, ' - your parameter has ', strlen, ' characters');
END;
$$
DELIMITER ;

Output:
SELECT hello_world('Earth');

MySQL function with a loop


DROP FUNCTION IF EXISTS looptest;
DELIMITER $$
CREATE FUNCTION looptest()
RETURNS INT READS SQL DATA
BEGIN
DECLARE v_total INT;

SET v_total = 0;

count_loop: LOOP
SET v_total = v_total + 1;

IF v_total = 10 THEN
LEAVE count_loop;
END IF;

END LOOP;

RETURN v_total;
END;
$$
DELIMITER ;

Output:
select looptest();

Section 30.3: Cursors

Introduction to MySQL cursor

Introduction to MySQL cursor. To handle a result set inside a stored procedure, you
use a cursor. A cursor allows you to iterate a set of rows returned by a query and
process each row accordingly. MySQL cursor is read-only, non-scrollable and a
sensitive.

MySQL cursor is read-only, non-scrollable and asensitive.


 Read-only: you cannot update data in the underlying table through the cursor.
 Non-scrollable: you can only fetch rows in the order determined by
the SELECT statement. You cannot fetch rows in the reversed order. In addition,
you cannot skip rows or jump to a specific row in the result set.
 Asensitive: there are two kinds of cursors: asensitive cursor and insensitive
cursor. An asensitive cursor points to the actual data, whereas an insensitive
cursor uses a temporary copy of the data. An asensitive cursor performs faster
than an insensitive cursor because it does not have to make a temporary copy of
data. However, any change that made to the data from other connections will
affect the data that is being used by an asensitive cursor, therefore, it is safer if
you do not update the data that is being used by an asensitive cursor. MySQL
cursor is asensitive.
You can use MySQL cursors in stored procedures, stored functions, and triggers.

Syntax
The syntax to declare a cursor in MySQL is:

DECLARE cursor_name CURSOR FOR


select_statement;

Parameters or Arguments
cursor_name
The name to assign to the cursor.
select_statement
The SELECT statement associated with the cursor.
Example:
DECLARE c1 CURSOR FOR
SELECT item_id FROM items WHERE item_name = name_in;

DELIMITER //

CREATE FUNCTION FindSiteID ( name_in VARCHAR(50) )


RETURNS INT

BEGIN

DECLARE done INT DEFAULT FALSE;


DECLARE itemID INT DEFAULT 0;

DECLARE c1 CURSOR FOR


SELECT item_id FROM items WHERE item_name = name_in;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

OPEN c1;
FETCH c1 INTO itemID;

CLOSE c1;

RETURN itemID;

END; //

DELIMITER ;

SELECT FindSiteID ('Keyboard');


Chapter 31: Indexes and Keys
Create index
-- Create an index for column 'name' in table 'my_table'
CREATE INDEX idx_name ON my_table(name);

CREATE TABLE t(c1 INT PRIMARY KEY, c2 INT NOT NULL,c3 INT NOT NULL, c4
VARCHAR(10), INDEX (c2,c3));

To add an index for a column or a set of columns, you use the CREATE
INDEX statement as follows:

CREATE INDEX index_name ON table_name (column_list)

To create an index for a column or a list of columns, you specify the index name, the
table to which the index belongs, and the column list.

For example, to add a new index for the column c4, you use the following statement:

CREATE INDEX idx_c4 ON t(c4);

Create unique index


A unique index prevents the insertion of duplicated data in a table. NULL values can
be inserted in the columns that form part of the unique index (since, by definition, a
NULL value is different from any other value, including another NULL value)

-- Creates a unique index for column 'name' in table 'my_table'


CREATE UNIQUE INDEX idx_name ON my_table(name);
create unique index idx_name ON items(item_id);

Create composite index


This will create a composite index of both keys, mystring and mydatetime and speed
up queries with both columns in the WHERE clause.

CREATE INDEX idx_mycol_myothercol ON my_table(mycol, myothercol)

create index idx_mycol on orders(order_id,supplier_id);

Drop index
-- Drop an index for column 'name' in table 'my_table'
DROP INDEX idx_name ON my_table;

drop index idx_mycol on orders;


Chapter 32: Full-Text search
MySQL supports text searching by using the LIKE operator and regular expression.
However, when the text column is large and the number of rows in a table is
increased, using these methods has some limitations:

 Performance: MySQL has to scan the whole table to find the exact text based on a
pattern in the LIKE statement or pattern in the regular expressions.
 Flexible search: with the LIKE operator and regular expression searches, it is
difficult to have a flexible search query e.g., to find product whose description
contains car but not classic.
 Relevance ranking: there is no way to specify which row in the result set is
more relevant to the search terms.
Because of these limitations, MySQL extended a very nice feature so-called full-text
search. Technically, MySQL creates an index from the words of the enabled full-text
search columns and performs searches on this index. MySQL uses a sophisticated
algorithm to determine the rows matched against the search query.

Defining FULLTEXT index using CREATE TABLE statement

Typically, you define the FULLTEXT index for a column when you create a new table
using the CREATE TABLE statement as follows:

CREATE TABLE table_name(


column1 data_type,
column2 data_type,
column3 data_type,

PRIMARY_KEY(key_column),
FULLTEXT (column1,column2,..)
);

To create the FULLTEXT index, you place a list of comma-separated columns in


parentheses after the FULLTEXT keyword.
The following statement creates a new table named posts that has a FULLTEXT index
that includes the post_content column.

CREATE TABLE posts (id int(4) NOT NULL AUTO_INCREMENT, title varchar(255) NOT
NULL,post_content text, PRIMARY KEY (id), FULLTEXT KEY post_content
(post_content));

Defining FULLTEXT index for existing tables

In case you already have existing tables and want to define full-text indexes, you can
use the ALTER TABLE statement or CREATE INDEX statement.

Defining FULLTEXT index using ALTER TABLE statement

The following syntax defines a FULLTEXT index using the ALTER TABLE statement:
ALTER TABLE table_name ADD FULLTEXT(column_name1, column_name2,…)

In this syntax, you put the table_name and the ADD FULLTEXT clause that defines
a FULLTEXT index for one or more columns.
For example, you can define a FULLTEXT index for the product_name column in
the products table as follows:
ALTER TABLE products ADD FULLTEXT(product_name);

Defining FULLTEXT index using CREATE INDEX statement


We can also use the CREATE INDEX statement to create a FULLTEXT index for existing
tables. See the following syntax:

CREATE FULLTEXT INDEX index_name


ON table_name(idx_column_name,...)

The following statement creates a FULLTEXT index for the post_content column of
the posts table.

CREATE FULLTEXT INDEX ords ON posts(post_content);

Notice that for a table which has many rows, it is faster to load the data into the table
that has no FULLTEXT index first and then create the FULLTEXT index, than loading a
large amount of data into a table that has an existing FULLTEXT index.

Removing full-text search columns

To remove a FULLTEXT index, you just delete the index using the ALTER TABLE …
DROP INDEX statement. For example, the following statement removes
the address FULLTEXT index in the offices table:

ALTER TABLE posts DROP INDEX ord;


Chapter 33: PREPARE Statements
Introduction to MySQL Prepared Statement

Prior MySQL version 4.1, the query is sent to the MySQL server in the textual format.
In turn, MySQL returns the data to the client using textual protocol. MySQL has
to fully parse the query and transforms the result set into a string before returning it
to the client.

The textual protocol has serious performance implication. To resolve this problem,
MySQL added a new feature called prepared statement since version 4.1.

The prepared statement takes advantage of client/server binary protocol. It passes


query that contains placeholders (?) to the MySQL server as the following example:

SELECT product_id, product_name FROM products WHERE product_id = ?

When MySQL executes this query with different productcode values, it does not have
to parse the query fully. As a result, this helps MySQL execute the query faster,
especially when MySQL executes the query multiple times. Because the prepared
statement uses placeholders (?), this helps avoid many variants of SQL injection
hence make your application more secure.

MySQL prepared statement usage

In order to use MySQL prepared statement, you need to use other three MySQL
statements as follows:

 PREPARE – Prepares statement for execution.


 EXECUTE – Executes a prepared statement preparing by a PREPARE statement.
 DEALLOCATE PREPARE – Releases a prepared statement.
The following diagram illustrates how to use the prepared statement:

MySQL prepared statement example

Let’s take a look at an example of using the MySQL prepared statement.

PREPARE stmt1 FROM 'SELECT product_id, product_name FROM products WHERE


product_id = ?';

SET @pc = 401 ;


EXECUTE stmt1 USING @pc;

DEALLOCATE PREPARE stmt1;


First, we used the PREPARE statement to prepare a statement for execution. We used
the SELECT statement to query product data from the products table based on a
specified product code. We used a question mark (?) as a placeholder for the product
code.
Next, we declared a product code variable @pc and set it values to S10_1678.
Then, we used the EXECUTE statement to execute the prepared statement with the
product code variable @pc.
Finally, we used the DEALLOCATE PREPARE to release the prepared statement.

Prepared statements in a stored procedure

create table students(id int, Name varchar(40));

DELIMITER $$
create procedure tbl_del6(tab_name varchar(40))
BEGIN
SET @A:= CONCAT('Select * from',' ',tab_name);
prepare stmt FROM @A;
EXECUTE stmt;
END $$
DELIMITER;

Calling procedures
CALL tbl_del4('students');

Output:
mysql> CALL tbl_del4('students');
+------+------+
| Id | Name |
+------+------+
| 1 | Sow |
| 2 | Ram |
| 3 | Sat |
+------+------+
3 rows in set (0.02 sec)
Chapter 34: MySQL Admin
Section 36.1: Atomic RENAME & Table Reload
RENAME TABLE t TO t_old, t_copy TO t;
No other sessions can access the tables involved while RENAME TABLE executes, so the rename
operation is not subject to concurrency problems.

Atomic Rename is especially for completely reloading a table without waiting for DELETE and load to
finish:
CREATE TABLE new LIKE real;
load `new` by whatever means - LOAD DATA, INSERT, whatever
RENAME TABLE real TO old, new TO real;
DROP TABLE old;

Section 36.2: Change root password


mysqladmin -u root -p'old-password' password 'new-password'

Section 36.3: Drop database


Useful for scripting to drop all tables and deletes the database:
mysqladmin -u[username] -p[password] drop [database]
Use with extreme caution.
To DROP database as a SQL Script (you will need DROP privilege on that database):
DROP DATABASE database_name
or
DROP SCHEMA database_name
Chapter 35: TRIGGERS
The MySQL trigger is a database object that is associated with a table. It will be
activated when a defined action is executed for the table. The trigger can be executed
when you run one of the following MySQL statements on the table: INSERT, UPDATE
and DELETE and it can be invoked before or after the event.

Mysql Trigger after Update


Mysql Trigger after Update fired automatically after we perform an update query on
table.
Understand with Example
The Tutorial understand an example from 'Mysql Trigger after Update'. To grasp
'Mysql Trigger after Update', we create a table 'Employee' with field attribute and
data type respectively.
Create table:-
drop table Employee
CREATE TABLE Employee(id int, first_name VARCHAR(30), last_name VARCHAR(15),
start_date DATE, end_date DATE, city VARCHAR(10),description VARCHAR(15));

Insert data into table:-


The insert into insert the records or rows into table 'Employee'.
insert into Employee values (01,'Girish','Tewari','20081225',
'20100625','Nainital','Programmer');

insert into Employee values


(02,'Komal','Choudhry','20071122', '20100421','Meerut','Programmer');

insert into Employee values


(03,'Mahendra','Singh','20061012', '20070512','Lucknow','Programmer');

View table:-
select * from employee;

Create table:-
Now Create another table 'Employee_log' with field name and data type respectively.
CREATE TABLE Employee_log(user_id VARCHAR(15), description VARCHAR(100));

View table:-
select * from employee_log;

Create Trigger:-
The Create Trigger create a Employee_Trigger on table 'employee'. The Trigger
'Employee_Trigger' fired automatically after update operation is performed on table
'employee'. Further,the update records is inserted on table 'Employee_log'.

delimiter $$
CREATE TRIGGER Employee_Trigger
AFTER UPDATE ON employee
FOR EACH ROW
BEGIN
INSERT into Employee_log
(user_id, description)VALUES (user(),
CONCAT('Id with ',NEW.id,' is modified ',
' from ',OLD.start_date, ' to ', NEW.start_date));
END$$
delimiter ;

Query to update employee table:-


update employee set start_date='20061231';

Table that has been modified after update query executes is Employee_log:-
Query to view Employee_log table:-
select * from Employee_log;

+----------------+------------------------------------------------------+
| user_id | description |
+----------------+------------------------------------------------------+
| root@localhost | Id with 1 is modified from 2008-12-25 to 2006-12-31 |
| root@localhost | Id with 2 is modified from 2007-11-22 to 2006-12-31 |
| root@localhost | Id with 3 is modified from 2006-10-12 to 2006-12-31 |
+----------------+------------------------------------------------------+

Mysql Trigger After Delete


Trigger in Mysql fired trigger automatically after you perform Delete Operation on
Table.

Mysql Trigger After Delete

Trigger in Mysql fired trigger automatically after you perform Delete Operation on
Table.

Understand with Example


The Tutorial illustrate an example from 'Trigger After Delete' in Mysql. To understand
this example, we create a table 'Employee'. The create table'employee' is created
with different field name and data type respectively.

Create table:-
drop table Employee;
CREATE TABLE Employee(id int, first_name VARCHAR(30), last_name VARCHAR(15),
start_date DATE, end_date DATE, city VARCHAR(10), description VARCHAR(15));

Insert data into table:-


The insert into add the records or rows into the table 'Employee'
insert into Employee values (01,'Girish','Tewari','20081225',
'20100625','Nainital','Programmer');

insert into Employee values (02,'Komal','Choudhry','20071122',


'20100421','Meerut','Programmer');
insert into Employee values (03,'Mahendra','Singh','20061012',
'20070512','Lucknow','Programmer');

insert into employee values


(4,'Amit','Kumar','20081225','20101203','Lucknow','Programmer');

View table:-
To view table employee, we use select keyword that show you the entire records
from table 'employee'.
select * from employee;

Create table:-
Now we include another table 'Employee_log'. The create tableconstruct another
table Employee_log.
drop table Employee_log;
CREATE TABLE Employee_log(id int, first_name varchar(50), last_name varchar(50),
start_date date, end_date date, city varchar(50),description varchar(50),Lasinserted
Time);

View table:-
Again, we use same select Query to return the records from a table employee_log.
select * from employee_log;

Create Trigger:-
Drop Trigger is used to delete trigger Employee_Trigger from database, in case if
there is any trigger existing on this name. The 'Employee_Triger' fired trigger after
you perform a delete operation on table 'employee'. The deleted records from table
'employee' copy into a table 'employee_log'.
drop trigger if exists Employee_Trigger;
delimiter $$
CREATE TRIGGER Employee_Trigger
AFTER delete ON employee
FOR EACH ROW
BEGIN
insert into employee_log values(old.id,old.first_name,
old.last_name,old.start_date,old.end_date,
old.city,old.description,curtime());
END$$
delimiter ;

Query to delete record from employee table:-


We run a delete query in table employee where id is '4'.
delete from employee where id =4;

Table that has been modified after delete query executes is Employee_log:-
Query to view Employee_log table:-
select * from employee_log;

Mysql Trigger After Insert


Mysql Trigger After Insert fired the trigger after you perform an insert a records or
rows to the table.

Understand with Example

The Tutorial illustrate an example from Mysql Trigger After Insert. To understand this,
we create a table 'Employee'. The create table is used to construct a table 'Employee'.

Create table:-
drop table Employee;
CREATE TABLE Employee(id int, first_name VARCHAR(30),last_name
VARCHAR(15),start_date DATE, end_date DATE, city VARCHAR(10), description
VARCHAR(15));

Insert data into table:-

Insert into add the records or rows into a table 'Employee'.

insert into Employee values(01,'Girish','Tewari','20081225',


'20100625','Nainital','Programmer');

insert into Employee values (02,'Komal','Choudhry','20071122',


'20100421','Meerut','Programmer');

insert into Employee values (03,'Mahendra','Singh','20061012',


'20070512','Lucknow','Programmer');

View table:-

To view a table employee we use select query that return the records from a table
'employee'.

select * from employee;

Create table:-
The create table construct a table Employee_log.
drop table Employee_log;
CREATE TABLE Employee_log(id int,first_name varchar(50),last_name varchar(50),
start_date date,end_date date,city varchar(50),description varchar(50),Lasinserted
Time);

View table:-
select * from employee_log;

Create Trigger:-

The Create Trigger create a trigger 'Employee_Trigger' on table 'employee'. The 'After
insert trigger' fired the trigger after you performed a insert operation on table.

delimiter $$
CREATE TRIGGER Employee_Trigger
AFTER insert ON employee
FOR EACH ROW
BEGIN
insert into employee_log values(new.id,new.first_name,
new.last_name,new.start_date,new.end_date,
new.city,new.description,curtime());
END$$
delimiter ;

The insert into add the records or rows into the table 'employee'.
insert into employee values
(4,'Amit','Kumar','20081225','20101203','Lucknow','Programmer');

Table that has been modified after update query executes is Employee_log:-
select * from employee_log;

Before Insert trigger example:


create table people(age int,name varchar(40));

delimiter //
CREATE TRIGGER agecheck BEFORE INSERT ON people FOR EACH ROW IF NEW.age <
0 THEN SET NEW.age = 0; END IF;//
delimiter ;

INSERT INTO people VALUES(-20,'Sid'),(30, 'Josh');

select * from people;

BEFORE UPDATE Trigger


This MySQL tutorial explains how to create a BEFORE UPDATE Trigger in MySQL with
syntax and examples.

Description
A BEFORE UPDATE Trigger means that MySQL will fire this trigger before the UPDATE
operation is executed.

Syntax
The syntax to create a BEFORE UPDATE Trigger in MySQL is:

CREATE TRIGGER trigger_name


BEFORE UPDATE
ON table_name FOR EACH ROW

BEGIN

-- variable declarations

-- trigger code

END;

Parameters or Arguments
trigger_name : The name of the trigger to create.
BEFORE UPDATE : It indicates that the trigger will fire before the UPDATE operation
is executed.
table_name: The name of the table that the trigger is created on.

Restrictions
You can not create a BEFORE trigger on a view.
You can update the NEW values.
You can not update the OLD values.

Note
See also how to create AFTER DELETE, AFTER INSERT, AFTER UPDATE, BEFORE
DELETE, and BEFORE INSERT triggers.

Example
Let's look at an example of how to create an BEFORE UPDATE trigger using the
CREATE TRIGGER statement in MySQL.

If you had a table created as follows:

CREATE TABLE contacts


( contact_id INT(11) NOT NULL AUTO_INCREMENT,
last_name VARCHAR(30) NOT NULL,
first_name VARCHAR(25),
birthday DATE,
created_date DATE,
created_by VARCHAR(30),
CONSTRAINT contacts_pk PRIMARY KEY (contact_id)
);

insert into
contacts(last_name,first_name,birthday,created_date,created_by)values('M','sou','198
61002','19801014','Kamesh');

create table contacts_audit(contact_id int,updated_date date,updated_by


varchar(40));

We could then use the CREATE TRIGGER statement to create an BEFORE UPDATE
trigger as follows:

DELIMITER //

CREATE TRIGGER contacts_before_update


BEFORE UPDATE
ON contacts FOR EACH ROW

BEGIN

DECLARE vUser varchar(50);

-- Find username of person performing the INSERT into table


SELECT USER() INTO vUser;

-- Insert record into audit table


INSERT INTO contacts_audit( contact_id,
updated_date,updated_by)VALUES(NEW.contact_id,SYSDATE(),vUser );
END; //

DELIMITER ;
update contacts set last_name = 'N' where last_name = 'M';

BEFORE DELETE Trigger


This MySQL tutorial explains how to create a BEFORE DELETE Trigger in MySQL with
syntax and examples.

Description
A BEFORE DELETE Trigger means that MySQL will fire this trigger before the DELETE
operation is executed.

Syntax
The syntax to create a BEFORE DELETE Trigger in MySQL is:

CREATE TRIGGER trigger_name


BEFORE DELETE
ON table_name FOR EACH ROW

BEGIN

-- variable declarations

-- trigger code

END;
Parameters or Arguments
trigger_name : The name of the trigger to create.
BEFORE DELETE: It ndicates that the trigger will fire before the DELETE operation is
executed.
table_name: The name of the table that the trigger is created on.
Restrictions
You can not create a BEFORE trigger on a view.
You can update the NEW values.
You can not update the OLD values.

Note
See also how to create AFTER DELETE, AFTER INSERT, AFTER UPDATE, BEFORE
INSERT, and BEFORE UPDATE triggers.

Example
Let's look at an example of how to create an BEFORE DELETE trigger using the
CREATE TRIGGER statement in MySQL.

If you had a table created as follows:

CREATE TABLE contacts


( contact_id INT(11) NOT NULL AUTO_INCREMENT,
last_name VARCHAR(30) NOT NULL,
first_name VARCHAR(25),
birthday DATE,
created_date DATE,
created_by VARCHAR(30),
CONSTRAINT contacts_pk PRIMARY KEY (contact_id)
);

We could then use the CREATE TRIGGER statement to create an BEFORE DELETE
trigger as follows:

DELIMITER //

CREATE TRIGGER contacts_before_delete BEFORE DELETE ON contacts FOR EACH


ROW

BEGIN

DECLARE vUser varchar(50);

-- Find username of person performing the DELETE into table


SELECT USER() INTO vUser;

-- Insert record into audit table


INSERT INTO contacts_audit ( contact_id, deleted_date, deleted_by) VALUES
( OLD.contact_id, SYSDATE(), vUser );

END; //

DELIMITER ;
Chapter 36: Events
Working with MySQL Scheduled Event
A MySQL event is a task that runs based on a predefined schedule therefore
sometimes it is referred to as a scheduled event. MySQL event is also known as
“temporal trigger” because it is triggered by time, not by table update like a trigger. A
MySQL event is similar to a cron job in UNIX or a task scheduler in Windows.

You can use MySQL events in many cases such as optimizing database tables,
cleaning up logs, archiving data, or generate complex reports during off-peak time.

MySQL event scheduler configuration

MySQL uses a special thread called event schedule thread to execute all scheduled
events. You can see the status of event scheduler thread by executing the following
command:

SHOW PROCESSLIST;

By default, the event scheduler thread is not enabled. To enable and start the event
scheduler thread, you need to execute the following command:

SET GLOBAL event_scheduler = ON;

Now to see the status of event scheduler thread, you execute the SHOW
PROCESSLIST command again.

To disable and stop the event the event scheduler thread, you execute the SET
GLOBAL command with value of the event_scheduler is OFF:

SET GLOBAL event_scheduler = OFF;

Creating new MySQL events

Creating an event is similar to creating other database objects such as stored


procedures or triggers. An event is a named object that contains SQL statements.

A stored procedure is only executed when it is invoked directly; a trigger is executed


when an event associated with a table such as an insert, update, or delete event
occurs while an event can be executed at once or more regular intervals.

To create and schedule a new event, you use the CREATE EVENT statement as
follows:
CREATE EVENT [IF NOT EXIST] event_name
ON SCHEDULE schedule
DO
event_body
This event makes the MySQL server drop a table exactly 5 days from now:
Example:
CREATE EVENT 'My event' ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 5 DAY
DO DROP TABLE t;
This event makes the MySQL server drop a table on February 24, 2018 at exactly 12
o'clock:
CREATE EVENT The_Main_Event
ON SCHEDULE AT TIMESTAMP '2018-02-24 12:00:00'
DO DROP TABLE t;

EVERY interval means "Do this repeatedly". A recurring interval starts with EVERY,
followed by a positive integer plus an INTERVAL interval, as we saw in the last blog.
For example, this event makes MySQL drop table t once each year, starting now:
CREATE EVENT e ON SCHEDULE EVERY 1 YEAR DO DROP TABLE t;

The STARTS and ENDS Clauses

An EVERY clause may contain an optional STARTS and/or ENDS clause.


STARTS is followed by a timestamp value that indicates when the action should begin
repeating, and may also use + INTERVAL interval to specify an amount of time "from
now". Not specifying STARTS is the same as using STARTS CURRENT_TIMESTAMP so
that the event begins repeating immediately upon creation of the event.
An EVERY clause may also contain an ENDS clause. The ENDS keyword is followed by
a timestamp value that tells MySQL when the event should stop repeating. Not using
ENDS means that the event continues executing indefinitely.
"EVERY interval [ STARTS timestamp1 ] [ ENDS timestamp2 ]" means "Do this
repeatedly, starting at timestamp1 if it's specified, ending at timestamp2 if it's
specified". For example, this event tells the database to drop a table once each year,
starting exactly 3 days from now:
CREATE EVENT evt
ON SCHEDULE EVERY 1 YEAR
STARTS CURRENT_TIMESTAMP + INTERVAL 3 DAY
DO DROP TABLE t;

This event would cause MySQL to drop a table once each year for five years, starting
exactly 2 days from now:

CREATE EVENT e
ON SCHEDULE EVERY 1 YEAR
STARTS CURRENT_TIMESTAMP + INTERVAL 2 DAY
ENDS CURRENT_TIMESTAMP + INTERVAL 5 YEAR
DO DROP TABLE t;

Let’s examine the statement in more detail.

 First, you specify the event name after the CREATE EVENT clause. The event
name must be unique within a database schema.
 Second, you put a schedule after the ON SCHEDULE clause. If the event is a one-
time event, you use the syntax: AT timestamp [+ INTERVAL] If the event is a
recurring event, you use the EVERY clause: EVERY interval STARTS timestamp
[+INTERVAL] ENDS timestamp [+INTERVAL]
 Third, you place the SQL statements after the DO keyword. It is important to
notice that you can call a stored procedure inside the body of the event. In case
you have compound SQL statements, you can wrap them in a BEGIN END block.
Let’s look at few examples of creating events to understand the syntax above.
To create and schedule a new one-time event that inserts a message into a table
called messages you do the following steps:.
First, create a new table named messages by using the CREATE TABLE statement as
follows:

CREATE TABLE IF NOT EXISTS messages (id INT PRIMARY KEY


AUTO_INCREMENT,message VARCHAR(255) NOT NULL,created_at DATETIME NOT
NULL);

Second, create an event by using the CREATE EVENT statement:


CREATE EVENT IF NOT EXISTS test_event_01
ON SCHEDULE AT CURRENT_TIMESTAMP
DO
INSERT INTO messages(message,created_at) VALUES('Test MySQL Event 1',NOW());

Third, check the messages table; you will see that we have 1 record. It means the
event was executed when it is created.

SELECT * FROM messages;

To shows all events of a database schema, you use the following statement:

SHOW EVENTS FROM classicmodels;

We don’t see any row returned because an event is automatically dropped when it is
expired. In our case, it is a one-time event and expired when its execution completed.
To change this behavior, you can use the ON COMPLETION PRESERVE clause. The
following statement creates another one-time event that is executed after its creation
time 1 minute and not dropped after execution.

CREATE EVENT test_event_02


ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MINUTE
ON COMPLETION PRESERVE
DO
INSERT INTO messages(message,created_at)VALUES('Test MySQL Event 2',NOW());

Wait for 1 minute, check the messages table, another record was added:
SELECT * FROM messages;

If we execute the SHOW EVENTS statement again, we see the event is there because
the effect of the ON COMPLETION PRESERVE clause:

SHOW EVENTS FROM classicmodels;


The following statement creates a recurring event that executes every minute and is
expired in 1 hour from its creation time:

CREATE EVENT test_event_03


ON SCHEDULE EVERY 1 MINUTE
STARTS CURRENT_TIMESTAMP
ENDS CURRENT_TIMESTAMP + INTERVAL 1 HOUR
DO
INSERT INTO messages(message,created_at)
VALUES('Test MySQL recurring Event',NOW());

Notice that we used STARTS and ENDS clauses to define expiration period for the
event. You can test this recurring event by waiting for few minutes and check
the messages table.

SELECT * FROM messages;

Drop MySQL events


To remove an existing event, you use the DROP EVENT statement as follows:
DROP EVENT [IF EXIST] event_name;

For example, to drop the test_event_03 event, you use the following statement:

DROP EVENT [IF EXIST] test_event_03;


Chapter 37: ENUM
Section 40.1: Why ENUM?
ENUM provides a way to provide an attribute for a row. Attributes with a small number of non-numeric
options
work best. Examples:
reply ENUM('yes', 'no')
gender ENUM('male', 'female', 'other', 'decline-to-state')
The values are strings:
INSERT ... VALUES ('yes', 'female')
SELECT ... --> yes female

Section 40.2: VARCHAR as an alternative


Let's say we have
type ENUM('fish','mammal','bird')
An alternative is
type VARCHAR(20) COMENT "fish, bird, etc"
This is quite open-ended in that new types are trivially added.
Comparison, and whether better or worse than ENUM:
(same) INSERT: simply provide the string
(worse?) On INSERT a typo will go unnoticed
(same) SELECT: the actual string is returned
(worse) A lot more space is consumed
Section 40.3: Adding a new option
ALTER TABLE tbl MODIFY COLUMN type ENUM('fish','mammal','bird','insect');
Notes
As with all cases of MODIFY COLUMN, you must include NOT NULL, and any other qualifiers that
originally
existed, else they will be lost.
If you add to the end of the list and the list is under 256 items, the ALTER is done by merely changing
the
schema. That is there will not be a lengthy table copy. (Old versions of MySQL did not have this
optimization.)
Section 40.4: NULL vs NOT NULL
Examples of what happens when NULL and 'bad-value' are stored into nullable and not nullable
columns. Also
shows usage of casting to numeric via +0.
CREATE TABLE enum (
e ENUM('yes', 'no') NOT NULL,
enull ENUM('x', 'y', 'z') NULL
sathish MySQL® Notes for Professionals 120
);
INSERT INTO enum (e, enull)
VALUES
('yes', 'x'),
('no', 'y'),
(NULL, NULL),
('bad-value', 'bad-value');
Query OK, 4 rows affected, 3 warnings (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 3
mysql>SHOW WARNINGS;
+---------+------+--------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------+
| Warning | 1048 | Column 'e' cannot be null |
| Warning | 1265 | Data truncated for column 'e' at row 4 |
| Warning | 1265 | Data truncated for column 'enull' at row 4 |
+---------+------+--------------------------------------------+
3 rows in set (0.00 sec)
What is in the table after those inserts. This uses "+0" to cast to numeric see what is stored.
mysql>SELECT e, e+0 FROM enum;
+-----+-----+
| e | e+0 |
+-----+-----+
| yes | 1 |
| no | 2 |
| | 0 | -- NULL
| | 0 | -- 'bad-value'
+-----+-----+
4 rows in set (0.00 sec)
mysql>SELECT enull, enull+0 FROM enum;
+-------+---------+
| enull | enull+0 |
+-------+---------+
|x|1|
|y|2|
| NULL | NULL |
| | 0 | -- 'bad-value'
+-------+---------+
4 rows in set (0.00 sec)
Chapter 38: Clustering
An index is an on-disk structure associated with a table or view that speeds retrieval
of rows from the table or view. An index contains keys built from one or more columns
in the table or view. These keys are stored in a structure (B-tree) that enables SQL
Server to find the row or rows associated with the key values quickly and efficiently.

A table or view can contain the following types of indexes:

 Clustered

o Clustered indexes sort and store the data rows in the table or view based on
their key values. These are the columns included in the index definition. There
can be only one clustered index per table, because the data rows themselves
can be stored in only one order.

o The only time the data rows in a table are stored in sorted order is when the
table contains a clustered index. When a table has a clustered index, the table
is called a clustered table. If a table has no clustered index, its data rows are
stored in an unordered structure called a heap.

 Nonclustered

o Nonclustered indexes have a structure separate from the data rows. A


nonclustered index contains the nonclustered index key values and each key
value entry has a pointer to the data row that contains the key value.

o The pointer from an index row in a nonclustered index to a data row is called a
row locator. The structure of the row locator depends on whether the data
pages are stored in a heap or a clustered table. For a heap, a row locator is a
pointer to the row. For a clustered table, the row locator is the clustered index
key.

o You can add nonkey columns to the leaf level of the nonclustered index to by-
pass existing index key limits, and execute fully covered, indexed, queries. For
more information, see Create Indexes with Included Columns. For details about
index key limits see Maximum Capacity Specifications for SQL Server.

Both clustered and nonclustered indexes can be unique. This means no two rows can
have the same value for the index key. Otherwise, the index is not unique and
multiple rows can share the same key value. For more information, see Create Unique
Indexes.

Indexes are automatically maintained for a table or view whenever the table data is
modified.
Indexes and Constraints

Indexes are automatically created when PRIMARY KEY and UNIQUE constraints are
defined on table columns. For example, when you create a table with a UNIQUE
constraint, Database Engine automatically creates a non-clustered index. If you
configure a PRIMARY KEY, Database Engine automatically creates a clustered index,
unless a clustered index already exists. When you try to enforce a PRIMARY KEY
constraint on an existing table and a clustered index already exists on that table, SQL
Server enforces the primary key using a nonclustered index.
Chapter 39: Partitioning
MySQL partitioning is about altering – ideally, optimizing – the way the database
engine physically stores data. It allows you to distribute portions of table data (a.k.a.
partitions) across the file system based on a set of user-defined rules (a.k.a. the
“partitioning function”).

 RANGE Partitioning
 LIST Partitioning
 COLUMNS Partitioning
 HASH Partitioning
 KEY Partitioning
 Subpartitioning
 How MySQL Partitioning Handles NULL
The types of partitioning which are available in MySQL 5.5. These include the types
listed here:

 RANGE partitioning. This type of partitioning assigns rows to partitions based


on column values falling within a given range.
A table that is partitioned by range is partitioned in such a way that each
partition contains rows for which the partitioning expression value lies within a
given range. Ranges should be contiguous but not overlapping, and are defined
using the VALUES LESS THAN operator. For the next few examples, suppose that
you are creating a table such as the following to hold personnel records for a
chain of 20 video stores, numbered 1 through 20:

Example:
drop table employees;
CREATE TABLE employees (id INT NOT NULL,fname VARCHAR(30),lname
VARCHAR(30),hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT
NULL DEFAULT '9999-12-31', job_code INT NOT NULL,store_id INT NOT NULL);

This table can be partitioned by range in a number of ways, depending on your needs.
One way would be to use the store_id column. For instance, you might decide to
partition the table 4 ways by adding a PARTITION BY RANGE clause as shown here:
drop table employee;
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN (21)
);
In this partitioning scheme, all rows corresponding to employees working at stores 1
through 5 are stored in partition p0, to those employed at stores 6 through 10 are
stored in partition p1, and so on. Note that each partition is defined in order, from
lowest to highest.

CREATE TABLE employees (


id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE
);

MAXVALUE represents an integer value that is always greater than the largest
possible integer value (in mathematical language, it serves as a least upper bound).
Now, any rows whose store_id column value is greater than or equal to 16 (the
highest value defined) are stored in partition p3. At some point in the future—when
the number of stores has increased to 25, 30, or more

 LIST partitioning. Similar to partitioning by RANGE, except that the partition is


selected based on columns matching one of a set of discrete values.
Suppose that there are 20 video stores distributed among 4 franchises as shown in
the following table.

Regio Store ID
n Numbers
North 3, 5, 6, 9, 17
1, 2, 10, 11, 19,
East 20
4, 12, 13, 14,
West 18
Centr
al 7, 8, 15, 16
To partition this table in such a way that rows for stores belonging to the same region
are stored in the same partition, you could use the CREATE TABLE statement shown
here:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY LIST(store_id) (
PARTITION pNorth VALUES IN (3,5,6,9,17),
PARTITION pEast VALUES IN (1,2,10,11,19,20),
PARTITION pWest VALUES IN (4,12,13,14,18),
PARTITION pCentral VALUES IN (7,8,15,16)
);

CREATE TABLE h2 (c1 INT,c2 INT)


PARTITION BY LIST(c1)
(
PARTITION p0 VALUES IN (1, 4, 7),
PARTITION p1 VALUES IN (2, 5, 8)
);

mysql>INSERT INTO h2 VALUES (3, 5);


ERROR 1525 (HY000): Table has no partition for value 3

TRUNCATE h2;
SELECT * FROM h2;
INSERT IGNORE INTO h2 VALUES (2, 5), (6, 10), (7, 5), (3, 1), (1, 9);
SELECT * FROM h2;

 HASH partitioning. With this type of partitioning, a partition is selected based


on the value returned by a user-defined expression that operates on column
values in rows to be inserted into the table. The function may consist of any
expression valid in MySQL that yields a nonnegative integer value. An extension to
this type, LINEAR HASH, is also available. See Section 3.4, “HASH Partitioning”.
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY HASH(store_id)
PARTITIONS 4;

CREATE TABLE employees (


id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY HASH( YEAR(hired) )
PARTITIONS 4;
 KEY partitioning. This type of partitioning is similar to partitioning by HASH,
except that only one or more columns to be assess are supplied, and the MySQL
server provides its own hashing function. These columns can contain other than
integer values, since the hashing function supplied by MySQL guarantees an
integer result regardless of the column data type. An extension to this
type, LINEAR KEY, is also available.
CREATE TABLE k1 (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(20)
)
PARTITION BY KEY()
PARTITIONS 2;

CREATE TABLE k1 (
id INT NOT NULL,
name VARCHAR(20),
UNIQUE KEY (id)
)
PARTITION BY KEY()
PARTITIONS 2;

Subpartitioning
Subpartitioning—also known as composite partitioning—is the further division of each
partition in a partitioned table. Consider the following CREATE TABLE statement:

CREATE TABLE ts (id INT, purchased DATE)


PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) )
SUBPARTITIONS 2 (
PARTITION p0 VALUES LESS THAN (1990),
PARTITION p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN MAXVALUE
);

CREATE TABLE ts (id INT, purchased DATE)


PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0,
SUBPARTITION s1
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s2,
SUBPARTITION s3
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4,
SUBPARTITION s5
)
);
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0,
SUBPARTITION s1
),
PARTITION p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s2,
SUBPARTITION s3
)
);

CREATE TABLE ts (id INT, purchased DATE)


PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0,
SUBPARTITION s1
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s2,
SUBPARTITION s3
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4,
SUBPARTITION s5
)
);

CREATE TABLE ts (id INT, purchased DATE)


ENGINE = MYISAM
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0
DATA DIRECTORY = '/disk0/data'
INDEX DIRECTORY = '/disk0/idx',
SUBPARTITION s1
DATA DIRECTORY = '/disk1/data'
INDEX DIRECTORY = '/disk1/idx'
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s2
DATA DIRECTORY = '/disk2/data'
INDEX DIRECTORY = '/disk2/idx',
SUBPARTITION s3
DATA DIRECTORY = '/disk3/data'
INDEX DIRECTORY = '/disk3/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s5
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
)
);

CREATE TABLE ts (id INT, purchased DATE)


ENGINE = MYISAM
PARTITION BY RANGE(YEAR(purchased))
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0a
DATA DIRECTORY = '/disk0'
INDEX DIRECTORY = '/disk1',
SUBPARTITION s0b
DATA DIRECTORY = '/disk2'
INDEX DIRECTORY = '/disk3'
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s1a
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s1b
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s2a,
SUBPARTITION s2b
)
);

You might also like