MYSQL 5.X DOCUMENTATION - LOCALIZATION OF E-GOVERNANCE PROJECT - PREPARED BY: PROJECT TEAM
←
→
Page content transcription
If your browser does not render page correctly, please read the page content below
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 NonMatching (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))); MultipleColumn 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