START-INFO-DIR-ENTRY
* mysql: (mysql-faq).         Frequently Asked Questions about MySQL.
END-INFO-DIR-ENTRY

Introduction
************

   Frequently Asked Questions about `MySQL'. $Revision$

   This document contains answers to some of the most frequently asked
questions about `MySQL'. They're all good questions, but they come up
often enough that substantial net bandwidth can be saved by looking
here first before asking.

   The latest version of this FAQ can be found at `http://www.tcx.se/'

   This FAQ is currently available in TeXInfo, ASCII, Info, Postscript
and HTML versions.

   The primary document is the TeXInfo file. The HTML version is
automatically produced with `texi2html'. The ASCII and info version is
produced using `makeinfo'. The Postscript version is produced using
`texi2dvi' and `divps'.

   If you have any suggested additions or corrections, please send them
to the MySQL mailing list `<mysql@tcx.se>' with a subject line of the
form `FAQ Suggestion: [Insert Topic Here]'. *Note Mailing-list::.

   This FAQ is written and maintained by David Axmark and Michael
(monty) Widenius.

Absolutely Important
********************

Subscribing to/un-subscribing from the `MySQL' mailing list.
============================================================

   Requests to be added or dropped from the `MySQL' list should be sent
to the electronic mail address `mdomo@tcx.se'.  Sending a one line
message saying either `subscribe mysql' or `un-subscribe mysql' will
suffice. If your reply address is not valid you may use `subscribe
mysql your@address.your-domain' or `un-subscribe mysql
your@address.your-domain'.

   Please *do not* send mail about [un]subscribing to `mysql@tcx.se'
since any mail sent to this address is automatically forwarded to
hundreds of other users.

   Your local site may have many subscribers to `MySQL'. In that case,
it may have a local mailing list, so that a single message from `tcx.se'
is sent to the site and propagated to the local list. In this case
please contact your system administrator to be added to or dropped from
the local `MySQL' list.

   Mail to `mdomo' is handled automatically by majordomo.

Asking questions or reporting bugs.
===================================

   Before you ask a question of the mailing list it's a good idea to
check in the manual.  If you can't find an answer in the manual, check
with your local `MySQL' expert. If you don't have any luck there, read
through this FAQ.  If you still don't have an answer to your question
go ahead and send mail to `mysql@tcx.se'.

   I think I have found a bug. What information do you need to help me?

   If you can use the `mysqlbug' script that you can find in the
scripts directory in the distribution. Othervise remember to specify (if
relevant):

  1. Which version of `MySQL'. You can find out which version you are
     running by typing `mysqladmin version'. If you know which
     distribution file file you used add that (for example
     mysql-3.20.0.tgz).

  2. The manufacturer and model of machine you are working on.

  3. The operating system. For most relevant operating systems you cant
     get this from `uname -a'.

  4. Sometimes the amount of memory (real and virtual) is also relevant.

  5. If this is a bug when compiling: Include the exact error messages
     and also a few lines around the offending code in the file from
     which you got the error.

  6. If this is a run time bug, please describe exactly how you got the
     error.  If you can include a test program which shows the error
     you can a more exact answer.

  7. If you are a support customer please post to the specified mailing
     list for higher priority treatment.

   When answers are sent to you individually and not to the mailing
list, it is considered good etiquette to summarize the answers and mail
them to the mailing list.

Guidelines for answering questions on the mailing list.
=======================================================

   Try to make your answer broad enough that people other than the
original poster may benefit from it.  If you consider your answer to
have broad interest, you may want to post it to the mailing list
instead of replying directly to the individual who asked.  In this
case, please make sure that your answer is not a duplication of a
previous answer.

   Try to summarize the essential part of the question in your reply,
but don't feel obliged to quote the whole question.

General Information
*******************

What is `MySQL'?
================

   `MySQL' is a SQL (Structured Query Language) database server.
`MySQL' was written by Michael (monty) Widenius. Se the CREDITS file in
the distribution for more credits for `MySQL' and related things.

History of `MySQL'
==================

   Our first intension was to use mSQL to connect to our own fast low
level (ISAM) tables. After some testing we came to the conclusion that
mSQL wasn't fast or flexible enough. This resulted in a new SQL
interface to our database but with almost the same API interface as
mSQL. This API was choosed to encourage code sharing.

   Where the name MySQL comes from is not perfectly clear. Our base
directory and lots of librarys and tools has had the prefix my for well
over 10 years. But Monty's daughter (some years younger) are also named
My. So there the names comes from is not perfectly clear.

What is the current `MySQL' version?
====================================

   You can always check `http://www.tcx.se/' for the latest version of
MySQL.

How do I get `MySQL'?
=====================

   On the Internet try using a web browser to `http://www.tcx.se/'

   Or ftp to `ftp://ftp.sunet.se/pub/unix/databases/relational/mysql/'.
That is Sunet's (Swedish University Network) FTP archive in Sweden.

Should I get `MySQL' in source form or binary?
==============================================

   If you want to read (and/or modify) the C and C++ code that makes up
`MySQL' you should always get a source distribution. The code is always
the ultimate manual. The source distribution also contains more tests
and examples.

   For most people who want to run `MySQL' on a platform that has binary
releases, a binary version of `MySQL' is more convenient. But tcx's
binary release is not compiled in the same way as the source release so
some differences in where support files are located exist.

Which operating systems does MySQL support?
===========================================

   We use GNU autoconf so it will be possible to port to all modern
systems with working Posix threads and a C++ compiler. The client code
does require C++ but not threads. We use the software ourselves
primarily on Solaris (currently 2.5.1) and some on Linux (currently
2.0.27).

   A working Posix thread library is needed for the server. On Solaris
2.5 we use SUN PThreads (the native thread support in 2.4 and before is
not good enough) and on Linux we use LinuxThreads by Xavier Leroy
(Xavier.Leroy@inria.fr).

   There is a patched version of Provenzano's Pthreads from MIT (see
`http://www.mit.edu:8001/people/proven/pthreads.html') in the
distribution. This can be used for some operating systems that doesn't
have posix threads.

   We have alose tried to use another user level thread package named
FSU Pthreads (see
`http://www.informatik.hu-berlin.de/~mueller/pthreads.html').

   This didn't work with MySQL because of problems with the
implementations. See the thr_lock and thr_alarm programs in the mysys
directory for some tests/examples of these problems. More information
can be found in the `PORTING' file in the distribution.

Which languages does `MySQL' support.
=====================================

   `mysqld' can give error messages in the following languages: English
(default), Germany and Swedish.

   To start `mysqld' with a language use the -language (-L) switch:

   `mysqld --language swedish' `mysqld --language
/usr/local/share/swedish'

   The language files are located (by default) in

   `MYSQL_BASE_DIR/share/LANGUAGE/'

How/when will you release updates?
==================================

   We are going to use the following policy when updating MySQL:

   Each minor patch made will increment the last number in the version
string. When there is new features or minor incompatibilities with
previous versions the second number in the version string will get
incremented.

   * In the rare occasion of a fatal bug that can't be avoided being
     found we will do new binary releases for Solaris & Linux as soon
     as possible.  Other people may make binary releases for other
     systems but probably less frequent.

   * For other fatal bugs we will make patches available as soon as we
     have found and fixed the bug.

   * For non critical but annoying bugs we will make patches available
     if they are sent to me, otherwise we will combine many of them
     into a bigger patch.

   * When there are more then about 10 patches we will make a new full
     source release.

   * When we have made a lot of changes we will make a new source and
     binary release. (About once a month?)

What is UNIREG ?
================

   Unireg is our tty interface builder, but it uses a low level
connection to our NISAM (with is used by MySQL) and because of this
it's very quick. It has existed since 1979 (on Unix in C since ~1986).

   It has the following components:

   * One table viewer with updates/browsing.

   * Multi table viewer (with 1 scrolling region)

   * Table creator. (With lots of column tags you can't create with
     MySQL) This is WYSIWYG (for a tty). You design a screen and Unireg
     prompts for the column specification.

   * Report generator

   * A lot of utilities (Quick export/import of tables to/from text
     files, analysis of table contents...)

   * Powerful multi table updates (This we use a lot) with a BASIC like
     language with LOTS of functions.

   * Dynamic languages (For now Swedish and Finnish :) If somebody
     wants an English version there are a couple of files one would
     have to translate...

   * The ability to run updates interactively or in a batch.

   * Emacs like key definitions with keyboard macros.

   * All this in a binary of 800k.

   * The convform utility. Changes .frm and text files between different
     character sets.

   * The pack_isam utility. Packs a NISAM table (makes it 50-80%
     smaller). The table can be read by MySQL like an ordinary table.
     Only 1 record has to be decompressed / access. Can't handle BLOB:s
     or updates (yet).

   We update most our production databases with the UNIREG interface and
serve web pages through MySQL (and in some extreme cases the UNIREG
report generator).

   Unireg takes about 3M of disk space and works on at least the
following platforms: SUN OS 4.x, Solaris, Linux, HPUX, ICL Unix, DNIX,
SCO and MSDOS.

   Unireg is currently only available in Swedish and Finnish.

   The price tag for UNIREG is 10,000 swedish kr (about 1500$ US), but
this includes support. UNIREG is distributed as a binary. (But all the
isam source can be found in MySQL). Usually we compile the binary for
the customer at their site.

   New development is concentrated to MySQL.

Licensing. When do I have to pay for MySQL?
*******************************************

   Basic licensing issues:

   * The easiest way to pay for MySQL to use the licence form at TCX's
     SSL enabled server at `https://www.tcx.sw:443/licence.htmy'

   * I hope everybody understand that the you only have to pay if you
     are selling MySQL directly or selling a product which includes the
     MySQL server.  You may not include MySQL in a distribution if you
     charge for some part of it.  For internal use you don't have to
     pay us if you don't want to.

   * The client code is in the Public Domain or under the GPL
     (readline). So there should not be any problems with client code
     in commercial programs.

   * We may add some additional functionality in the commercial
     version. The likely test candidate for this is fast compressed
     read only databases. The current server includes support to read
     such databases but not the packing tool. If we get enough revenue
     from support we will probably release this under the same license
     as the other stuff.

   * But if you like MySQL and want to encourage futher development
     please buy licenses or support.

   For more information se the rest of this chapter and the file
`PUBLIC' in the distribution.

How much does `MySQL' cost?
===========================

   For normal use `MySQL' costs nothing. When you sell `MySQL' directly
or as a part of another product you have to pay for it. See the file
`PUBLIC' in the distribution.

   The client access part of MySQL is in the public domain. The command
line client inlcudes parts that is under the GNU Public Licence
(readline).

   The current price is $200 for one licence and $1000 for 10 licences
if payed for at the same time.

   If you have a low margin high volume product you can always talk to
us about other terms.

How do I get support
====================

   A licence includes really basic support. This means that we are
trying to answer any relevant question. If the answer is in the FAQ, we
are going to redirect the answer to the FAQ. If you do not have a
licence/support we will probably not answer at all.

   If you discover what we consider a real bug, we are likely to fix it
in any case. But if you pay for support we will notify you about the fix
status instead of just fixing it in a later release.

   More comprehensive support will be sold separately. One year of basic
email support costs $200. One year of more extensive email/telnet
support costs $2000.

How do I pay for a licence?
===========================

   Well currently we can take SWIFT payments, cheques or credit cards.

   Payment should be made to:
               Postgirot Bank AB
               105 06 STOCKHOLM, SWEDEN
     
               T.C.X DATAKONSULT AB
               BOX 6434
               11382 STOCKHOLM
     
               SWIFT address: PGSI SESS
               Account number: 96 77 06 - 3
     
               Specify: license and/or support and your name and email address.

   In europe and japan you can use EuroGiro (that should be cheaper) to
the same account.

   If you want to pay by cheque make it payable to "Detron HB". And
mail it to the address below.

     Detron HB
     David Axmark
     Kungsgatan 65 B
     753 21 UPPSALA
     SWEDEN

   If you want to pay with credit card over internet you can use
`https://www.tcx.sw:443/licence.htmy'

Who do I contact when I want support/a licence?
===============================================

   For commercial licensing or if you have any questions about any of
the information in this document, please contact:

     Detron HB
     David Axmark
     Kungsgatan 65 B
     753 21 UPPSALA
     SWEDEN
     Voice Phone +46-18-10 22 80
     Fax +46-8-729 69 05 (I prefer email if possible)
     E-Mail: mysql-c@detron.se

What Copyright does `MySQL' use?
================================

   There are four different copyright's on the `MySQL' distribution.

  1. The `MySQL' specific source needed to make the `mysqlclient'
     library and programs in the `client' directory is in the public
     domain. Each file which is in the public domain has a header which
     clearly states so.  This is everything in `client' directory and
     some parts of mysys, mystring and dbug libraries.

  2. Some small parts of the source (GNU getopt) are covered by the
     "GNU LIBRARY GENERAL PUBLIC LICENSE". See the `mysys/COPYING.LIB'
     file.

  3. Some parts of the source (GNU readline) are covered by the "GNU
     GENERAL PUBLIC LICENSE". See the `readline/COPYING' file.

  4. Some parts of the source (the regexp library) are covered by a
     Berkeley style copyright.

  5. The other source needed for the `MySQL' server is AGPL. See the
     file PUBLIC for more info.

   Our philosophy behind this is:

   - The SQL client library should be totally free so it can be
     included in commercial products without limitations.

   - People who want free access to the software we have put a lot of
     work into can have it so long they do not try to make money
     directly by distributing it for profit.

   - People who want the right to keep their own software proprietary,
     but also want the value from our work, can pay for the privilege.

   - That means that normal in house use is FREE. But if you use it for
     something important to you, you may want to support further
     development of `MySQL' by purchasing a support license.

When may I distribute MySQL commercially without a fee
======================================================

   This is a clarification of the information in the `PUBLIC' file.

   MySQL may be *used* freely, including by commercial entities for
evaluation or unsupported internal use.  However, *distribution* for
commercial purposes of MySQL, or anything containing or derived from
MySQL in whole or in part, requires a written commercial license from
TcX AB, the sole entity authorized by to grant such licenses.

   You may not include MySQL "free" in a package containing anything for
which a charge is being made exept as noted below.

   The intent of the exception provided in the second clause is to allow
commercial organizations operating an FTP server or a bulletin board to
distribute MySQL freely from it, provided that:

  1. the organization complies with the other provisions of the FPL,
     which include among other things a requirement to distribute the
     full source code of MySQL and of any derived work, and to
     distribute the FPL itself along with MySQL;

  2. the only charge for downloading MySQL is a charge based on the
     distribution service and not one based on the content of the
     information being retrieved (i.e., the charge would be the same
     for retrieving a random collection of bits of the same size);

  3. the server or BBS is accessible to the general public, i.e., the
     phone number or IP address is not kept secret, and anyone may
     obtain access to the information (possibly by paying a
     subscription or access fee that is not dependent on or related to
     purchasing anything else).

   If you want to distribute software in a commercial context that
incorporates MySQL and you do *not* want to meet these conditions, you
should contact TcX AB to find out about commercial licensing.
Commercial licenses involve a payment, and include support and other
benefits. These are the only ways you legally can distribute MySQL or
anything containing MySQL: either by distributing MySQL under the
requirements of the FPL, or by getting a commercial license from TcX AB.

I'm selling a product that can be configured to use MySQL
=========================================================

   I'm selling a product that can be configured to use MySQL although my
customer is responsible for obtaining/installing MySQL (or some other
supported alternative).  Does one of us owe you money if my customer
choses to use MySQL?

   If your product REQUIRED MySQL to work you would have to pay a
licence. If MySQL just added some new features it should fall inside
normal use. For example is using MySQL added logging to a database
instead of a text file it should not require a licence. This would of
course mean that the user has to fetch and install MySQL by himself.
If the program is (almost) useless without MySQL you would have to get a
MySQL licence to sell your product.

I am running a commercial web server using MySQL.
=================================================

   Do I have to get a licence for my copy?

   No you are not selling MySQL itself. But is this case we would like
you to purchase MySQL support. That is either your support of MySQL or
our support of you (the later is more expensive since our time is
limited).

Possible future changes in the licensing.
=========================================

   We may choose to distribute older versions of MySQL with the GPL in
the future. However these versions will be identified as "GNU MySQL".
Also all copyright notices in the relevant files will be changed to the
GPL.

Features of MySQL
*****************

Main features of MySQL
======================

   * Multi-threading.

   * Join optimizer with one-sweep multi-join (all joins made in one
     pass).

   * A privilege and password system with is very flexible (the mysql
     database).

   * All password traffic on the net is encrypted.

   * Fixed and variable length records.

   * 16 keys/table. Each key may consist of 1 to 15 columns. Max key
     length is 127 bytes, but may be increased to 500 by changeing one
     line of source.  `CREATE TABLE' supports the `PRIMARY KEY
     (columns)', `INDEX (columns)' and `UNIQUE (columns)' syntaxes. A
     `PRIMARY KEY' is always `UNIQUE'. A key may be a prefix of a CHAR
     field.

   * All columns have default values. One can always use INSERT on any
     subset of columns.

   * ODBC Open-DataBase-Connectivity for Windows95 (with source).

   * Almost all ODBC functions (and lots of others). Functions are
     implemented through a very optimized class library and should be
     as fast as they can get! Usually there shouldn't be any memory
     allocation after the query initialization.

   * Very fast B-tree disk tables.

   * In memory hash tables always used as temporary tables.

   * Can handle big databases (we are using MySQL with some databases
     with 50,000,000 records).

   * C and Perl API (The Perl API is a superset of the mSQL Perl API).
     Other languages with mSQL bindings should be simple to add

   * Uses GNU autoconfig for portability.

   * Written in C and C++. Tested with gcc 2.7.2.1.

   * A thread based malloc system (very fast and no memory trashing).

   * No memory leaks (tested with purify).

   * A very fast table check and repair utility (`isamchk').

   * All data saved in ISO8859_1 format. All comparisons for normal
     string columns are case insensitive.

   * Full ISO8859_1 (Latin1) support. For example Scandinavian едц
     is allowed in table and column names.

   * Sorts by ISO8859_1 Latin1 (The swedish way for the moment). It is
     possibly to change this in the source by adding new sort order
     arrays.

   * Alias on tables and columns as in the SQL92 standard.

   * Support for functions in the fields part of the select. Example
     `select (column1+column2) from table'

   * Support for group functions (`sum', `max', `min', `avg' & `count').

   * User commands as `show tables', `show keys from table' and `show
     columns from table'

   * `INSERT',`UPDATE' and `DELETE' returns how many rows was affected.

   * Functions names don't clash with table or column names. (For
     example ABS is a valid column name). The only restriction is that
     space is not allowed between a function name and the '(' when
     using functions.

   * Explicit test with functions `=' and `<>' to constant `NULL' is
     identical as the `IS NULL', `IS NOT NULL' tests. This is an SQL
     extension to be compatible with mSQL. (Of course one should use
     `IS NULL'.)

   * All MySQL commands have `--help' or `-?' as help.

   * The server supports error messages to client's in Swedish, English
     or (partly) German.

   * The client uses a socket or TCP connection when connecting to
     server.

What column (column) types are available with MySQL?
====================================================

   The following column types are supported:
`TINYINT'
     A very small integer. Can be a (part of) a key. Signed range
     -128-127. Unsigned range 0-255. Takes 1 byte (8 bits).

`SMALLINT'
     A small integer. Can be a (part of) a key. Signed range
     -32768-32767. Unsigned range 0-65535. Takes 2 bytes (16 bits).

`MEDIUMINT'
     A medium integer. Can be a (part of) a key. Signed range
     -8388608-8388607.  Unsigned range 0-16777215. Takes 3 bytes (24
     bits).

`INT'
     A normal integer. Can be a (part of) a key. Signed range
     -2147483648-2147483647. Unsigned range 0-4294967295. Takes 4 bytes
     (32 bits).

`BIGINT'
     A large integer. Can be a (part of) a key. Signed range
     -9223372036854775808-9223372036854775807. Unsigned Range
     0-18446744073709551615. Takes 8 bytes (64 bits).

`FLOAT'
     A small floating point number. Can be a (part of) a key. Cannot be
     unsigned. Range -3.402823466E+38F - -1.175494351E-38, 0,
     -1.175494351E-38 - 3.402823466E+38F. Takes 4 bytes (32 bits).

`DOUBLE'
     A normal floating point number. Can be a (part of) a key. Cannot be
     unsigned. Range -1.7976931348623157E+308 -
     -2.2250738585072014E-308, 0, 2.2250738585072014E-308 -
     1.7976931348623157E+308. Takes 8 bytes (64 bits).

`DECIMAL'
     A unpacked floating point number. Can be a (part of) a key. Cannot
     be unsigned. Currently the same range maximum range as a double.
     The number behaves as a CHAR column and takes length+decimals
     bytes.

`TIMESTAMP'
     A automatic timestamp. Has a range of 1 Dec 1970 kl 0.00 to
     sometime in the year 2106 and a resolution of a second. Will be
     automaticly updated if not used in a statement that updates a row
     or if set to NULL. Can be a (part of) a key. Takes 4 bytes (32
     bits). Note that if you have many timestamp fields in a row, then
     only the first timestamp field will be automaticly updated. Any
     timestamp field will be set to the current time if set to NULL.

`DATE'
     A type to store date information. Uses the "YYYY-MM-DD" syntax,
     but may be updated with a number or a string. Understand at least
     the following syntaxes: 'YY-MM-DD', 'YYYY-MM-DD', 'YYMMDD',
     'YYMM', 'YY'.  Range 0000-00-00 to 9999-12-31.  Takes 4 byte.

`TIME'
     A type to store time information. Uses the "HH:MM:SS" syntax, but
     may be updated with a number or a string. Understand at least the
     following syntaxes: 'HH:MM:DD, 'HHMMDD', 'HHMM', 'HH'. Takes 3
     bytes.

`FIXED LENGTH STRING'
     A string that is always filled up with spaces to the specified
     length. Can be a (part of) a key. Range 1-255 characters. Takes
     the same amount of space in the table.

`VARIABLE LENGTH STRING'
     A string that is stored with its length. Can be a (part of) a key.
     Maximum range 1-255 characters. Takes the (varying per row) length
     + 1 byte in the table.

`TINYBLOB'
     A binary object that is stored with its length. Can NOT be a key.
     Max length 255 characters (8 bits length). Takes the (varying per
     row) length + 1 byte in the table.

`BLOB'
     A binary object that is stored with its length. Can NOT be a key.
     Max length 16535 characters (16 bits length). Takes the (varying
     per row) length + 2 bytes in the table.

`MEDIUMBLOB'
     A binary object that is stored with its length. Can NOT be a key.
     Max length 16777216 characters (24 bits length). Takes the
     (varying per row) length + 3 bytes in the table.

`LONGBLOB'
     A binary object that is stored with its length. Can NOT be a key.
     Range 4294967295 characters (32 bits length). Takes the (varying
     per row) length + 4 bytes in the table. This column type

What is a BLOB?
===============

   A BLOB is a binary large object which can hold any amount of data :)
There are 4 kinds of blobs *Note Column types::.  Normaly one can
regard a BLOB as a VARCHAR without specified limit.

   There are some constraints because of the message buffer used.  The
default size of the buffer is 64K for the server and 512K for the
clients.  To change the buffer length for the server, use `mysqld -O
max_allowed_packet=max_blob_length'. This allows the message buffer to
grow up to this limit when needed.

   `myODBC' defines BLOB:s as `LONGVARCHAR'.

   Restrictions for blobs:

  1. BLOB columns can't be keys.

  2. One can't group or sort on BLOB. One can group on a expression
     involving a blob though: `SELECT id,SUBSTR(blob,1,100) GROUP BY 2'

  3. I blob is regarded as 'binary data'. This means that there is no
     end space truncation for BLOB columns.

What extension has MySQL to ANSI SQL?
=====================================

   The following are useful extensions that MySQL that you probably
won't find in other SQL:s. Be warned that if you use this your code
won't be portable to other SQL servers.

   bullet Use of `INTO OUTFILE' in a `SELECT' statement. *Note Select::

   bullet Use of key names, keys on a subpart of a field, and use of
     `KEY' or `INDEX' in a `CREATE TABLE' statement. *Note Create
     table::

   bullet Use of `DROP column' or `CHANGE column' in a `ALTER TABLE'
     statement. *Note Alter table::

   bullet Use of `LOAD DATA INFILE'. This syntax is in many cases
     compatible with Oracles `LOAD DATA INFILE'. *Note Load::

   bullet Using `"' instead of `'' to enclose strings.

   bullet Using the escape `\' character.

   bullet The `SET OPTION' statement.

   bullet Using in the `SELECT' part of a `GROUP BY' statement fields
     or functions that doesn't appear in the `GROUP BY' list.  In MySQL
     this means 'any matching value'. By using this one can get much
     higher performance by avoiding sorting and grouping on unnecessary
     items.  This is often used in this context:
          SELECT order.customerid,customer.name,max(payments) from order,customer
          WHERE order.customerid = customer.customerid GROUP BY order.customerid;
     In ANSI SQL you should have to add the customer.name in the GROUP
     BY clause, but in MySQL you don't have to.

   bullet Use of any of the following functions:
        bullet `=', `<>', `<=' ,`<', `>=',`>', `AND', `OR', or `LIKE'
          in a column statement

        bullet `REGEXP' or `NOT REGEXP'.

        bullet `CONCAT()' with other than 2 arguments. MySQL can take
          any number of arguments.

        bullet `BIT_COUNT()', `ELT()', `FROM_DAYS()', `FORMAT()',
          `IF()', `PASSWORD()', `PERIOD_ADD()', `PERIOD_DIFF()',
          `TO_DAYS()', or `WEEKDAY()'.

        bullet The `STD()' group function.

        bullet Use of `MIN()' or `MAX()' as functions, not group
          functions.

Compiling and installing MySQL
******************************

Compiling MySQL
===============

   Se the file `INSTALL-SOURCE' in the MySQL distribution.

Problems starting MySQL
=======================

   Check the log file to see if mysqld started up correctly

     cd <localstatedir default /usr/local/var>
     tail <your host name>.log

   To verify that MySQL is working run the following tests:

     > cd /usr/local/bin
     > ./mysqlshow
     +-----------+
     | Databases |
     +-----------+
     | mysql     |
     +-----------+
     
     > ./mysqlshow mysql
     Database: mysql
     +--------+
     | Tables |
     +--------+
     | db     |
     | host   |
     | user   |
     +--------+
     
     > ./mysql -e "select host,db,user from db" mysql
     +------+--------+------+
     | host | db     | user |
     +------+--------+------+
     | %    | test   |      |
     | %    | test_% |      |
     +------+--------+------+

   You can also run the test in the test subdirectory. To run
`auto_increment.tst':

     ./mysql -vf test < ./tests/auto_increment.tst

   Expected results are shown in the file `./tests/auto_increment.res'

Automatic start/stop of MySQL
=============================

   To start or stop MySQL you may use the following commands:

     scripts/mysql.server stop
     scripts/mysql.server start

   You will probably want to add these start and stop commands to the
appropriate places in your /etc/rc* files when you start using MySQL for
production applications.

How to debug MySQL
==================

   If you are porting MySQL to an new system you should first try to get
mysys/thr_lock and mysys/thr_alarm to work. They shouldn't core dump and
not print any error (they print a lot of other information thought).

   By starting bin/safe_mysqld with `--log' one will get a log in
`install-directory/var/'hostname'.log' (the top level database
directory).  This log will contain all successfull connections and all
commands issued to the MySQL server.

   If you have compiled MySQL with -with-debug=yes you can can also get
a very informative log with:

     libexec/mysqld --debug

   which makes a big log in /tmp/mysql.trace. The default debug option
is `d:i:t:o,/tmp/mysql.trace'

   You can get a smaller log with:

     libexec/mysqld --debug=d,info,query,general:o,/tmp/mysql.trace

   and even smaller (on stdout):

     libexec/mysqld --debug=d,general,query

   You can get more information about the debug switches by examining
the file `dbug/dbug.c'

Compatibility
*************

What functionality is missing in MySQL.
=======================================

   The following functionality is missing in the current version of
MySQL.  For the priority of new extensions you should consult:
`http://www.tcx.se/TODO'

   * `WHERE' with expressions. The current WHERE can only use operators
     of type `column = column' or `column = constant' or `constant =
     constant'.  This is because the interface to the UNIREG range
     optimizer is real simple. In 3.21.0 the range optimizer is totally
     rewritten and the `WHERE' will work as expected. In the mean time
     one should move the expressions to the `HAVING' part. `HAVING' is
     like a `WHERE' on the result but because `HAVING' isn't optimized
     expressions works. The only problem with `HAVING' is that all
     fields that are used in the `HAVING' part must also be in the
     `select' part.  *Note Select::

   * The following functions: `IN'.

   * Sub-`SELECT'. The following will not work in MySQL:
          SELECT * from table WHERE id IN (SELECT id from table2)
     MySQL only supports `INSERT ... SELECT...'. Independent
     sub-`SELECT's will be availably quite soon.

   * `SELECT ... INTO TABLE....'.  MySQL only supports `SELECT ... INTO
     OUTFILE...'.

   * Outer joins.

   * Transactions.  MySQL will shortly support atomic updates which is
     like transactions without rollback.

   * Triggers. The atomic update language can also be used for stored
     procedures, but without triggers. Triggers usually slow down
     everything too much for queries when they aren't needed.

How about msql tools like msql-tcl, msqljava?
=============================================

   According to my experience it would would just take a few hours to
convert a tool using the mSQL C API to the MySQL C API.

   The procedure:

  1. Run the shell script msql2mysql on the source. This needs the
     binary program replace, which is distributed with MySQL.

  2. Compile

  3. Fix all compiler errors:

   Differences between the MySQL and mSQL C API's.
   * MySQL uses `MYSQL' as a connection type (`mSQL' uses an `int')

   * MySQL connect takes a pointer to a MYSQL struct as a parameter.
     It's easy to define one globally or use malloc to get one.

   * mysql_connect takes 2 extra parameters. You may set these to
     NULL,NULL for default use (user and password).

   * mysql_error takes MYSQL as a parameter. Just add it to fix this.

   * Some incompatibilities exist as a result of MySQL supporting
     multiple connections to the server from the same process.

How different from `mSQL' are the MySQL client/server communications protocols?
===============================================================================

   Enough different that it's impossible (at least not easy) to support
both.

   The biggest differences between `MySQL' and `mSQL':

   * A message buffer may contain many result rows.

   * On the server side the message buffers are dynamically enlarged as
     necessary for big questions from the client.

   * All packages are numbered to catch out of sync packages.

   * All columns are sent in ASCII, the length of columns and length of
     rows are sent in packed binary coding (1,2 or 3 bytes).

   * MySQL can read in the result unbuffered.

   * If a single write/read takes more than 30 seconds then the server
     closes the connection.

   * If nothing has happened on a connection for 8 hours the server
     closes the connection.

   I don't think it makes sense to give a full spec, as we have plans to
optimize this in the near future.

What are the differences in the SQL syntax between `MySQL' & `mSQL' 2.0?
========================================================================

   * `CREATE TABLE'
    `MySQL'
          Has the following column option types:
             - UNSIGNED for integer columns.

             - ZEROFILL for integer columns.

             - AUTO_INCREMENT for integer columns.

             - DEFAULT values for all non null columns.

    `mSQL'
   * To create indexes
    `MySQL'
          All indexes have to be given to `CREATE TABLE'. Indexes can
          not be removed without recreating the table. *Note Alter
          table::

    `mSQL'
          Indexes must be created by a separate `CREATE INDEX' clause.
          Indexes may be removed with DROP INDEX.

   * To get a unique identifier in a table at insert
    `MySQL'
          Use `autoincrement' as a column type specifier. The given
          identifier may be retrieved after update by the API function
          `mysql_insert_id()'.

    `mSQL'
          Create a SEQUENCE on a table and use the __seq function to
          get a unique index.

   * Group functions (functions that can be used in a SQL `group by'
     clause)
    `MySQL'
          `count()', `avg()', `min()', `max()', `sum()' and `std()'.
          `min()' and `max()' may take string arguments. `count(*)' is
          optimized to return very quickly if no other column is used.

    `mSQL'
          Does not support `GROUP BY' yet.

   * How do I search independent of character case.
    `MySQL'
          LIKE is always case independent. If possible `MySQL' uses
          indexes if the like argument doesn't start with a wild-card.

    `mSQL'
          Use CLIKE.

   * How do I search with regular expressions?
    `MySQL'
          Use REGEXP or RLIKE. The syntax should be basically POSIX.

    `mSQL'
          Use RLIKE.

   * What are the differences in the WHERE statement?
    `MySQL'
          MySQL does everything according to mathematical priorities
          (AND is evaluated before OR). To get `mSQL' behavior in
          `MySQL', use braces: `select * from table where a=1 and b=2
          or a=3 and b=4' -> `select * from table where (a=1 and (b=2
          or (a=3 and (b=4))))'.

    `mSQL'
          Evaluates everything from left to right. That means that some
          logical calculation with more that 3 arguments can not be
          expressed.

   * Qualifying column names
    `MySQL'
          If a column name is unique you don't have to use the full
          qualifier.

    `mSQL'
          When using more than one table in a select you must use full
          table qualifiers.

   * Aliasing
    `MySQL'
          Has table and column aliasing.

    `mSQL'
          Has table aliasing.

   * Insert/update with calculations.
    `MySQL'
          Full calculation support. In a insert you may use values of
          preceding columns.

    `mSQL'
          Only insert update with constants.

   * Which formulas may be used in the select statement
    `MySQL'
          To many to print here. *Note Select::.

    `mSQL'
          No function support yet.

   * SQL `HAVING' clause.
    `MySQL'
          Supported, but can only use calculation on the selected
          columns. To select on a calculated value one must use a
          column alias. Ex: `SELECT COUNT(*) AS id_count,id FROM groups
          GROUP BY id HAVING id_count > 10'.

    `mSQL'
          Not supported.

   * Access Control
    `MySQL'
          Has tables to store grant options per user, host and db.
          *Note Privileges::

    `mSQL'
          Has a file `mSQL.acl' where you can grant read/write
          privileges for users.

Problems with AND and OR priority
=================================

   Remember that `AND' has higher priority in boolean algebra than
`OR'. It's like 1+2*3 is = 1+ (2*3) = 7.

   Always when you are in doubt:

  1. Remove all distinct keywords.

  2. Write all fields from all tables.

   This will make it easier to see what goes wrong. Distinct may also
be a lot slower than a normal select.

What standards do MySQL follow
==============================

   Entry level SQL92. ODBC level 0-2.

What functions exist only for compability?
==========================================

   `' `GRANT'. *Note Grant::. This always succeedes.  You should use
     the MySQL privilege tables. *Note Privileges::

   `' `CREATE INDEX'. *Note Create Index::. This always succeeds.  You
     should create your index with `CREATE TABLE'. *Note Create table::.
     You can also use `ALTER TABLE'. *Note Alter table::.

   `' `DROP INDEX'. *Note Drop Index::. This always succeeds.  You can
     use `ALTER TABLE' to drop indexes. *Note Alter table::.

Optimizations
*************

How does `MySQL' use memory ?
=============================

   You can get the currently used buffer sizes with:

   > `./mysqld --help'

   This should result in a all mysqld options and a list of
configurable variables like the following this. *Note Memory buffer
sizes::.

     Possibly variables to option --set-variable (-O) are:
     keybuffer             current value: 1048568
     max_allowed_packet    current value: 65536
     net_buffer_length     current value: 16384
     max_connections       current value: 128
     table_cache           current value: 64
     recordbuffer          current value: 524280
     sortbuffer            current value: 2097144

   * All threads share the same base memory.

   * Nothing is memmaped yet (except compressed tables but that's
     another story). This is because 32bit memory space of 4GB is not
     big enough for many big tables. When we get a system with 64 bit
     address space we may add general support for memmaping.

   * When starting `mysqld' one can specify a key buffer. This will
     buffer all keys in all tables at FIFO basis. (variable keybuffer)

   * Each connections uses some thread space, a stack and a connection
     buffer (variable net_buffer_length).

   * Each request doing a sequential scan over a table allocates a read
     buffer (variable recordbuffer).

   * Each request doing a sort allocates a sortbuffer and a one or two
     temporary files. The maximum extra disk-space needed is
     (sort_key_length +sizeof(long))*2.

   * All joins are done in one pass and the result is saved in a memory
     hash table. So now you know how to crash `MySQL' the easy way: Do
     a full join and a sort on two big tables :-(. In the future we
     will handle this by after some given memory size limit having the
     hash heap automatically change to a file based NISAM table. Now
     you know how to fill a disk in the future :-). In many cases
     `mysql' can optimize the query so it doesn't need a temporary
     table, but one case where this can't be done is when sorting and
     grouping on different things.

   * Almost all memory used when parsing and calculating is done on a
     local store which may be freed in a bug hunk: No memory overhead
     is needed for small items and the normal slow memory
     allocation/freeing is avoided. Memory is only allocated for
     unexpectedly big strings (This is done with malloc/free).

   * Each index file is opened once and the data file is opened once
     for each concurrently running thread. For each concurrent thread
     there is allocated full table structs and column structs and
     memory for 3 full column rows. (A BLOB has a memory overhead of
     5-8 bytes)

   * For each table having BLOBS, a buffer is enlarged dynamically to
     read in bigger BLOB's. If one scans a table there will be a
     allocated buffer as big as the biggest BLOB.

   * All used tables are saved in a cache and used by FIFO. Normally
     the cache is 64 tables. If a table has been used by 2 running
     threads at the same time, there will be 2 entries of the table in
     the cache.

   * A `MySQLadmin reload' closes all tables that are not used and
     marks all used tables to be closed when the running thread
     finishes. This will effectively free most used memory.

How should I arrange my table to be as fast/small as possible.
==============================================================

   * Use `NOT NULL' if possible. It makes everything quicker (and you
     save 1 bit per column).

   * All columns have default values. Only insert when the default value
     isn't acceptable. You don't have to insert the columns of a
     timestamp or a autoincremented key in the insert statement.

   * Use the smaller int types if possible to get smaller tables. For
     example `MEDIUMINT' is often better than `INT'.

   * If you don't have any `VARCHAR' columns a fixed size record format
     will be used. This is much quicker (but of course it may waste some
     space). *Note Row format::.

   * To make MySQL optimize querys better run `isamchk -a' on the table
     once it is loaded with relevant data. This updates a value for each
     index that tells how many rows that have the same value for this
     key in average. Of course this is always 1 for unique indexes.

   * To sort a index and data according to a index use `isamchk -Sir1'
     (if you want so sort on index 1). If you have a unique key that
     you want to read all records from in numeric order this is a good
     way to make that faster.

   To check how you are doing, run `isamchk -evi' on the .ISM file.

What factors MySQL insert statement speeds.
===========================================

   The time to insert a record consists of:

   * Connect:                 (3)

   * Sending query to server: (2)

   * Parsing query:           (2)

   * Inserting record:        (1 x size of record)

   * Inserting keys:          (1 x keys)

   * Close:                   (1)

   Where (number) is proportional time. Here is not calculated the
initial overhead to open tables (which is done 1 time for every
simultaneous running query).

   The size of the table slows down the insert of keys with N log N
(B-trees).

What kind of optimization is done on the WHERE clause?
======================================================

   (Incomplete, `MySQL' does a lot of optimizations)

   * Brace removal (All unnecessary braces are removed) `((a AND b) AND
     c OR (((a AND b) AND (c AND d))))' -> `(a AND b) OR (a AND b AND c
     AND d)'

   * Constant folding `(a<b AND b=c) AND a=5' -> `b>5 AND b=c A=5'

   * Constant condition removal (Needed because of constant folding).
     `(b>=5 AND b=5) OR (b=6 and 5=5) or (B=7 and 5=6)' -> `B=5 or B=6'

   * Return zero rows if impossible select.

   * Find all keys that may be used. Use the key which finds least
     records. A key is used for the following cases: `=', `>', `>=',
     `<', `<=', `BETWEEN' and a `LIKE' with a character prefix like
     'something%'.

   * Remove keys that don't span all `AND' levels.
        - have all preceding key_parts specified.

        - `key = 1 or A = 10' -> `NULL' (Can't use key)

        - `key = 1 or A = 10 and key=2' -> `key = 1 OR key = 2'

        - `key_part_1 = const and key_part_3 = const' -> `key_part_1 =
          const'

   * Read all constant tables. A constant table is:

       1. A table with only 1 record.

       2. A table with a uses only other const tables and constants on
          a full unique key.
          `const_table.key = constant' `const_table.key_part_1 =
     const_table2.column and const_table.key_part_2 = constant'

   * Find the best join combination to join the tables (By trying all
     possibilities :( ) If a there is a `ORDER BY' or `GROUP' on columns
     from one table and the sort and group are the same, or only one of
     sort and group is given, then the sorted table is preferred first
     in join cue.

   * If there is a order clause and a different group clause or if the
     order or group contains columns from other tables than the first
     table in the join cue a temporary table is created.

   * For each table use a ranged key, if possibly to read records. Each
     table index is queried and if there exists a key range that spans
     < 30% of the records then a key is used. If no such key can be
     found a quick table scan is used.

   * Before each record is output-ed, skip those that match the HAVING
     clause.

How can I change the buffer sizes of `mysqld' ?
===============================================

   With the `mysqld -O variable=size' command.  Example run:

   `> mysqld --help' (or `> mysqld -?')

     >mysqld --help
     /my/monty/sql/mysqld  Ver 3.20.5-beta for SOLARIS 2.5 (SPARCstation)
     TCX Datakonsult AB, by Monty. This is FPL, not free software
     This software comes with NO WARRANTY: see the file PUBLIC for details.
     
     Starts the mysql server
     
     Usage: /my/monty/sql/mysqld [OPTIONS]
     
       -b, --basedir=path	path to installation directory
       -h, --datadir=path	path to the database root
       -#, --debug=...       output debug log. Often this is 'd:t:o,filename`
       -T, --debug-info	print some debug info at exit
       -?, --help		display this help and exit
       -L, --language=...	client error messages in given language
       -l, --log[=filename]	log connections and queries to file
           --log-isam[=filename]
     			log all isam changes to file
       -O, --set-variable var=option
     			give a variable an value. --help lists variables
       --skip-new-routines	don't use new possible wrong routines.
       --skip-grant-tables	start without grant tables. This gives anyone FULL
     			ACCESS to all tables!
       --skip-locking	don't use system locking. To use isamchk one has
     			to shut down the server.
       --skip-unsafe-select  skipp unsafe select optimizations.
       -V, --version		output version information and exit
     
     Current base_dir: /my/monty
     Current data_dir: data/
     Current language: english/
     
     Possibly variables to option --set-variable (-O) are:
     keybuffer             current value: 1048568
     max_allowed_packet    current value: 65536
     net_buffer_length     current value: 16384
     max_connections       current value: 128
     table_cache           current value: 64
     recordbuffer          current value: 524280
     sortbuffer            current value: 2097144

   `> mysqld -O keybuffer=512k -O sortbuffer=100k -O recordbuffer=100k'

   * The keybuffer is shared by all threads.

   * `mysqld' demon starts with a cd to 'mysql-data-dir'. After this
     mysqld-data-dir is changed to './' (current dir). All paths
     (databases, pid file, and log file) are prefixed with './'

What options to use to get `mysqld' to run at full speed?
=========================================================

   `mysqld -O keybuffer=16m -O sortbuffer=1m -O recordbuffer=512k
--skip-locking'

   `--skip-locking' disables file locking between SQL requests. If this
is used then the following can happen:

   * If `mysqld' or the machine crashes a table has a higher risk of
     being corrupted. Tables should at least be checked with `isamchk
     *.ISM' after a crash.

   * One *MUST* flush all tables with `mysqladmin reload' before one
     tries to check/repair tables with `isamchk'. (`isamchk -d
     table_name' is always allowed).

   The `--skip-locking' is default when compiling with MIT threads.

What is the different row formats? Or when to use VARCHAR/CHAR?
===============================================================

   Actually using no `VARCHAR' or `BLOB' types results in a fixed row
size. Otherwise `CHAR' and `VARCHAR' are the same. Se the below for a
more exact definition.

   You can check the format used for a table with `isamchk -d'.

   `MySQL' has three different table formats:

  1. Fixed length tables;
        * The default format.

        * All non packed columns are space filled

        * Very quick.

        * Easy to cash

        * Easy to reconstruct if crashed (Of course this only
          theoretical :-) because records are on fixed positions.

        * Don't have to be reorganized unless a huge number of records
          are deleted.

  2. Dynamic tables
        * Is used if there exists any VARCHAR or BLOB columns in table.

        * All strings are dynamic (except if length < 3).

        * Each record is preceded with a bitmap for which columns are
          not empty (this isn't the same as null columns).

        * Each string is saved with a length byte + string. If string
          is zero length or a number is zero it takes no extra place
          (just the zero length bit for each column).

        * Each record is uses exactly the needed record space. If a
          record gets larger it's split into as many pieces as needed.

        * Takes little disk space.

        * If records are changed a lot, `isamchk -r' should be run now
          and then to reorganize the table. This is to get a better
          layout. Use `isamchk -ei table_name' for some statistics.

        * Not as easy to reconstruct because a record may be in many
          pieces and a link may be missing.

        * The expected row length for dynamic sized records is: 3 +
          (number_of_columns + 7) / 8 + (number of char columns) +
          packed_size_of_number_columns + length_of_strings +
          (null_columns + 7) / 8. There will be a penalty of 6 bytes
          for each link. A dynamic record will be linked whenever a
          update causes a enlargement of the record. Each new link will
          be at least 20 bytes, so the next enlargement will probably
          go in the same link. If not there will be another link. You
          may check how many links there are with `isamchk -ed'. All
          links may be removed with `isamchk -r'.

  3. Compressed tables (this is only with UNIREG/pack_isam)
        * Read only tables.

        * Takes very little disk space. Minimizes disk usage.

        * Each record is compressed separately (very little access
          overhead)

        * Can handle fixed or dynamic length records (but no BLOB:s).

        * Can be uncompressed with isamchk.

MySQL C API
***********

After `mysql_query()' returns success, `mysql_store_result()' sometimes returns NULL.
=====================================================================================

   It means one of the following:

  1. Malloc failure.

  2. The data couldn't be read (Error on connection).

  3. The statement was a statement which doesn't ever return data
     (`INSERT' or `UPDATE' or `DELETE').

   You can always check if the statement should given a result by
checking that `mysql_num_columns(MYSQL *)' isn't 0.  If this is 0 the
last query was a statement that did not return values `INSERT,
DELETE...'.

   You have got an error if `mysql_error(MYSQL *)' isn't empty!

What results can I get from a query?
====================================

   `mysql_affected_rows(MYSQL *)' returns the number of affected rows
in the last query when doing an INSERT, UPDATE or DELETE.

   `mysql_insert_id(MYSQL *)' returns the given ID of the last query
when inserting a row into a table with a `AUTO_INCREMENT' key.

   Some querries, `LOAD DATA INFILE...' and `INSERT INTO ... SELECT
...', return additional info.  This result is returned in
`mysql_info(MYSQL *)'.  `mysql_info()' returns a null pointer if there
is no additional information.

How can I get the unique ID for the last row?
=============================================

   If you insert a record which have a `AUTO_INCREMENT' key then you
can get the given id with `mysql_insert_id(MYSQL *)'.

   You can check if an auto_increment key is used by the following
code. This also checks if the query was a insert with a
`auto_increment' key.

     if (mysql_error(MYSQL)[0] == 0 &&
         mysql_num_fields(MYSQL_RESULT) == 0 &&
         mysql_insert_id(MYSQL) != 0)
       used_id = mysql_insert_id(MYSQL);

What is the difference between `mysql_use_result()' and `mysql_store_result()' modes?
=====================================================================================

   This says to `MySQL' to use the result directly from the server (no
local store like in `mSQL'), which is somewhat faster and doesn't use
memory to buffer the hole result.

   This shouldn't be used if there is much processing for each row at
the client side, or if the output is sent to a screen on which the user
may do a ^S (stop scroll), because this would tie up the server.  One
can't use `mysql_data_seek' when using `mysql_use_result'.

Problems linking with C API.
============================

   When linking with the C API you can get the following errors on some
systems:

     gcc -g -o client test.o -L/usr/local/lib/mysql -lmysqlclient -lsocket -lnsl
     
     Undefined        first referenced
      symbol          in file
     floor            /usr/local/lib/mysql/libmysqlclient.a(password.o)
     ld: fatal: Symbol referencing errors. No output written to client

   This means that on your system you have to include the math library
(-lm) last in the compile/link line.

MySQL Syntax
************

Literals. How do you write strings and numbers?
===============================================

   STRINGS

   A string may have ' or " around it.

   \ is a escape character. The following escape characters are
recognized:
`\0'
     A ascii 0 character.

`\n'
     A newline character.

`\t'
     A tab character.

`\r'
     A return character.

`\b'
     A backspace character.

`\''
     A `'' character.

`\"'
     A `"' character.

`\\'
     A `\' character.

`\%'
     A `%' character. This is used in wild-card strings to search after
     `%'.

`\_'
     A `_' character. This is used in wild-card strings to search after
     `_'.

     A ' inside a string started with ' may be written as ''.
     A " inside a string started with " may be written as "".

     MySQL> select 'hello', "'hello'", '""hello""', '''h''e''l''l''o''', "hel""lo";
     1 rows in set (0.00 sec)
     
     +-------+---------+-----------+-------------+--------+
     | hello | 'hello' | ""hello"" | 'h'e'l'l'o' | hel"lo |
     +-------+---------+-----------+-------------+--------+
     | hello | 'hello' | ""hello"" | 'h'e'l'l'o' | hel"lo |
     +-------+---------+-----------+-------------+--------+
     
     mysql> select 'hello', "hello", '""hello""', "'ello", 'e''l''lo', '\'hello';
     1 rows in set (0.00 sec)
     
     +-------+-------+-----------+-------+--------+--------+
     | hello | hello | ""hello"" | 'ello | e'l'lo | 'hello |
     +-------+-------+-----------+-------+--------+--------+
     | hello | hello | ""hello"" | 'ello | e'l'lo | 'hello |
     +-------+-------+-----------+-------+--------+--------+
     
     
     mysql> select "This\nIs\nFour\nlines";
     1 rows in set (0.00 sec)
     
     +--------------------+
     | This
     Is
     Four
     lines |
     +--------------------+
     | This
     Is
     Four
     lines |
     +--------------------+

   If you want to insert binary data into a blob the following
characters must be represented by escape sequences:
`\0'
     Ascii 0. Should be replaced with "\0" (A backslash and a 0 digit).

`\'
     Ascii 92, backslash

`''
     Ascii 39, Single quote

`"'
     Ascii 33, Double quote

   NUMBERS

   Integers are just a sequence of digits.  Floats use `.' as a decimal
separator.

   Examples of valid numbers are: `1221', `294.42', `-32032.6809e+10'.

   NULL

   When using the text file export formats, NULL may be represented by
\N. *Note Load::

CREATE TABLE syntax.
====================

     CREATE TABLE table_name ( create_definition,... )
     
     create_definition:
     	column_name type NOT NULL [DEFAULT default_value] [ PRIMARY KEY ]
       or	column_name type [NULL] [ PRIMARY KEY ]
       or	PRIMARY KEY ( key_column_name,... )
       or	KEY [key_name] KEY( key_column_name,...)
       or	INDEX [key_name] ( key_column_name,...)
       or	UNIQUE [key_name] ( key_column_name,...)
       or    FOREIGN KEY key_name ( key_column_name,...) REFERENCES table_name [ ON DELETE { RESTRICT | CASCADE | SET NULL }]
     
     key_column_namne:
     	column_namn [ (length) ]

   To have a `DEFAULT' the column must be declared as NOT NULL.

`TINYINT [(length)] [UNSIGNED] [ZEROFILL]'
`SMALLINT [(length)] [UNSIGNED] [ZEROFILL]'
`MEDIUMINT [(length)] [UNSIGNED] [ZEROFILL]'
`INT [(length)] [UNSIGNED] [ZEROFILL]'
`INTEGER [(length)] [UNSIGNED] [ZEROFILL]'
`BIGINT [(length)] [UNSIGNED] [ZEROFILL]'
     A packed integer of length 1,2,3,4 or 8 bytes. *Note Column
     types::.  Unsigned means that only number from 0 and up are
     allowed. ZEROFILL means that the column will be padded with zeroes
     to length number of characters.

`FLOAT [(precision)]'
     Floating point number. FLOAT(4) and FLOAT is single precision.
     FLOAT(8) is double precision.

`FLOAT  [(length,decimals)].'
     A single precision number with a max length and a fixed number of
     decimals.

`DOUBLE [(length,decimals)].'
     A double precision number with a max length and a fixed number of
     decimals.  Length and decimals are for formating and calculation
     of max column width.

`REAL [(length,decimals)].'
     This is the same as `DOUBLE'.

`DOUBLE PRECISION [(length,decimals)].'
     This is the same as `DOUBLE'.

`DECIMAL [(length,decimals)]'
     Unpacked fixed size integer/floating point number. If the number
     of decimals is zero the number is handled like an integer.

`NUMERIC [(length,decimals)]'
     Synonym for `DECIMAL'.

`CHAR(NUM)'
     Fixed with string (1 <= NUM <= 255).

`VARCHAR(NUM)'
     Variable length string (1 <= NUM <= 255).

`TINYBLOB'
`BLOB'
`MEDIUMBLOB'
`LONGBLOB'
     Binary Large OBject with a length integer of 1,2,3 or 4 bytes.

`DATE'
     A date type. Format "YYYY-MM-DD".  Takes 4 bytes.

`TIME'
     A time type. Format "HH:MM:SS". Takes 3 bytes.

`DATETIME'
     A Date and time type. Format "YYYY-MM-DD HH:MM:SS". Takes 8 bytes.
     Range '0000-01-01 00:00:00' - '9999-12-31 23:59:59'

`TIMESTAMP[(LENGTH)]'
     Changes automatically on insert/update (YYYYMMDDHHMMSS). The
     length determines how the output is formatted. (YYYYMMDDHHMMSS,
     YYMMDDHHMMSS, YYMMDDHHMM, YYYYMMDD, YYMMDD, YYMM, YY) Range
     '1970-01-01 00:00:00' - About '2050-12-31 23:59:59'. Takes 4 bytes.

   * ZEROFILL means that number is pre-zeroed to maximal length. With
     `INT(5) ZEROFILL' a value of 5 is retrieved as `00005'.

   * The FOREIGN syntax is only for compatibility. It doesn't do
     anything.

   * INDEX is only a synonym for KEY.

   * If one doesn't assign a name to a key the key will get the same
     name as the first key_column with an optional _# to make it unique.

   * Key columns and timestamp columns can't be NULL. For these columns
     the NULL attribute is silently removed.

   * With `column_namn(length)' syntax one can specify a key with is
     only a part of a `string' column. This can make the index file
     much smaller.

   * A number column may have the additional AUTO_INCREMENT to
     automatically get get the biggest value+1 for each insert where
     column value is NULL or 0.

   * One can insert NULL for timestamp and auto_increment columns. This
     results in the current time / the next number

   * Blob columns can't be keys.

   * One can't group directly on a BLOB. *Note BLOB Limitations::

   * One can't use a blob COLUMN directly in a WHERE. Move the test to
     the HAVING clause. *Note BLOB Limitations::

   * Deleted records are in a linked list and subsequent inserts will
     reuse old positions. To get smaller files one can use the
     `isamchk' utility to reorganize tables.

   * Each null column takes 1 bit extra (Rounded up to the nearest
     byte).

   * The maximum record length can be calculated as follows: 1+
     sum_of_column_lengths + null_columns/8 + number of variable length
     columns.

   * In some case a attribute may silently change after creation:
     `VARCHAR' columns with a length of 1 or 2 are changed to `CHAR'.
     When using one `VARCHAR' columns all `CHAR' columns longer than 2
     are changed to `VARCHAR''s.

   * On `INSERT'/`UPDATE' all strings (`CHAR' and `VARCHAR') are
     silently chopped/padded to the maximal length given by CREATE. All
     end spaces are also automatically removed. For example VARCHAR(10)
     means that the column can contain strings with a length up to 10
     characters.

   * Something/0 gives a NULL value.

   * The regular expression function (`REGEXP' and `RLIKE') uses
     ISO8859-1 (Latin1) when deciding the type of a character.

ALTER TABLE syntax
==================

     ALTER [IGNORE] TABLE table_name alter_specification [, alter_specification ...]
     
     alter_specification:
     	ADD [COLUMN] create_definition
     or	CHANGE [COLUMN] old_column_name create_definition
     or	ALTER [COLUMN] column_name { SET default | DROP DEFAULT }
     or	DROP [COLUMN] column_name
     or	DROP PRIMARY KEY
     	DROP INDEX key_name

   * ALTER TABLE works by creating a temporary table and copying all
     info to this and then the old one is deleted and the new one is
     renamed.  This is done in such a way that all updates is
     automaticly redirect to the new table without any failed updates.
     While the ALTER TABLE is working, the old table is readable for
     other clients. Table updates/writes to the table are stalled and
     only executed after the new table is ready.

   * If IGNORE isn't specified then the copy will be aborted and rolled
     back if there would exist any duplicated unique keys in the new
     table. This is a MySQL extension.

   * The `CHANGE column_name', `DROP column_name' and `DROP INDEX' is
     MySQL extensions to ANSI SQL92.

   * The optional word `COLUMN' is pure noiseword and can be omitted.

   * The `ADD' and `CHANGE' takes the same create_definition as `CREATE
     TABLE'. *Note Create table::.

   * `ALTER COLUMN' sets a new default value or removes the old default
     value for a column.

   * `DROP INDEX' drops and index. This is an MySQL extension.

   * `DROP FOREIGN KEY' is for future compatibility only. It doesn't do
     anything.

   * If one drops a column_name which is part of some key, this key
     part is removed. If all key parts are removed then the key is
     removed.

   * `DROP PRIMARY KEY' drops the first `UNIQUE' key in table.

   * `CHANGE' tries to convert data to the new format as good as
     possibly.

   * With `mysql_info(MYSQL*)' one can retrive how many records was
     copied and how many records was deleted because of multiple keys.

   * To use `ALTER TABLE' one have to have select, insert, delete,
     update, create and drop privileges on the table.

DROP TABLE syntax.
==================

   `DROP TABLE table_name [, table_name....]'

   Removes one or more tables. All the data and the definition is
*removed* so take it easy with this command!

DELETE syntax.
==============

   `DELETE FROM table_name WHERE where_definition'

   Returns records affected.

   If one does a delete without a where clause then the table is
truncated (This is much faster). In this case it returns records
affected as zero.  This will work even if the datafiles doesn't exists,
because it uses only information from the table definition file,
`table_name.frm'.

     where_definition:
     	where_expr
     or	where_expr [ AND | OR ] where_expr
     
     where_expr:
     	column_name [> | >= | = | <> | <= | < ] column_name_or_constant
     or	column_name LIKE column_name_or_constant
     or	column_name IS NULL
     or	column_name IS NOT NULL
     or	( where_definition )

   * All string comparisons are case independent with case according to
     ISO-8859-1 Latin1.

   * LIKE is allowed on numerical columns.

   * Compare with explicit NULL (column == NULL) is the same as if IS
     NULL was used (column IS NULL). This is is done to be consistent
     with mSQL.

SELECT syntax
=============

   `SELECT [DISTINCT | ALL] select_expression,... [ FROM tables...
[WHERE where_definition ] [GROUP BY column,...] [ ORDER BY column [ASC
| DESC] ,..] HAVING full_where_definition [LIMIT [offset,] rows]
[PROCEDURE procedure_name]] [INTO OUTFILE 'file_name' ...] '

`+'
`-'
`*'
`/'
     Normal math operations. A divide by zero results in a `NULL'.

`|'
`&'
     Bit functions (These has a range of maximum 48 bits because MySQL
     uses double arithmetic).

`-'
     Sign

`(,)'
     Parenthesis

`NOT'
`!'
     NOT returns TRUE (1) or FALSE (0).

`OR'
`AND'
     Normal logical operators. Returns TRUE (1) or FALSE (0).

`='
`<>'
`<='
`<'
`>='
`>'
     comparison operators. Returns TRUE (1) or FALSE (0)

`expr LIKE expr'
     SQL simple regular expression comparison. Returns TRUE (1) or
     FALSE (0).

`expr NOT LIKE expr'
     Returns TRUE (1) or FALSE (0).

`expr REGEXP expr'
     Check string against extended regular expr.

`expr NOT REGEXP expr'
     Check string against extended regular expr.

`ABS()'
`FLOOR()'
`CEILING()'
`ROUND()'
`EXP()'
`LOG()'
`LOG10()'
`POW()'
`SQRT()'
     Math functions. These returns NULL in the case of a error.

`RAND([integer_expr])'
     Returns a random float, 0 <= x <= 1.0, using integer_expr as the
     option seed value.

`SIGN()'
     Sign of argument. Returns -1, 0 or 1.

`BIT_COUNT()'
     Number of set bits in argument.

`MOD()'
`%'
     Module (like in C)

`MIN()'
`MAX()'
     Min or max value of argument. Must have 2 or more arguments, else
     this is group functions

`CONCAT()'
     Concatenate strings. May have more than 2 arguments.

`DATABASE()'
     Returns current database name.

`LENGTH()'
     Length of string

`STRCMP()'
     Returns 0 if the strings are the same. Otherwise return -1 if
     first argument is smaller according to sort-order, else return 1.

`LOCATE(A,B)'
     Return position of B substring in A. The first position is 1.
     Returns 9 if b is not in A.

`LOCATE(A,B,C)'
     Return position of B substring in A starting at C.

`LEFT(str,length)'
     Get length characters from beginning of string.

`RIGHT(str,right)'
     Get length characters from end of string.

`LTRIM(str)'
     Remove space characters from the beginning of str.

`RTRIM(str)'
     Remove space characters from the end of str.

`SOUNDEX(str)'
     Get a soundex string from str. Two strings that sounds 'about the
     same' should have identical soundex strings. A 'standard' soundex
     string is 4 long, but this function returns a arbitrary long
     string. One can use `SUBSTRING' on the result to get a 'standard'
     soundex string.  All non alpha characters are ignored in the given
     string. All characters outside the A-Z range are treated as vocals.

`SUBSTRING(A,B,C)'
     Get substring from A starting at B with C chars.

`REPLACE(A,B,C)'
     Replace all occurrences of B in A with C.

`INSERT(org,start,length,new)'
     Replace substring org[start...length] with new. First position in
     string=1.

`LCASE(A)'
     Change A to lower case.

`UCASE(A)'
     Change A to upper case.

`PASSWORD()'
     Calculate a password string. This must be used to store a password
     in the 'user' grant table.

`INTERVAL(A,a,b,c,d)'
     Return 1 if A == a, 2 if A == b. If no match return 0.
     A,a,b,c,d... are strings.

`ELT(N,a,b,c,d,...)'
     Return a if N == 1, b if N == 2. a,b,c,d are strings.

`FIELD(A,a,b,c,d,...)'
     Return index of A in the a,b,c... list. The complement of ELT().

`BETWEEN(A,B,C)'
     Is the same as (A >= B AND A <= C). B and C may be numbers or
     strings.

`PERIOD_ADD(P:N)'
     Add N months to period P (of type YYMM or YYYYMM). Returns YYYYMM.

`PERIOD_DIFF(A,B)'
     Returns months between periods A,B. A and B should be of format
     YYMMM or YYYYMM. Example: `PERIOD_DIFF(199712,9612)'.

`TO_DAYS(DATE)'
     Change a DATE to a daynumber.  DATE may be a date string, a
     datetime string, a timestamp([6 | 8 | 14]) or a number of format
     YYMMDD or YYYYMMDD.

`FROM_DAYS()'
     Change a daynumber to a DATE.

`WEEKDAY(DATE)'
     Get weekday for date (0 = Monday, 1 = Tuesday).  DATE may be a
     date string, a datetime string, a timestamp([6 | 8 | 14]) or a
     number of format YYMMDD or YYYYMMDD.

`CURDATE()'
     Return date of today. In form YYYYMMDD or "YYYY-MM-DD".  depending
     of if CURDATE() is used in a number or string context.

`NOW()'
     Return current time. In format YYYYMMDDHHMMSS or "YYYY-MM-DD
     HH:MM:SS" depending of if NOW() is used in a number or string
     context.

`UNIX_TIMESTAMP([DATE])'
     If called without any arguments returns a unix timestamp (seconds
     in GMT since 1970.01.01 00:00:00). Normally is called with a
     `timestamp' column as argument in which case it returns the
     timestamp.  DATE may also be a date string, a datetime string, or
     a number of format YYMMDD or YYYMMDD in local time.

`ISNULL(A)'
     Returns 1 if A is NULL else 0. Same as '( A == NULL ').

`IFNULL(A,B)'
     If A is not null return A, else B.

`IF(A,B,C)'
     If A is true (!= 0 and != NULL) then return B, else return C.

`USER()'
     Returns current user name.

`FORMAT(nr,NUM)'
     Format number to a format like '#,###,###.##'  with NUM decimals.

   Functions for `GROUP BY' clause:
``count(expr)''
     Number of rows.

``avg(expr)''
     Average value of expr.

``min(expr)''
``max(expr)''
     Minimum/Maximum value of expr.  `sum(expr)' Sum of expr.
     `std(expr)' Standard derivation of expression. This is a extension
     to `ANSI SQL'.

   `min()' and `max()' may take string arguments. `count(*)' is
optimized to return directly if no other column is used.

   These can't be used in expression, even if argument may be an
expression.  Eg: `SUM(value/10)' is allowed but `SUM(value)/10' is not
(yet!).

   MySQL has extended the use of `GROUP BY'. You can use columns or
calculations in the `SELECT' expressions with doesn't appear in the
`GROUP BY' part. This stands for 'any possible value for this group'.
By using this one can get much higher performance by avoiding sorting
and grouping on unnecessary items.  For example, in the following query
one doesn't need to sort on b.name:

     SELECT a.id,b.name,COUNT(*) from a,b WHERE a.id=b.id GROUP BY a.id

   Strings are automatically converted to numbers and numbers to strings
when needed (ala perl).  If in a compare operation (`(=, <>, <= ,<, >=,
>)') either if the arguments are a numerical the arguments are compared
as numbers, else the arguments are compared as strings. All string
compares are done case-independent by ISO8859-1.

   - A column names does not have to have a table prefix if the given
     column name is unique.

   - A select expression may be given an alias which will be column
     name and can be used when sorting and grouping or in the `HAVING'
     clause.
          select concat(last_name,' ',first_name) as name from table order by name

   - In LIKE expressions % and _ may be preceded with '\' to skip the
     wild-card meaning.

   - A DATE is a string with one the following syntaxes:
        - YYMMDD        (Year is assumed to be 2000 if YY < 70)

        - YYYYMMDD

        - YY.MM.DD	Where '.' may be any non numerical separator

        - YYYY.MM.DD	Where '.' may be any non numerical separator

   - `IFNULL()' and `IF()' returns number or string value according to
     use.

   - `ORDER' and `GROUP' columns may be given as column names, column
     alias or column number in `SELECT' clause.

   - The `HAVING' clause can take any columns or alias in the
     select_expressions. It is applied last, just before items are sent
     to the client, without any optimization. Don't use it for items
     that should be in the WHERE clause.  You can't write (yet):

     `SELECT user,MAX(salary) FROM users GROUP BY users HAVING
     max(salary)>10'

     Change it to:

     `SELECT user,MAX(salary) AS sum FROM users GROUP BY users HAVING
     sum > 10'

   - LIMIT takes one or two numerical arguments.
        `' If one argument the argument indicates the maximum number of
          rows in a result.

        `' If two arguments the first arguments says the offset to the
          first row to return, the second is the maximum number of rows.

   - INTO OUTFILE 'filename' writes the given set to a file. The file
     can not exist from before. *Note Load::.

INSERT syntax
=============

     	INSERT INTO table [ (column_name,...) ] VALUES (expression,...)
     or	INSERT INTO table [ (column_name,...) ] SELECT ....

   An expression make use any previous column in column_name list (or
table if no column name list is given).

   The following holds for a multi-row `INSERT' statement:
   - The query cannot contain an `ORDER BY' clause.

   - The target table of the `INSERT' statement cannot appear in the
     FROM clause of the query.

   - If one uses `INSERT INTO ... SELECT ...' then one can get the
     following info string with the C API function `mysql_info()'.

     Records: 100  Duplicates: 0  Warnings: 0=> Duplicates are number
     of rows which couldn't be written because some key would be
     duplicated. Warnings are columns which was set to NULL, but has
     been declared NOT NULL. These will be set to their default value.

   - If one sets a time stamp value to anything other than NULL, the
     time stamp value will be copied to the result table.

   - Auto increment fields works as usually.

LOAD DATA INFILE syntax
=======================

   ` LOAD DATA INFILE 'table_interval.text' [REPLACE | IGNORE] INTO
TABLE table_interval [FIELDS [TERMINATED BY ',' [OPTIONALLY] ENCLOSED
BY '"' ESCAPED BY '\\' ]] [LINES TERMINATED BY '\n'] [(field list)]'

   This is used to read rows from a textfile.

   To write data to a textfile, use the `SELECT ...  INTO OUTFILE
'interval.tab' fields terminated by ',' enclosed by '"' escaped by '\\'
lines terminated by '\n'' syntax.

   Normally you don't have to specify any of the textfile type options.
The default is a compact textfile with columns sepearated with `tab'
characters and all rows ends with a newline. Tabs, newlines and `\'
inside fields are prefixed with a `\'. NULL's are read and written as
\N.

   `FIELDS TERMINATED BY' has default value of `\t'.  `FIELDS
[OPTIONALLY] ENCLOSED BY' has default value of `''' `FIELDS ESCAPED BY'
has default value of `'\\''.  `LINES TERMINATED BY' has default value
of `'\n''.

   `FIELDS TERMINATED BY' and `LINES TERMINATED BY' may be more than 1
character.

   If `LINES TERMINATED BY' is a empty string and `FIELDS TERMINATED
BY' is not empty then lines are also terminated by `FIELDS TERMINATED
BY'.

   If `FIELDS TERMINATED BY' and `FIELDS ENCLOSED BY' both are empty
strings (`''') then this gives a fixed row size ("not delimited"
importation format). With a fixed row size NULL values are outputed as a
blank string.

   If you specify `OPTIONALLY' in `ENCLOSED BY', then only strings are
enclosed in `ENCLOSED BY' by the `SELECT ... INTO' statement.

   When using `LOAD' duplicated `ENCLOSED BY' are removed inside an
`ENCLOSED BY'. For example 'He"llo' is read as 'He'llo'.

   If `ESCAPED BY' is not empty then the following characters will be
prefixed with the escape character: `ESCAPED BY', `ASCII 0', and the
first character in any of `fields terminated by', `FIELDS ENCLOSED BY'
and `LINES TERMINATED BY'.

   If `FIELDS ENCLOSED BY' is not empty then `NULL' is read as a `NULL'
value. If `FIELDS ESCAPED' is not empty then `\N' is also read as a
`NULL' value.

   If `REPLACE' is used the new row will replace all rows which has a
same unique key. If `IGNORE' is used the row will be skipped if there
already exist a record with a identical unique key. If no of the above
options is used an error will be issued. The rest of the textfile will
be ignored if one gets a duplicate key error.

   Some possible cases that's not supported by `LOAD DATA':
   `' Fixed size rows (`FIELDS TERMINATED BY' and `FIELDS ENCLOSED BY'
     both are empty) and BLOB fields.

   `' If some of the separators are a prefix of another.

   `' `FIELDS ESCAPED BY' is empty and the data contains `LINES
     TERMINATED BY' or `FIELDS ENCLOSED BY' followed by `FIELDS
     TERMINATED BY'.

   All rows are read into table. If a row has too few fields the rest
fields are set to default values.

   For security reasons the textfile must either reside in the database
directory or be readable by all.

   For more info about the escaped syntax *Note Base Syntax::.

   When the `LOAD DATA' query is done one can get the following info
string with the C API function `mysql_info()'.

   Records: 1  Deleted: 0  Skipped: 0  Warnings: 0=>

   Warnings is incremented for each column which can't be stored without
loss of precision, for each column which didn't get a value from the
read text line (happens if the line is too short) and for each line
which has more data than can fit into the given columns.

   Example that load all fields;

     LOAD DATA INFILE 'persondata.text' INTO TABLE persondata;

UPDATE syntax
=============

   UPDATE table SET column=expression,... WHERE where_definition

   All updates are done from left to right. IF one accesses a column in
the expression it uses the current value (a given value or the default
value).

SHOW syntax. Get information about names of columns.
====================================================

     	SHOW DATABASES [LIKE wild]
     or 	SHOW TABLES [FROM database] [LIKE wild]
     or	SHOW COLUMNS FROM table [FROM database] [LIKE wild]

   Gives information about databases, tables or columns.  The wild is a
LIKE string. `FIELDS' may be used as an alias for `COLUMNS'.

DESCRIBE syntax. Get information about names of columns.
========================================================

   `(DESCRIBE | DESC) table [column]'

   Gives information about columns. This command is for Oracle
compability. *Note Show:: Column may be a column name or a string.
Strings may contain wildcards.

SET OPTION syntax.
==================

     	SET OPTION SQL_VALUE_OPTON=value, ...

   The used options remain in effect for the hole current session.

   The different options are:

`SQL_SELECT_LIMIT=value'
     The maximun number of records to return in any select.  If a
     select has a limit clause it overrides this statement.

GRANT syntax. (Compability function).
=====================================

       GRANT (ALL PRIVILEGES | (SELECT, INSERT, UPDATE, DELETE,
             REFERENSES (column list), USAGE))
             ON table TO user,... [WITH GRANT OPTION]

   This command doesn't do anything. It's only in mysql for compability
reasons.  Privileges in MySQL is handled with the mysql grant tables.
*Note Privileges::

CREATE INDEX syntax (Compability function).
===========================================

   `CREATE [UNIQUE] INDEX index_name ON table_name ( column_name,... )'

   This function doesn't do anything. It's only in mysql for compability
reasons.  You can create new index with ALTER TABLE. *Note Alter table::

DROP INDEX syntax (Compability function).
=========================================

   `DROP INDEX index_name'

   This always succeeds.  You can drop an index with ALTER TABLE. *Note
Alter table::

Is `MySQL' picky about reserved words?
======================================

   It seems that I can't create a table with column names `timestamp' or
`group'.

   Functions doesn't clash with table or column names. (For example
`ABS' is an allowed column name). The only restriction is that space is
not allowed between a function name and the `'('' when using functions.

   The following are reserved words in `MySQL'. Most of them (for
example) `group', are forbidden by ANSI SQL92 as column and/or and a few
are because `MySQL' needs them and (currently) is using a Yacc parser:

   `add', `all', `alter', `and', `as', `asc', `auto_increment',
`between', `bigint', `blob',`by', `cascade', `char', `character',
`change', `column', `columns' `create', `data', `databases', `date',
`datetime', `dec', `decimal', `default', `delete', `desc', `describe',
`distinct', `double', `drop', `fields', `float', `float4', `float8',
`foreign', `from', `grant', `group',`having', `ignore', `in', `index',
`infile', `insert', `int', `int1', `int2', `int3', `int4', `int8',
`integer', `interval', `into', `is', `key', `keys', `like', `lines',
`limit', `load', `longblob', `mediumblob', `mediumint', `middleint',
`not', `null', `numeric', `on', `option', `or', `order', `precision',
`primary', `procedure', `privileges', `real', `references', `regexp',
`replace', `restrict', `rlike', `select', `set', `show', `smallint',
`sql_big_tables', `sql_big_selects',
`sql_select_limit',`straight_join', `table', `tables', `terminated',
`time', `timestamp', `tinyblob', `tinyint', `unique', `unsigned',
`update', `usage', `values', `varchar', `varying', `where', `zerofill'.

MySQL Use
*********

What does the executables do?
=============================

`mysql'
     A SQL shell (with gnu readline). Supports interactive use or as a
     non interactive query tool. When used interactively gives result
     in a ascii-table format, when using as a filter gives
     tab-separated output.

`mysqladmin'
     Administration utility. Create/Drop of databases. reload (read new
     users and flush tables to disk). Version and process info.

`mysqld'
     The SQL deamon. This should always be running.

`mysqldump'
     Dump a MySQL database. Freeware by Igor Romanenko.

`mysqlshow'
     Show information about database, tables and fields.

`safe_mysqld'
     Start the mysqld demon with some safety features. Restarts on
     error and has logging of runtime info to a logfile.

`mysqlaccess'
     Script to check the priviliges for a host, user and database
     combination.

`mysqlbug'
     This script should always be used when filing a bug report to the
     mysql list.

`mysql_install_db'
     Creates the mysql grant tables with default privileges. This is
     usually only executed when installing the first MySQL release on a
     new system.

`isamchk'
     Check, optimize and repair MySQL tables.

`msql2mysql'
     A shell script to convert a mSQL program to MySQL. Doesn't handle
     all cases but gives a good start when converting.

`replace'
     Binary used for msql2mysql. Utility program to change strings
     inplace in files or on stdin. Uses a finite state machine to match
     longer strings first.  Can be used to swap strings, for example
     'replace a b b a - files' swaps 'a' and 'b' in the given files.

`make_binary_release'
     Makes a binary release of a compiled MySQL. This could be sent by
     ftp to www.tcx.se/pub/mysql/Incoming for the convenience of other
     MySQL users.

Limitations of BLOB's
=====================

   If you want to group or sort on a blob, make the BLOB into a fixed
length object with the `SUBSTRING' or similar functions.

How do you check/repair/reconstruct an MySQL table?
===================================================

   If MySQL crashed (f ex if the computer is turned off) when all data
is not written to disk the tables may be crashed.  To check a table use

`isamchk table_name'
     This finds 99.99 % of all errors. What is can't find is when only
     the data file has been corrupted.

`isamchk -e table_name'
     This goes through all data and does a compleat check.

`isamchk -ei table_name'
     As the above but with some statistics.

   Always backup a table before trying to repair it.

   To repair a table(REMEMBER TO BACKUP A TABLE BEFORE TRYING TO REPAIR
IT!):
`isamchk -r table_name'
     Does a fast rebuild of the index and data files. This needs disk
     space for about two tables.

`isamchk -rq table_name'
     Updates only the index file. Quicker but can't fix errors in the
     data file.

How to get a description of a table.
====================================

   To get a description/statistics from a table us the forms below.
Sometimes we will explain some of the information in more detail.

`isamchk -d table_name'
     A short form.
          ISAM file:     company.ISM
          Data records:           1403698  Deleted blocks:              0
          Recordlength:               226
          Record format: Fixed length
          
          table description:
          Key Start Len Index   Type
          1   2     8   unique  double
          2   15    10  multip. text packed stripped
          3   219   8   multip. double
          4   63    10  multip. text packed stripped
          5   167   2   multip. unsigned short
          6   177   4   multip. unsigned long
          7   155   4   multip. text
          8   138   4   multip. unsigned long
          9   177   4   multip. unsigned long
              193   1           text
     For explanations se below.

`isamchk -d -v table_name'
     A little more verbose.
          ISAM file:     company.ISM
          Isam-version:  2
          Creation time: 1996-08-28 11:44:22
          Recover time:  1997-01-12 18:35:29
          Data records:           1403698  Deleted blocks:              0
          Datafile: Parts:        1403698  Deleted data:                0
          Datafilepointer (bytes):      3  Keyfile pointer (bytes):     3
          Max datafile length: 3791650815  Max keyfile length: 4294967294
          Recordlength:               226
          Record format: Fixed length
          
          table description:
          Key Start Len Index   Type                       Root  Blocksize    Rec/key
          1   2     8   unique  double                 15845376       1024          1
          2   15    10  multip. text packed stripped   25062400       1024          2
          3   219   8   multip. double                 40907776       1024         73
          4   63    10  multip. text packed stripped   48097280       1024          5
          5   167   2   multip. unsigned short         55200768       1024       4840
          6   177   4   multip. unsigned long          65145856       1024       1346
          7   155   4   multip. text                   75090944       1024       4995
          8   138   4   multip. unsigned long          85036032       1024         87
          9   177   4   multip. unsigned long          96481280       1024        178
              193   1           text

    `ISAM file'
          Name of isam file.

    `Isam-version'
          Version of isam format. Currently always 2.

    `Creation time'
          When was the data file created.

    `Recover time'
          When was the index/data file last reconstructed.

    `Data records'
          How many records/rows.

    `Deleted blocks'
          How many deleted blocks do still have reserved space. *Note
          Repairing a table::.

    `Datafile: Parts'
          For dynamic record format this shows how many data blocks
          there are. For a just optimized table without splits this is
          the same as `Data records'.

    `Deleted data'
          How many bytes of non reclaimed deleted data.

    `Datafilepointer'
          How many bytes is the datafile pointer. This is usually 2, 3
          or 4 bytes. Most tables manage with 2 bytes but this cannot
          be controlled from MySQL yet. For fixed tables this is a
          record address. For dynamic tables this is a byte address.

    `Keyfile pointer'
          How many bytes is the datafile pointer. This is usually 1, 2
          or 3 bytes. Most tables manage with 2 bytes but this is
          calculated automatically by MySQL. This is always a block
          address.

    `Max datafile length'
          For this table how long (in bytes) can the data file (`.ISD')
          get.

    `Max keyfile length'
          For this table how long (in bytes) can the key file (`.ISM')
          get.

    `Recordlength'
          How much space does each record/row take.

    `Record format'
          Which format does each record/row have. This example uses
          `Fixed length'.

    `table description'
          A list of all keys in the table. For each key some low level
          information is presented.
         `Key'
               This keys number.

         `Start'
               Where in the record/row does this index-part start.

         `Len'
               How long is this index-part. For packed numbers this
               should always be the full length of the field. For
               string it may be shorter than the full length.

         `Index'
               `unique' or `multip.'. If one value can exist multiple
               times in this index.

         `Type'
               What data-type does this index part have. This is a `C'
               data-type with a optional packed or stripped.

         `Root'
               Address of the root index block.

         `Blocksize'
               The size of each index block. This is by default 1024
               but may be changed compile time.

         `Rec/key'
               This is a statistical value used by the optimizer. It
               tell how many records there are per value for this key.
               A unique key always has a value of 1. This may be
               updated after a table is loaded (or greatly changed)
               with `isamchk -a'. If this is not updated at all a
               default value of 30 is given.  The 9th key is a multiple
          part key with two parts.

`isamchk -eis table_name'
     Show only the most important information from table. Slow since it
     must read the whole table.
          Checking ISAM file: company.ISM
          Key:  1:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
          Key:  2:  Keyblocks used:  98%  Packed:   50%  Max levels:  4
          Key:  3:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
          Key:  4:  Keyblocks used:  99%  Packed:   60%  Max levels:  3
          Key:  5:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
          Key:  6:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
          Key:  7:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
          Key:  8:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
          Key:  9:  Keyblocks used:  98%  Packed:    0%  Max levels:  4
          Total:    Keyblocks used:  98%  Packed:   17%
          
          Records:          1403698    M.recordlength:     226   Packed:             0%
          Recordspace used:     100%   Empty space:          0%  Blocks/Record:   1.00
          Recordblocks:     1403698    Deleteblocks:         0
          Recorddata:     317235748    Deleted data:         0
          Lost space:             0    Linkdata:             0
          
          User time 1626.51, System time 232.36
          Maximum resident set size 0, Integral resident set size 0
          Non physical pagefaults 0, Physical pagefaults 627, Swaps 0
          Blocks in 0 out 0, Messages in 0 out 0, Signals 0
          Voluntary contexts switches 639, Involuntary contexts switches 28966

    `Keyblocks used'
          How many percent of the keyblocks are used. Since this table
          has just been reorganized with isamchk the values are very
          high (Very near theoretical maximum).

    `Packed'
          MySQL tries to pack keys with a common suffix. This only can
          be used for `CHAR'/`VARCHAR'/`DECIMAL' keys. For long string
          like names this can reduce the spaced used significantly. In
          the above example the 4 key is 10 characters long and gets a
          60% reduction in space.

    `Max levels'
          How deep is the btree for this key. Big tables with long keys
          get high values.

    `Records'
          How many rows does the table have.

    `M.recordlength'
          Average recordlength. For fixed tables this is the
          recordlength.

    `Packed'
          MySQL strips spaces from the end of strings. How many percent
          did we save by doing this.

    `Recordspace used'
          How many percent of the datafile is used.

    `Empty space'
          How many percent of the datafile is unused.

    `Blocks/Record'
          How many blocks are there per record. This is always 1 for
          fixed format tables. This value should stay as close to 1.0
          as possible. If it gets to great you can reorganize the table
          with `isamchk'. Se *Note Repairing a table::.

    `Recordblocks'
          How many blocks is used. For fixed format this is the same as
          the number of records.

    `Deleteblocks'
          How many block are deleted.

    `Recorddata'
          How many bytes of actual user data there are in the datafile.

    `Deleted data'
          How many bytes of deleted data there are in the datafile.

    `Lost space'
          If a record is updated to a shorter length some space is
          lost. This is the sum of all such.

    `Linkdata'
          When the dynamic format is used blocks are linked with
          pointers (length 4-7 bytes). This is the sum of all such
          pointers.

`isamchk -eiv table_name'
     Same as above but tells you what it is doing.
          Checking ISAM file: company.ISM
          Data records: 1403698   Deleted blocks:       0
          - check file-size
          - check delete-chain
          index  1:
          index  2:
          index  3:
          index  4:
          index  5:
          index  6:
          index  7:
          index  8:
          index  9:
          No recordlinks
          - check index reference
          - check data record references index: 1
          Key:  1:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
          - check data record references index: 2
          Key:  2:  Keyblocks used:  98%  Packed:   50%  Max levels:  4
          - check data record references index: 3
          Key:  3:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
          - check data record references index: 4
          Key:  4:  Keyblocks used:  99%  Packed:   60%  Max levels:  3
          - check data record references index: 5
          Key:  5:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
          - check data record references index: 6
          Key:  6:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
          - check data record references index: 7
          Key:  7:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
          - check data record references index: 8
          Key:  8:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
          - check data record references index: 9
          Key:  9:  Keyblocks used:  98%  Packed:    0%  Max levels:  4
          Total:    Keyblocks used:   9%  Packed:   17%
          
          - check records and index references
          [LOTS OF ROW NUMBERS DELETED]
          
          Records:          1403698    M.recordlength:     226   Packed:             0%
          Recordspace used:     100%   Empty space:          0%  Blocks/Record:   1.00
          Recordblocks:     1403698    Deleteblocks:         0
          Recorddata:     317235748    Deleted data:         0
          Lost space:             0    Linkdata:             0
          
          User time 1639.63, System time 251.61
          Maximum resident set size 0, Integral resident set size 0
          Non physical pagefaults 0, Physical pagefaults 10580, Swaps 0
          Blocks in 4 out 0, Messages in 0 out 0, Signals 0
          Voluntary contexts switches 10604, Involuntary contexts switches 122798

   Here is the data file sizes of the table used above.

     -rw-rw-r--   1 monty    tcx     317235748 Jan 12 17:30 company.ISD
     -rw-rw-r--   1 davida   tcx      96482304 Jan 12 18:35 company.ISM

How does the privilege system work?
===================================

   The MySQL privilege system makes sure that each user may do exactly
the things that she is supposed to be allowed to.  The system decides to
grant different privileges depending on *which user* connects from
*which host* to *which database*.  The decision is based on the
contents of the three tables in the `MySQL' database: `user', `host'
and `db'.

   The grantable privileges on rows are *select*, *insert*, *update*
and *delete*.

   The table and database privileges are *create* and *drop*.  Create
and drop are for both tables and databases.  Since a user with a drop
grant can delete any table, this is the same thing as a drop grant for
the database.

   Other privileges give the right to use files (for LOAD DATA INFILE
and SELECT INTO OUTFILE) and to use the administrative commands
*shutdown*, *reload* and *process* (to get the current process list).

   The privilege tables are read into `mysqld' with `mysqladmin
reload'.  If the privilege tables are empty or non-existent or if the
server is started with `--skip-grant-tables', full access is granted to
everyone.

   You can always test your privileges with the script `mysqlaccess',
which Yves Carlier has provided for the MySQL distribution.  *Note
Access denied::

   * The HOST and DB fields may contain a SQL regexp with chars `%' and
     `_'.  Leaving any of these fields empty is equivalent to setting
     it to '%'.

   * A HOST may be `localhost', a hostname, an IP number or an SQL
     expression.  An empty host in the db table means any host in the
     host table.  An empty host in the host or user table means *any
     host that can create a TCP connection to your server*.

   * A DB is the name of a database or an SQL regexp.

   * A empty USER field means any username will do.

   * An empty password means that the entry will only be used if no
     password is supplied.

   * The privileges from the user table are OR'ed to the `db' table.
     This means that a superuser only needs to be in the user table
     with all privilege-flags set to `Y'.

   Everything granted in the `user' table is valid for every database
that cannot be found in the `db' table.  For this reason, it might be
wise to grant users (apart from superusers) priviliges on a per-database
basis only.

   The `host' table is mainly there to maintain a list of "secure"
servers.  At TCX `host' contains a list of all machines on the local
network. These are granted all privileges.

   The connecting user's privileges are calculated by the following
algorithm:

  1. First sort all three tables by host by putting hosts without
     wildcards first, followed by hosts with wildcards and entries with
     `host = ""'.  Within each host (i.e. very much like `GROUP BY
     Host'), sort by user using the same rules. Finally, in the `db'
     table sort by db using the same rules.  In the steps below, we
     will look through the sorted tables and *always use the first
     match found*.

  2. Get the privileges for the connecting user from the `db' table
     using the first match found.  Call this set of privileges P.

  3. If `host = ""' for the entry found in the `db' table, AND P with
     the privileges for the host in the `host' table, i.e.  remove all
     privileges that are not "Y" in both.  (If `host <> ""', P is not
     affected.  In this case, `host' must have matched the connecting
     host's name at least partially.  Therefor it can be assumed that
     the privileges found in this row match the connecting host's
     profile.)

  4. OR (add) P with the privileges for the user from the `user' table,
     i.e. add all privileges that are "Y" in `user'.

   The connecting user gets the set of privileges P.

   Let's show an example of the sorting and matching! Suppose that the
user table contains this:
     +-----------+----------+-
     | Host      | User     | ...
     +-----------+----------+-
     | %         | root     | ...
     | %         | jeffrey  | ...
     | localhost | root     | ...
     | localhost |          | ...
     +-----------+----------+-

   Then the search order will be:

   `' localhost/root

   `' localhost/any

   `' any/jeffrey

   `' any/root

   So jeffrey attempting to connect on localhost will be matched by the
`localhost/any' line, not by the `any/jeffrey' line.  The first match
found is used!

   So if you have access problems, print out the user table, sort it by
hand, and see where the match is being made.

Adding new user privileges to MySQL
===================================

   To add privileges to the `MySQL' database:

   This assumes the current user has insert privileges for the mysql db
table and reload privileges. The server (mysqld) has to be running.  If
it is not, start it with `safe_mysqld --log &'.

     > mysql mysql
       insert into user values ('%','monty',password('something'),'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y') ;
       insert into user (host,user,password) values('localhost','dummy','') ;
       insert into user values ('%','admin','','N','N','N','N','N','N','Y','N','Y','Y') ;
       quit
     > mysqladmin reload

   This makes three new users:
`monty'
     Full superuser, but must use password when using `MySQL'.

`admin'
     Doesn't need a password but is only allowed to use `mysqladmin
     reload' and `mysqladmin processlist'. May be granted individual
     database privileges through table `db'.

`dummy'
     Must be granted individual database privileges through table `db'.

Default privileges.
===================

   The default privileges (set in `scripts/mysql_install_db') is that
root can do anything. Any user can do anything with any database whose
name is 'test' or start with 'test_'. A normal user can't use
`mysqladmin shutdown' or `mysqladmin processlist'. See the script
(`scripts/mysql_install_db') for a example on how to add other users.

   The privilege tables are read into mysqld with 'mysqladmin reload'.
If the privilege tables are empty (or non-existent) full access are
granted to everyone.

A example of permission setup.
==============================

   A common mistake is to try something like:

   `INSERT INTO user VALUES
('%','jeffrey','bLa81m0','Y','Y','Y','N','N','N','N','N', 'N','N');'

   Then (of course) a `mysqladmin reload' to make the authentication
change take effect, then trying to connect to the server:

   $ ` ./mysql -h sqlserver -u jeffrey -p bLa81m0 test' Access denied

   Try with this instead:

   `INSERT INTO user VALUES
('%','jeffrey',password('bLa81m0'),'Y','Y','Y','N','N','N','N','N','N','N');'

   And like before `mysqladmin reload' to make the authentication change
take effect.

   Now things should work.

Can I install `MySQL' without root access?
==========================================

   Yes. You just have to make some user to be able to create databases.
The easiest way to do this is to change the word `root' to your user
name in the script `scripts/mysql_install_db'. And then run this script.

Why so many open tables?
========================

   When you run `mysqladmin status' you get something like:

     Uptime: 426  Running threads: 1  Questions: 11082  Reloads: 1  Open tables: 12

   This can be somewhat perplexing if you only have 6 tables.

   Because MySQL is multithread it may have many queries on the same
table at once. To minimize the problem with two threads having
different states on the same file, I open the table again for each
concurrent thread. This takes some memory and one extra file descriptor
for the data file. The index file descriptor is shared for all threads.

Adding functionality to mysql
*****************************

Adding new functions to MySQL
=============================

   If you need it as sql function (like SOUNDEX()), its real easy:

  1. Add one line in sql_lex.cc defining the function name in the
     sql_functions array.

  2. Add two lines in sql_yacc.y.  On defines the preprocessor symbol
     yacc can define (this should be added at the start of the file).
     Then define the function parameters and create a 'item' with
     theese parameters.  Check for example all occurrences of SOUNDEX
     in sql_yacc.y

  3. In item_func.h declare a class inheriting from Item_num_func or
     Item_str_func depending of if your function returns a number or a
     string.

  4. In `item_func.cc' add: `double *Item_func_newname::val()' If you
     are defining a number function or `String
     *Item_func_newname::Str(String *str)' If you are defining a string
     function.

  5. You should probably also define the following function:

     `void Item_func_newname::fix_length_and_dec()'

     This should at least calcutate `max_length' based on the given
     arguments. `max_length' is the maximal number of chars the function
     may return. If the function can't return a `NULL', one should set
     `maybe_null = 0'.

   About string functions:
  1. For string functions the 'String *str' argument provides is a
     string buffer that may be used to hold the result.

  2. A string function should return the string that holds the result.

  3. All current string functions tries to avoid to alloc any memory
     unless absolutely necessary!

Porting
*******

What files must be changed when porting to another system ?
===========================================================

   Se the file PORTING in the distribution.

ODBC
****

Which operating systems does `MySQL' ODBC support?
==================================================

   `MySQL' ODBC is a 32 bit ODBC (2.50) level 0 for Windows95 and NT.
We hope somebody will port it to Windows 3.x.

How should I report problems with `MySQL' ODBC?
===============================================

   We have only tested ODBC with Admndemo, some C programs, Msquery and
Excel.

   To give some light about any problem we would like to have the log
file from the ODBC manager (the log you get when requesting logs from
ODBCADMIN) and a MYODBC log.

   To get a MYODBC log, please put this `MYSQL_DEBUG=d:t:O,filename' in
your AUTOEXEC.BAT and restart.

   The log will be written to file `filename'.

How do I fill in the various fields in the ODBC administrator program.
======================================================================

   There are three possibilities for sepcifying the server name on
windows95:

  1. Use the IP.

  2. Add a file lmhosts with the following info:

     ip hostname

     For example: 194.216.84.21 my

  3. Configure the PC to use DNS.

   Example to fill in the 'ODBC setup'.

     Data Source Name:   test
     Description:        This is my test database
     Server:             194.216.84.21
     User:               monty
     Password:           my
     Port:

   These are default values to be given when prompting for a Driver
connect. You don't have to give 'server', 'user' or 'password' in this
screen.  If port is not given the default port (3333) is used.

   When connection to a ODBC source you have the option to change the
server, user, password and port.

Problems
********

Why do I get 'Access denied'?
=============================

   * Have you installed the MySQL grant tables with the script
     'mysql_install_db'? Test by executing 'mysql -u root test'. This
     should not give a error. You can also check if you have a file
     'user.ISD' in the mysql database directory (ordinary
     install_dir/var/mysql/user.ISD).  The binary release of MySQL
     always install some default grant tables.

   * Remember that you have to do 'mysqladmin reload' each time you
     change the grant tables. Othervise the old tables are used!

   * For testing you should start the mysqld demon with the
     `--without-grant-tables' option.  Now you can change the MySQL
     grant tables and use the script `mysqlaccess' to check if your
     grant's should work. `mysqladmin reload' tells the mysqld demon to
     start using the new grant tables.

   * Even if you have accessproblems with perl, python, or ODBC, always
     test your privilege problems with `mysql -u user database' or
     `mysql -uuser -ppassword database'.

   * If you get the error 'Access denied' when trying to connect to the
     database with `mysql -u user database' then you have a problem with
     the 'user' table.  Check this by doing `mysql -u root mysql' and
     `select * from user'. You should have an entry with 'hostname' and
     'user' matching your computers hostname and your username. If the
     client and the server is running on the same host and you haven't
     used the `--host' option to mysql and you are not using MIT
     threads, 'localhost' is a synonym for your hostname.

   * If `mysql -u root test' works but `mysql -h your_hostname -u root
     test' gives 'Access denied' then you don't have the right name for
     your host in the user table.  For example if you have an entry
     with host 'tcx' in the 'user' table, but your DNS tells MySQL that
     your hostname is 'tcx.subnet.se' then the entry can't work.  Test
     by adding a record with the IP of your host in the 'user' table.
     You can of course also add a host with a wildcard (for example
     'tcx%') in the 'user table' (but using hostnames ending with % is
     pretty insecure).

   * When using MIT threads, localhost is never used. All connections
     to the mysqld demon is done by TCP IP and you must have your real
     hostname in 'user' even if you are running the client on the same
     host as the server.

   * If you get the error 'Access to database denied' then you have a
     problem with the db table. If the used entry in the db table has
     an empty hostname, check also the corresponding entry in the
     'host' table.

   * If `mysql -u user database' to work on the server machine, but
     `mysql -u host -u user database' doesn't work on another client
     machine, then you don't have the client machine in the 'user' or
     the 'db' table.

   * If you can't get password to work, remember that passwords must be
     inserted with the PASSWORD function. *Note Security example::

   * If `mysql -u user test' works but `mysql -u user other_database'
     doesn't work, you don't have the other_database in the 'db' table.

   * If you get 'Access to database denied' when using the `SELECT ...
     INTO OUTFILE' or `LOAD DATA' SQL commands the you probably don't
     have the file_priv privilege set for you in the user table.

   * If everything else fails, start the `mysqld' demon with:
     `--debug=d,general,query'. This will print info about the host and
     user that tries to connect and also information about each command
     issued. *Note debugging::

   * If you have some more problems with the MySQL grant tables and
     feel you must post the problem to the list, always add a dump of
     the MySQL grant tables. You can dump the tables with the
     'mysqldump mysql' command.  Post your problem with the mysqlbug
     script.

   * *Note Privileges::

Problems using DATE fields.
===========================

   The format of DATE is 'YYYY-MM-DD'. Actually nothing else is allowed
(ANSI SQL). One should use this format to update or in the WHERE clouse.
Ie:  select * from table_1 where idate >= '1997-05-05';

   As a convinience MySQL automaticly converts the date to a number if
used in a number context. It's also smart enough to allow a 'relaxed'
string form when updating, but only when updating.

   This means that the following works:

     insert into table_1 (idate) values (19970505) ;
     insert into table_1 (idate) values ('19970505') ;
     insert into table_1 (idate) values ('1997-05-05');
     insert into table_1 (idate) values ('1997.05.05');
     insert into table_1 (idate) values ('1997 05 05');
     
     select idate from table_1 where idate >= '1997-05-05';
     select idate from table_1 where idate >= 19970505;
     select mod(idate,100)1 from table_1 where idate >= 19970505;

   The following will not work:

     select idate from table_1 where idate >= '19970505';
   Because '19970505' is compared as a string to '1997-05-05'.

How MySQL uses keys
===================

   All keys, PRIMARY, UNIQUE and INDEX(), are stored in B trees.
Strings are automaticly prefix- and end-space compressed.

   INDEX(col1, col2) creates a multiple index over the two columns.
The key can be seen like a concatenation of the given columns.  If you
use INDEX(col1), INDEX(col2) instead of INDEX(col1,col2) you get two
separate keys instead.

     SELECT * FROM table WHERE col1=# AND col2=#

   In case of INDEX(col1,col2) the right row(s) can be fetched directly.
In case of INDEX(col1), INDEX(col2) the optimizer decides which index
will find fewer rows and this index will be used to fetch the rows.

   If the table have a index INDEX(col1,col2,col3....) and prefix of
this can be used by the optimizer to find the rows.  This means that
above gives you search capabilities on: INDEX(col1) and
INDEX(col1,col2) and INDEX(col1,col2,col3)...

   MySQL can't use a sub part of a key to locate rows through a key.

   With the definition INDEX(col1,col2,col3):

     SELECT * FROM table WHERE col1=#
     SELECT * FROM table WHERE col2=#
     SELECT * FROM table WHERE col2=# and col3=#

   Only the first query will use keys.

