MYSQL 5.X DOCUMENTATION - LOCALIZATION OF E-GOVERNANCE PROJECT - PREPARED BY: PROJECT TEAM

Page created by Zachary Richards
 
CONTINUE READING
LOCALIZATION OF E-GOVERNANCE PROJECT

   MySQL 5.x Documentation

                        Prepared by:
                        Project Team,
                        The ePlatform Model
                         DIT, MoIC, RGoB
CONTENTS
1. MySQL Data Types                                                2
        a. Numeric Values                                          2
        b. String (Character) Values                               2
        c. Date and Time                                           4
        d. The NULL Value                                          4
2. MySQL Column Types                                              5
3. Types of SQL Statement                                          9
        a. Selecting, Creating, Dropping, and Altering Databases   10
        b. Creating, Dropping, Indexing, and Altering Tables       11
        c. Getting Information about Databases and Tables          13
        d. Retrieving Records from Multiple Tables (join)          14
        e. Rewriting Subselects That Select Matching Values        18
4. Transactions                                                    21
5. FULLTEXT Searches                                               23
6. MySQL Query Optimizer                                           23
7. Indexes                                                         25
8. Stored Procedures and Functions                                 26
        a. CREATE PROCEDURE                                        26
        b. CREATE FUNCTION                                         27
        c. ALTER PROCEDURE and ALTER FUNCTION Syntax               27
        d. DROP PROCEDURE and DROP FUNCTION Syntax                 27
        e. CALL Statement Syntax                                   27
9. Triggers                                                        27
        a. CREATE TRIGGER Syntax                                   27
        b. DROP TRIGGER Syntax                                     29
10. View                                                           29
        a. ALTER VIEW Syntax                                       29
        b. CREATE VIEW Syntax                                      29
        c. DROP VIEW Syntax                                        30
11. MySQL User Account Management                                  30
        a. Adding New User Accounts to MySQL                       30
        b. Limiting Account Resources                              32
        c. Assigning Account Passwords                             32
12. Backup and Recovery                                            33
        a. Using mysqldump                                         33
        b. Using mysqlhotcopy                                      34
13. Cursors                                                        34
14. Character Sets and Collations                                  37
15. Storage Engines                                                41

                                                                        Page | 1
MySQL Data Types
MySQL knows about several data types—that is, general categories in which values can be
represented. These include numbers, string values, temporal values such as dates and times, and the
NULL value.

Numeric Values

Numbers are values such as 48 or 193.62. MySQL understands numbers specified as integers (with
no fractional part) or floating-point values (with a fractional part). Integers can be specified in
decimal or hexadecimal format.

An integer consists of a sequence of digits with no decimal point.

A floating-point number consists of a sequence of digits, a decimal point, and another sequence of
digits. One sequence of digits or the other can be empty, but not both.

MySQL understands scientific notation. This is indicated by immediately following an integer or
floating-point number with 'e' or 'E', a sign character ('+' or '-'), and an integer exponent. 1.34E+12
and 43.27e-1 are numbers in legal scientific notation. The number 1.34E12 is also legal even though
it is missing a sign character before the exponent, but only as of MySQL 3.23.26. Prior to that
version, a sign character is required.

Hexadecimal numbers cannot be used in scientific notation: The 'e' that begins the exponent part is
also a legal hex digit and thus would be ambiguous.

Any number can be preceded by a minus sign ('-') to indicate a negative value.

String (Character) Values

Strings are values, such as 'Madison, Wisconsin', or 'patient shows improvement'. You can
use either single or double quotes to surround a string value. The ANSI SQL standard specifies single
quotes, so statements written using them are more portable to other database engines.

Several escape sequences are recognized within strings and can be used to indicate special characters,
as shown below. Each sequence begins with a backslash character ('\') to signify a temporary escape
from the usual rules for character interpretation. Note that a NUL byte is not the same as the NULL
value; NUL is a zero-valued byte, whereas NULL is the absence of a value.

Table 2.1. String Escape Sequences
Sequence                  Meaning
\0                        NUL (ASCII 0)

                                                                                               Page | 2
\'                        Single quote
\"                        Double quote
\b                        Backspace
\n                        Newline (linefeed)
\r                        Carriage return
\t                        Tab
\\                        Backslash
\Z                        Ctrl-Z (Windows EOF character)

To include either kind of quote character within a string, you can do one of three things:

     •   Double the quote character if the string is quoted using the same character:

           'I can''t'
           "He said, ""I told you so."""

     •   Quote the string with the other quote character; in this case, you do not double the quote
         characters within the string:

           "I can't"
           'He said, "I told you so."'

     •   Escape the quote character with a backslash; this works regardless of the quote characters
         used to quote the string:

           'I can\'t'
           "I can\'t"
           "He said, \"I told you so.\""
           'He said, \"I told you so.\"'

Hexadecimal constants can be used to specify string values. There are two different syntaxes for such
constants. The first consists of '0x' followed by one or more hexadecimal digits ('0' through '9' and 'a'
through 'f'). For example, 0x0a is 10 decimal, and 0xffff is 65535 decimal. Non-decimal hex digits
can be specified in uppercase or lowercase, but the leading '0x' cannot be given as '0X'. That is, 0x0a
and 0x0A are legal, but 0X0a and 0X0A are not. In string context, pairs of hexadecimal digits are
interpreted as ASCII codes, converted to characters, and the result is used as a string. In numeric
context, a hexadecimal constant is treated as a number. The following statement illustrates both uses:

mysql> SELECT 0x616263, 0x616263+0;
+----------+------------+
| 0x616263 | 0x616263+0 |
+----------+------------+
| abc      |    6382179 |
+----------+------------+

                                                                                                 Page | 3
As of MySQL 4.0, string values can also be specified using the ANSI SQL notation X'val', where
val consists of pairs of hexadecimal digits. As with 0x notation, such values are interpreted as strings
but can be used as numbers in a numeric context:

mysql> SELECT X'616263', X'616263'+0;
+-----------+-------------+
| X'616263' | X'616263'+0 |
+-----------+-------------+
| abc       |     6382179 |
+-----------+-------------+

Unlike 0x notation, the leading 'X' is not case sensitive:

mysql> SELECT X'61', x'61';
+-------+-------+
| X'61' | x'61' |
+-------+-------+
| a     | a     |
+-------+-------+

Date and Time (Temporal) Values

Dates and times are values such as '2002-06-17' or '12:30:43'. MySQL also understands
combined date/time values, such as '2002-06-17 12:30:43'. Take special note of the fact that
MySQL represents dates in year-month-day order. This often surprises newcomers to MySQL,
although this format is the ANSI SQL standard (also known as ISO 8601 format). You can display
date values any way you want by using the DATE_FORMAT() function, but the default display format
lists the year first, and input values must be specified with the year first.

The NULL Value
NULL is something of a "typeless" value. Generally, it's used to mean "no value," "unknown value,"
"missing value," "out of range," "not applicable," "none of the above," and so on. You can insert NULL
values into tables, retrieve them from tables, and test whether a value is NULL. However, you cannot
perform arithmetic on NULL values; if you try, the result is NULL.

                                                                                                Page | 4
MySQL Column Types
Each table in a database is made up of one or more columns. When you create a table using a CREATE
TABLE statement, you specify a type for each column. A column type is more specific than a data
type, which is just a general category, such as "number" or "string." A column type precisely
characterizes the kind of values a given table column can contain, such as SMALLINT or VARCHAR(32).

MySQL's column types are the means by which you describe what kinds of values a table's columns
contain, which in turn determines how MySQL treats those values. For example, if you have numeric
values, you can store them using a numeric or a string column type, but MySQL will treat the values
somewhat differently depending on how you store them. Each column type has several
characteristics:

   •   What kind of values you can store in it
   •   How much space values take up, and whether the values are fixed-length (all values of the
       type taking the same amount of space) or variable-length (the amount of space depending on
       the particular value being stored)
   •   How values of the type are compared and sorted
   •   Whether the type allows NULL values
   •   Whether the type can be indexed

The following discussion surveys MySQL's column types briefly in a broad overview and then
describes in more detail the properties that characterize each type.

Overview of Column Types

MySQL provides column types for values from all the general data type categories except the NULL
value. NULL spans all types in the sense that the property of whether a column can contain NULL
values is treated as a type attribute.

MySQL has numeric column types for both integer and floating-point values, as shown in Table
below. Integer columns can be signed or unsigned. A special attribute allows sequential integer
column values to be generated automatically, which is useful in applications that require a series of
unique identification numbers.

Numeric Column Types
Type Name            Meaning
TINYINT              A very small integer
SMALLINT             A small integer
MEDIUMINT            A medium‐sized integer
INT                  A standard integer

                                                                                             Page | 5
BIGINT                A large integer
FLOAT                 A single‐precision floating‐point number
DOUBLE                A double‐precision floating‐point number
DECIMAL               A floating‐point number, represented as a string
MySQL string column types are shown below. Strings can hold anything, even arbitrary binary data
such as images or sounds. Strings can be compared according to whether or not they are case
sensitive. In addition, you can perform pattern matching on strings. (Actually, in MySQL you can
perform pattern matching on any column type, but it's most often done with string types.)

String Column Types
Type Name       Meaning
CHAR            A fixed‐length character string
VARCHAR         A variable‐length character string
TINYBLOB        A very small BLOB (binary large object)
BLOB            A small BLOB
MEDIUMBLOB      A medium‐sized BLOB
LONGBLOB        A large BLOB
TINYTEXT        A very small text string
TEXT            A small text string
MEDIUMTEXT      A medium‐sized text string
LONGTEXT        A large text string
ENUM            An enumeration; column values may be assigned one enumeration member
SET             A set; column values may be assigned multiple set members

TINYTEXT, TEXT, MEDIUMTEXT and LONGTEXT

A character large object that can hold a variable amount of case-insensitive text data.

TINYTEXT

A character large object column with a maximum length of 255 (2^8 - 1) characters.

TEXT

A character large object column with a maximum length of 65535 (2^16 - 1) characters.

MEDIUMTEXT

A character large object column with a maximum length of 16777215 (2^24 - 1) characters.

                                                                                          Page | 6
LONGTEXT

A character large object column with a maximum length of 4294967295 (2^32 - 1)
characters.

MySQL date and time types are shown in Table below, where CC, YY, MM, DD hh, mm, and ss represent
century, year, month, day, hour, minute, and second. For temporal values, MySQL provides types for
dates and times (either combined or separate) and timestamps (a special type that allows you to track
when changes were last made to a record). There is also a type for efficiently representing year values
when you don't need an entire date.

Date and Time Column Types
Type Name            Meaning
DATE                 A date value, in 'CCYY-MM-DD' format
TIME                 A time value, in 'hh:mm:ss' format
DATETIME             A date and time value, in 'CCYY-MM-DD hh:mm:ss' format
TIMESTAMP            A timestamp value, in CCYYMMDDhhmmss format
YEAR                 A year value, in CCYY format

Numeric Column Type Ranges
Type Specification       Range
TINYINT[(M)]             Signed values: –128 to 127 (–27 to 27 – 1)
                         Unsigned values: 0 to 255 (0 to 28 – 1)
SMALLINT[(M)]            Signed values: –32768 to 32767 (–215 to 215 – 1)
                         Unsigned values: 0 to 65535 (0 to 216 – 1)
MEDIUMINT[(M)]           Signed values: –8388608 to 8388607 (–223 to 223 – 1)
                         Unsigned values: 0 to 16777215 (0 to 224 – 1)
INT[(M)]                 Signed values: –2147683648 to 2147483647 (–231 to 231 – 1)
                         Unsigned values: 0 to 4294967295 (0 to 232 – 1)
BIGINT[(M)]              Signed values: –9223372036854775808 to 9223372036854775807 (–263 to 263 – 1)
                         Unsigned values: 0 to 18446744073709551615 (0 to 264 – 1)
FLOAT[(M,D)]             Minimum non‐zero values: ±1.175494351E–38
                         Maximum non‐zero values: ±3.402823466E+38
DOUBLE[(M,D)]            Minimum non‐zero values: ±2.2250738585072014E–308
                         Maximum non‐zero values: ±1.7976931348623157E+308
DECIMAL([M[,D]]) Varies; range depends on M and D

                                                                                                Page | 7
Numeric Column Type Storage Requirements
Type Specification        Storage Required
TINYINT[(M)]              1 byte
SMALLINT[(M)]             2 bytes
MEDIUMINT[(M)]            3 bytes
INT[(M)]                  4 bytes
BIGINT[(M)]               8 bytes
FLOAT[(M,D)]              4 bytes
DOUBLE[(M,D)]             8 bytes
DECIMAL([M[,D]])
                          M bytes (MySQL < 3.23), M+2 bytes (MySQL   3.23)

CREATE TABLE mytbl
(
    itiny     TINYINT,
    itiny_u   TINYINT UNSIGNED,
    ismall    SMALLINT,
    ismall_u SMALLINT UNSIGNED,
    imedium   MEDIUMINT,
    imedium_u MEDIUMINT UNSIGNED,
    ireg      INT,
    ireg_u    INT UNSIGNED,
    ibig      BIGINT,
    ibig_u    BIGINT UNSIGNED
);

+-----------+-----------------------+
| Field     | Type                  |
+-----------+-----------------------+
| itiny     | tinyint(4)            |
| itiny_u   | tinyint(3) unsigned   |
| ismall    | smallint(6)           |
| ismall_u | smallint(5) unsigned |
| imedium   | mediumint(9)          |
| imedium_u | mediumint(8) unsigned |
| ireg      | int(11)               |
| ireg_u    | int(10) unsigned      |
| ibig      | bigint(20)            |
| ibig_u    | bigint(20) unsigned   |
+-----------+-----------------------+

                                                                             Page | 8
Types of SQL Statement
SELECTING, CREATING, DROPPING, AND ALTERING DATABASES

USE

CREATE DATABASE

DROP DATABASE

ALTER DATABASE
CREATING, ALTERING, AND DROPPING TABLES

CREATE TABLE

DROP TABLE

ALTER TABLE
GETTING INFORMATION ABOUT DATABASES AND TABLES

DESCRIBE

SHOW
RETRIEVING INFORMATION FROM TABLES

SELECT

UNION
PERFORMING TRANSACTIONS

BEGIN

COMMIT

ROLLBACK

SET AUTOCOMMIT
MODIFYING INFORMATION IN TABLES

DELETE

INSERT

LOAD DATA

REPLACE

                                                        Page | 9
UPDATE
ADMINISTRATIVE STATEMENTS

FLUSH

GRANT

REVOKE

Selecting, Creating, Dropping, and Altering Databases

MySQL provides several database-level statements: USE for selecting a default database, CREATE
DATABASE for creating databases, DROP DATABASE for removing them, and ALTER DATABASE for
modifying global database characteristics.

Selecting Databases

The USE statement selects a database to make it the default (current) database for a given connection
to the server:

USE db_name;

You must have some access privilege for the database or you cannot select it. If you do have access to
a database, you can use its tables even without selecting the database explicitly by qualifying table
names with the database name. For example, to retrieve the contents of the president table in the
sampdb database without selecting the database first, write the query like this:

SELECT * FROM sampdb.president;

However, it's much more convenient to refer to tables without having to specify a database qualifier.

Selecting a default database doesn't mean it must be the default for the duration of the connection.
You can issue any number of USE statements to switch back and forth among databases as often as
you want, as long as you have access privileges to use them. Nor does selecting a database limit you
to using tables only from that database. While one database is the default, you can refer to tables in
other databases by qualifying their names with the appropriate database name.

Creating Databases

Creating a database is easy; just name it in a CREATE DATABASE statement:

CREATE DATABASE db_name;

The constraints on database creation are that the name must be legal, the database must not already
exist, and you must have sufficient privileges to create it.

                                                                                             Page | 10
Dropping Databases

Dropping a database is just as easy as creating one, assuming you have sufficient privileges:

DROP DATABASE db_name;

However, the DROP DATABASE statement is not something you should use with wild abandon. It
removes the database and all tables within it. After you drop a database, it's gone forever. In other
words, don't try out this statement just to see how it works. If your administrator has been performing
database backups regularly, you may be able to get the database back. But I can guarantee that no
administrator will be sympathetic if you say, "Uh, I was just playing around with DROP DATABASE to
see what would happen, and, uh…can you restore my database for me?"

Altering Databases

The ALTER DATABASE statement, available as of MySQL 4.1, makes changes to a database's global
characteristics or attributes. Currently, the only such characteristic is the default character set:

ALTER DATABASE db_name DEFAULT CHARACTER SET charset;

charset should be the name of a character set supported by the server, such as latin1_de or sjis.
(To find out which sets your server supports, issue a SHOW CHARACTER SET statement.) charset can
also be DEFAULT to indicate that the database uses the server-level character set by default.

Creating, Dropping, Indexing, and Altering Tables

Creating Tables

To create a table, use a CREATE TABLE statement. The full syntax for this statement is complex
because there are so many optional clauses, but in practice, it's usually fairly simple to use. For
example, all of the CREATE TABLE statements that we used in Chapter 1 are reasonably
uncomplicated. If you start with the more basic forms and work up, you shouldn't have much trouble.

The CREATE TABLE specifies, at a minimum, the table name and a list of the columns in it—for
example:

CREATE TABLE mytbl
(
    name   CHAR(20),
    age    INT NOT NULL,
    weight INT,
    sex    ENUM('F','M')
);

Dropping Tables

Dropping a table is much easier than creating it because you don't have to specify anything about its
contents. You just have to name it:

                                                                                                Page | 11
DROP TABLE tbl_name;

MySQL extends the DROP TABLE statement in some useful ways. First, you can drop several tables by
specifying them all on the same statement:

DROP TABLE tbl_name1, tbl_name2, ... ;

Second, if you're not sure whether or not a table exists, but you want to drop it if it does, you can add
IF EXISTS to the statement. This causes MySQL not to complain or issue an error if the table or
tables named in the statement don't exist:

DROP TABLE IF EXISTS tbl_name;

IF EXISTS is particularly useful in scripts that you use with the mysql client. By default, mysql exits
when an error occurs, and it is an error to try to remove a table that doesn't exist.

Altering Table Structure

ALTER TABLE is a versatile statement in MySQL, and you can use it to do many things. ALTER TABLE
is useful when you find that the structure of a table no longer reflects what you want to do with it.
You may want to use the table to record additional information, or perhaps it contains information
that has become superfluous.

The syntax for ALTER TABLE is as follows:

ALTER TABLE tbl_name action, ... ;

Renaming a table.

Use a RENAME clause that specifies the new table name:

ALTER TABLE tbl_name RENAME TO new_tbl_name;

Another way to rename tables is with RENAME TABLE, available as of MySQL 3.23.23. The syntax
looks like this:

RENAME TABLE old_name TO new_name;

One thing that RENAME TABLE can do that ALTER TABLE cannot is rename multiple tables in the same
statement. For example, you can swap the names of two tables like this:

RENAME TABLE t1 TO tmp, t2 TO t1, tmp TO t1;

If you qualify a table name with a database name, you can move a table from one database to another
by renaming it. Either of the following statements move the table t from the sampdb database to the
test database:

                                                                                               Page | 12
ALTER TABLE sampdb.t RENAME TO test.t;
RENAME TABLE sampdb.t TO test.t;

You cannot rename a table to use a name that already exists, however.

Getting Information about Databases and Tables

MySQL provides a SHOW statement that has several variant forms that display information about
databases and the tables in them. SHOW is helpful for keeping track of the contents of your databases
and for reminding yourself about the structure of your tables. You can also use SHOW prior to issuing
ALTER TABLE; it's often easier to figure out how to specify a change to a column after you determine
the column's current definition.

The SHOW statement can be used to obtain information about several aspects of your databases and
tables:

   •   List the databases managed by the server:

         SHOW DATABASES;

   •   List the tables in the current database or in a given database:

         SHOW TABLES;
         SHOW TABLES FROM db_name;

       Note that SHOW TABLES doesn't show TEMPORARY tables.

   •   Display information about columns or indexes in a table:

         SHOW COLUMNS FROM tbl_name;
         SHOW INDEX FROM tbl_name;

The DESCRIBE tbl_name and EXPLAIN tbl_name statements are synonymous with SHOW COLUMNS
FROM tbl_name.

   •   Display descriptive information about tables in the current database or in a given database:

       SHOW TABLE STATUS;
       SHOW TABLE STATUS FROM db_name;

   •   Display the CREATE TABLE statement that corresponds to the current structure of a table:

         SHOW CREATE TABLE tbl_name;

mysql> SHOW TABLE TYPES;
+------------+---------+----------------------------------------------------------------+
| Engine     | Support | Comment                                                            |

                                                                                                Page | 13
+------------+---------+----------------------------------------------------------------+
| MyISAM     | YES     | Default engine as of MySQL 3.23 with great performance         |
| MEMORY     | YES     | Hash based, stored in memory, useful for temporary tables      |
| InnoDB     | DEFAULT | Supports transactions, row-level locking, and foreign keys     |
| BerkeleyDB | NO      | Supports transactions and page-level locking                       |
| BLACKHOLE | YES      | /dev/null storage engine (anything you write to it disappears) |
| EXAMPLE    | NO      | Example storage engine                                             |
| ARCHIVE    | YES     | Archive storage engine                                             |
| CSV        | NO      | CSV storage engine                                                 |
| ndbcluster | NO      | Clustered, fault-tolerant, memory-based tables                     |
| FEDERATED | YES      | Federated MySQL storage engine                                     |
| MRG_MYISAM | YES     | Collection of identical MyISAM tables                              |
| ISAM       | NO      | Obsolete storage engine                                            |
+------------+---------+----------------------------------------------------------------+
12 rows in set, 1 warning (0.00 sec)

Retrieving Records from Multiple Tables

It does no good to put records in a database unless you retrieve them eventually and do something
with them. That's the purpose of the SELECT statement—to help you get at your data. SELECT
probably is used more often than any other in the SQL language, but it can also be the trickiest; the
constraints you use to choose rows can be arbitrarily complex and can involve comparisons between
columns in many tables.

The basic syntax of the SELECT statement looks like this:

SELECT selection_list              #   What columns to select
FROM table_list                    #   Where to select rows from
WHERE primary_constraint           #   What conditions rows must satisfy
GROUP BY grouping_columns          #   How to group results
ORDER BY sorting_columns           #   How to sort results
HAVING secondary_constraint        #   Secondary conditions rows must satisfy
LIMIT count;                       #   Limit on results

Everything in this syntax is optional except the word SELECT and the selection_list part that
specifies what you want to retrieve. Some databases require the FROM clause as well. MySQL does
not, which allows you to evaluate expressions without referring to any tables:

SELECT SQRT(POW(3,2)+POW(4,2));

Using Join

Many of the examples that demonstrate how to use the forms of join operations that MySQL supports
use the following two tables, t1 and t2. They're small, which makes them simple enough that the
effect of each type of join can be seen readily:

Table t1:        Table t2:
+----+----+      +----+----+
| i1 | c1 |      | i2 | c2 |
+----+----+      +----+----+
| 1 | a |        | 2 | c |
| 2 | b |        | 3 | b |
| 3 | c |        | 4 | a |

                                                                                                Page | 14
+----+----+        +----+----+

The Trivial Join

The simplest join is the trivial join, in which only one table is named. In this case, rows are selected
from the named table:

mysql> SELECT * FROM t1;
+----+----+
| i1 | c1 |
+----+----+
| 1 | a |
| 2 | b |
| 3 | c |
+----+----+

Some people don't consider this form of SELECT a join at all and use the term only for SELECT
statements that retrieve records from two or more tables. I suppose it's a matter of perspective.

The Full Join

If a SELECT statement names multiple tables in the FROM clause with the names separated by commas,
MySQL performs a full join. For example, if you join t1 and t2 as follows, each row in t1 is
combined with each row in t2:

mysql> SELECT t1.*, t2.* FROM t1, t2;
+----+----+----+----+
| i1 | c1 | i2 | c2 |
+----+----+----+----+
| 1 | a | 2 | c |
| 2 | b | 2 | c |
| 3 | c | 2 | c |
| 1 | a | 3 | b |
| 2 | b | 3 | b |
| 3 | c | 3 | b |
| 1 | a | 4 | a |
| 2 | b | 4 | a |
| 3 | c | 4 | a |
+----+----+----+----+

A full join is also called a cross join because each row of each table is crossed with each row in every
other table to produce all possible combinations. This is also known as the cartesian product. Joining
tables this way has the potential to produce a very large number of rows because the possible row
count is the product of the number of rows in each table. A full join between three tables that contain
100, 200, and 300 rows, respectively, could return 100x200x300 = 6 million rows. That's a lot of
rows, even though the individual tables are small. In cases like this, a WHERE clause will normally be
used to reduce the result set to a more manageable size.

                                                                                              Page | 15
If you add a WHERE clause causing tables to be matched on the values of certain columns, the join
becomes what is known as an equi-join because you're selecting only rows with equal values in the
specified columns:

mysql> SELECT t1.*, t2.* FROM t1, t2 WHERE t1.i1 = t2.i2;
+----+----+----+----+
| i1 | c1 | i2 | c2 |
+----+----+----+----+
| 2 | b | 2 | c |
| 3 | c | 3 | b |
+----+----+----+----+

Left and Right Joins

An equi-join shows only rows where a match can be found in both tables. Left and right joins show
matches, too, but also show rows in one table that have no match in the other table. The examples in
this section use LEFT JOIN, which identifies rows in the left table that are not matched by the right
table. RIGHT JOIN is the same except that the roles of the tables are reversed. (RIGHT JOIN is
available only as of MySQL 3.23.25.)

A LEFT JOIN works like this: You specify the columns to be used for matching rows in the two
tables. When a row from the left table matches a row from the right table, the contents of the rows are
selected as an output row. When a row in the left table has no match, it is still selected for output, but
joined with a "fake" row from the right table in which all the columns have been set to NULL. In other
words, a LEFT JOIN forces the result set to contain a row for every row in the left table whether or
not there is a match for it in the right table. The rows with no match can be identified by the fact that
all columns from the right table are NULL.

Consider once again our two tables, t1 and t2:

Table t1:         Table t2:
+----+----+       +----+----+
| i1 | c1 |       | i2 | c2 |
+----+----+       +----+----+
| 1 | a |         | 2 | c |
| 2 | b |         | 3 | b |
| 3 | c |         | 4 | a |
+----+----+       +----+----+

If we use a cross join to match these tables on t1.i1 and t2.i2, we'll get output only for the values 2
and 3, which appear in both tables:

mysql> SELECT t1.*, t2.* FROM t1, t2 WHERE t1.i1 = t2.i2;
+----+----+----+----+
| i1 | c1 | i2 | c2 |
+----+----+----+----+
| 2 | b | 2 | c |
| 3 | c | 3 | b |
+----+----+----+----+

                                                                                                Page | 16
A left join produces output for every row in t1, whether or not t2 matches it. To write a left join,
name the tables with LEFT JOIN in between (rather than a comma) and specify the matching
condition using an ON clause (rather than a WHERE clause):

mysql> SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON t1.i1 = t2.i2;
+----+----+------+------+
| i1 | c1 | i2   | c2   |
+----+----+------+------+
| 1 | a | NULL | NULL |
| 2 | b |      2 | c    |
| 3 | c |      3 | b    |
+----+----+------+------+

Now there is an output row even for the value 1, which has no match in t2.

LEFT JOIN is especially useful when you want to find only those left table rows that are unmatched
by the right table. Do this by adding a WHERE clause that looks for rows in the right table that have
NULL values—in other words, the rows in one table that are missing from the other:

mysql> SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON t1.i1 = t2.i2
    -> WHERE t2.i2 IS NULL;
+----+----+------+------+
| i1 | c1 | i2   | c2   |
+----+----+------+------+
| 1 | a | NULL | NULL |
+----+----+------+------+

Normally, what you're really after are the unmatched values in the left table. The NULL columns from
the right table are of no interest for display purposes, so you wouldn't bother naming them in the
output column list:

mysql> SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.i1 = t2.i2
    -> WHERE t2.i2 IS NULL;
+----+----+
| i1 | c1 |
+----+----+
| 1 | a |
+----+----+

LEFT JOIN actually allows the matching conditions to be specified two ways. ON is one of these; it
can be used whether or not the columns you're joining on have the same name:

SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON t1.i1 = t2.i2;

The other syntax involves a USING() clause; this is similar in concept to ON, but the name of the
joined column or columns must be the same in each table. For example, the following query joins
mytbl1.b to mytbl2.b:

SELECT mytbl1.*, mytbl2.* FROM mytbl1 LEFT JOIN mytbl2 USING (b);

                                                                                            Page | 17
LEFT JOIN has a few synonyms and variants. LEFT OUTER JOIN is a synonym for LEFT JOIN. There
is also an ODBC-style notation for LEFT JOIN that MySQL accepts (the OJ means "outer join"):

{ OJ tbl_name1 LEFT OUTER JOIN tbl_name2 ON join_expr }

NATURAL LEFT JOIN is similar to LEFT JOIN; it performs a LEFT JOIN, matching all columns that
have the same name in the left and right tables.

One thing to watch out for with LEFT JOIN is that if the columns that you're joining on are not
declared as NOT NULL, you may get problematic rows in the result. For example, if the right table
contains columns with NULL values, you won't be able to distinguish those NULL values from NULL
values that identify unmatched rows.

Rewriting Subselects That Select Matching Values

The following is an example query containing a subselect; it selects scores from the score table for
all tests (that is, it ignores quiz scores):

SELECT * FROM score
WHERE event_id IN (SELECT event_id FROM event WHERE type = 'T');

Rewriting Subselects That Select Non­Matching (Missing) Values

Another common type of subselect query searches for values in one table that are not present in
another table. As we've seen before, the "which values are not present" type of problem is a clue that
a LEFT JOIN may be helpful. The following is a query with a subselect that tests for students who are
not listed in the absence table (it finds those students with perfect attendance):

SELECT * FROM student
WHERE student_id NOT IN (SELECT student_id FROM absence);

This query can be rewritten using a LEFT JOIN as follows:

SELECT student.*
FROM student LEFT JOIN absence ON student.student_id = absence.student_id
WHERE absence.student_id IS NULL;

Retrieving from Multiple Tables with UNION

If you want to create a result set by selecting records from multiple tables one after the other, you can
do that using a UNION statement. UNION is available as of MySQL 4, although prior to that you can use
a couple of workarounds (shown later).

For the following examples, assume you have three tables, t1, t2, and t3 that look like this:

mysql> SELECT * FROM t1;
+------+-------+
| i    | c     |

                                                                                                Page | 18
+------+-------+
|    1 | red   |
|    2 | blue |
|    3 | green |
+------+-------+
mysql> SELECT * FROM t2;
+------+------+
| i    | c    |
+------+------+
|   -1 | tan |
|    1 | red |
+------+------+
mysql> SELECT * FROM t3;
+------------+------+
| d          | i    |
+------------+------+
| 1904-01-01 | 100 |
| 2004-01-01 | 200 |
| 2004-01-01 | 200 |
+------------+------+

Tables t1 and t2 have integer and character columns, and t3 has date and integer columns. To write
a UNION statement that combines multiple retrievals, just write several SELECT statements and put the
keyword UNION between them. For example, to select the integer column from each table, do this:

mysql> SELECT i FROM t1 UNION SELECT i FROM t2 UNION SELECT i FROM t3;
+------+
| i    |
+------+
|    1 |
|    2 |
|    3 |
|   -1 |
| 100 |
| 200 |
+------+

UNION has the following properties:

The names and data types for the columns of the UNION result come from the names and types of the
columns in the first SELECT. The second and subsequent SELECT statements in the UNION must select
the same number of columns, but they need not have the same names or types. Columns are matched
by position (not by name), which is why these two queries return different results:

mysql> SELECT i, c FROM t1 UNION SELECT i, d FROM t3;
+------+------------+
| i    | c          |
+------+------------+
|    1 | red        |
|    2 | blue       |
|    3 | green      |
| 100 | 1904-01-01 |
| 200 | 2004-01-01 |
+------+------------+

                                                                                            Page | 19
mysql> SELECT i, c FROM t1 UNION SELECT d, i FROM t3;
+------+-------+
| i    | c     |
+------+-------+
|    1 | red   |
|    2 | blue |
|    3 | green |
| 1904 | 100   |
| 2004 | 200   |
+------+-------+

In both cases, the columns selected from t1 (i and c) determine the types used in the UNION result.
These columns have integer and string types, so type conversion takes place when selecting values
from t3. For the first query, d is converted from date to string. That happens to result in no loss of
information. For the second query, d is converted from date to integer (which does lose information),
and i is converted from integer to string.

By default, UNION eliminates duplicate rows from the result set:

mysql> SELECT * FROM t1 UNION SELECT * FROM t2 UNION SELECT * FROM t3;
+------+-------+
| i    | c     |
+------+-------+
|    1 | red   |
|    2 | blue |
|    3 | green |
|   -1 | tan   |
| 1904 | 100   |
| 2004 | 200   |
+------+-------+

t1 and t2 both have a row containing values of 1 and 'red', but only one such row appears in the
output. Also, t3 has two rows containing '2004-01-01' and 200, one of which has been eliminated.

If you want to preserve duplicates, follow the first UNION keyword with ALL:

   mysql> SELECT * FROM t1 UNION ALL SELECT * FROM t2 UNION SELECT * FROM t3;
   +------+-------+
   | i    | c     |
   +------+-------+
   |    1 | red   |
   |    2 | blue |
   |    3 | green |
   |   -1 | tan   |
   |    1 | red   |
   | 1904 | 100   |
   | 2004 | 200   |
   | 2004 | 200   |
   +------+-------+

                                                                                             Page | 20
Transactions

Using Transactions to Ensure Safe Statement Execution

mysql> CREATE TABLE t (name CHAR(20), UNIQUE (name)) TYPE = INNODB;
mysql> BEGIN;
mysql> INSERT INTO t SET name = 'William';
mysql> INSERT INTO t SET name = 'Wallace';
mysql> COMMIT;
mysql> SELECT * FROM t;
+---------+
| name    |
+---------+
| Wallace |
| William |
+---------+

You can see that the rows have been recorded in the table. If you had started up another instance of
mysql and selected the contents of t after the inserts but before the commit, the rows would not show
up. They would not become visible to the other mysql process until the COMMIT statement had been
issued by the first process.

If an error occurs during a transaction, you can cancel it with ROLLBACK. Using the t table again, you
can see this by issuing the following statements:

mysql> BEGIN;
mysql> INSERT INTO t SET name = 'Gromit';
mysql> INSERT INTO t SET name = 'Wallace';
ERROR 1062: Duplicate entry 'Wallace' for key 1
mysql> ROLLBACK;
mysql> SELECT * FROM t;
+---------+
| name    |
+---------+
| Wallace |
| William |
+---------+

The second INSERT attempts to place a row into the table that duplicates an existing name value. The
statement fails because name has a UNIQUE index. After issuing the ROLLBACK, the table has only the
two rows that it contains prior to the failed transaction. In particular, the INSERT that was performed
just prior to the point of the error has been undone and its effect is not recorded in the table.

FULLTEXT Searches

The full text search engine allows you to look for words or phrases without using pattern-matching
operations.

A FULLTEXT index is created the same way as other indexes. That is, you can define it with CREATE
TABLE when creating the table initially or add it afterward with ALTER TABLE or CREATE INDEX.

                                                                                              Page | 21
Because FULLTEXT indexes require you to use MyISAM tables, you can take advantage of one of the
properties of the MyISAM handler if you're creating a new table to use for FULLTEXT searches: Table
loading proceeds more quickly if you populate the table and then add the indexes afterward rather
than loading data into an already indexed table. Suppose you have a data file named apothegm.txt
containing famous sayings and the people to whom they're attributed:

Aeschylus                Time as he grows old teaches many lessons
Alexander Graham Bell    Mr. Watson, come here. I want you!
Benjamin Franklin        It is hard for an empty bag to stand upright
Benjamin Franklin        Little strokes fell great oaks
Benjamin Franklin        Remember that time is money
Miguel de Cervantes      Bell, book, and candle
Proverbs 15:1            A soft answer turneth away wrath
Theodore Roosevelt       Speak softly and carry a big stick
William Shakespeare      But, soft! what light through yonder window breaks?

If you want to search by phrase and attribution separately or together, you need to index the columns
separately and also create an index that includes both columns. You can create, populate, and index a
table named apothegm as follows:

CREATE TABLE apothegm (attribution VARCHAR(40), phrase TEXT);
LOAD DATA LOCAL INFILE 'apothegm.txt' INTO TABLE apothegm;
ALTER TABLE apothegm
    ADD FULLTEXT (phrase),
    ADD FULLTEXT (attribution),
    ADD FULLTEXT (phrase, attribution);

After setting up the table, perform searches on it using MATCH to name the column or columns to
search and AGAINST() to specify the search string. For example:

mysql> SELECT * FROM apothegm WHERE MATCH(attribution) AGAINST('roosevelt');
+--------------------+------------------------------------+
| attribution        | phrase                             |
+--------------------+------------------------------------+
| Theodore Roosevelt | Speak softly and carry a big stick |
+--------------------+------------------------------------+

mysql> SELECT * FROM apothegm WHERE MATCH(phrase) AGAINST('time');
+-------------------+-------------------------------------------+
| attribution       | phrase                                    |
+-------------------+-------------------------------------------+
| Benjamin Franklin | Remember that time is money               |
| Aeschylus         | Time as he grows old teaches many lessons |
+-------------------+-------------------------------------------+
mysql> SELECT * FROM apothegm WHERE MATCH(attribution,phrase)
    -> AGAINST('bell');
+-----------------------+------------------------------------+
| attribution           | phrase                             |
+-----------------------+------------------------------------+
| Alexander Graham Bell | Mr. Watson, come here. I want you! |
| Miguel de Cervantes   | Bell, book, and candle             |
+-----------------------+------------------------------------+
mysql> SELECT COUNT(*) FROM apothegm WHERE MATCH(phrase) AGAINST('time');
+----------+
| COUNT(*) |

                                                                                            Page | 22
+----------+
|        2 |
+----------+

MySQL Query Optimizer

The MySQL query optimizer takes advantage of indexes, of course, but it also uses other information.
For example, if you issue the following query, MySQL will execute it very quickly, no matter how
large the table is:

SELECT * FROM tbl_name WHERE 1 = 0;

In this case, MySQL looks at the WHERE clause, realizes that no rows can possibly satisfy the query,
and doesn't even bother to search the table. You can see this by issuing an EXPLAIN statement, which
tells MySQL to display some information about how it would execute a SELECT query without
actually executing it. To use EXPLAIN, just put the word EXPLAIN in front of the SELECT statement:

mysql> EXPLAIN SELECT * FROM tbl_name WHERE 1 = 0;
+------------------+
| Comment          |
+------------------+
| Impossible WHERE |
+------------------+

Normally, EXPLAIN returns more information than that, including information about the indexes that
will be used to scan tables, the types of joins that will be used, and estimates of the number of rows
that will need to be scanned from each table.

Overriding Optimization
To empty a table with minimal side effects.

When you need to empty a table completely, it's fastest to have the server just drop the table and re-
create it based on the description stored in its .frm file. To do this, use a TRUNCATE TABLE statement:

TRUNCATE TABLE tbl_name;

Prior to MySQL 4, you can achieve the same effect by using a DELETE statement with no WHERE
clause:

DELETE FROM tbl_name;

To override the optimizer's table join order.

                                                                                              Page | 23
Use STRAIGHT_JOIN to force the optimizer to use tables in a particular order. If you do this, you
should order the tables so that the first table is the one from which the smallest number of rows will
be chosen. In other words, try to order the tables to cause the most restrictive selection to come first.
Queries perform better the earlier you can narrow the possible candidate rows. Make sure to try the
query both ways; there may be some reason the optimizer isn't joining tables the way you think it
should, and STRAIGHT_JOIN may not actually help.

To retrieve results in random order.

You can use ORDER BY RAND() to sort results randomly. Another technique, which is useful for older
versions of MySQL, is to select a column of random numbers and sort on that column. However, if
you try writing the query as follows, the optimizer defeats your intent:

SELECT ..., RAND() as rand_col FROM ... ORDER BY rand_col;

To avoid an endless update loop.

Prior to MySQL 3.23.2, if you update a column that is indexed, it's possible for the rows that are
updated to be updated endlessly if the column is used in the WHERE clause and the update moves the
index value into the part of the range that hasn't been processed yet. Suppose the mytbl table has an
integer column key_col that is indexed. Queries such as the following can cause problems:
UPDATE mytbl SET key_col = key_col+1 WHERE key_col > 0;

The solution for this is to use key_col in an expression term in the WHERE clause such that MySQL
can't use the index:
UPDATE mytbl SET key_col = key_col+1 WHERE key_col+0 > 0;

Indexes
Column Indexes

All MySQL data types can be indexed. Use of indexes on the relevant columns is the best way to
improve the performance of SELECT operations.

With col_name(N) syntax in an index specification, you can create an index that uses only the
first N characters of a string column. Indexing only a prefix of column values in this way can make
the index file much smaller.

CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));

Multiple­Column Indexes

MySQL can create composite indexes (that is, indexes on multiple columns). An index may consist of
up to 15 columns. For certain data types, you can index a prefix of the column.

                                                                                               Page | 24
CREATE TABLE test (
id INT NOT NULL,
last_name CHAR(30) NOT NULL,
first_name CHAR(30) NOT NULL,
PRIMARY KEY (id),
INDEX name (last_name,first_name)
);

The name index is an index over the last_name and first_name columns. The index can be used for
queries that specify values in a known range for last_name, or for both last_name and first_name.
Therefore, the name index is used in the following queries:

SELECT * FROM test WHERE last_name='Widenius';
SELECT * FROM test
WHERE last_name='Widenius' AND first_name='Michael';
SELECT * FROM test
WHERE last_name='Widenius'
AND (first_name='Michael' OR first_name='Monty');
SELECT * FROM test
WHERE last_name='Widenius'
AND first_name >='M' AND first_name < 'N';

However, the name index is not used in the following queries:

SELECT * FROM test WHERE first_name='Michael';
SELECT * FROM test
WHERE last_name='Widenius' OR first_name='Michael';

Stored Procedures and Functions
Stored routines (procedures and functions) are supported in MySQL 5.0. A stored procedure is a set
of SQL statements that can be stored in the server. Once this has been done, clients don't need to keep
reissuing the individual statements but can refer to the stored procedure instead.

CREATE PROCEDURE and CREATE FUNCTION
Syntax
CREATE
      [DEFINER = { user | CURRENT_USER }]
      PROCEDURE sp_name ([proc_parameter[,...]])
      [characteristic ...] routine_body
CREATE
      [DEFINER = { user | CURRENT_USER }]
      FUNCTION sp_name ([func_parameter[,...]])
      RETURNS type
      [characteristic ...] routine_body
proc_parameter:
      [ IN | OUT | INOUT ] param_name type
func_parameter:
      param_name type
type:
      Any valid MySQL data type
characteristic:
      LANGUAGE SQL

                                                                                              Page | 25
[NOT] DETERMINISTIC
      { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
      SQL SECURITY { DEFINER | INVOKER }
      COMMINT 'string'
routine_body:
      Valid SQL procedure statement

CREATE PROCEDURE
mysql> delimiter //
mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
-> BEGIN
-> SELECT COUNT(*) INTO param1 FROM t;
-> END;
-> //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> CALL simpleproc(@a);
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @a;
+------+
| @a   |
+------+
| 3    |
+------+
1 row in set (0.00 sec)

CREATE FUNCTION
mysql> CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)
-> RETURN CONCAT('Hello, ',s,'!');
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT hello('world');
+----------------+
| hello('world') |
+----------------+
| Hello, world! |
+----------------+
1 row in set (0.00 sec)

ALTER PROCEDURE and ALTER FUNCTION Syntax
ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
characteristic:
{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'

DROP PROCEDURE and DROP FUNCTION Syntax
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name

CALL Statement Syntax
CALL sp_name([parameter[,...]])

                                                                       Page | 26
Triggers
Support for triggers is included beginning with MySQL 5.0.2. A trigger is a named database object
that is associated with a table and that is activated when a particular event occurs for the table. For
example, the following statements create a table and an INSERT trigger.
mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
Query OK, 0 rows affected (0.03 sec)
mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account
-> FOR EACH ROW SET @sum = @sum + NEW.amount;
Query OK, 0 rows affected (0.06 sec)

CREATE TRIGGER Syntax
CREATE
[DEFINER = { user | CURRENT_USER }]
TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_stmt

Beginning with MySQL 5.0.10, you can write triggers such as the one named testref shown in this
example:
CREATE TABLE test1(a1 INT);
CREATE TABLE test2(a2 INT);
CREATE TABLE test3(a3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
CREATE TABLE test4(
a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
b4 INT DEFAULT 0
);
DELIMITER |
CREATE TRIGGER testref BEFORE INSERT ON test1
FOR EACH ROW BEGIN
INSERT INTO test2 SET a2 = NEW.a1;
DELETE FROM test3 WHERE a3 = NEW.a1;
UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
END;
|
DELIMITER ;
INSERT INTO test3 (a3) VALUES
(NULL), (NULL), (NULL), (NULL), (NULL),
(NULL), (NULL), (NULL), (NULL), (NULL);
INSERT INTO test4 (a4) VALUES
(0), (0), (0), (0), (0), (0), (0), (0), (0), (0);
Suppose that you insert the following values into table test1 as shown here:
mysql> INSERT INTO test1 VALUES
-> (1), (3), (1), (7), (1), (8), (4), (4);
Query OK, 8 rows affected (0.01 sec)
Records: 8 Duplicates: 0 Warnings: 0

As a result, the data in the four tables will be as follows:
mysql> SELECT * FROM test1;
+------+
| a1   |
+------+
|    1 |
|    3 |
|    1 |
|    7 |
|    1 |

                                                                                                 Page | 27
|    8 |
|    4 |
|    4 |
+------+
8 rows in set (0.00 sec)
mysql> SELECT * FROM test2;
+------+
|   a2 |
+------+
|    1 |
|    3 |
|    1 |
|    7 |
|    1 |
|    8 |
|    4 |
|    4 |
+------+
8 rows in set (0.00 sec)
mysql> SELECT * FROM test3;
+----+
| a3 |
+----+
| 2 |
| 5 |
| 6 |
| 9 |
| 10 |
+----+
5 rows in set (0.00 sec)
mysql> SELECT * FROM test4;
+----+------+
| a4 | b4   |
+----+------+
| 1 |     3 |
| 2 |     0 |
| 3 |     1 |
| 4 |     2 |
| 5 |     0 |
| 6 |     0 |
| 7 |     1 |
| 8 |     1 |
| 9 |     0 |
| 10 |    0 |
+----+------+
10 rows in set (0.00 sec)

DROP TRIGGER Syntax
DROP TRIGGER [schema_name.]trigger_name

View
ALTER VIEW Syntax
ALTER
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = { user | CURRENT_USER }]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement

                                                Page | 28
[WITH [CASCADED | LOCAL] CHECK OPTION]

CREATE VIEW Syntax
CREATE
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = { user | CURRENT_USER }]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]

Example
mysql>    CREATE   TABLE t (qty INT, price INT);
mysql>    INSERT   INTO t VALUES(3, 50);
mysql>    CREATE   VIEW v AS SELECT qty, price, qty*price AS value FROM t;
mysql>    SELECT   * FROM v;
+------+-------+-------+
| qty | price | value |
+------+-------+-------+
|    3 |    50 |   150 |
+------+-------+-------+

If you create a view and then change the query processing environment by changing system variables,
that may affect the results that you get from the view:
mysql> CREATE VIEW v AS SELECT CHARSET(CHAR(65)), COLLATION(CHAR(65));
Query OK, 0 rows affected (0.00 sec)
mysql> SET NAMES 'latin1';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM v;
+-------------------+---------------------+
| CHARSET(CHAR(65)) | COLLATION(CHAR(65)) |
+-------------------+---------------------+
|            latin1 |   latin1_swedish_ci |
+-------------------+---------------------+
1 row in set (0.00 sec)
mysql> SET NAMES 'utf8';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM v;
+-------------------+---------------------+
| CHARSET(CHAR(65)) | COLLATION(CHAR(65)) |
+-------------------+---------------------+
|              utf8 |     utf8_general_ci |
+-------------------+---------------------+
1 row in set (0.00 sec)

DROP VIEW Syntax
DROP VIEW [IF EXISTS]
view_name [, view_name] ...
[RESTRICT | CASCADE]

DROP VIEW removes one or more views. You must have the DROP privilege for each view.

                                                                                          Page | 29
MySQL User Account Management
A MySQL account is defined in terms of a username and the client host or hosts from which the user
can connect to the server. The account also has a password.

When you connect to a MySQL server with a command-line client, you should specify the username
and password for the account that you want to use:

shell> mysql --user=monty --password=guess db_name

If you prefer short options, the command looks like this:

shell> mysql -u monty -pguess db_name

Adding New User Accounts to MySQL

After connecting to the server as root, you can add new accounts. The following statements use
GRANT to set up four new accounts:

mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost'
-> IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%'
-> IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql> GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost';
mysql> GRANT USAGE ON *.* TO 'dummy'@'localhost';

As an alternative to GRANT, you can create the same accounts directly by issuing INSERT
statements and then telling the server to reload the grant tables using FLUSH PRIVILEGES:
shell> mysql --user=root mysql
mysql> INSERT INTO user
-> VALUES('localhost','monty',PASSWORD('some_pass'),
-> 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO user
-> VALUES('%','monty',PASSWORD('some_pass'),
-> 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO user SET Host='localhost',User='admin',
-> Reload_priv='Y', Process_priv='Y';
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('localhost','dummy','');
mysql> FLUSH PRIVILEGES;

To create the accounts with GRANT, use the following statements:
shell> mysql --user=root mysql
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
-> ON bankaccount.*
-> TO 'custom'@'localhost'
-> IDENTIFIED BY 'obscure';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP

                                                                                            Page | 30
-> ON expenses.*
-> TO 'custom'@'whitehouse.gov'
-> IDENTIFIED BY 'obscure';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
-> ON customer.*
-> TO 'custom'@'server.domain'
-> IDENTIFIED BY 'obscure';

To set up the custom accounts without GRANT, use INSERT statements as follows to modify the
grant tables directly:

shell> mysql --user=root mysql
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('localhost','custom',PASSWORD('obscure'));
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('whitehouse.gov','custom',PASSWORD('obscure'));
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('server.domain','custom',PASSWORD('obscure'));
mysql> INSERT INTO db
-> (Host,Db,User,Select_priv,Insert_priv,
-> Update_priv,Delete_priv,Create_priv,Drop_priv)
-> VALUES('localhost','bankaccount','custom',
-> 'Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
-> (Host,Db,User,Select_priv,Insert_priv,
-> Update_priv,Delete_priv,Create_priv,Drop_priv)
-> VALUES('whitehouse.gov','expenses','custom',
-> 'Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO db
-> (Host,Db,User,Select_priv,Insert_priv,
-> Update_priv,Delete_priv,Create_priv,Drop_priv)
-> VALUES('server.domain','customer','custom',
-> 'Y','Y','Y','Y','Y','Y');
mysql> FLUSH PRIVILEGES;

Limiting Account Resources

To set resource limits with a GRANT statement, use a WITH clause that names each resource to be
limited and a per-hour count indicating the limit value. For example, to create a new account that can
access the customer database, but only in a limited fashion, issue this statement:
mysql> GRANT ALL ON customer.* TO 'francis'@'localhost'
-> IDENTIFIED BY 'frank'
-> WITH MAX_QUERIES_PER_HOUR 20
-> MAX_UPDATES_PER_HOUR 10
-> MAX_CONNECTIONS_PER_HOUR 5
-> MAX_USER_CONNECTIONS 2;

To set or change limits for an existing account, use a GRANT USAGE statement at the global level
(ON *.*). The following statement changes the query limit for francis to 100:
mysql> GRANT USAGE ON *.* TO 'francis'@'localhost'
-> WITH MAX_QUERIES_PER_HOUR 100;

                                                                                              Page | 31
Assigning Account Passwords

Passwords may be assigned from the command line by using the mysqladmin command:

shell> mysqladmin -u user_name -h host_name password "newpwd"

The account for which this command resets the password is the one with a user table row that
matches user_name in the User column and the client host from which you connect in the Host
column.
Another way to assign a password to an account is to issue a SET PASSWORD statement:
mysql> SET PASSWORD FOR 'jeffrey'@'%' = PASSWORD('biscuit');

To establish a password when creating a new account, provide a value for the Password column:

shell> mysql -u root mysql
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('%','jeffrey',PASSWORD('biscuit'));
mysql> FLUSH PRIVILEGES;

To change the password for an existing account, use UPDATE to set the Password column value:
shell> mysql -u root mysql
mysql> UPDATE user SET Password = PASSWORD('bagel')
-> WHERE Host = '%' AND User = 'francis';
mysql> FLUSH PRIVILEGES;

Backup and Recovery
Using mysqldump

The most common use of mysqldump is probably for making a backup of an entire database:

shell> mysqldump --opt db_name > backup-file.sql

You can read the dump file back into the server like this:
shell> mysql db_name < backup-file.sql

Or like this:
shell> mysql -e "source /path-to-backup/backup-file.sql" db_name

mysqldump is also very useful for populating databases by copying data from one MySQL server
to another:
shell> mysqldump --opt db_name | mysql --host=remote_host -C db_name

                                                                                          Page | 32
You can also read