# Frequently Asked Questions about MySQL.

# 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]`. See section Subscribing to/un-subscribing from the `MySQL` 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 isSunet'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 thedistribution. 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 See section What column (column) types are available with MySQL?. 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.

- Use of `INTO OUTFILE` in a `SELECT` statement. See section SELECT syntax
- Use of key names, keys on a subpart of a field, and use of `KEY` or `INDEX` in a `CREATE TABLE` statement. See section CREATE TABLE syntax.
- Use of `DROP column` or `CHANGE column` in a `ALTER TABLE` statement. See section ALTER TABLE syntax
- Use of `LOAD DATA INFILE`. This syntax is in many cases compatible with Oracles `LOAD DATA INFILE`. See section LOAD DATA INFILE syntax
- Using `"` instead of `'` to enclose strings.
- Using the escape `\` character.
- The `SET OPTION` statement.
- 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.
- Use of any of the following functions:
  - `=`, `<>`, `<=` ,`<`, `>=`,`>`, `AND`, `OR`, or `LIKE` in a column statement
  - `REGEXP` or `NOT REGEXP`.
  - `CONCAT()` with other than 2 arguments. MySQL can take any number of arguments.
  - `BIT_COUNT()`, `ELT()`, `FROM_DAYS()`, `FORMAT()`, `IF()`, `PASSWORD()`, `PERIOD_ADD()`, `PERIOD_DIFF()`, `TO_DAYS()`, or `WEEKDAY()`.
  - The `STD()` group function.
  - 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. See section SELECT syntax
- 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. See section ALTER TABLE syntax
  `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. See section SELECT syntax.
  `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. See section How does the privilege system work?
  `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`. See section GRANT syntax. (Compability function).. This always succeedes. You should use the MySQL privilege tables. See section How does the privilege system work?
- `CREATE INDEX`. See section CREATE INDEX syntax (Compability function).. This always succeeds. You should create your index with `CREATE TABLE`. See section CREATE TABLE syntax.. You can also use `ALTER TABLE`. See section ALTER TABLE syntax.
- `DROP INDEX`. See section DROP INDEX syntax (Compability function).. This always succeeds. You can use `ALTER TABLE` to drop indexes. See section ALTER TABLE syntax.

# 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. See section How can I change the buffer sizes of `mysqld` ?.

    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 @math{(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). See section What is the different row formats? Or when to use VARCHAR/CHAR?.
- 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. See section LOAD DATA INFILE syntax

## 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. See section What column (column) types are available with MySQL?. 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. See section Limitations of BLOB's
- One can't use a blob COLUMN directly in a WHERE. Move the test to the HAVING clause. See section Limitations of BLOB's
- 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`. See section CREATE TABLE syntax..
- `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. See section LOAD DATA INFILE syntax.

## 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()`. @result{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 See section Literals. How do you write strings and numbers?.

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

@result{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. See section SHOW syntax. Get information about names of columns. 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. See section How does the privilege system work?

## 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. See section ALTER TABLE syntax

## DROP INDEX syntax (Compability function).

`DROP INDEX index_name`

This always succeeds. You can drop an index with ALTER TABLE. See section ALTER TABLE syntax

## 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. See section How do you check/repair/reconstruct an MySQL 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 See section How do you check/repair/reconstruct an MySQL 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. See section Why do I get '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. See section A example of permission setup.
- 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. See section How to debug MySQL
- 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.
- See section How does the privilege system work?

## 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.

This document was generated on 8 June 1997 using the texi2html translator version 1.51.