MySQL includes some extensions that you probably
will not find in other SQL databases. Be warned that if you use them,
your code will not be portable to other SQL servers.
In some cases, you
can still write portable code that includes MySQL
extensions by using comments of the form /*! ... */. In this
case, MySQL will execute the code within the comment. For example:
SELECT /*! STRAIGHT_JOIN */ col_name from table1,table2 WHERE ...
MySQL extensions are listed below:
MEDIUMINT, SET, ENUM and the
different BLOB and TEXT types.
AUTO_INCREMENT, BINARY,
UNSIGNED and ZEROFILL.
BINARY
attribute, which causes comparisons to be done according to the ASCII order
used on the MySQL server host.
db_name.tbl_name syntax. Some SQL servers provide
the same functionality but call this User space.
MySQL dosen't support tablespaces like in:
create table ralph.my_table...IN my_tablespace.
LIKE is allowed on numeric columns.
INTO OUTFILE and STRAIGHT_JOIN in a SELECT
statement. See section 7.11 SELECT syntax.
EXPLAIN SELECT to get a description on how tables are joined.
INDEX or KEY in a CREATE TABLE
statement. See section 7.6 CREATE TABLE syntax.
CHANGE col_name, DROP col_name or DROP INDEX
in an ALTER TABLE statement. See section 7.7 ALTER TABLE syntax.
IGNORE in an ALTER TABLE statement.
ADD, ALTER, DROP or CHANGE
clauses in an ALTER TABLE statement.
DROP TABLE with the keywords IF EXISTS.
DROP TABLE with more than one table.
LOAD DATA INFILE. In many cases, this syntax is compatible with
Oracle's LOAD DATA INFILE. See section 7.15 LOAD DATA INFILE syntax.
OPTIMIZE TABLE.
SET OPTION statement. See section 7.24 SET OPTION syntax.
GROUP BY part.
This gives better performance for some very specific, but quite normal
queries.
See section 7.3.12 Functions for use with GROUP BY clauses.
|| and && operators to mean
logical OR and AND, as in the C programming language. In MySQL,
|| and OR are synonyms, as are && and AND.
Because of this nice syntax, MySQL doesn't support
the ANSI SQL operator || for string concatenation; use
CONCAT() instead. Since CONCAT() takes any number
of arguments, it's easy to convert use of the || operator to
MySQL.
STRAIGHT_JOIN in
SQL code that should be portable, you can embed them in a /* */
comment that starts with a '!'. In this case MySQL will
parse the comment as it would any other MySQL statement, but
other SQL servers will ignore the extensions. For example:
SELECT /*! STRAIGHT_JOIN */ * from table1,table2 WHERE ...
CREATE DATABASE or DROP DATABASE.
See section 7.4 CREATE DATABASE syntax.
% instead of MOD(). % is supported for C programmers and
for compatibility with PostgreSQL.
=, <>, <= ,<, >=,>, <<,
>>, AND, OR or LIKE in a column statement.
LAST_INSERT_ID().
See section 18.4.49 How can I get the unique ID for the last inserted row?.
REGEXP or NOT REGEXP.
CONCAT() or CHAR() with one or more than two arguments. In
MySQL these functions can take any number of arguments.
BIT_COUNT(), ELT(), FROM_DAYS(), FORMAT(),
IF(), PASSWORD(), ENCRYPT(),
PERIOD_ADD(), PERIOD_DIFF(), TO_DAYS(),
or WEEKDAY().
TRIM() to trim substrings. ANSI SQL only supports removal
of single characters.
STD(), BIT_OR() and BIT_AND() group functions.
REPLACE instead of DELETE + INSERT.
See section 7.14 REPLACE syntax.
FLUSH flush_option command.
The following functionality is missing in the current version of MySQL. For the priority of new extensions, you should consult the MySQL TODO list. That is the latest version of the TODO list in this manual. See section F List of things we want to add to MySQL in the future (The TODO).
The following will not work in MySQL:
SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);
MySQL only supports INSERT ... SELECT ... and REPLACE
... SELECT ... Independent sub-selects will be probably be available in
3.23.0. You can now use the function IN() in other contexts,
however.
SELECT INTO TABLE
MySQL doesn't yet support SELECT ... INTO TABLE .... Currently,
MySQL only supports SELECT ... INTO OUTFILE ..., which is basically the
same thing.
Transactions are not supported. MySQL shortly will support
atomic operations, which are like transactions without rollback. With
atomic operations, you can execute a group of insert/select/whatever
commands and be guaranteed that no other thread will interfere. In this
context, you won't usually need rollback. Currently, you can prevent
interference from other threads with the help of the LOCK TABLES
and UNLOCK TABLES commands.
See section 7.23 LOCK TABLES/UNLOCK TABLES syntax.
A stored procedure is a set of SQL commands that can be compiled and stored in the server. Once this has been done, clients don't need to keep reissuing the entire query but can refer to the stored procedure. This provides more speed because the query has to be parsed only once and less data need be sent between the server and the client. You can also raise the conceptual level by having libraries of functions in the server.
A trigger is a stored procedure that is invoked when a particlar event occurs. For example, you can install a stored procedure that is triggered each time a record is deleted from a transaction table and that automatically deletes the corresponding customer from a customer table when all his transactions are deleted.
The planned update language will be able to handle stored procedures, but without triggers. Triggers usually slow down everything, even queries for which they are not needed.
To see when MySQL might get stored procedures, see section F List of things we want to add to MySQL in the future (The TODO).
Note that foreign keys in SQL are not used to join tables, but are used
mostly for checking referential integrity. If you want to get results from
multiple tables from a SELECT statement, you do this by joining
tables!
SELECT * from table1,table2 where table1.id = table2.id
See section 7.12 JOIN syntax.
The FOREIGN KEY syntax in MySQL exists only for compatibility
with other SQL vendors' CREATE TABLE commands; it doesn't do anything.
The FOREIGN KEY syntax without ON DELETE ... is mostly used
for documentation purposes. Some ODBC applications may use this to
produce automatic WHERE clauses, but this is usually
easy to override. FOREIGN KEY is sometimes used as a constraint check,
but this check is unnecessary in practice if rows are inserted into the tables
in the right order. MySQL only supports these clauses because some
applications require them to exist (regardless of whether or not they work!).
In MySQL, you can work around the problem of ON DELETE
... not being implemented by adding the appropriate DELETE statement to
an application when you delete records from a table that has a foreign key.
In practice this is as quick (in some cases quicker) and much more portable
than using foreign keys.
In the near future we will extend the FOREIGN KEY implementation so
that at least the information will be saved and may be retrieved by
mysqldump and ODBC.
There are so many problems with FOREIGN KEYs that we don't
know where to start:
INSERT and
UPDATE statements, and in this case almost all FOREIGN KEY
checks are useless because one usually inserts records in the right
tables in the right order.
The only nice aspect of foreign key is that it gives ODBC and some other client programs the ability to see how a table is connected and use this to show connection diagrams and to help building applicatons.
MySQL will soon store FOREIGN KEY definitions so that
a client can ask for and receive an answer how the original connection was
made. The current `.frm' file format does not have any place for it.
MySQL doesn't support views, but this is on the TODO.
Some other SQL databases use `--' to start comments. MySQL
has `#' as the start comment character, even if the mysql
command line tool removes all lines that start with `--'.
You can also use the C comment style /* this is a comment */ with
MySQL.
See section 7.28 Comment syntax.
MySQL will not support `--'; this degenerate comment style has
caused many problems with automatically-generated SQL queries that have used
something like the following code, where we automatically insert the value of
the payment for !payment!:
UPDATE tbl_name SET credit=credit-!payment!
What do you think will happen when the value of payment is negative?
Because 1--1 is legal in SQL, we think it is terrible that
`--' means start comment.
If you have a SQL program in a text file that contains `--' comments you should use:
shell> replace " --" " #" < text-file-with-funny-comments.sql \
| mysql database
instead of the normal:
shell> mysql database < text-file-with-funny-comments.sql
You can also change the `--' comments to `#' comments in the command file:
shell> replace " --" " #" -- text-file-with-funny-comments.sql
Change them back with this command:
shell> replace " #" " --" -- text-file-with-funny-comments.sql
Entry level SQL92. ODBC level 0-2.
BLOB and TEXT types
If you want to use GROUP BY or ORDER BY on a BLOB or
TEXT field, you must make the field into a fixed-length
object. The standard way to do this is with the SUBSTRING
function. For example:
mysql> select comment from tbl_name order by SUBSTRING(comment,20);
If you don't do this, only the first max_sort_length bytes
(default=1024) are considered when sorting.
BLOB and TEXT cannot have DEFAULT values
and will also always be NULL columns.
COMMIT-ROLLBACK
MySQL doesn't support COMMIT-ROLLBACK. The problem is
that handling COMMIT-ROLLBACK efficiently would require a
completely different table layout than MySQL uses today.
MySQL would also need extra threads that do automatic cleanups on
the tables and the disk usage would be much higher. This would make
MySQL about 2-4 times slower than it is today. MySQL is
much faster than almost all other SQL databases (typically at least 2-3 times
faster). One of the reasons for this is the lack of
COMMIT-ROLLBACK.
For the moment, we are much more for implementing the SQL server
language (something like stored procedures). With this you would very
seldom really need COMMIT-ROLLBACK. This would also give much
better performance.
Loops that need transactions normally can be coded with the help of
LOCK TABLES, and you don't need cursors when you can update records
on the fly.
We have transactions and cursors on the TODO but not quite prioritized. If
we implement these, it will be as an option to CREATE TABLE. That
means that COMMIT-ROLLBACK will only work on those tables and
only those tables will be slower.
We at TcX have a greater need for a real fast database than a 100% general database. Whenever we find a way to implement these features without any speed loss, we will probably do it. For the moment, there are many more important things to do. Check the TODO for how we prioritize things at the moment. Customers with higher levels of support can alter this, so things may be reprioritized.
The current problem is actually ROLLBACK. Without ROLLBACK, you
can do any kind of COMMIT action with LOCK TABLES. To support
ROLLBACK, MySQL would have to be changed to store all old
records that were updated and revert everything back to the starting point if
ROLLBACK was issued. For simple cases, this isn't that hard to do (the
current isamlog could be used for this purpose), but it would be much
more difficult to implement ROLLBACK for ALTER/DROP/CREATE
TABLE.
To avoid using ROLLBACK, you can use the following strategy:
LOCK TABLES ... to lock all the tables you want to access.
UNLOCK TABLES
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 this case, all locks will be 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:
For example, when we are doing updates on some customer information, we
update only the customer data that have changed and test only that none
of the changed data, or data that depend on the changed data, have
changed compared to the original row. The test for changed data is done with the
WHERE clause in the UPDATE statement. If the record wasn't
updated, we give the client a message: "Some of the data you have changed
have been changed by another user". Then we show the old row versus
the new row in a window, so the user can decide which version of the
customer record he should use.
This gives us something that is similar to "column locking" but is actually
even better, because we only update some of the columns with 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+'relative change';
UPDATE customer
SET
customer_date='current_date',
address='new address',
phone='new phone',
money_he_owes_us=money_he_owes_us+'new_money'
WHERE
customer_id=id AND address='old address' AND phone='old phone';
As you can see, this is very efficient and works even if another client has
changed the values in the pay_back or money_he_owes_us columns.
In many cases, users have wanted ROLLBACK and/or LOCK
TABLES to manage unique identifiers for some tables. This can be
handled much more efficiently by using an AUTO_INCREMENT column
and either the SQL LAST_INSERT_ID() function or the C API function
mysql_insert_id(). See section 18.4.49 How can I get the unique ID for the last inserted row?.
At TcX, we have never had any need for row-level locking because we have always been able to code around it. Some cases really need row locking, but they are very few. If you want row-level locking, you can use a flag column in the table and do something like this:
UPDATE tbl_name SET row_flag=1 WHERE id=ID;
MySQL returns 1 for the number of affected rows if the row was
found and row_flag wasn't already 1 in the original row.
Go to the first, previous, next, last section, table of contents.