This section describes how MySQL relates to the ANSI/ISO SQL standards. MySQL Server has many extensions to the SQL standard, and here you can find out what they are and how to use them. You can also find information about functionality missing from MySQL Server, and how to work around some of the differences.
The SQL standard has been evolving since 1986 and several versions exist. In this manual, “SQL-92” refers to the standard released in 1992, “SQL:1999” refers to the standard released in 1999, and “SQL:2003” refers to the current version of the standard. We use the phrase “the SQL standard” or “standard SQL” to mean the current version of the SQL Standard at any time.
One of our main goals with the product is to continue to work
toward compliance with the SQL standard, but without sacrificing
speed or reliability. We are not afraid to add extensions to SQL
or support for non-SQL features if this greatly increases the
usability of MySQL Server for a large segment of our user base.
The HANDLER
interface is an example of this
strategy. See Section 13.2.3, “HANDLER
Syntax”.
We continue to support transactional and non-transactional databases to satisfy both mission-critical 24/7 usage and heavy Web or logging usage.
MySQL Server was originally designed to work with medium-sized databases (10-100 million rows, or about 100MB per table) on small computer systems. Today MySQL Server handles terabyte-sized databases, but the code can also be compiled in a reduced version suitable for hand-held and embedded devices. The compact design of the MySQL server makes development in both directions possible without any conflicts in the source tree.
Currently, we are not targeting real-time support, although MySQL replication capabilities offer significant functionality.
MySQL supports high-availability database clustering using the
NDBCluster
storage engine. See
Chapter 15, MySQL Cluster.
XML support is to be implemented in a future version of the database server.
Our aim is to support the full ANSI/ISO SQL standard, but without making concessions to speed and quality of the code.
ODBC levels 0-3.51.
The MySQL server can operate in different SQL modes, and can apply these modes differentially for different clients. This capability enables each application to tailor the server's operating mode to its own requirements.
SQL modes control aspects of server operation such as what SQL syntax MySQL should support and what kind of data validation checks it should perform. This makes it easier to use MySQL in different environments and to use MySQL together with other database servers.
You can set the default SQL mode by starting
mysqld with the
--sql-mode="
mode_value
"
option. Beginning with MySQL 4.1, you can also change the mode
at runtime by setting the sql_mode
system
variable with a SET [SESSION|GLOBAL]
sql_mode='
mode_value
'
statement.
For more information on setting the SQL mode, see Section 5.2.5, “The Server SQL Mode”.
You can tell mysqld to run in ANSI mode with
the --ansi
startup option. Running the server
in ANSI mode is the same as starting it with the following
options:
--transaction-isolation=SERIALIZABLE --sql-mode=ANSI
As of MySQL 4.1.1, you can achieve the same effect at runtime by executing these two statements:
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET GLOBAL sql_mode = 'ANSI';
You can see that setting the sql_mode
system
variable to 'ANSI'
enables all SQL mode
options that are relevant for ANSI mode as follows:
mysql>SET GLOBAL sql_mode='ANSI';
mysql>SELECT @@global.sql_mode;
-> 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI'
Note that running the server in ANSI mode with
--ansi
is not quite the same as setting the SQL
mode to 'ANSI'
. The --ansi
option affects the SQL mode and also sets the transaction
isolation level. Setting the SQL mode to
'ANSI'
has no effect on the isolation level.
See Section 5.2.1, “mysqld Command Options”, and Section 1.9.2, “Selecting SQL Modes”.
MySQL Server supports some extensions that you probably won't find in other SQL DBMSs. Be warned that if you use them, your code won't be portable to other SQL servers. In some cases, you can write code that includes MySQL extensions, but is still portable, by using comments of the following form:
/*! MySQL-specific code
*/
In this case, MySQL Server parses and executes the code within
the comment as it would any other SQL statement, but other SQL
servers will ignore the extensions. For example, MySQL Server
recognizes the STRAIGHT_JOIN
keyword in the
following statement, but other servers will not:
SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2 WHERE ...
If you add a version number after the
‘!
’ character, the syntax within
the comment is executed only if the MySQL version is greater
than or equal to the specified version number. The
TEMPORARY
keyword in the following comment is
executed only by servers from MySQL 3.23.02 or higher:
CREATE /*!32302 TEMPORARY */ TABLE t (a INT);
The following descriptions list MySQL extensions, organized by category.
-
Organization of data on disk
MySQL Server maps each database to a directory under the MySQL data directory, and maps tables within a database to filenames in the database directory. This has a few implications:
-
Database and table names are case sensitive in MySQL Server on operating systems that have case-sensitive filenames (such as most Unix systems). See Section 9.2.2, “Identifier Case Sensitivity”.
-
You can use standard system commands to back up, rename, move, delete, and copy tables that are managed by the
MyISAM
storage engine. For example, it is possible to rename aMyISAM
table by renaming the.MYD
,.MYI
, and.frm
files to which the table corresponds. (Nevertheless, it is preferable to useRENAME TABLE
orALTER TABLE ... RENAME
and let the server rename the files.)
Database and table names cannot contain pathname separator characters (‘
/
’, ‘\
’). -
-
General language syntax
-
By default, strings can be enclosed by either ‘
"
’ or ‘'
’, not just by ‘'
’. (If theANSI_QUOTES
SQL mode is enabled, strings can be enclosed only by ‘'
’ and the server interprets strings enclosed by ‘"
’ as identifiers.) -
‘
\
’ is the escape character in strings. -
In SQL statements, you can access tables from different databases with the
db_name.tbl_name
syntax. Some SQL servers provide the same functionality but call thisUser space
. MySQL Server doesn't support tablespaces such as used in statements like this:CREATE TABLE ralph.my_table ... IN my_tablespace
.
-
-
SQL statement syntax
-
The
ANALYZE TABLE
,CHECK TABLE
,OPTIMIZE TABLE
, andREPAIR TABLE
statements. -
The
CREATE DATABASE
,DROP DATABASE
, andALTER DATABASE
statements. See Section 13.1.3, “CREATE DATABASE
Syntax”, Section 13.1.6, “DROP DATABASE
Syntax”, and Section 13.1.1, “ALTER DATABASE
Syntax”. -
The
DO
statement. -
EXPLAIN SELECT
to obtain a description of how tables are processed by the query optimizer. -
The
FLUSH
andRESET
statements. -
The
SET
statement. See Section 13.5.3, “SET
Syntax”. -
The
SHOW
statement. See Section 13.5.4, “SHOW
Syntax”. As of MySQL 5.0, the information produced by many of the MySQL-specificSHOW
statements can be obtained in more standard fashion by usingSELECT
to queryINFORMATION_SCHEMA
. See Chapter 20, TheINFORMATION_SCHEMA
Database. -
Use of
LOAD DATA INFILE
. In many cases, this syntax is compatible with Oracle'sLOAD DATA INFILE
. See Section 13.2.5, “LOAD DATA INFILE
Syntax”. -
Use of
RENAME TABLE
. See Section 13.1.9, “RENAME TABLE
Syntax”. -
Use of
REPLACE
instead ofDELETE
plusINSERT
. See Section 13.2.6, “REPLACE
Syntax”. -
Use of
CHANGE
col_name
,DROP
col_name
, orDROP INDEX
,IGNORE
orRENAME
inALTER TABLE
statements. Use of multipleADD
,ALTER
,DROP
, orCHANGE
clauses in anALTER TABLE
statement. See Section 13.1.2, “ALTER TABLE
Syntax”. -
Use of index names, indexes on a prefix of a column, and use of
INDEX
orKEY
inCREATE TABLE
statements. See Section 13.1.5, “CREATE TABLE
Syntax”. -
Use of
TEMPORARY
orIF NOT EXISTS
withCREATE TABLE
. -
Use of
IF EXISTS
withDROP TABLE
andDROP DATABASE
. -
The capability of dropping multiple tables with a single
DROP TABLE
statement. -
The
ORDER BY
andLIMIT
clauses of theUPDATE
andDELETE
statements. -
INSERT INTO
tbl_name
SETcol_name
= ... syntax. -
The
DELAYED
clause of theINSERT
andREPLACE
statements. -
The
LOW_PRIORITY
clause of theINSERT
,REPLACE
,DELETE
, andUPDATE
statements. -
Use of
INTO OUTFILE
orINTO DUMPFILE
inSELECT
statements. See Section 13.2.7, “SELECT
Syntax”. -
Options such as
STRAIGHT_JOIN
orSQL_SMALL_RESULT
inSELECT
statements. -
You don't need to name all selected columns in the
GROUP BY
clause. This gives better performance for some very specific, but quite normal queries. See Section 12.10, “Functions and Modifiers for Use withGROUP BY
Clauses”. -
You can specify
ASC
andDESC
withGROUP BY
, not just withORDER BY
. -
The ability to set variables in a statement with the
:=
assignment operator:mysql>
SELECT @a:=SUM(total),@b=COUNT(*),@a/@b AS avg
->FROM test_table;
mysql>SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
-
-
Data types
-
The
MEDIUMINT
,SET
, andENUM
data types, and the variousBLOB
andTEXT
data types. -
The
AUTO_INCREMENT
,BINARY
,NULL
,UNSIGNED
, andZEROFILL
data type attributes.
-
-
Functions and operators
-
To make it easier for users who migrate from other SQL environments, MySQL Server supports aliases for many functions. For example, all string functions support both standard SQL syntax and ODBC syntax.
-
MySQL Server understands the
||
and&&
operators to mean logical OR and AND, as in the C programming language. In MySQL Server,||
andOR
are synonyms, as are&&
andAND
. Because of this nice syntax, MySQL Server doesn't support the standard SQL||
operator for string concatenation; useCONCAT()
instead. BecauseCONCAT()
takes any number of arguments, it's easy to convert use of the||
operator to MySQL Server. -
Use of
COUNT(DISTINCT
value_list
) wherevalue_list
has more than one element. -
String comparisons are case-insensitive by default, with sort ordering determined by collation of the current character set, which is
latin1
(cp1252 West European) by default. If you don't like this, you should declare your columns with theBINARY
attribute or use theBINARY
cast, which causes comparisons to be done using the underlying character code values rather then a lexical ordering. -
The
%
operator is a synonym forMOD()
. That is,N
%M
is equivalent toMOD(
N
,M
).%
is supported for C programmers and for compatibility with PostgreSQL. -
The
=
,<>
,<=
,<
,>=
,>
,<<
,>>
,<=>
,AND
,OR
, orLIKE
operators may be used in expressions in the output column list (to the left of theFROM
) inSELECT
statements. For example:mysql>
SELECT col1=1 AND col2=2 FROM my_table;
-
The
LAST_INSERT_ID()
function returns the most recentAUTO_INCREMENT
value. See Section 12.9.3, “Information Functions”. -
LIKE
is allowed on numeric values. -
The
REGEXP
andNOT REGEXP
extended regular expression operators. -
CONCAT()
orCHAR()
with one argument or more than two arguments. (In MySQL Server, these functions can take a variable number of arguments.) -
The
BIT_COUNT()
,CASE
,ELT()
,FROM_DAYS()
,FORMAT()
,IF()
,PASSWORD()
,ENCRYPT()
,MD5()
,ENCODE()
,DECODE()
,PERIOD_ADD()
,PERIOD_DIFF()
,TO_DAYS()
, andWEEKDAY()
functions. -
Use of
TRIM()
to trim substrings. Standard SQL supports removal of single characters only. -
The
GROUP BY
functionsSTD()
,BIT_OR()
,BIT_AND()
,BIT_XOR()
, andGROUP_CONCAT()
. See Section 12.10, “Functions and Modifiers for Use withGROUP BY
Clauses”.
-
For a prioritized list indicating when new extensions are added to MySQL Server, you should consult the online MySQL development roadmap at http://dev.mysql.com/doc/mysql/en/roadmap.html.
We try to make MySQL Server follow the ANSI SQL standard and the ODBC SQL standard, but MySQL Server performs operations differently in some cases:
-
For
VARCHAR
columns, trailing spaces are removed when the value is stored. (This is fixed in MySQL 5.0.3). See Section A.8, “Known Issues in MySQL”. -
In some cases,
CHAR
columns are silently converted toVARCHAR
columns when you define a table or alter its structure. (This is fixed in MySQL 5.0.3). See Section 13.1.5.1, “Silent Column Specification Changes”. -
There are several differences between the MySQL and standard SQL privilege systems. For example, in MySQL, privileges for a table are not automatically revoked when you delete a table. You must explicitly issue a
REVOKE
statement to revoke privileges for a table. For more information, see Section 13.5.1.5, “REVOKE
Syntax”. -
The
CAST()
function does not support cast toREAL
orBIGINT
. See Section 12.8, “Cast Functions and Operators”. -
Standard SQL requires that a
HAVING
clause in aSELECT
statement be able to refer to columns in theGROUP BY
clause. This cannot be done before MySQL 5.0.2.
MySQL 4.1 and up supports subqueries and derived tables. A
“subquery” is a SELECT
statement nested within another statement. A “derived
table” (an unnamed view) is a subquery in the
FROM
clause of another statement. See
Section 13.2.8, “Subquery Syntax”.
For MySQL versions older than 4.1, most subqueries can be rewritten using joins or other methods. See Section 13.2.8.11, “Rewriting Subqueries as Joins for Earlier MySQL Versions”, for examples that show how to do this.
MySQL Server doesn't support the SELECT ... INTO
TABLE
Sybase SQL extension. Instead, MySQL Server
supports the INSERT INTO ... SELECT
standard SQL syntax, which is basically the same thing. See
Section 13.2.4.1, “INSERT ... SELECT
Syntax”. For example:
INSERT INTO tbl_temp2 (fld_id) SELECT tbl_temp1.fld_order_id FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
Alternatively, you can use SELECT ... INTO
OUTFILE
or CREATE TABLE ...
SELECT
.
As of MySQL 5.0, you can use SELECT ...
INTO
with user-defined variables. The same syntax
can also be used inside stored routines using cursors and
local variables. See Section 17.2.7.3, “SELECT ... INTO
Statement”.
MySQL Server (version 3.23-max and all versions 4.0 and above)
supports transactions with the InnoDB
and
BDB
transactional storage engines.
InnoDB
provides full
ACID
compliance. See
Chapter 14, Storage Engines and Table Types. For information about
InnoDB
differences from standard SQL with
regard to treatment of transaction errors, see
Section 14.2.15, “InnoDB
Error Handling”.
The other non-transactional storage engines in MySQL Server
(such as MyISAM
) follow a different
paradigm for data integrity called “atomic
operations.” In transactional terms,
MyISAM
tables effectively always operate in
AUTOCOMMIT=1
mode. Atomic operations often
offer comparable integrity with higher performance.
Because MySQL Server supports both paradigms, you can decide whether your applications are best served by the speed of atomic operations or the use of transactional features. This choice can be made on a per-table basis.
As noted, the trade-off for transactional versus
non-transactional storage engines lies mostly in performance.
Transactional tables have significantly higher memory and disk
space requirements, and more CPU overhead. On the other hand,
transactional storage engines such as
InnoDB
also offer many significant
features. MySQL Server's modular design allows the concurrent
use of different storage engines to suit different
requirements and deliver optimum performance in all
situations.
But how do you use the features of MySQL Server to maintain
rigorous integrity even with the non-transactional
MyISAM
tables, and how do these features
compare with the transactional storage engines?
-
If your applications are written in a way that is dependent on being able to call
ROLLBACK
rather thanCOMMIT
in critical situations, transactions are more convenient. Transactions also ensure that unfinished updates or corrupting activities are not committed to the database; the server is given the opportunity to do an automatic rollback and your database is saved.If you use non-transactional tables, MySQL Server in almost all cases allows you to resolve potential problems by including simple checks before updates and by running simple scripts that check the databases for inconsistencies and automatically repair or warn if such an inconsistency occurs. Note that just by using the MySQL log or even adding one extra log, you can normally fix tables perfectly with no data integrity loss.
-
More often than not, critical transactional updates can be rewritten to be atomic. Generally speaking, all integrity problems that transactions solve can be done with
LOCK TABLES
or atomic updates, ensuring that there are no automatic aborts from the server, which is a common problem with transactional database systems. -
To be safe with MySQL Server, regardless of whether you use transactional tables, you only need to have backups and have binary logging turned on. When that is true, you can recover from any situation that you could with any other transactional database system. It is always good to have backups, regardless of which database system you use.
The transactional paradigm has its benefits and its drawbacks. Many users and application developers depend on the ease with which they can code around problems where an abort appears to be necessary, or is necessary. However, even if you are new to the atomic operations paradigm, or more familiar with transactions, do consider the speed benefit that non-transactional tables can offer on the order of three to five times the speed of the fastest and most optimally tuned transactional tables.
In situations where integrity is of highest importance, MySQL
Server offers transaction-level reliability and integrity even
for non-transactional tables. If you lock tables with
LOCK TABLES
, all updates stall until
integrity checks are made. If you obtain a READ
LOCAL
lock (as opposed to a write lock) for a table
that allows concurrent inserts at the end of the table, reads
are allowed, as are inserts by other clients. The newly
inserted records are not be seen by the client that has the
read lock until it releases the lock. With INSERT
DELAYED
, you can write inserts that go into a local
queue until the locks are released, without having the client
wait for the insert to complete. See
Section 7.3.3, “Concurrent Inserts”, and
Section 13.2.4.2, “INSERT DELAYED
Syntax”.
“Atomic,” in the sense that we mean it, is nothing magical. It only means that you can be sure that while each specific update is running, no other user can interfere with it, and there can never be an automatic rollback (which can happen with transactional tables if you are not very careful). MySQL Server also guarantees that there are no dirty reads.
Following are some techniques for working with non-transactional tables:
-
Loops that need transactions normally can be coded with the help of
LOCK TABLES
, and you don't need cursors to update records on the fly. -
To avoid using
ROLLBACK
, you can employ the following strategy:-
Use
LOCK TABLES
to lock all the tables you want to access. -
Test the conditions that must be true before performing the update.
-
Update if the conditions are satisfied.
-
Use
UNLOCK TABLES
to release your locks.
This is usually a much faster method than using transactions with possible rollbacks, although not always. The only situation this solution doesn't handle is when someone kills the threads in the middle of an update. In that case, all locks are released but some of the updates may not have been executed.
-
-
You can also use functions to update records in a single operation. You can get a very efficient application by using the following techniques:
-
Modify columns relative to their current value.
-
Update only those columns that actually have changed.
For example, when we are updating customer information, we update only the customer data that has changed and test only that none of the changed data, or data that depends on the changed data, has changed compared to the original row. The test for changed data is done with the
WHERE
clause in theUPDATE
statement. If the record wasn't updated, we give the client a message: “Some of the data you have changed has been changed by another user.” Then we show the old row versus the new row in a window so that the user can decide which version of the customer record to use.This gives us something that is similar to column locking but is actually even better because we only update some of the columns, using values that are relative to their current values. This means that typical
UPDATE
statements look something like these:UPDATE tablename SET pay_back=pay_back+125; UPDATE customer SET customer_date='current_date', address='new address', phone='new phone', money_owed_to_us=money_owed_to_us-125 WHERE customer_id=id AND address='old address' AND phone='old phone';
This is very efficient and works even if another client has changed the values in the
pay_back
ormoney_owed_to_us
columns. -
-
In many cases, users have wanted
LOCK TABLES
orROLLBACK
for the purpose of managing unique identifiers. This can be handled much more efficiently without locking or rolling back by using anAUTO_INCREMENT
column and either theLAST_INSERT_ID()
SQL function or themysql_insert_id()
C API function. See Section 12.9.3, “Information Functions”, and Section 22.2.3.36, “mysql_insert_id()
”.You can generally code around the need for row-level locking. Some situations really do need it, and
InnoDB
tables support row-level locking. Otherwise, withMyISAM
tables, you can use a flag column in the table and do something like the following:UPDATE
tbl_name
SET row_flag=1 WHERE id=ID;MySQL returns
1
for the number of affected rows if the row was found androw_flag
wasn't1
in the original row. You can think of this as though MySQL Server changed the preceding statement to:UPDATE
tbl_name
SET row_flag=1 WHERE id=ID AND row_flag <> 1;
Stored procedures and functions are implemented beginning with MySQL 5.0. See Chapter 17, Stored Procedures and Functions.
Basic trigger functionality is implemented beginning with MySQL 5.0.2, with further development planned for MySQL 5.1. See Chapter 18, Triggers.
In MySQL Server 3.23.44 and up, the InnoDB
storage engine supports checking of foreign key constraints,
including CASCADE
, ON
DELETE
, and ON UPDATE
. See
Section 14.2.6.4, “FOREIGN KEY
Constraints”.
For storage engines other than InnoDB
,
MySQL Server parses the FOREIGN KEY
syntax
in CREATE TABLE
statements, but does not
use or store it. In the future, the implementation will be
extended to store this information in the table specification
file so that it may be retrieved by
mysqldump and ODBC. At a later stage,
foreign key constraints will be implemented for
MyISAM
tables as well.
Foreign key enforcement offers several benefits to database developers:
-
Assuming proper design of the relationships, foreign key constraints make it more difficult for a programmer to introduce an inconsistency into the database.
-
Centralized checking of constraints by the database server makes it unnecessary to perform these checks on the application side. This eliminates the possibility that different applications may not all check the constraints in the same way.
-
Using cascading updates and deletes can simplify the application code.
-
Properly designed foreign key rules aid in documenting relationships between tables.
Do keep in mind that these benefits come at the cost of additional overhead for the database server to perform the necessary checks. Additional checking by the server affects performance, which for some applications may be sufficiently undesirable as to be avoided if possible. (Some major commercial applications have coded the foreign key logic at the application level for this reason.)
MySQL gives database developers the choice of which approach
to use. If you don't need foreign keys and want to avoid the
overhead associated with enforcing referential integrity, you
can choose another storage engine instead, such as
MyISAM
. (For example, the
MyISAM
storage engine offers very fast
performance for applications that perform only
INSERT
and SELECT
operations. In this case, the table has no holes in the middle
and the inserts can be performed concurrently with retrievals.
See Section 7.3.3, “Concurrent Inserts”.)
If you choose not to take advantage of referential integrity checks, keep the following considerations in mind:
-
In the absence of server-side foreign key relationship checking, the application itself must handle relationship issues. For example, it must take care to insert rows into tables in the proper order, and to avoid creating orphaned child records. It must also be able to recover from errors that occur in the middle of multiple-record insert operations.
-
If
ON DELETE
is the only referential integrity capability an application needs, you can achieve a similar effect as of MySQL Server 4.0 by using multiple-tableDELETE
statements to delete rows from many tables with a single statement. See Section 13.2.1, “DELETE
Syntax”. -
A workaround for the lack of
ON DELETE
is to add the appropriateDELETE
statements to your application when you delete records from a table that has a foreign key. In practice, this is often as quick as using foreign keys and is more portable.
Be aware that the use of foreign keys can sometimes lead to problems:
-
Foreign key support addresses many referential integrity issues, but it is still necessary to design key relationships carefully to avoid circular rules or incorrect combinations of cascading deletes.
-
It is not uncommon for a DBA to create a topology of relationships that makes it difficult to restore individual tables from a backup. (MySQL alleviates this difficulty by allowing you to temporarily disable foreign key checks when reloading a table that depends on other tables. See Section 14.2.6.4, “
FOREIGN KEY
Constraints”. As of MySQL 4.1.1, mysqldump generates dump files that take advantage of this capability automatically when they are reloaded.)
Note that foreign keys in SQL are used to check and enforce
referential integrity, not to join tables. If you want to get
results from multiple tables from a SELECT
statement, you do this by performing a join between them:
SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.id;
See Section 13.2.7.1, “JOIN
Syntax”, and
Section 3.6.6, “Using Foreign Keys”.
The FOREIGN KEY
syntax without ON
DELETE ...
is often used by ODBC applications to
produce automatic WHERE
clauses.
Views (including updatable views) are implemented beginning with MySQL Server 5.0.1. See Chapter 19, Views.
Views are useful for allowing users to access a set of relations (tables) as if it were a single table, and limiting their access to just that. Views can also be used to restrict access to rows (a subset of a particular table). For access control to columns, you can also use the sophisticated privilege system in MySQL Server. See Section 5.8, “The MySQL Access Privilege System”.
In designing an implementation of views, our ambitious goal, as much as is possible within the confines of SQL, has been full compliance with “Codd's Rule #6” for relational database systems: “All views that are theoretically updatable, should in practice also be updatable.”
Standard SQL uses the C syntax /* this is a comment
*/
for comments, and MySQL Server supports this
syntax as well. MySQL also support extensions to this syntax
that allow MySQL-specific SQL to be embedded in the comment,
as described in Section 9.4, “Comment Syntax”.
Standard SQL uses ‘--
’ as a
start-comment sequence. MySQL Server uses
‘#
’ as the start comment
character. MySQL Server 3.23.3 and up also supports a variant
of the ‘--
’ comment style. That
is, the ‘--
’ start-comment
sequence must be followed by a space (or by a control
character such as a newline). The space is required to prevent
problems with automatically generated SQL queries that use
constructs such as the following, where we automatically
insert the value of the payment for
payment
:
UPDATE account SET credit=credit-payment
Consider about what happens if payment
has
a negative value such as -1
:
UPDATE account SET credit=credit--1
credit--1
is a legal expression in SQL, but
‘--
’ is interpreted as the
start of a comment, part of the expression is discarded. The
result is a statement that has a completely different meaning
than intended:
UPDATE account SET credit=credit
The statement produces no change in value at all. This
illustrates that allowing comments to start with
‘--
’ can have serious
consequences.
Using our implementation requires a space following the
‘--
’ in order for it to be
recognized as a start-comment sequence in MySQL Server 3.23.3
and newer. Therefore, credit--1
is safe to
use.
Another safe feature is that the mysql
command-line client ignores lines that start with
‘--
’.
The following information is relevant only if you are running a MySQL version earlier than 3.23.3:
If you have an SQL script in a text file that contains
‘--
’ comments, you should use
the replace utility as follows to convert
the comments to use ‘#
’
characters before executing the script:
shell>replace " --" " #" < text-file-with-funny-comments.sql \
| mysql
db_name
That is safer than executing the script in the usual way:
shell>mysql
db_name
< text-file-with-funny-comments.sql
You can also edit the script file “in place” to
change the ‘--
’ comments to
‘#
’ comments:
shell> replace " --" " #" -- text-file-with-funny-comments.sql
Change them back with this command:
shell> replace " #" " --" -- text-file-with-funny-comments.sql
MySQL allows you to work both with transactional tables that allow rollback and with non-transactional tables that do not. Because of this, constraint handling is a bit different in MySQL than in other DBMSs. We must handle the case when you have inserted or updated a lot of rows in a non-transactional table for which changes cannot be rolled back when an error occurs.
The basic philosophy is that MySQL Server tries to produce an error for anything that it can detect while parsing a statement to be executed, and tries to recover from any errors that occur while executing the statement. We do this in most cases, but not yet for all.
The options MySQL has when an error occurs are to stop the statement in the middle or to recover as well as possible from the problem and continue. By default, the server follows the latter course. This means, for example, that the server may coerce illegal values to the closest legal values.
Beginning with MySQL 5.0.2, several SQL mode options are available to provide greater control over handling of bad data values and whether to continue statement execution or abort when errors occur. Using these options, you can configure MySQL Server to act in a more traditional fashion that is like other DBMSs that reject improper input. The SQL mode can be set globally at server startup to affect all clients. Individual clients can set the SQL mode at runtime, which enables each client to select the behavior most appropriate for its requirements. See Section 5.2.5, “The Server SQL Mode”.
The following sections describe how MySQL Server handles different types of constraints.
Normally, an error occurs when you try to
INSERT
or UPDATE
a row
that causes a primary key, unique key, or foreign key
violation. If you are using a transactional storage engine
such as InnoDB
, MySQL automatically rolls
back the statement. If you are using a non-transactional
storage engine, MySQL stops processing the statement at the
row for which the error occurred and leaves any remaining rows
unprocessed.
If you want to ignore such key violations, MySQL supports an
IGNORE
keyword for
INSERT
and UPDATE
. In
this case, MySQL ignores any key violations and continues
processing with the next row. See Section 13.2.4, “INSERT
Syntax”,
and Section 13.2.10, “UPDATE
Syntax”.
You can get information about the number of rows actually
inserted or updated with the mysql_info()
C
API function. In MySQL 4.1 and up, you also can use the
SHOW WARNINGS
statement. See
Section 22.2.3.34, “mysql_info()
”, and
Section 13.5.4.25, “SHOW WARNINGS
Syntax”.
Currently, only InnoDB
tables support
foreign keys. See
Section 14.2.6.4, “FOREIGN KEY
Constraints”. Foreign key
support in MyISAM
tables is scheduled for
implementation in MySQL 5.2. See Section 1.6, “MySQL Development Roadmap”.
Before MySQL 5.0.2, MySQL is forgiving of illegal or improper data values and coerces them to legal values for data entry. In MySQL 5.0.2 and up, that remains the default behavior, but you can change the server SQL mode to select more traditional treatment of bad values such that the server rejects them and aborts the statement in which they occur. Section 5.2.5, “The Server SQL Mode”.
This section describes the default (forgiving) behavior of MySQL, as well as the newer strict SQL mode and how it differs.
If you are not using strict mode, then whenever you insert an
“incorrect” value into a column, such as a
NULL
into a NOT NULL
column or a too-large numeric value into a numeric column,
MySQL sets the column to the “best possible
value” instead of producing an error: The following
rules describe in more detail how this works:
-
If you try to store an out of range value into a numeric column, MySQL Server instead stores zero, the smallest possible value, or the largest possible value, whichever is closest to the invalid value.
-
For strings, MySQL stores either the empty string or as much of the string as can be stored in the column.
-
If you try to store a string that doesn't start with a number into a numeric column, MySQL Server stores 0.
-
Invalid values for
ENUM
andSET
columns ae handled as described in Section 1.9.6.3, “ENUM
andSET
Constraints”. -
MySQL allows you to store certain incorrect date values into
DATE
andDATETIME
columns (such as'2000-02-31'
or'2000-02-00'
). The idea is that it's not the job of the SQL server to validate dates. If MySQL can store a date value and retrieve exactly the same value, MySQL stores it as given. If the date is totally wrong (outside the server's ability to store it), the special “zero” date value'0000-00-00'
is stored in the column instead. -
If you try to store
NULL
into a column that doesn't takeNULL
values, an error occurs for single-rowINSERT
statements. For multiple-rowINSERT
statements or forINSERT INTO ... SELECT
statements, MySQL Server stores the implicit default value for the column data type. In general, this is0
for numeric types, the empty string (''
) for string types, and the “zero” value for date and time types. Implicit default values are discussed in Section 11.1.4, “Data Type Default Values”. -
If an
INSERT
statement specifies no value for a column, MySQL inserts its default value if the column definition includes an explicitDEFAULT
clause. If the definition has no suchDEFAULT
clause, MySQL inserts the implicit default value for the column data type.
The reason for using the preceding rules in non-strict mode is that we can't check these conditions until the statement has begun executing. We can't just roll back if we encounter a problem after updating a few rows, because the storage engine may not support rollback. The option of terminating the statement is not that good; in this case, the update would be “half done,” which is probably the worst possible scenario. In this case, it's better to “do the best you can” and then continue as if nothing happened.
In MySQL 5.0.2 and up, you can select stricter treatment of
input values by using the
STRICT_TRANS_TABLES
or
STRICT_ALL_TABLES
SQL modes:
SET sql_mode = 'STRICT_TRANS_TABLES'; SET sql_mode = 'STRICT_ALL_TABLES';
STRICT_TRANS_TABLES
enables strict mode for
transactional storage engines, and also to some extent for
non-transactional engines. It works like this:
-
For transactional storage engines, bad data values occurring anywhere in a statement cause the statement to abort and roll back.
-
For non-transactional storage engines, a statement aborts if the error occurs in the first row to be inserted or updated. (When the error occurs in the first row, the statement can be aborted to leave the table unchanged, just as for a transactional table.) Errors in rows after the first do not abort the statement, because the table has already been changed by the first row. Instead, bad data values are adjusted and result in warnings rather than errors. In other words, with
STRICT_TRANS_TABLES
, a wrong value causes MySQL to roll back all updates done so far, if that can be done without changing the table. But once the table has been changed, further errors result in adjustments and warnings.
For even stricter checking, enable
STRICT_ALL_TABLES
. This is the same as
STRICT_TRANS_TABLES
except that for
non-transactional storage engines, errors abort the statement
even for bad data in rows following the first row. This means
that if an error occurs partway through a multiple-row insert
or update for a non-transactional table, a partial update
results. Earlier rows are inserted or updated, but those from
the point of the error on are not. To avoid this for
non-transactional tables, either use single-row statements or
else use STRICT_TRANS_TABLES
if conversion
warnings rather than errors are acceptable. To avoid problems
in the first place, do not use MySQL to check column content.
It is safest (and often faster) to let the application ensure
that it passes only legal values to the database.
With either of the strict mode options, you can cause errors
to be treated as warnings by using INSERT
IGNORE
or UPDATE IGNORE
rather
than INSERT
or UPDATE
without IGNORE
.
ENUM
and SET
columns
provide an efficient way to define columns that can contain
only a given set of values. See Section 11.4.4, “The ENUM
Type”, and
Section 11.4.5, “The SET
Type”. However, before MySQL 5.0.2,
ENUM
and SET
columns do
not provide true constraints on entry of invalid data:
-
ENUM
columns always have a default value. If you specify no default value, then it isNULL
for columns that can haveNULL
, otherwise it is the first enumeration value in the column definition. -
If you insert an incorrect value into an
ENUM
column or if you force a value into anENUM
column withIGNORE
, it is set to the reserved enumeration value of0
, which is displayed as an empty string in string context. -
If you insert an incorrect value into a
SET
column, the incorrect value is ignored. For example, if the column can contain the values'a'
,'b'
, and'c'
, an attempt to assign'a,x,b,y'
results in a value of'a,b'
.
As of MySQL 5.0.2, you can configure the server to use strict
SQL mode. See Section 5.2.5, “The Server SQL Mode”. With strict
mode enabled, the definition of a ENUM
or
SET
column does act as a constraint on
values entered into the column. An error occurs for values
that do not satisfy these conditions:
-
An
ENUM
value must be one of those listed in the column definition, or the internal numeric equivalent thereof. The value cannot be the error value (that is, 0 or the empty string). For a column defined asENUM('a','b','c')
, values such as''
,'d'
, or'ax'
are illegal and are rejected. -
A
SET
value must be the empty string or a value consisting only of the values listed in the column definition separated by commas. For a column defined asSET('a','b','c')
, values such as'd'
or'a,b,c,d'
are illegal and are rejected.
Errors for invalid values can be suppressed in strict mode if
you use INSERT IGNORE
or UPDATE
IGNORE
. In this case, a warning is generated rather
than an error. For ENUM
, the value is
inserted as the error member (0
). For
SET
, the value is inserted as given except
that any invalid substrings are deleted. For example,
'a,x,b,y'
results in a value of
'a,b'
.