This is the MySQL reference manual. This version documents the 3.21.30 version of MySQL.
MySQL is a basically free SQL database server. See section 3 Licensing or When do I have/want to pay for MySQL?.
The latest information about MySQL is found at the MySQL Home page
To see what it can do. See section 1.4 The main features of MySQL.
For installation instructions See section 4 Compiling and installing MySQL. For tips on how to port MySQL to new machines/operating systems See section G Comments on porting to other systems..
If you have any suggestions concerning additions or corrections to this
manual, please send them to the MySQL mailing list
documentation suggestion: [Insert Topic Here]
.
See section 2.1 Subscribing to/un-subscribing from the MySQL mailing list..
See section 8.5.1 Upgrading to 3.21 from a 3.20 version, for information about upgrading from a 3.20 release.
For examples of SQL and benchmarking information see the `bench' directory.
For future plans See section F List of things we want to add to MySQL in the future..
A history of new features/bug fixes See section D MySQL change history.
For the currently known bugs/misfeatures (known errors) See section E Known errors and design deficiencies in MySQL.
For A list of all the contributors to this product See section C Who has helped to make MySQL..
IMPORTANT:
Send bug (error) reports, questions and comments to the mailing list at
Please use the mysqlbug
script when posting bug reports or
questions about MySQL. mysqlbug
will gather some
information about your system and start your editor with a form in which
you can describe your problem. Bug reports might be silently ignored by
the MySQL maintainers if there is not a good reason included in
the report as to why mysqlbug has not been used. A report that says
'MySQL does not work for me. Why?' is not consider a valid bug report.
The mysqlbug script can be found in the `scripts' directory in the distribution, that is `there-you-installed-mysql/scripts'.
MySQL is a SQL (Structured Query Language) database server.
SQL is the most popular database language in the world. MySQL
is a client server implementation that consists of a server daemon
mysqld
and many different client programs/libraries.
The main goals of MySQL are speed and robustness.
The base upon which MySQL is built is a set of routines that have been used in a highly demanding production environment for many years. While MySQL is still in development it already offers a rich and highly useful function set.
The official way to pronounce MySQL is 'My Ess Que Ell' (Not MY-SEQUEL).
This manual is currently available in TeXInfo, Raw text, Info and HTML versions. A PostScript version as available do download separately because of its size.
The primary document is the TeXInfo file. The HTML version is
automatically produced with a modified texi2html
. The ASCII and
info version are produced with makeinfo
. The Postscript version
is produced using texi2dvi
and dvips
.
This manual is written and maintained by David Axmark, Michael (Monty) Widenius and Kim Aldale. For other contributors See section B Contributed programs.
We once started off with the intention to use mSQL
to connect to
our own fast low level (ISAM) tables. However, after some testing we
came to the conclusion that mSQL
was not fast or flexible enough
for our needs. This resulted in a new SQL interface to our database but
with almost the same API interface as mSQL
. This API was chosen
to ease porting of third-party code.
It is not perfectly clear where the name MySQL derives from. Our base directory and a large amount of our libraries and tools have had the prefix 'my' for well over 10 years. However, Monty's daughter (some years younger) is also named My. So which of the two gave its name to MySQL is still a mystery, even for us.
FLOAT
, DOUBLE
, CHAR
, VARCHAR
,
TEXT
, BLOB
, DATE
, SET
and ENUM
types. See section 7.2 Column types.
select column1 + column2 from table where column1/column2 > 0
GROUP BY
and ORDER BY
. Support for
group functions (COUNT
, AVG
, SUM
, MAX
and
MIN
).
LEFT OUTER JOIN
with ANSI SQL and ODBC syntax.
autoconf
for portability.
purify
).
DELETE
, INSERT
, REPLACE
, and UPDATE
returns
how many rows were affected.
--help
or -?
for help.
show tables
, SHOW INDEX FROM table
and
show columns from table
There is one SQL tutor on the net at http://w3.one.net/~jhoffman/sqltut.htm
This one has been recommended by a lot of people on the MySQL mailing list.
Judith S. Bowman, Sandra L. Emerson and Marcy Darnovsky "The Practical SQL Handbook: Using Structured Query Language" Second Edition Addison Wesley ISBN 0-201-62623-3 http://www.awl.com
And another book also recommended by people on the MySQL mailing list.
Understanding SQL ISBN 0-89588-644-8 Publisher Sybex 510 523 8233 Alameda CA USA
There are also many web pages that use MySQL. See section A Some users of MySQL.. Send any additions to this list to
A stored procedure is a set of SQL commands that can be stored and compiled in the server. After this, the client doesn't have to issue the whole query but can refer to the stored procedure. This gives some more speed because the query only has to be parsed once and there is less data that has to be sent between the server and the client. You can also raise the conceptual level by having libraries of functions in the server.
A trigger is a stored procedure that is invoked when something happens. For example one can install a stored procedure that checks every delete to a transaction table and does an automatic delete on the corresponding customer when all his transactions are deleted.
To see when MySQL might get these functions See section F List of things we want to add to MySQL in the future..
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 automatically forwarded to hundreds of other users.
Your local site may have many subscribers to mysql@tcx.se. 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
such cases, please contact your system administrator to be added to or
dropped from the local mysql@tcx.se list.
Mail to mdomo
is handled automatically by majordomo.
The following mailinglists exists:
mysql-announce
mysql
mysql-digest
mysql-Java
mysql-win32
myodbc
msql-mysql-modules
msql-mysql-modules-digest
You subscribe/unsubscribe to all lists in the same way as described
above. Just exchange mysql
with the list name.
Before you ask a question on the mailing list, it is a good idea to check this manual. If you can't find an answer here, check with your local MySQL expert. If you still can't find an answer to your question go ahead and read the next section about how to send mail to
If you can, please use the `mysqlbug' script that can be found in the scripts directory in the distribution. If that is not possible, remember to specify (if relevant) the following. Note that it is possible to answer a letter with too much information but not one with too little. You should always use `mysqlbug' if your question is anyway related to a MySQL version you are using!
mysqlbug should automaticly finds most of the following information, but if something important missing please include this in your question!
mysqladmin version
.
uname -a
.
If you are a support customer, please post the bug report 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 summarise the answers and mail them to the mailing list.
Since it is very hard to now why something crashing please do one of the following things.
First try to check if thigs that work for other crash for you:
--with-debug
switch to
configure. This will include a safe memory allocator that can find some
errors. This also gives a lot of output about what is happening.
back
(or the backtrace command in your debugger) when
mysqld
core dumps.
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 such cases, please make sure that your answer is not a duplication of a previous answer.
Try to summarise the essential part of the question in your reply, but don't feel obliged to quote the whole question.
Basic licensing issues:
See section J The MySQL server license.
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 section J The MySQL server license.
The client access part of MySQL is in the public domain. The command line client includes parts that is under the GNU Public License (readline).
These are our current license prices. All prices are in US Dollars. If you pay by credit card, the currency is FIM (Finish Marks) so the prices will differ slightly.
Number of licenses | Price/Copy | Total |
1 | US $200 | US $200 |
10 pack | US $150 | US $1500 |
50 pack | US $120 | US $6000 |
licenses | Price/Copy | Minimum at one time | Minimum Payment |
100-1000 | $40 | 100 | $4000 |
1000-2500 | $25 | 200 | $5000 |
2500-5000 | $20 | 400 | $8000 |
A full-price license includes really basic support. This means that we are trying to answer any relevant question. If the answer is in the documentation, we are going to direct you to the relevant documentation. If you do not have a license/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 is sold separately:
One year of basic email support costs $200 (USD).
It includes:
One year of extended email support costs $1000 (USD).
Extended basic supports contains everything in basic email support with these additions:
BLOB
or TEXT
types
yet). The current server includes support to read such databases but not
the packing tool.
One year of email/phone/telnet support costs $2000 (USD).
Login supports contains everything in extended basic email support with these additions:
One year of extended email/phone/telnet support costs $5000 (USD).
Extended login supports contains everything in login support with these additions:
select my_calculation(column1,column2) from database;
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, SWEDEN 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 "Monty Program KB". And mail it to the address below.
T.C.X DataKonsult AB BOX 6434 11382 STOCKHOLM, SWEDEN
If you want to pay with credit card over the Internet you can use TcX's secure license form
For commercial licensing, or if you have any questions about any of the information in this section, please contact:
David Axmark Detron HB Kungsgatan 65 B 753 21 UPPSALA SWEDEN Voice Phone +46-18-10 22 80 (Swedish and English spoken) Fax +46-8-729 69 05 (Email *much* preferred) E-Mail: mysql-licensing@tcx.se
There are (at least) four different copyright's on the MySQL distribution.
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 the `client' directory and some parts of
mysys, mystring and dbug libraries.
getopt
) are covered by the
"GNU LIBRARY LIBRARY GENERAL PUBLIC LICENSE".
See the `mysys/COPYING.LIB' file.
readline
) are covered by the
"GNU GENERAL PUBLIC LICENSE". See the `readline/COPYING' file.
regexp
library) are covered by a Berkeley
style copyright.
Our philosophy behind this is:
This is a clarification of the information in the 'MySQL FREE PUBLIC LICENSE'. See section J The MySQL server license.
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 authorised to grant such licenses.
You may not include MySQL "free" in a package containing anything for which a charge is being made except as noted below.
The intent of the exception provided in the second clause is to allow commercial organisations operating an FTP server or a bulletin board to distribute MySQL freely from it, provided that:
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 want to sell 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 chooses to use MySQL?
If your product REQUIRES MySQL to work, you would have to buy a license. If MySQL just added some new features it should fall inside normal use. For example, if using MySQL added logging to a database instead of a text file it would not require a license. 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 license to sell your product.
Do I have to get a license for my copy?
No, you are not selling MySQL itself. But in 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).
Is your script designed for MySQL alone? Does it require MySQL to function at all? Or is it designed for `a database' and can run under MySQL, PostgreSQL, or something else?
If you've designed it strictly around MySQL then you've really made a commercial product that requires the engine, so you need to buy a license.
If, however, you can support any database with a base level of functionality (and you don't rely on anything that only MySQL supports) you probably DO NOT have to pay.
It also depends on what you're doing for the client. Are you tying into a database you expect to already exist by the time your software is purchased? Then you again probably don't have to pay. Or do you plan to distribute MySQL or give them detailed instructions on installing it with your software? Then you probably do.
One thing I'd like to suggest, folks. Look, development won't last forever if nobody pays. I agree that buying a copy for every software user is prohibitive compared to other products available but would it not be courtesy for commercial developers to register their OWN copy that they develop with?
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.
You can always check MySQL's home page to read the latest news.
But since the Internet connection at TcX is not very fast we would prefer if you do the actual downloading from one of the mirrors below.
Europe:
North America:
Asia:
Australia:
The first decision is if you want to use the latest development release or the last stable release.
Normally if you are starting with development we recommend going with the development release. This is because there are usually no really bad bugs in the development release and you can easily test it on your machine with the crash-me and benchmark tests. See section 11 MySQL benchmark suite.
The second decision is if you want a source or a binary release.
If you want to run MySQL on a platform that has a current binary release, use that. A binary version of MySQL is easier to install.
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 than the binary distribution.
To clarify our naming schema:
All MySQL versions are run through our standard test and the benchmarks to ensure that they are relatively safe to use. The standard tests are also extended the whole time to test for all previously found bugs, so it gets better the whole time.
The MySQL release numbers consist of 3 numbers and a suffix.
So a release name like mysql-3.21.17-beta
means.
Note that all releases have at least been tested with:
Another test is our internal production. We usually use the latest version for this (at least on one machine) and we have more than 100 gigabytes of data to work with.
We are using the following policy when updating MySQL:
Each minor update will increment the last number in the version string. When there are major new features or minor incompatibilities with previous versions, the second number in the version string will be incremented. When the file format changes the first number will be increased.
We use GNU autoconf so it is possible to port MySQL to all modern systems with working Posix threads and a C++ compiler. The client code requires C++ but not threads. We use/develop the software ourselves primarily on Sun Solaris (versions 2.5 & 2.6) and some on RedHat Linux 5.0.
The following OS/thread packages have been reported to compile MySQL successfully. Note that for many OSes the native thread support only works in the latest versions.
What you need:
gzip
to uncompress the distribution.
tar
to unpack the distribution. GNU tar
is
known to work.
C++
compiler. gcc >= 2.7, SGI C++, SunPro C++ are
some of the compilers that are known to work. libg++
is not
needed when using gcc
.
make
program. If you have problems we recommend trying GNU
make
.
Unpack tar archive in a directory. The tar file should be named like mysql-VERSION.tar.gz (VERSION is a number like 3.21.30). A directory named mysql-VERSION should be created.
zcat mysql-VERSION.tar.gz | tar xvf -
cd mysql-VERSION
./configure
make
make install
./scripts/mysql_install_db
'installation_directory'/bin/mysqladmin version
mysqladmin Ver 6.3 Distrib 3.21.17, for pc-linux-gnu on i686 TCX Datakonsult AB, by Monty Server version 3.21.17-alpha Protocol version 10 Connection Localhost via UNIX socket TCP port 3306 UNIX socket /tmp/mysql.sock Uptime: 16 sec Running threads: 1 Questions: 20 Reloads: 2 Open tables: 3
Remember that if you reconfigure MySQL you have to do
rm config.cache
or make distclean
before doing a new configure!
Usual configure switches:
--without-server
. If you only
want to have the client library and don't have a C++ compiler, you
can remove the code in configure (in the source distribution) that tests
for the C++ compiler and then compile with --without-server. Ignore in
this case any warnings about mysql.cc
(The only MySQL client
that needs C++).
--prefix=/usr/local
or --prefix=/usr/local
--localstatedir=/usr/local/data/mysql
--with-unix-socket-path=absolute_file_name
Internal compiler error: program cc1plus got fatal signal 11
or
Out of virtual memory
you can try the configure switch:
--with-low-memory
.
This adds -fno-inline
to the compile line if you are using gcc
and -O0 if you are using something else. The problem is that gcc requires
about 180M to compile sql_yacc.cc with inline functions.
--with-charset=charset
.
Where [charset] may be one of: big5
, czech
, dec8
,
dos
, german1
, hp8
, koi8_ru
, latin1
,
latin2
, swe7
, usa7
, ujis
, or sjis
.
If you want to add another character set to MySQL you must:
mysql_source_directory/strings/ctype-$CHARSET_NAME.c
.
CHARSETS_AVAILABLE
list in
configure
.in
#define MY_CHARSET_<C> X #if MY_CHARSET_CURRENT == MY_CHARSET_<C> #define USE_MB #define USE_MB_IDENT #define ismbchar(p, end) (...) #define ismbhead(c) (...) #define mbcharlen(c) (...) #define MBMAXLEN N #endif
MY_CHARSET_<C> | unique value. |
USE_MB | This charset have mb-char. |
USE_MB_IDENT: | Use mb-char as identifier. (optional) |
ismbchar(p, e) | return 0 if not mb-char, or size of char if mb-char. Check from (char*)p to (char*)e-1. |
ismbhead(c) | Is c first char of mb or not? |
mbcharlen(c) | Size of char if c is first char of mb. |
MBMAXLEN | Maximum size of one character. |
SET OPTION CHARACTER SET
.
See section 7.20 SET OPTION syntax.
Warning: If you change character sets after having created a
table you will have to run isamchk -r -q
on every
table. Otherwise things will be sorted incorecctly in some cases (but
not all!).
make
is always recommended and is sometimes required.
About creating the grants database `mysql_install_db':
The default priviliges is that anybody may create/use the databases
named test
or starting with test_
. root
can do
anyting. See section 6.2 How does the privilege system work?.
To change the defaults edit the script before running it. If this is
the first time you install MySQL you must run this command. If
you don't do it you will get the error: Can't find file:
'./mysql/host.frm'
. This script also starts the mysqld daemon the first
time.
If you want to change things in the grant tables after installing you
should use mysql -u root mysql
to connect to the grant tables
as the 'root' user.
Normal start of the MySQL server daemon (not needed the first
time): 'installation_directory'/bin/safe_mysqld --log
Some times patches appear on the mailing list. To apply them, do something like this:
cd 'old-mysql-source-distribution-path' gunzip < patch-file-name.gz | patch -p1 rm config.cache make clean
And then follow the instructions for a normal source install from the
./configure
step.
And then restart your MySQL server.
If your compile fails with something like:
configure: error: installation or configuration problem: C++ compiler cannot create executables.
Try setting the environment variable CXX
to "gcc -O3"
(If
you are using gcc
). For example CXX="gcc -O3"
./configure
. If you use this you don't nead to have libg++ installed!
If you have any problems with using g++, or libg++ or libstdc++, you can probably always solve these by configuring as above!
You can also install libg++. By default `configure' picks
c++
as a compiler name and GNU c++
links with
-lg++
.
making all in mit-pthreads make: Fatal error in reader: Makefile, line 18: Badly formed macro assignmentThis means you have to upgrade your make to GNU
make
.
CC="gcc -O4" CXX="gcc -O4" export CC CXX
make
stops with Can't find Makefile.PL
when
you should try using GNU make
. Solaris and FreeBSD
are known to have troublesome make
programs.
pthread.h: No such file or directory
This means you have to upgrade your make
to GNU make
(GNU make
version 3.75 is known to work).
client/libmysql.c:273: parse
error before `__attribute__'
This means you need to upgrade your gcc compiler (2.7.2 is known to work).
mysqlbug
when posting questions to mysql@tcx.se. See section 2.3 I think I have found a bug. What information do you need to help me?.
Even if the problem isn't a bug, mysqlbug gathers some system
information that will help others solve your problem!
configure --with-debug=yes
and link your clients with
the new client library.
Before running a client you should do:
MYSQL_DEBUG=d:t:O,/tmp/client.trace export MYSQL_DEBUGYou will now get a trace file in `/tmp/client.trace'.
cxx: Error: mysqld.cc, line 645: In this statement, the referenced type of the pointer value "&length" is "unsigned long", which is not compatible with "int". new_sock = accept(sock, (struct sockaddr *)&cAddr, &length);Then configure didn't detect the type of the last argument to
accept()
, getsockname()
and getpeername()
. Search
after the line:
/* Define as the base type of the last arg to accept */ #define SOCKET_SIZE_TYPE ###and change ### to size_t or int depending on your operating system.
mysql --debug=d:t:o,/tmp/client.trace
before mailing a bug
report. See section 2.3 I think I have found a bug. What information do you need to help me?.
All MySQL programs compile clean (no warnings) for us (on Solaris using gcc). But warning may appear because of different system include files. Se below for warnings that may occur when using mit-pthreads.
You probably have to use bison to compile sql_yacc.yy. If you get an error like:
"sql_yacc.yy", line xxx fatal: default action causes potential...
you have to install bison (the GNU yacc).
If you want to have static linked code, use (with gcc):
LDFLAGS="-static" ./configure ...
You can on most systems force the usage of mit-pthreads with the configure
switch --with-mit-threads
.
Building in a non source directory is not supported when using MIT-threads. This is because we want to keep our changes to this code minimal.
MIT-pthreads doesn't support the AF_UNIX
protocol so we must use
the TCP/IP protocol for all connections (which is a little slower). If
you can't connect to a table, try using the host (-h
or
--host
) switch to mysql
. This must be done if you have
compiled the client code --without-server
because the default
connection is to use Unix sockets.
MySQL compiled with MIT threads has system locking disabled by
default for performance reasons. One can start the server with system
locking with the --use-locking
switch.
Sometimes (at least on Solaris) the pthread bind()
command fails
to bind to a socket without any error message. The result of this is
that all connections to server fails.
> mysqladmin ver mysqladmin: connect to server at " failed; error: 'Can't connect to mysql server on localhost (146)'
The solution to this is to kill the mysqld
daemon and restart it.
This has only happened to us when we have forced the daemon down and done
a restart immediately.
sleep()
isn't interruptible with SIGINT
(break) with
MIT-threads. This is only notable in mysqladmin --sleep
. One must
wait for the end of the sleep()
before the interrupt is served
and the process stops.
We haven't got readline to work with MIT threads. (This isn't needed, but may be interesting for someone)
When linking (at least on Solaris) you will receive warning messages like:
ld: warning: symbol `_iob' has differing sizes: (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4; file /usr/lib/libc.so value=0x140); /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken ld: warning: symbol `__iob' has differing sizes: (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4; file /usr/lib/libc.so value=0x140); /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken
Some other warnings which also can be ignored:
implicit declaration of function `int strtoll(...)' implicit declaration of function `int strtoul(...)'
The included perl client code requires perl5.004 or later.
If you got a the following error (from mysqlperl or DBD-mysql):
/usr/bin/perl: can't resolve symbol '__moddi3' /usr/bin/perl: can't resolve symbol '__divdi3'
You are probably using gcc (or using an old binary compiled with
gcc). Add -L/usr/lib/gcc-lib/... -lgcc
to the link command where
-L/...
is the path to the directory where libgcc.a
exists.
Sun native threads only work on Solaris 2.5 and higher. For 2.4 and earlier versions, you can use MIT-pthreads. See section 4.8 MIT-pthreads notes. (FreeBSD).
If there are too many processes that try to connect very rapidly to the
mysqld
one will get Error in accept : Protocol error
in
the mysql log.
If you have the Sun Workshop 4.2 compiler you can configure with:
CC="cc -Xa -fast -xstrconst" CXX="CC -xsb -noex -fast"
./configure
You may also have to change the row in configure:
#if !defined(__STDC__) || __STDC__ != 1
to #if
!defined(__STDC__)
because if you turn on __STDC__
with the
-Xc
switch, the Sun compiler can't compile with the Solaris
`pthread.h' header files anymore. This is a Sun bug (Broken
compiler or broken include file).
If the compiled mysqld
gives a error like: libc internal
error: _rmutex_unlock: rmutex not held.
you probably are using the Sun
pro compiler on Solaris 2.6. Either ask sun for a working compiler or
upgrade to gcc (gcc also produces about 10% faster C++ code).
The tar in Solaris can't handle long file names; You may get the following error (or something similar) when unpacking the MySQL distribution:
x mysql-3.21.21a-beta-sun-solaris2.6-sparc/perl/Mysql-modules/blib/lib/auto/Msql-Mysql-modules, 0 bytes, 0 tape blocks tar: directory checksum error
You have to use gnu tar to unpack the distribution. You can find copy of precompiled gnu tar (gtar) for Solaris at http://www.mysql.com/Downloads/
On SunOS 4, MIT-pthreads is needed. You must have GNU make
to compile
(because of MIT-pthreads).
In readline you may get warnings about duplicate defines. These may be ignored.
When compiling mysqld there will be some warnings about implicit
declaration of function
. These may be ignored.
On Linux you should use the --skip-locking
flag to mysqld
(it is added automatically by safe_mysqld
). This is because a bug
in Linux file locking calls. This bug is known to exist as recently as
Linux version 2.0.32.
When using LinuxThreads you will see a minimum of three processes running. These are in fact threads. There will be one thread for the Linux Threads manager, one thread to handle connections, and one thread to handle alarms and signals.
if you are using RedHat you might get errors like:
/usr/bin/perl is needed... /usr/sh is needed... /usr/sh is needed...
If so upgrade rpm itself to rpm-2.4.11-1.i386.rpm & rpm-devel-2.4.11-1.i386.rpm (or later versions).
You can get the 4.2 updates from ftp://ftp.redhat.com/updates/4.2/i386. Or http://www.sunsite.unc.edu/pub/Linux/distributions/redhat/code/rpm/ for other distributions.
LinuxThreads should be installed before configuring MySQL!
MySQL requires libc version 5.4.12 or newer. glibc version 2.0.6 and later should also work. There has been some problems with the glibc rpms from RedHat so if you have problems, check if there are any updates!
On some older Linux distributions configure
may give a error
about: Syntax error in sched.h. Change _P to __P in the
/usr/include/sched.h file.\
See the Installation chapter in the Reference Manual
. Just do what the
error says and add a extra underscore to the _P
macro that only
has one underscore. Then try again.
You may get some warnings when compiling: (these can be ignored)
mysqld.cc -o objs-thread/mysqld.o mysqld.cc: In function `void init_signals()': mysqld.cc:315: warning: assignment of negative value `-1' to `long unsigned int' mysqld.cc: In function `void * signal_hand(void *)': mysqld.cc:346: warning: assignment of negative value `-1' to `long unsigned int'
If you want in Debian GNU/Linux to get MySQL to auto start when system boots, do the following:
> cp scripts/mysql.server /etc/init.d/mysql.server > /usr/sbin/update-rc.d mysql.server defaults 99
If mysqld always core dumps when starting, the problem may be that you have an old `/lib/libc.a'. Try renaming this, remove sql/mysqld and do a new make install and try again. This problem has been reported on some Slackware installations.
If you install all the official redhat patches (including glibc-2.0.6-9 and glibc-devel-2.0.6-9) it should work out of the box (se above for how to configure).
The updates are needed since there is a bug in glibc 2.0.5 in how pthread_key_create variables are freed. With glibc 2.0.5 you must use the static-linked MySQL binary distribution. If you want to compile from source you must install the corrected version of Linuxthreads from http://www.tcx.se/Downloads/Linux or upgrade your glibc.
If you have a wrong glibc or linuxthread version the symptom is that
mysqld crashes after each connections. For example mysqladmin version
will crash mysqld when it finishes!
Another symptom of wrong libraries is that mysqld crashes at once when it
starts. One some Linux systems this can be fixed by configuring with
LDFLAGS=-static ./configure
. On some RedHat 5.0 system it will only
work WITHOUT LDFLAGS=-static
. This is known to happen even with
new versions as glibc 2.0.7-4 !
For the source distribution of glibc 2.0.6 you can find a patch at
http://www.tcx.se/Download/Linux/glibc-2.0.6-total-patch.tgz
that is easy to apply and is tested with MySQL
!
If you experience crashes like these when you build MySQL, you can always download the newest binary version of MySQL. This is compiled staticly to avoid library conflicts and should work on all Linux systems!
In some implementations readdir_r
is broken. This will be
noticed when SHOW DATABASES
always returns an empty set. This
can be fixed by removing HAVE_READDIR_R
from `config.h'.
Some problems will require patching your Linux installation. The patch can be found at http://www.tcx.se/patches/Linux-sparc-2.0.30.diff. This patch is against the Linux distribution `sparclinux-2.0.30.tar.gz', that is available at vger.rutgers.edu. This is a version Lf linux which was never merged with the official 2.0.30. You must also install linuxthreads 0.6 or newer.
Thanks to jacques@solucorp.qc.ca for the above information.
The first problem is linuxthreads. You must patch linuxthreads for alpha because the RedHat distribution uses an old (broken) linuxthreads version.
CC=gcc CCFLAGS="-Dalpha_linux_port" CXX=gcc CXXFLAGS="-O3 -Dalpha_linux_port" ./configure --prefix=/usr/local/mysql
Note that Alpha-Linux is still an alpha platform for MySQL. With RedHat 5.0 and the patched linuxthreads you have a very good chance of it working.
When compiling threaded programs under Digital UNIX using CC / CXX the
documentation recommends the switch to cc and cxx and the libraries
-lmach -lexc
(in addition to -lpthread
).
So you have to configure with something like this:
CC="cc -pthread" CXX="cxx -pthread -O" ./configure
-with-named-thread-libs="-lpthread -lmach -lexc -lc"
When compiling mysqld you will may this warning for mysqld for a couple of lines:
mysqld.cc: In function void handle_connections()': mysqld.cc:626: passing long unsigned int *' as argument 3 of accept(int,sockad ddr *, int *)'
You can safely ignore these. This is because configure can't detect warnings, only errors.
You may get problems with the server exiting directly. If so, try
starting it with nohup safe_mysqld [options]
nohup
is a command that ignores any SIGHUP
sent from the
terminal.
If you have problems compiling and have Dec CC and gcc installed you can try the following compile line (with sh or bash):
CC=cc CFLAGS=-O CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql
On OSF1 V4.0D and compiler "DEC C V5.6-071 on Digital UNIX V4.0 (Rev. 878)" the compiler had some strange behaviour (One gets undefined 'asm' symbols). /bin/ld appears also to be broken (one gets _exit undefined when linking mysqld). On this we have managed to compile MySQL with the following configure line, after replacing /bin/ld from OSF 4.0C:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql
In some versions of OSF1, the alloca()
functions is broken. Fix
this by removing 'HAVE_ALLOCA'
from config.h.
The alloca()
function can also have a wrong prototype in
/usr/include/alloca.h
. This warning can be ignored.
Configure will automaticly use the following thread libraries:
-with-named-thread-libs="-lpthread -lmach -lexc -lc"
When using gcc you can also try to use:
CFLAGS=-D_PTHREAD_USE_D4 CXX=gcc CXXFLAGS=-O3 ./configure ....
You may have to undefine some things in `config.h' (generated by `./configure').
In some Irix implementations the alloca()
function is broken. If
the mysqld server dies on some selects, remove HAVE_ALLOC
&
HAVE_ALLOCA_H
from `config.h'. If mysqladmin create doesn't
work, remove HAVE_READDIR_R
from config.h. Also you may have to
remove HAVE_TERM_H
.
Irix 6.2 doesn't support POSIX threads out of of the box. You have install these patches, available from SGI if you have support:
1403, 1404, 1644, 1717, 1918, 2000, 2044
If you get the something like the following error when compiling mysql.cc:
"/usr/include/curses.h", line 82: error(1084): invalid combination of type
Type the following in the mysql installation directory:
> extra/replace bool curses_bool < /usr/include/curses.h > include/curses.h > make
There have also been reports about scheduling problems. This is because if only one thread is running, things go slow. Avoid this by starting another client. This may lead to a 2-10 fold increase in execution speed thereafter for the other thread.
This is a poorly-understood problem with IRIS threads, so you may have to improvise to find solutions until this can be fixed.
If you are compiling with gcc, you can use the following configure line:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-thread-safe-client
If you get a error on 'make install' that it can't find /usr/include/pthreads, configure didn't detect that one neads mit-threads on FreeBSD. This is fixed by doing:
rm config.cache ./configure --with-mit-threads
If you get link errors when compiling mysqlperl (Type
ient.a(my_getwd.o): RRS text relocation at 0x9a9f for
"__db_pargs_"
)
You must recompile the Perl code with -DPIC -fpic
.
Do the following:
CFLAGS = -g -O2
to
CFLAGS = -O2 -DPIC -fpic
cd client
rm *.o
make libmysqlclient.a
cd ../perl
make
This shall hopefully be handled automatically in the future.
The FreeBSD make
behaviour is slightly different from GNU
make
. If you have a problem that `perl/Makefile'
doesn't get generated, you should install GNU make
.
If mysql or mysqladmin takes a long time to respond, a user said the following:
Are you running the ppp user process? On ine FreeBSD box (2.2.5) MySQL clients takes a couple of seconds to connect to mysqld if the ppp process is running.
FreeBSD is also known to have a very low default file handle limit. See section 15.6 File not found
If you have a problem that select NOW() returns GMT and not your local time,
you have to set the TZ
environment variable to your current timezone.
You have to configure with:
--with-named-thread-libs=-lc_r
The pthreads library for FreeBSD doesn't contain the sigwait
function and there is some bugs in it. To fix this, get the
`FreeBSD-3.0-libc_r-1.0.diff' file and apply this in the
`/usr/src/lib/libc_r/uthread' directory. Follow after this the
instructions that can be found with man pthread
about how to
recompile the libc_r
library.
You can test if you have a 'modern' libpthread.a
with:
> nm /usr/lib/libc_r.a | grep sigwait.
If the above doesn't find sigwait
you have to use the above patch
and recompile libc_r
.
From Jan Legenhausen jleg@csl-gmbh.net.
I finally got mysqlperl working on BSDI2.1.
What i did was almost nothing:
GCC="shlicc2"
per default;
perl5 automagically uses shlicc2 - you should use _one_ version (either
gcc
or shlicc2
) for both Mysql.c
and
libmysqlclient.a
!)
rm *.o
gmake libmysqlclient.a
cd ../perl/mysqlperl
make clean
$sysliblist=" -L$tmp -lgcc -lcompat";
to Makefile.PL line 45
(just to be sure - i didn't check if one could leave out this one)
perl Makefile.PL
libmysqlclient.a
's in /usr/lib
and
/usr/contrib/lib
make install
If you get the following error when compiling MySQL:
item_func.h: In method `Item_func_ge::Item_func_ge(const Item_func_ge &)': item_func.h:28: virtual memory exhausted make[2]: *** [item_func.o] Error 1
Then your ulimit for virtual memory is too low. Try using: ulimit
-v 80000
and do make
again.
If you are using gcc you can also add the flag '-fno-inline' to the compile line when compiling sql_yacc.cc.
If you have a problem that select NOW() returns GMT and not your local time,
you have to set the TZ
environment variable to your current timezone.
env CXX=shlicc++ CC=shlicc2 ./configure --prefix=/usr/local/mysql --localstatedir=/var/mysql --without-perl --with-unix-socket-path=/var/mysql/mysql.sockThe following is also known to work:
env CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-unix-socket-path=/var/mysql/mysql.sock
You can change the directory locations if you wish, or just use their defaults by not specifying them.
The current port is only tested on a 'sco3.2v5.0.4' system.
as
.
make
when making MySQL.
SCO development notes:
-lgthreads -lsocket -lgthreads
When using the IBM compiler, something like this is needed:
CC="xlc_r -ma -O3 -qstrict" CXX="xlC_r -ma -O3 -qstrict" ./configure
Automatic detection of xlC is missing from autoconf.
There is a couple of 'small' problems when compiling mysql on HPUX. Below we describe some problems and workarounds when using the HPUX compiler and gcc 2.8.0 .
gcc 2.8.0 can't compile readline on HPUX (internal compiler error). mit-pthreads can't be compiled with HPUX compiler, because it can't compile .S (assembler) files.
We got MySQL to compile on HPUX 10.20 by doing the following:
CC=cc CFLAGS="+z +e -Dhp9000s800 -D__hpux__" CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-low-memory cd mit-pthreads rm config.cache CC=gcc CXX=gcc ./configure cd .. make make install scripts/mysql_install_db
The MySQL-win32 version has by now proven itself to be very stable. The MySQL-win32 version has all the features as the corresponding Unix version of MySQL with the following exceptions:
ALTER TABLE
ALTER TABLE
on file if it is hold open by another thread
or the table cache. On MySQL-win32 I have added code to close the
file owned by the thread that does ALTER TABLE
but MySQL
can't yet close the the file descriptors used by other threads. We have to do
a major recode of the file lock system to handle this. For now, when using
ALTER TABLE
, one must be sure that no other threads are using the table.
One can be sure of this by doing a 'mysqladmin refresh' before doing an
ALTER TABLE
.
Increasing the table cache
Win95 and threads
Other win32 specific issues are described in the README file that comes with the MySQL-win32 distribution.
Please always use the mysqlbug script when posting questions to the mailinglist (mysql@tcx.se). Even if the problem isn't a bug, mysqlbug gathers some system information that will help other solve your problem! See section 2.3 I think I have found a bug. What information do you need to help me?.
> cd /usr/local > zcat /<where ever you put it>/mysql-3.20.0-SunOS5.tgz | tar xvf - > ln -s mysql-VERSION mysql
> scripts/mysql_install_dbSee section 4.13 Problems running mysql_install_db If you want to change things in the grant tables after installing you should use
mysql -u root mysql
to connect to the grant tables
as the 'root' user.
The mysql_install_db
script also starts the mysqld
daemon.
> bin/safe_mysqld --log &
> bin/mysqladmin verThat should print something like this. The exact output depends on you platfrom and use.
bin/mysqladmin Ver 6.3 Distrib 3.21.15-alpha, for SOLARIS 2.5 on SPARCstation TCX Datakonsult AB, by Monty Server version 3.21.15-alpha Protocol version 9 Connection Localhost via UNIX socket TCP port 3306 UNIX socket /tmp/mysql.sock Uptime: 2 days 1 hour 42 min 3 sec Running threads: 2 Questions: 450378 Reloads: 17 Open tables: 64
cd perl/DBI perl Makefile.PL make make install cd ../Mysql-modules perl Makefile.PL make make install
You should use the safe_mysqld
script to the server.
safe_mysqld
expects one of two conditions to be true:
/usr/local/mysql
)
/my/
. To get it to run correctly,
you should cd to /usr/local/mysql
and then execute
safe_mysqld
or modify the script so that it expects the base
mysql directory to be `/usr/local/mysql' rather than the default
`/my/'.
When you execute this:
> bin/mysqld --help
You will get the options for mysqld (and safe_mysqld) and the current
paths. Normally you only should need to change the
--basedir=path
. You can test the path switches by executing:
> bin/mysqld --basedir=/usr/local --help
If you would like to use mysqlaccess and have the mysql distribution in
some nonstandard place, you must change the path to mysql in
mysqlaccess. bin/mysqlaccess
about line 308:
$MYSQL = '/usr/local/bin/mysql --batch --unbuffered';
If you don't change the path, you will get a 'broken pipe' error when using mysqlaccess.
If you would like MySQL to start when you boot your machine,
you can copy bin/mysql.server
to where your system has it startup
files. More information can be bound in the bin/mysql.server script
itself.
The binary distribution of MySQL for HP/UX is distributed as an HP depot file. This means that you must be running at least HP/UX 10.x to have access to HP's software depot tools.
This version of MySQL was compiled on an HP 9000/8xx server under HP/UX 10.20, and uses MIT Pthreads. It is known to work well under this configuration. This version does not use HP's native thread package. It is highly unlikely that MySQL will use HP native threads on anything but HP/UX 10.30 or later.
Other configurations that may work:
9000/7xx - HP/UX 10.20+ 9000/8xx - HP/UX 10.30 (does not use HP native threads)
The following configurations almost definitely won't work:
9000/7xx or 8xx - HP/UX 10.x where x < 2 9000/7xx or 8xx - HP/UX 9.x
To install (everything, including server, client and development tools):
/usr/sbin/swinstall -s <full path to the depot file> mysql.full
To install server only:
/usr/sbin/swinstall -s <full path to the depot file> mysql.server
To install client pack only:
/usr/sbin/swinstall -s <full path to the depot file> mysql.client
To install development tools only:
/usr/sbin/swinstall -s <full path to the depot file> mysql.developer
The depot will place binaries/libraries in /opt/mysql and data in /var/opt/mysql. The depot will also create the appropriate entries in /sbin/init.d and /sbin/rc2.d to automatically start the server on boot. This obviously entails being root to install.
Clients have to be linked with: -lmysqlclient
It may happen that mysql_install_db
doesn't install the privilige
tables but ends with:
Starting mysql server starting mysqld demon with databases from xxxxxx mysql demon ended
In this case you should examine the log in the xxxxxx directory very carefully! This contains the reason why mysqld didn't start. If you can't understand what happens, you should at least include the log when you post a bug report using mysqlbug!
Possible problems when running mysql_install_db
are:
There is already a mysqld deamon running.
Installing a second mysqld daemon doesn't work when one daemon is running.
MYSQL_UNIX_PORT=/tmp/mysqld-new.sock MYSQL_TCP_PORT=3307 export MYSQL_UNIX_PORT MYSQL_TCP_PORT scripts/mysql_install_dbAfter this you should edit your server boot script to start both daemon with different sockets and ports (safe_mysqld --socket=... --port=....).
mysqld crashes at once.
MySQL
mail archives.
See section 4.10.3 Linux notes for all versions
Can't connect to the server (when using mit-threads)
mysql_install_db
can't connect to the server you should check
that you have an entry in `/etc/hosts' like:
127.0.0.1 localhostThe above is only a problem on system that doesn't have a thread library and MySQL has to use mit-threads.
You don't have write access to create a socket file (in /tmp ?)
mysqld --help
.
You can also specify paths for safe_mysqld by doing the following:
MYSQL_UNIX_PATH=/some_directory_for_tmp_files/mysqld.sock MYSQL_TCP_PORT=3306 TMPDIR=/some_directory_for_tmp_files/ export MYSQL_UNIX_PATH MYSQL_TCP_PORT TMPDIR scripts/mysql_install_db or bin/mysqld --skip-grant bin/mysql -u root mysqlAfter this you can execute the sql commands in mysql_install_db.
The paths may be different from what mysqld expects.
mysqld --help
for more information. You can edit
bin/safe_mysqld to reflect the paths for your installation.
A simple test to see that everything is working is:
bin/mysqladmin version
Check the log file to see if mysqld started up correctly.
mysqld
daemon 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) have this directory as base path './'. If you
have any problems with wrong paths, try mysqld --help
to see
your current paths. Every path can be changed by a startup option to
safe_mysqld
or mysqld
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_% | | +------+--------+------+
There is also a benchmark suite so you can compare how MySQL performs on different platforms. In the near future this will also be used to compare MySQL to other SQL databases.
> cd bench > run-auto-increment-test
You can also run the tests 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'.
The safe_mysqld script is written that it should be able to start a source and a binary version of mysqld, even if these have sligtly different paths!
You can install a binary release of MySQL anywhere as long as you start safe_mysqld from installation directory:
cd mysql_installation_directory bin/safe_mysqld &
If you want to change the startup options to mysqld you can always edit safe_mysqld! In this case you should copy safe_mysqld to some other location that it will not be overwritten if you sometimes decide to upgrade MySQL!
To start or stop MySQL use the following commands:
scripts/mysql.server stop scripts/mysql.server start
You might want to add these start and stop commands in the appropriate places in your `/etc/rc*' files when you start using MySQL for production applications. You can edit the mysql.server script to start safe_mysqld from some specific location and as some specific user. You can also add startup options to mysqld here.
The following are useful extensions in MySQL that you probably will not find in other SQL databases. Be warned that if you use them, your code will not be portable to other SQL servers.
MEDIUMINT
, SET
, ENUM
and the
different BLOB
and TEXT
types.
AUTO_INCREMENT
, BINARY
,
UNSIGNED
and ZEROFILL
.
BINARY
attribute.
INTO OUTFILE
and STRAIGHT_JOIN
in a SELECT
statement. See section 7.10 SELECT syntax.
EXPLAIN SELECT
to get a description on how tables are joined.
INDEX
or KEY
in a CREATE TABLE
statement. See section 7.6 CREATE TABLE syntax.
DROP column
or CHANGE column
in an ALTER TABLE
statement. See section 7.7 ALTER TABLE syntax.
LOAD DATA INFILE
. This syntax is in many cases compatible with
Oracle's LOAD DATA INFILE
. See section 7.14 LOAD DATA INFILE syntax.
"
instead of '
to enclose strings.
\
character.
SET OPTION
statement. See section 7.20 SET OPTION syntax.
GROUP BY
part.
See section 7.3.12 Functions for GROUP BY
clause.
||
and &&
operators are, in MySQL, synonyms for
OR
and AND
, like in the C programming language.
Likewise |
and &
stand for bitwise OR
and
AND
. Because of this nice syntax, MySQL doesn't support
the ANSI SQL operator ||
for string concatenation, one has to use
CONCAT()
instead. As CONCAT()
takes any number
of arguments it's easy to convert use of the ||
operator to
MySQL.
CREATE DATABASE
or DROP DATABASE
.
See section 7.4 Create database syntax.
%
instead of mod(). %
is supported for C programmers and
for compatibility with PostgreSQL.
=
, <>
, <=
,<
, >=
,>
, AND
,
OR
, or LIKE
in a column statement
LAST_INSERT_ID
.
See section 17.1.3 How can I get the unique ID for the last inserted row?
REGEXP
or NOT REGEXP
.
CONCAT()
or CHAR()
with one or more than two arguments. In
MySQL the above functions can take any number of arguments.
BIT_COUNT()
, ELT()
, FROM_DAYS()
, FORMAT()
,
IF()
, PASSWORD()
, ENCRYPT()
,
PERIOD_ADD()
, PERIOD_DIFF()
, TO_DAYS()
,
or WEEKDAY()
.
TRIM
to trim substrings. ANSI SQL only supports removal
of single characters.
STD()
, BIT_OR
and BIT_AND
group functions.
MIN()
or MAX()
as normal functions, not only group
functions.
REPLACE
instead of DELETE
+ INSERT
.
See section 7.13 REPLACE syntax
The following functionality is missing in the current version of MySQL. For the priority of new extensions you should consult: The MySQL Todo list. That is the latest version of the Todo list in this manual. See section F List of things we want to add to MySQL in the future..
The following will not work in MySQL:
SELECT * from table WHERE id IN (SELECT id from table2)
MySQL only supports INSERT ... SELECT...
and REPLACE
... SELECT...
. Independent sub-selects will be probably be available in
3.22.0. One can now use the function IN()
in other context
however.
MySQL doesn't yet support SELECT ... INTO TABLE...
. Currently
MySQL only supports SELECT ... INTO OUTFILE...
, which is basicly the
same thing..
Transactions are not supported. MySQL will shortly support
atomic operations which is like transactions without rollback. With
atomic operations you can make a bunch of insert/select/whatever
commands and be guaranteed that no other thread will interfere. In this
context you won't usually need rollback. Currently you can do this with
the help of the LOCK TABLES/UNLOCK TABLES
command.
See section 7.19 LOCK TABLES
syntax
Triggers are not supported. The planned update language will be able to handle stored procedures, but without triggers. Triggers usually slow down everything, even for queries when they aren't needed.
The FOREIGN KEY
syntax in MySQL exists only for compatibility
with other SQL vendors CREATE TABLE
commands: It doesn't do anything.
The FOREIGN KEY
syntax without ON DELETE ..
is mostly used
for documentation purposes. Some ODBC applications may use this to
produce automatic WHERE
clauses though, but this is usually
easy to override. FOREIGN KEY
is sometimes used as a constraint check,
but this check is in practice unnecessary if rows are inserted into the tables
in the right order. MySQL only supports these commands because some
application require them to exists (but not work!).
In MySQL one can work around the problem that ON DELETE
...
isn't implemented by adding the approative DELETE
statement to
the application when one deletes records from a table that has
FOREIGN KEY
. In practice this is as quick (in some case quicker)
and much more portable than using FOREIGN KEY
.
Foreign keys are something that makes life very complicated, because the foreign key definition must be stored in a database and implementing them would mean that the whole 'nice approach' of using files that can be moved, copied and removed would be destroyed.
In the near future we will extend FOREIGN KEYS
so that at least
the information will be saved and may be retrieved by mysqldump and
ODBC.
There are so many problems with the FOREIGN KEY
s that we don't
know where to start.
INSERTING
and
UPDATING
records and in this case almost all FOREIGN KEY
checks are useless because one usually inserts records in the right
tables in the right order.
The only nice aspect of foreign key is that it gives ODBC and some other client programs the ability to see how a table is connected and use this to show connection diagrams and to help building applicatons.
MySQL will soon store the FOREIGN KEY
definitions so that
a client can ask and receive an answer how the original connection was
made. The current .frm
file format does not have any place for it.
MySQL doesn't support views, but this is on the TODO.
Some other SQL databases have --
as start comment. MySQL
has #
as the start comment character, even if the mysql
command line tool removes all lines that starts with --
.
You can also use the C comment style /* this is a comment */
with
MySQL.
See section 7.24 Comment syntax
MySQL will not support this degenerated comment style because we have had many problems with automatically generated SQL queries that have used something like the following code:
UPDATE table_name SET credit=credit-!payment!
Where instead of !payment! we automaticly insert the value of the payment.
What do you think will happen when 'payment' is negative ?
Because 1--1 is legal in SQL, we think is terrible that '--' means start comment.
If you have a sql program in a textfile that contains --
comments
you should use:
replace " --" " #" < text-file-with-funny-comments.sql | mysql database. instead of the normal mysql database < text-file-with-funny-comments.sql
You can also change the --
to #
comments in the command file:
replace " --" " #" -- text-file-with-funny-comments.sql
Change them back with:
replace " #" " --" -- text-file-with-funny-comments.sql
Entry level SQL92. ODBC level 0-2.
GRANT
. See section 7.21 GRANT syntax. (Compatibility function). This always succeeds. You should use the
MySQL privilege tables. See section 6.2 How does the privilege system work?
CREATE INDEX
. See section 7.22 CREATE INDEX syntax (Compatibility function). This always succeeds. You
should create your index with CREATE TABLE
. See section 7.6 CREATE TABLE syntax.
You can also use ALTER TABLE
. See section 7.7 ALTER TABLE syntax.
DROP INDEX
. See section 7.23 DROP INDEX syntax (Compatibility function). This always succeeds. You can use
ALTER TABLE
to drop indexes. See section 7.7 ALTER TABLE syntax.
BLOB
and TEXT
types
If you want to GROUP BY
or ORDER BY
on a BLOB
or
TEXT
field, you must make the field into a fixed length
object. The standard way to do this is with the SUBSTRING
functions. If you don't do this only the first max_sort_length
(default=1024) will considered when sorting.
SELECT comment from table order by substring(comment,20);
MySQL doesn't support COMMIT-ROLLBACK. The problem with COMMIT-ROLLBACK is that to handle this efficiently it would require a completely different table layout than MySQL uses today. MySQL would also need extra threads that do automatic cleanups on the tables and the disk usage would be much higher. This would make MySQL about 2-4 times slower than it is today. One of the reasons that MySQL is so much faster than almost all other SQL databases (typical times are at least 2-3 times faster) is the lack of COMMIT-ROLLBACK.
For the moment, we are much more for implementing the SQL server language (someting like stored procedures). With this you would very seldom really need COMMIT-ROLLBACK. This would also give much better performance.
Loops that need transactions can normally be coded with the help of
LOCK TABLES
, and one doesn't need cursors when one can update records
on the fly.
We have transactions and cursors on the TODO but not quite prioritised. If
it is implemented it will be as a option to CREATE TABLE
. That
means that COMMIT-ROLLBACK will only work on those tables and only those
tables will be slower.
We at TcX have a greater need for a real fast database than a 100% general database. Whenever we find a way to implement these without any speed loss we will probably do it. For the moment there are many more important things to do. Check the TODO for how we prioritise things at the moment. Customers with higher levels of support can alter this, so things may be reprioritised.
The current problem is actually ROLLBACK
. Without ROLLBACK
you can do anything with LOCK TABLES
. To support ROLLBACK
MySQL would have to be changed to store all old records that were
updated and revert everything back to the starting point if
ROLLBACK
was issued. For simple cases this isn't that hard to do
(the current isamlog could be used for this), but if one wants to have
ROLLBACK
with ALTER/DROP/CREATE TABLE
it would make
everything much harder to implement.
To avoid using ROLLBACK
one can do:
LOCK TABLES ...
UNLOCK TABLES
This is usually much faster, but not always. The only thing this doesn't handle if someone does a kill on the process.
One can also use functions to update things in one operation. By doing all updates relatively and/or only updating those fields that actually have changed one can get a very efficient application.
For example, when we are doing updates on some customer information, we
only update the customer data that has changed and only test that none
of the changed data, or data that depends on the changed data, has
changed in the original row. The test for change is done with the
WHERE
clause in the UPDATE
statement. If the record wasn't
updated we give the client a message: "Some of the data you have changed
has been changed by another user", and then we show the old row versus
the new row in a window. The user can then decide which version of the
customer record he should use.
This gives us something like 'column locking' but actually even better, because we only update some of the columns with relative information. This means that a typical update statement looks something like:
UPDATE tablename SET pay_back=pay_back+'relative change' UPDATE customer set customer_date='current_date', address='new address', phone='new phone', money_he_owes_us=money_he_owes+'new_money' where customer_id=id and address='old address' and phone='old phone';
As you can see, this is very efficient and even if another client has changed the 'money_he_owes_us' or 'pay_back' amount this will still work.
In many cases, users have wanted ROLLBACK
and/or LOCK
TABLES
to manage unique identifiers for some tables. This can be
handled much more efficiently by using an AUTO_INCREMENT
column
and the MySQL API function
mysql_insert_id
. See section 17.1.3 How can I get the unique ID for the last inserted row?
At TcX we have never had any need for row level locking as we have always been able to code around it. I know some cases that really need row locking, but they are very few. If you want to have row level locking you can do something like:
UPDATE table_name SET row_flag=1 WHERE id=ID;
MySQL returns affected rows
= 1 if the row was found and row_flag
wasn't 1 in the original document. On the TODO there is GET_LOCK
and
RELEASE_LOCK
for those that want to implement application level
locking.
MySQL has an advanced but non-standard security/privilege system.
The basic function of the MySQL privilege system is to give a username on a host select, insert, update and delete privileges on a database.
Extra functionality includes the ability to have a anonymous user and give
permission to use MySQL specific funtions like LOAD DATA
INFILE
.
Please note that the user names for a SQL database, like MySQL, has
nothing to do with Unix users. As a convenience most MySQL clients
tries to log in with the current user name, but this may be changed
with the --user
switch. This means that you can't in any way
make a database secure without having passwords for all users.
In MySQL the combination of host and user is the unique identity. Don't think of users, think of host+user and everything should be much clearer. You can for example have a user named 'Robb' at two different hosts (with different privileges) in MySQL without any conflicts.
The MySQL privilege system makes sure that each user may do exactly the things that they are supposed to be allowed to do. The system decides to grant different privileges depending on which xuser connects from which host to which database.
You can always test your privileges with the script mysqlaccess
,
which Yves Carlier has provided for the MySQL distribution.
See section 6.7 Why do I get this Access denied?
error.
See section 6.8 How to make MySQL secure against crackers.
All privileges are stored in three tables. user
, host
and
db
.
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) privileges 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:
Table | Sorted by |
host | host without wild/hosts with wild/empty hosts |
db | host without wild/hosts with wild/empty hosts |
user | host/user |
host = ""
. Within each 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.
user
table
using the first match found.
Call this set of privileges
Priv.
db
table
using the first match found.
host = ""
for the entry found in the db
table, AND
Priv with the privileges for the host in the host
table, i.e.
remove all privileges that are not "Y" in both. (If host <> ""
,
Priv is not affected. In such cases, host
must have matched the
connecting host's name at least partially. Therefore it can be assumed
that the privileges found in this row match the connecting host's
profile.)
user
table, i.e. add all privileges that are "Y" in user
.
mysqladmin reload
to make the changes take effect.
The connecting user gets the set of privileges Priv.
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/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.
Here follows an example to add a user 'custom' that can connect from hosts
'localhost', 'server.domain' and 'whitehouse.gov'. He wants to have password
'stupid'. The database 'bankaccount' he only want to use from 'localhost' and
the 'customer' database he wants to be able to reach from all three hosts.
shell> mysql mysql. mysql> insert into user (host,user,password) values('localhost','custom',password('stupid')); mysql> insert into user (host,user,password) values('server.domain','custom',password('stupid')); mysql> insert into user (host,user,password) values('whitehouse.gov','custom',password('stupid')); mysql> insert into db (host,db,user,Select_priv,Insert_priv,Update_priv,Delete_priv, Create_priv,Drop_priv) values ('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y'); mysql> insert into db (host,db,user,Select_priv,Insert_priv,Update_priv,Delete_priv, Create_priv,Drop_priv) values ('%','customers','custom','Y','Y','Y','Y','Y','Y');You can of course also use xmysqladmin, mysql_webadmin, mysqladmin and even xmysql to insert/change and update values in the privilege tables. You can find these utilities in the Contrib directory.
The grant tables 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, refresh and process.
The privilege system is based on 3 tables.
user
table
user
table has the following columns:
Field | Type | Key | Default |
Host | char(60) | PRI | "" |
User | char(16) | PRI | "" |
Password | char(16) | - | "" |
Select_priv | enum('N','Y') | - | N |
Insert_priv | enum('N','Y') | - | N |
Update_priv | enum('N','Y') | - | N |
Delete_priv | enum('N','Y') | - | N |
Create_priv | enum('N','Y') | - | N |
Drop_priv | enum('N','Y') | - | N |
Reload_priv | enum('N','Y') | - | N |
Shutdown_priv | enum('N','Y') | - | N |
Process_priv | enum('N','Y') | - | N |
File_priv | enum('N','Y') | - | N |
db
table
Contains which databases a host+user is allowed to use, and what he can
do with the tables in each database. The db
table has the
following columns:
Field | Type | Key | Default |
Host | char(60) | PRI | "" |
Db | char(64) | PRI | "" |
User | char(16) | PRI | "" |
Select_priv | enum('N','Y') | - | N |
Insert_priv | enum('N','Y') | - | N |
Update_priv | enum('N','Y') | - | N |
Delete_priv | enum('N','Y') | - | N |
Create_priv | enum('N','Y') | - | N |
Drop_priv | enum('N','Y') | - | N |
host
table
Is only used in big networks as a lookup for empty host entries in the
db table. This means that if you want a user to be able to use the
database from all hosts in your network, you should put " as the host
name in the db table. In this case the host
table should contain
a entry for every host in your network. The host
table has the
following columns:
Field | Type | Key | Default |
Host | char(60) | PRI | "" |
Db | char(64) | PRI | "" |
Select_priv | enum('N','Y') | - | N |
Insert_priv | enum('N','Y') | - | N |
Update_priv | enum('N','Y') | - | N |
Delete_priv | enum('N','Y') | - | N |
Create_priv | enum('N','Y') | - | N |
Drop_priv | enum('N','Y') | - | N |
%
and _
. Leaving any of these columns empty is
equivalent to setting it to '%'.
localhost
, a hostname, an IP number or a
string with wildcards. 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.
user
table will be processed
as a no-name user.
db
table.
This means that a superuser only needs to be in the user table with all
privilege-flags set to Y
.
123.444.444.%
in the host
table to give every user on an IP C-net access. To avoid the
possibility that somebody tries to fool this setup by naming a host
123.444.444.somewhere.com
, MySQL disallows all hostnames
that start with digits and a dot. So if your host is named something like
1.2.foo.com
it will never be allowed with name matching. Use the
IP number in this case.
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
admin
mysqladmin reload
,
mysqladmin refresh
and mysqladmin processlist
. May be granted
individual database privileges through table db
.
dummy
db
.
The default privileges (set in `scripts/mysql_install_db')
let root do anything. Any user can do anything with any database whose
name is 'test' or starts with 'test_'. A normal user can't use
mysqladmin shutdown
or mysqladmin processlist
. See the
script (`scripts/mysql_install_db') for an example on how to add
other users.
The privilege tables are read into mysqld with mysqladmin reload
.
A common mistake is to forget that passwords are stored encrypted, which leads to 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 this instead:
INSERT INTO user VALUES ('%','jeffrey',password('bLa81m0'),'Y','Y','Y','N','N','N','N','N','N','N');
As before, mysqladmin reload
to make the authentication change
take effect.
Now things should work.
Access denied?
error.mysql -u root test
. This
should not give an error. You can also check if you have a file 'user.ISD'
in the mysql database directory (ordinary install_dir/var/mysql/user.ISD).
mysqladmin reload
each time you change
the grant tables. Otherwise the old tables are still used!
--without-grant-tables
option. Now you can change the MySQL
grant tables and use the script mysqlaccess
to check if your
grant worked. mysqladmin reload
tells the mysqld daemon to
start using the new grant tables.
mysql -u user database
or
mysql -u user -ppassword database
. Please notice that there is no
space between -p and the password. One can also use the
--password=your_password
syntax to give the password!
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 get an entry with 'hostname' and
'user' matching your computers hostname and your username. If the client
and the server are 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.
Access denied
error message will tell you who you are trying
to log in as, from which host you are trying to log in, and if you
were using a password or not. You should normally have one entry in the
user
table that exactly matches your host and user, exactly as
given in the error message.
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 will not work. Test by adding
a record with the IP of your host in the 'user' table. You can,
natuarally, also add a host with a wildcard (for example 'tcx%') in the
'user table' (but using hostnames ending with % is pretty insecure).
mysql -u user database
works 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.
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.
SELECT
... INTO OUTFILE
or LOAD DATA
SQL commands then you probably
don't have the File_priv
privilege set for you in the user table.
mysqld
daemon 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 18.9 Debugging MySQL.
mysqldump mysql
command. As always, post your problem with the
mysqlbug
script.
Can't connect to local mySQL server
or
Can't connect to MySQL server on some_hostname
this means that
the daemon mysqld is not running or you are trying to connect to the wrong
socket or port. Check that the socket exists (normally /tmp/mysql.sock) or
try to connect to the port with telnet: telnet hostname 3306
.
You can also try mysqladmin version
to get some more information.
To make a MySQL system secure you should think about the following:
mysql_install_db
script or
only for the MySQL root user with:
mysql -u root -e "update user set password=password('new_password') where user='root'" mysql
SELECT INTO OUTFILE
are generated readable by all and one can't overwrite existing files.
The following options to mysqld
affects security:
--secure
get_hostbyname
resolves
back to the original hostname. This is done to make it harder for
someone on the outside to get access by simulating another host.
This options also adds some sanity checks of hostnames.
This is turned off by default since it sometimes takes a long time to check this.
--skip-grant-tables
--skip-name-resolve
--skip-networking
A string may have ' or " around it.
\ is a escape character. The following escape characters are recognised:
\0
\n
\t
\r
\b
\'
'
character.
\"
"
character.
\\
\
character.
\%
%
character. This is used in wildcard strings to search for
%
.
\_
_
character. This is used in wildcard strings to search for
_
.
A ' inside a string started with ' may be written as ". A " inside a string started with " may be written as "".
Some example selects that shows how it works.
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
\
'
"
One doesn't have to escape "
inside '
and "
inside
'
.
If you write C code you can use the C API function
mysql_escape_string(char *to,char *from,uint length)
to escape
characters for the INSERT
clause. (Note that 'to' must be at least
2 times bigger than from). In perl you can use the quote
function.
You should run the escape function on every possible string that may have a one of the above special characters!
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 7.14 LOAD DATA INFILE syntax
Database, table, index and column names all follow the same rules in MySQL.
A name may use alphanumeric characters from the default character set. This is by default ISO-8859-1 Latin1 but may be changed when compiling MySQL.
Since MySQL needs to be able to decide if something is a name or a number the following special cases occurs.
1e
. This is because
expressions like 1e+1
may be interpreted like the expression
1e + 1
or the number 1e+1
.
Punctuation characters like .
and @
are not allowed in names
since they will be used to extend MySQL.
The following column types are supported:
Name | Description | Size |
TINYINT[(M)] [UNSIGNED] [ZEROFILL] | A very small integer. Signed range -128 - 127. Unsigned range 0 - 255. | 1 |
SMALLINT[(M)]. [UNSIGNED] [ZEROFILL] | A small integer. Signed range -32768 - 32767. Unsigned range 0 - 65535. | 2 |
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL] | A medium integer. Signed range -8388608-8388607. Unsigned range 0 - 16777215. | 3 |
INT[(M)] [UNSIGNED] [ZEROFILL] | A normal integer. Signed range -2147483648 - 2147483647. Unsigned range 0 - 4294967295. | 4 |
BIGINT[(M)] [UNSIGNED] [ZEROFILL] | A large integer. Signed range -9223372036854775808 - 9223372036854775807. Unsigned Range 0 - 18446744073709551615. Because all arithmetic is done with signed BIGINT or DOUBLE, one shouldn't use unsigned big integers bigger than 9223372036854775807 (63 bits) with anything else than bit functions! | 8 |
FLOAT(Precision) | A small floating point number. Precision can be 4 or 8. FLOAT(4) is a single precision number and FLOAT(8) is a double precision number (se the DOUBLE entry). This syntax is for ODBC compatibility. Range -3.402823466E+38F - -1.175494351E-38, 0, -1.175494351E-38 - 3.402823466E+38F. | 4 |
FLOAT[(M,D)] | A small floating point number. Cannot be unsigned. Range -3.402823466E+38F - -1.175494351E-38, 0, -1.175494351E-38 - 3.402823466E+38F. | 4 |
DOUBLE PRECISION[(M,D)] | A normal floating point number. Cannot be unsigned. Range -1.7976931348623157E+308 - -2.2250738585072014E-308, 0, 2.2250738585072014E-308 - 1.7976931348623157E+308. | 8 |
REAL[(M,D)] | Same as DOUBLE | 8 |
DECIMAL [(M,D)] | An unpacked floating point number. Cannot be unsigned. Currently the same range maximum range as a double. Behaves as a CHAR column | M+D |
NUMERIC [(M,D)] | Same as DECIMAL | M+D |
TIMESTAMP [(M)] | An automatic timestamp. | 4 |
DATE | A type to store date information. Uses the "YYYY-MM-DD" syntax, but may be updated with a number or a string. Understands at least the following syntaxes: 'YY-MM-DD', 'YYYY-MM-DD', and 'YYMMDD'. Range 0000-00-00 to 9999-12-31. | 4 |
TIME | A type to store time information. Uses the "HH:MM:SS" syntax, but may be updated with a number or a string. Understands at least the following syntaxes: 'HH:MM:SS, 'HHMMSS', 'HHMM', 'HH'. | 3 |
DATETIME | A type to store date and time information. Format "YYYY-MM-DD HH:MM:SS". Takes 8 bytes. Range '0000-01-01 00:00:00' - '9999-12-31 23:59:59'. | 8 |
CHAR(M) [binary] | A fixed length string that is always filled up with spaces to the specified length. Range 1 - 255 characters. All end space are removed when retrieved. Is sorted and compared case insensitively unless the binary keyword is given. | M |
VARCHAR(M) [binary] | A variable length string that is stored with its length. All end space are removed when storing it. Maximum range 1 - 255 characters. Is sorted and compared case insensitively unless the binary keyword is given. | L+1 |
TINYTEXT and TINYBLOB |
A TEXT /BLOB with max length of 255 characters. | L+1 |
TEXT and BLOB |
A TEXT /BLOB with max length of 65535 characters. | L+2 |
MEDIUMTEXT and MEDIUMBLOB |
A TEXT /BLOB with max length of 16777216 characters. | L+3 |
LONGTEXT and LONGBLOB |
A TEXT /BLOB with max length of 4294967295 characters. | L+4 |
ENUM('value','value2',...) | A string object that can have only one set of allowed values (or NULL). See section 7.2.1 More about data types | 1 or 2 |
SET('value','value2',...) | A string object that can have one or many values of a set of allowed values. See section 7.2.1 More about data types. | 1-8 |
In the above table L means the actual length of a instance and M the maximum length. So L+1 for "abcd" means 5 bytes in the database.
If you use any data type with an L in the length field you will get a variable length record format.
All integer types can have an optional argument unsigned
. This
can be used when you only want to allow positive numbers in the column
or you need a little bigger numerical range for the column.
Also for all integer columnsn, the optional argument ZEROFILL
means
that the column will be padded with zeroes up to the maximum length.
Max display size and decimals are for formatting and calculation of maximum column width.
When storing a value in an integer that is outside its range,
MySQL stores the maximum (or minimum) possible value. When
doing an ALTER TABLE
or LOAD DATA INFILE
one gets these
conversions as 'warnings'. We have on the TODO to fix INSERT and
UPDATE so they can return warnings, but this is scheduled for the next
protocol change.
For example when storing -999999999999999
into an int column the
value ends up as -2147483648
. And 9999999999999999
ends up
as 2147483647
.
And if the int
is unsigned the stored values above becomes 0
and
4294967296
.
The same rules go for all other integer types.
When returning data for an int(4) column that exceeds the allocated space,
MySQL will return 9.99. If the operation is an UPDATE
a warning will be issued.
Note that a type like decimal(4,2)
means maximum 4 characters
with two decimal points. That gives a range between -.99
->
9.99
.
To avoid some rounding problems, MySQL always rounds everything
that it stores in any floating point column according to the number of
decimals. This means that 2.333
stored into float(8,2)
is
stored as 2.33
.
TIMESTAMP
type
Has a range of 1 Dec 1970 time 0.00 to sometime in the year 2106 and a
resolution of one second. A TIMESTAMP column will automatically be updated
on INSERT
and UPDATE
statements if set to NULL
or if
the column is not updated in the statement. Can be (part of) an index.
Note that if you have many timestamp columns in a row, then only the
last timestamp column will be automatically updated. Any timestamp column
will be set to the current time if set to NULL
. Depending on
the display size one gets one of the following formats: "YYYY-MM-DD HH:MM:SS",
"YY-MM-DD HH:MM:SS", "YYYY-MM-DD" or "YY-MM-DD".
TEXT
and BLOB
types
These are objects that can have a variable length without upper limit.
All TEXT and BLOB objects are stored with their length (saved in 1 to 4
bytes depending on the type of object). The maximum TEXT
and
BLOB
length you can use is dependent on available memory and
client buffers. The only differences between TEXT
and BLOB
is that TEXT
is sorted and compared case insensitively while
BLOB
is compared case sensitively (by character
values). TEXT
and BLOB
objects CANNOT be an index.
A BLOB is a binary large object which can hold any amount of data. There are 4 kinds of blobs See section 7.2 Column types.. Normally one can regard a BLOB as a VARCHAR without a specified limit.
TEXT
is a BLOB
that is sorted and compared case
insensitively.
A BLOB
/TEXT
column may not be bigger that the message
buffer. Note that you have to change the message buffer on both the
server and the client. See section 10.1 How does one change the size of MySQL buffers?.
MyODBC
defines BLOB
s as LONGVARBINARY
and
TEXT
s as LONGVARCHAR
.
Restrictions for BLOB
and TEXT
columns:
BLOB
or TEXT
cannot be an index or a part of an index
BLOB
or TEXT
, only the first
max_sort_length
(default 1024) of the blob is used. This value
can be changed by the -O
option when starting the mysqld
daemon. One can group on an expression involving a BLOB
/
TEXT
: SELECT id,SUBSTR(blob,1,100) GROUP BY 2
BLOB
and TEXT
as
there is for CHAR
and VARCHAR
.
ENUM
type
A string object that can have only one of a set of allowed values. The value
to be stored may be given case independently. If one tries to store a
non-existing value, "" is stored. If used in a number context this
object returns/stores the value index. If there is less than 255
possible values this object occupies 1 byte, else two bytes (with a
maximum of 65535 different values). Note that if an integer is put in the
ENUM
you get the corresponding string with the first counting as
number 1. (0 is reserved for wrong enum values). Sorting on ENUM
types are done according to the order of the strings in the enum.
If declared NOT NULL
the default value is the first value, else
the default value is NULL
.
For example the column test ENUM("one","two", "three")
can have
any of these values:
NULL "one" "two" "three"
SET
type
A string object that can have one or many values from a set of allowed
values. Each value is separated by a ','. If used in a number context
this object returns/stores the bit positions of the used values. This
object occupies (number_of_different_values-1)/8+1 bytes, rounded up to
1,2,3,4 or 8. One can't have more than 64 different values. Note that if
an integer is put in the SET
you get the corresponding string with
the first bit corresponding to the first string. Sorting on SET
types are done numerically.
For example the column test SET("one","two") NOT NULL
can have any of
these values:
"" "one" "two" "one,two"
Normally on SELECT on a SET column with LIKE or FIND_IN_SET():
SELECT * from banner where banner_group LIKE '%value%'; SELECT * from banner where FIND_IN_SET('value',banner_group)>0;
But the following will also work:
SELECT * from banner where banner_group = 'v1,v2'; ;Exact match SELECT * from banner where banner_group & 1; ;Is in first group
Try to use the most precise type in all cases. For example for an integer
between 1-99999 a unsigned mediumint
is the best type.
A common problem is representing monetary values accurately. In
MySQL you should use the DECIMAL
type. This is stored as
a string so no loss of accuracy should occur. If accuracy is not to
too important the DOUBLE
type may also be good enough.
For high precision you can always convert to a fixed point type
stored in a BITINT
. This allows you to do all calculations with
integers and only convert the result back to floating point.
See section 10.12 What are the different row formats? Or when to use VARCHAR/CHAR?.
You can have indexes on all MySQL columns except BLOB
and TEXT
types. Using indexes on the relevant columns is the best
way to improve the performance of selects.
For CHAR
and VARCHAR
columns you can have an index on a
prefix. The example below shows how to create an index for the first 10
characters of a column. This is much faster and requires less disk space
than having an index on the whole column.
CREATE TABLE test ( name CHAR(200) NOT NULL, KEY index_name (name(10));
MySQL can have one index on parts of different columns.
A multiple-column index can be considered a sorted array where the columns are concatenated. This makes for fast queries where the first column in the index is a known quantity and the other columns are not.
Suppose that you have a table:
CREATE TABLE test ( id INT NOT NULL, last_name CHAR(30) NOT NULL, first_name CHAR(30) NOT NULL, PRIMARY KEY (id), INDEX name (last_name,first_name));
Then the index name
is an index over last_name and first_name.
The name
index will be used in the following queries:
SELECT * FROM test WHERE last_name="Widenius"; SELECT * FROM test WHERE last_name="Widenius" AND first_name="Michael"; SELECT * FROM test WHERE last_name="Widenius" AND (first_name="Michael" OR first_name="Monty"); SELECT * FROM test WHERE last_name="Widenius" and first_name >="M" and first_name < "N";
The name
index will NOT be used in the following queries:
SELECT * FROM test WHERE first_name="Michael"; SELECT * FROM test WHERE last_name="Widenius" or first_name="Michael";
To support easier use of code from different SQL vendors, MySQL does supports the following mappings:
binary(num) | char(num) binary |
char varying | varchar |
float4 | float |
float8 | double |
int1 | tinyint |
int2 | smallint |
int3 | mediumint |
int4 | int |
int8 | bigint |
long varbinary | blob |
long varchar | text |
middleint | mediumint |
varbinary(num) | varchar(num) binary |
SELECT
and WHERE
clauses
A select_expression
or where_definition
can consist of any
expression using the following functions:
In the examples below the output of the mysql
program has been
shortened. So this:
mysql> select mod(29,9); 1 rows in set (0.00 sec) +-----------+ | mod(29,9) | +-----------+ | 2 | +-----------+
Has been converted to:
mysql> select mod(29,9); -> 2
(
)
mysql> select 1+2*3; -> 7 mysql> select (1+2)*3; -> 9
+
-
*
/
NULL
.
mysql> select 102/(1-1); -> NULL
These have a range of maximum 64 bits because MySQL uses bigint (64 bit) arithmetic.
|
mysql> select 29 | 15; -> 31
&
mysql> select 29 & 15; -> 13
BIT_COUNT()
mysql> select bit_count(29); -> 4
All logical function return 1 (TRUE) or 0 (FALSE).
NOT
!
mysql> select NOT 1; -> 0 mysql> select NOT NULL; -> NULL mysql> select ! (1+1); -> 0 mysql> select ! 1+1; -> 1
OR
||
mysql> select 1 || 0; -> 1 mysql> select 0 || 0; -> 0 mysql> select 1 || NULL; -> 1
AND
&&
mysql> select 1 && NULL; -> 0 mysql> select 1 && 0; -> 0
Returns 1 (TRUE), 0 (FALSE) or NULL
. These functions work for both
numbers and strings. MySQL uses the following rules to decide how the
compare is done:
TIMESTAMP
or DATETIME
column and
the other argument is a constant. In this case the constant is converted
to a timestamp before the comparasion. This is to be more ODBC
friendly.
If one or both of the arguments are NULL
the result of the comparison
is NULL
.
=
mysql> select 1 = 0; -> 0 mysql> select '0' = 0; -> 1 mysql> select '0.0' = 0; -> 1 mysql> select '0.01' = 0; -> 0 mysql> select '.01' = 0.01; -> 1
<>
!=
mysql> select '.01' <> '0.01'; -> 1 mysql> select .01 <> '0.01'; -> 0 mysql> select 'zapp' <> 'zappp'; -> 1
<=
mysql> select 0.1 <= 2; -> 1
<
mysql> select 2 <= 2; -> 1
>=
mysql> select 2 >= 2; -> 1
>
mysql> select 2 > 2; -> 0
ISNULL(A)
A
is NULL
else 0.
mysql> select isnull(1+1); -> 0 mysql> select isnull(1/0); -> 1
A BETWEEN B AND C
A
is bigger or equal as B
and A
is smaller or equal
to C
. Does the same thing as (A >= B AND A <= C)
if
all arguments are of the same type. It's the first argument (A
)
that decides how the comparison should be done! If A
is a string
expression, compare as case insensitive strings. If A
is a binary
string, compare as binary strings. If A
is an integer expression
compare as integers, else compare as reals.
mysql> select 1 between 2 and 3; -> 0 mysql> select 'b' between 'a' and 'c'; -> 1 mysql> select 2 between 2 and '3'; -> 1 mysql> select 2 between 2 and 'x-3'; -> 0
expr IN (value,...)
IN
list, else it
returns 0. If all values are constants, then all values are evaluated
according to the type of expr and sorted. The search for the item is
then done by using a binary search. This means IN
is very quick
when used with constants in the IN
part.
mysql> select 2 in (0,3,5,'wefwf'); -> 0 mysql> select 'wefwf' in (0,3,5,'wefwf'); -> 1
expr NOT IN (value,...)
NOT (expr IN (value,...))
expr LIKE expr
LIKE
you have two wild characters.
% | Matches any number of characters, even zero characters. |
_ | Matches exactly one character. |
\% | Matches one % .
|
\_ | Matches one _ .
|
mysql> select 'David!' like 'David_'; -> 1 mysql> select 'David!' like 'David\_'; -> 0 mysql> select 'David_' like 'David\_'; -> 1 mysql> select 'David!' like '%D%v%'; -> 1 mysql> select 10 like '1%'; -> 1
LIKE
is allowed on numerical expressions! (Extension)
NOT (expr LIKE expr)
.
\n
)
You must double any '\'
that you uses in your REGEXP strings.
mysql> select 'Monty!' regexp 'm%y%%'; -> 0 mysql> select 'Monty!' regexp '.*'; -> 1 mysql> select 'new*\n*line' regexp 'new\\*.\\*line'
NOT (expr REGEXP expr)
.
mysql> select strcmp('text', 'text2'); -> -1 mysql> select strcmp('text2', 'text'); -> 1 mysql> select strcmp('text', 'text'); -> 0
IFNULL(A,B)
A
is not NULL
it returns A
, else B
.
mysql> select ifnull(1,0); -> 1 mysql> select ifnull(0,10); -> 0 mysql> select ifnull(1/0,10); -> 10
IF(A,B,C)
A
is true (A <> 0
and A <> NULL
) then return
B
, else return C
. A is evaluated as an INTEGER, which means
that if you are using floats you should also use a comparison operation.
mysql> select if(1>2,2,3); -> 3
All mathematical functions returns NULL
in the case of a error.
-
mysql> select - 2; -> -2
ABS()
mysql> select abs(2); -> 2 mysql> select abs(-32); -> 32
SIGN()
mysql> select sign(-32); -> -1 mysql> select sign(0); -> 0 mysql> select sign(234); -> 1
MOD()
%
mysql> select mod(234, 10); -> 4 mysql> select 253 % 7; -> 1 mysql> select mod(29,9); -> 2
FLOOR()
mysql> select floor(1.23); -> 1 mysql> select floor(-1.23); -> -2
CEILING()
mysql> select ceiling(1.23); -> 2 mysql> select ceiling(-1.23); -> -1
ROUND(N)
N
to an integer.
mysql> select round(-1.23); -> -1 mysql> select round(-1.58); -> -2 mysql> select round(1.58); -> 2
ROUND(Number,Decimals)
Number
to a number with Decimals
decimals.
mysql> select ROUND(1.298, 1); -> 1.3
EXP(N)
e
(the base of natural logarithms) raised to
the power of N
.
mysql> select exp(2); -> 7.389056 mysql> select exp(-2); -> 0.135335
LOG(X)
X
.
mysql> select log(2); -> 0.693147 mysql> select log(-2); -> NULL
LOG10(X)
X
.
mysql> select log10(2); -> 0.301030 mysql> select log10(100); -> 2.000000 mysql> select log10(-100); -> NULL
POW(X,Y)
POWER(X,Y)
X
raised to the power of Y
.
mysql> select pow(2,2); -> 4.000000 mysql> select pow(2,-2); -> 0.250000
sqrt(X)
X
.
mysql> select sqrt(4); -> 2.000000 mysql> select sqrt(20); -> 4.472136
PI()
mysql> select PI(); -> 3.141593
COS(X)
X
, where X
is given in radians.
mysql> select cos(PI()); -> -1.000000
SIN(X)
X
, where X
is given in radians.
mysql> select sin(PI()); -> 0.000000
TAN(X)
X
, where X
is given in radians.
mysql> select tan(PI()+1); -> 1.557408
ACOS(X)
X
; that is the value whose cosine is
X
. If X
is not in the range -1 to 1 NULL
is
returned.
mysql> select ACOS(1); -> 0.000000 mysql> select ACOS(1.0001); -> NULL mysql> select ACOS(0); -> 1.570796
ASIN(X)
X
; that is the value whose sine is
X
. If X
is not in the range -1 to 1 NULL
is
returned.
mysql> select ASIN(0.2); -> 0.201358 mysql> select ASIN('foo'); -> 0.000000
ATAN(X)
X
; that is the value whose tangent is
X
.
mysql> select ATAN(2); -> 1.107149 mysql> select ATAN(-2); -> -1.107149
ATAN2(X,Y)
X
and Y
. It is
similar to calculating the arc tangent of Y / X
, except that the
signs of both arguments are used to determine the quadrant of the
result.
mysql> select ATAN(-2,2); -> -0.785398 mysql> select ATAN(PI(),0); -> 1.570796
COT(N)
N
.
mysql> select COT(12); -> -1.57267341 mysql> select COT(0); -> NULL
RAND([X])
0 <= x <= 1.0
, using the integer
expression X
as the optional seed value.
mysql> SELECT RAND(); -> 0.5925 mysql> SELECT RAND(20); -> 0.1811 mysql> SELECT RAND(20); -> 0.1811 mysql> SELECT RAND(); -> 0.2079 mysql> SELECT RAND(); -> 0.7888One can't do a ORDER BY on a column with RAND() values because ORDER BY would evaluate the column multiple times.
MIN(X,Y...)
GROUP BY
functions. The arguments are compared as numbers. If no
records are found NULL
is returned.
mysql> SELECT MIN(2,0); -> 0 mysql> SELECT MIN(34,3,5,767); -> 3 mysql> SELECT MIN(a) from table where 1=0; -> NULL
MAX(X,Y...)
GROUP BY
functions. The arguments are compared as numbers. If no
records are found NULL
is returned.
mysql> SELECT MAX(34,3,5,767); -> 767 mysql> SELECT MAX(2,0,4,5,34); -> 34 mysql> SELECT MAX(a) from table where 1=0; -> NULL
DEGREES(N)
N
converted from radians to degrees.
mysql> select DEGREES(PI()); -> 180.000000
RADIANS(N)
N
converted from degrees to radians.
mysql> select RADIANS(90); -> 1.570796
TRUNCATE(Number, Decimals)
Number
to Decimals
decimals.
mysql> select TRUNCATE(1.223,1); -> 1.2 mysql> select TRUNCATE(1.999,1); -> 1.9 mysql> select TRUNCATE(1.999,0); -> 1
ASCII(S)
S
. If
S
is NULL
return NULL
.
mysql> SELECT ascii(2); -> 50 mysql> SELECT ascii('dx'); -> 100
CHAR(X,...)
NULLs
are skipped.
mysql> SELECT char(77,121,83,81,'76'); -> 'MySQL'
CONCAT(X,Y...)
mysql> SELECT CONCAT('My', 'S', 'QL'); -> 'MySQL'
LENGTH(S)
OCTET_LENGTH(S)
CHAR_LENGTH(S)
CHARACTER_LENGTH(S)
mysql> SELECT length('text'); -> 4 mysql> SELECT octet_length('text'); -> 4
LOCATE(A,B)
POSITION(B IN A)
A
substring in B
. The first position
is 1. Returns 0 if A
is not in B
.
mysql> select locate('bar', 'foobarbar'); -> 4 mysql> select locate('xbar', 'foobar'); -> 0
INSTR(A,B)
B
in string A
. This is
the same as LOCATE
with swapped parameters.
mysql> select instr('foobarbar', 'bar'); -> 4 mysql> select instr('xbar', 'foobar'); -> 0
LOCATE(A,B,C)
A
in string B
starting
at C
.
mysql> select locate('bar', 'foobarbar',5); -> 7
LEFT(str,length)
mysql> select left('foobarbar', 5); -> 'fooba'
RIGHT(A,B)
SUBSTRING(A FROM B)
B
characters from end of string A
.
mysql> select right('foobarbar', 5); -> 'arbar' mysql> select substring('foobarbar' from 5); -> 'arbar'
LTRIM(str)
mysql> select ltrim(' barbar'); -> 'barbar'
RTRIM(str)
TRIM([[ BOTH | LEADING | TRAILING] [ A ] FROM ] B)
A
prefixes and/or suffixes
removed from B
. If BOTH
, LEADING
and
TRAILING
isn't used BOTH
are assumed. If A
is not
given, then spaces are removed.
mysql> select trim(' bar '); -> 'bar' mysql> select trim(leading 'x' from 'xxxbarxxx'); -> 'barxxx' mysql> select trim(both 'x' from 'xxxbarxxx'); -> 'bar' mysql> select trim(trailing 'xyz' from 'barxxyz'); -> 'barx'
SOUNDEX(S)
S
. Two strings that sound 'about the
same' should have identical soundex strings. A 'standard' soundex string
is 4 characters long, but this function returns an 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.
mysql> select soundex('Hello'); -> 'H400' mysql> select soundex('Bдttre'); -> 'B360' mysql> select soundex('Quadratically'); -> 'Q36324'
SUBSTRING(A, B, C)
SUBSTRING(A FROM B FOR C)
MID(A, B, C)
A
starting at B
with C
chars. The variant with FROM
is ANSI SQL 92 syntax.
mysql> select substring('Quadratically',5,6); -> ratica
SUBSTRING_INDEX(String, Delimiter, Count)
String
after Count
Delimiters
. If Count
is positive the strings are searched
from left else if count is negative the substrings are searched and
returned from right.
mysql> select substring_index('www.tcx.se', '.', 2); -> 'www.tcx' mysql> select substring_index('www.tcx.se', '.', -2); -> 'tcx.se'
SPACE(N)
N
spaces.
mysql> select SPACE(6); -> ' '
REPLACE(A, B, C)
B
in string A
with
string C
.
mysql> select replace('www.tcx.se', 'w', 'Ww'); -> 'WwWwWw.tcx.se'
REPEAT(String, Count)
String
Count
times. If Count <= 0
returns a
empty string. If String
or Count
is NULL
or
LENGTH(string)*count > max_allowed_size
returns NULL
.
mysql> select repeat('MySQL', 3); -> 'MySQLMySQLMySQL'
REVERSE(String)
mysql> select reverse('abc'); -> 'cba'
INSERT(Org, Start, Length, New)
Org
starging at Start
and
Length
long with New
. First position in Org
is
numbered 1.
mysql> select insert('Quadratic', 3, 4, 'What'); -> 'QuWhattic'
INTERVAL(N, N1, N2, N3...)
Nn
> N3
> N2
> N1
is
this function shall work. This is because a binary search is used (Very
fast). Returns 0 if N
< N1
, 1 if N
< N2
and
so on. All arguments are treated as numbers.
mysql> select INTERVAL(23, 1, 15, 17, 30, 44, 200); -> 3 mysql> select INTERVAL(10, 1, 10, 100, 1000); -> 2 mysql> select INTERVAL(22, 23, 30, 44, 200); -> 0
ELT(N, A1, A2, A3...)
A1
if N
= 1, A2
if N
= 2 and so
on. If N
is less than 1 or bigger than the number of arguments
NULL
is returned.
mysql> select elt(1, 'ej', 'Heja', 'hej', 'foo'); -> 'ej' mysql> select elt(4, 'ej', 'Heja', 'hej', 'foo'); -> 'foo'
FIELD(S, S1, S2, S3...)
S
in S1
, S2
,
S3
... list. The complement of ELT()
. Return 0 when S is
not found.
mysql> select FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo'); -> 2 mysql> select FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo'); -> 0
FIND_IN_SET(string,string of strings)
mysql> SELECT FIND_IN_SET('b','a,b,c,d') -> 2This function will not work properly if the first argument contains a ','.
LCASE(A)
LOWER(A)
A
to lower case according to current character set
,dmappings (Default Latin1).
mysql> select lcase('QUADRATICALLY'); -> 'quadratically'
UCASE(A)
UPPER(A)
A
to upper case.
mysql> select ucase('Hej'); -> 'HEJ'
Some examples using more than one date function:
Select all record with a date_field from the last 30 days.
SELECT something FROM table WHERE TO_DAYS(NOW()) - TO_DAYS(date_field) <= 30;
A Date
expression may be a date string, a datetime string, a
timestamp([6 | 8 | 14]) or a number of format YYMMDD
or YYYYMMDD
.
In a date expression a year may be 2 or 4 digits. 2 digits is assumed to be in the range 1970-2069. Dates 100-199 is converted to 2000-2999 to make year arithmetic easier! The special date '0000-00-00' can be stored and retrieved as 0000-00-00.
A Time
expression may be a date string, a datetime string, a
timestamp([6 | 8 | 14]) or a number of format HHMMSS
or YYYYMMDDHHMMSS
.
DAYOFWEEK(date expr)
Date
(1 = Sunday, 2 = Monday, 2 = Tuesday ..)
This is according to the ODBC standard.
mysql> select dayofweek('1998-02-03'); -> 3
WEEKDAY(date expr)
Date
(0 = Monday, 1 = Tuesday ..)
mysql> select WEEKDAY('1997-10-04 22:23:00'); -> 5 mysql> select WEEKDAY('1997-11-05'); -> 2
DAYOFMONTH(date expr)
mysql> select DAYOFMONTH('1998-02-03'); -> 3
DAYOFYEAR(date expr)
mysql> select DAYOFYEAR('1998-02-03'); -> 34
MONTH(date expr)
mysql> select MONTH('1998-02-03'); -> 02
DAYNAME(date expr)
mysql> select dayname("1998-02-05"); -> Thursday
MONTHNAME(date expr)
mysql> select monthname("1998-02-05"); -> February
QUARTER(date expr)
mysql> select QUARTER('98-04-01'); -> 2
WEEK(date expr)
mysql> select WEEK('98-02-20'); -> 7
YEAR(date expr)
mysql> select YEAR('98-02-03'); -> 1998
HOUR(time expr)
mysql> select HOUR('10:05:03'); -> 10
MINUTE(time expr)
mysql> select MINUTE('98-02-03 10:05:03'); -> 5
SECOND(time expr)
mysql> select SECOND('10:05:03'); -> 3
PERIOD_ADD(P, N)
N
months to period P
(of type YYMM
or
YYYYMM
). Returns YYYYMM
.
mysql> select PERIOD_ADD(9801,2); -> 199803
PERIOD_DIFF(A, B)
A
and B
. A
and
B
should be of format YYMM
or YYYYMM
.
mysql> select PERIOD_DIFF(9802,199703); -> 11
TO_DAYS(Date)
Date
to a daynumber (Number of days since year
0). Date
may be a DATE
string, a DATETIME
string, a
TIMESTAMP([6 | 8 | 14])
or a number of format YYMMDD
or
YYYYMMDD
.
mysql> select TO_DAYS(9505); -> 733364 mysql> select TO_DAYS('1997-10-07); -> 729669
FROM_DAYS()
mysql> select from_days(729669); -> 1997-10-07
DATE_FORMAT(Date, Format)
Date
(a date or a timestamp) according to the
Format
string. The following format commands are known:
M | Month name |
W | Weekday name |
D | Day of the month with english suffix |
Y | Year with 4 digits |
y | Year with 2 digits |
a | Abbreviated weekday name (Sun..Sat) |
d | Day of the month, numeric |
m | Month, numeric |
b | Abbreviated month name (Jan.Dec) |
j | Day of year (001..366) |
H | Hour (00..23) |
k | Hour ( 0..23) |
h | Hour (01..12) |
I | Hour (01..12) |
l | Hour ( 1..12) |
i | Minutes, numeric |
r | Time, 12-hour (hh:mm:ss [AP]M) |
T | Time, 24-hour (hh:mm:ss) |
S | Seconds (00..59) |
s | Seconds (00..59) |
p | AM or PM |
w | Day of the week (0=Sunday..) |
mysql> select date_format('1997-10-04 22:23:00', 'W M Y h:i:s'); -> 'Saturday October 1997 22:23:00' mysql> select date_format('1997-10-04 22:23:00', 'D y a d m b j H k I r T S w'); -> '4th 97 Sat 04 10 Oct 277 22 22 10 10:23:00 PM 22:23:00 00 6'
YYYYMMDD
or 'YYYY-MM-DD'
depending on whether CURDATE()
is used in a number or string
context.
mysql> select CURDATE(); -> '1997-12-15' mysql> select CURDATE()+0; -> 19971215
HHMMSS
or 'HH:MM:SS'
,
depending on whether CURTIME()
is used in a number or string
context.
mysql> select CURTIME(); -> '23:50:20' mysql> select CURTIME()+0; -> 235026
YYYYMMDDHHMMSS
or
'YYYY-MM-DD HH:MM:SS'
depending on whether NOW()
is used
in a number or string context.
mysql> select NOW(); -> '1997-12-15 23:51:26' mysql> select NOW()+0; -> 19971215235131
TIMESTAMP
column
as an argument in which case it returns the columns value in seconds.
Date
may also be a date string, a datetime string, or a number of
format YYMMDD or YYYMMDD in local time.
mysql> select UNIX_TIMESTAMP(); -> 882226357 mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00'); -> 875996580
YYYY-MM-DD HH:MM:SS
or
YYYYMMDDHHMMSS
format depending on context (numeric/string).
mysql> select FROM_UNIXTIME(875996580); -> '1997-10-04 22:23:00'
M | Month, textual |
W | Day (of the week), textual |
D | Day (of the month), numeric plus english suffix |
Y | Year, numeric, 4 digits |
y | Year, numeric, 2 digits |
m | Month, numeric |
d | Day (of the month), numeric |
h | Hour, numeric |
i | Minutes, numeric |
s | Seconds, numeric |
w | Day (of the week), numeric |
All other | All other characters are just copied. |
mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(), 'Y D M h:m:s x'); -> '1997 23rd December 03:12:30 x'
H:MM:SS
or HMMSS
format depending on context.
mysql> select SEC_TO_TIME(2378); -> '00:39:38' mysql> select SEC_TO_TIME(2378)+0; -> 3938
Time
to seconds.
mysql> select TIME_TO_SEC('22:23:00'); -> 80580 mysql> select TIME_TO_SEC('00:39:38'); -> 2378
DATABASE()
mysql> select DATABASE(); -> 'test'
USER()
SYSTEM_USER()
SESSION_USER()
mysql> select USER(); -> 'davida'
PASSWORD(String)
String
. This
must be used to store a password in the 'user' grant table.
mysql> select PASSWORD('badpwd'); -> '7f84554057dd964b'
ENCRYPT(String[, Salt])
String
with the unix crypt()
command. The
Salt
should be a string with 2 characters. If crypt()
was
not found NULL
will always be returned.
LAST_INSERT_ID()
mysql> select LAST_INSERT_ID(); -> 1
FORMAT(Nr, Num)
Nr
to a Format like '#,###,###.##' with Num
decimals.
mysql> select FORMAT(12332.33, 2); -> '12,332.33'
VERSION
mysql> select version(); -> '3.21.16-beta-log'
GET_LOCK(String,timeout)
mysqladmin kill
.
A lock is released if one executes RELEASE_LOCK
, executes a new
GET_LOCK
or if the thread ends. This function can be used to implement
application locks or simulate record locks.
mysql> select get_lock("automaticly released",10); -> 1 mysql> select get_lock("test",10); -> 1 mysql> select release_lock("test"); -> 1 mysql> select release_lock("automaticly released") -> NULL
RELEASE_LOCK(String)
GET_LOCK
. Returns 1 if the
lock was released, 0 if lock wasn't locked by this thread and NULL if
the lock 'String' didn't exist.
GROUP BY
clause.COUNT(Expr)
NULL
rows. count(*)
is optimised to
return very quickly if no other column is used in the SELECT
.
select count(*) from student; select count(if(length(name)>3,1,NULL)) from student;
AVG(expr)
MIN(expr)
MAX(expr)
min()
and max()
may take a
string argument and will then return the minimum/maximum string value.
SUM(expr)
STD(expr)
STDDEV(expr) (Oracle format)
ANSI
SQL
.
BIT_OR(expr)
OR
of all bits in expr. Calculation done with 64 bit
precision.
BIT_AND(expr)
AND
of all bits in expr. Calculation done with 64
bit precision.
MySQL has extended the use of GROUP BY
. You can use columns or
calculations in the SELECT
expressions which don't appear in
the GROUP BY
part. This stands for 'any possible value for this
group'. By using this, one can get a higher performance by avoiding
sorting and grouping on unnecessary items. For example, in the
following query one doesn't need to group on b.name:
SELECT a.id,b.name,COUNT(*) from a,b WHERE a.id=b.id GROUP BY a.id
In ANSI SQL you would have to add the customer.name in the GROUP BY
for the following query. In MySQL the name redundant.
SELECT order.custid,customer.name,max(payments) from order,customer WHERE order.custid = customer.custid GROUP BY order.custid;
Note that you can't use expressions in the GROUP BY
or ORDER BY
clause. You can on the other hand use an alias on a expression and use
this to solve the problem:
SELECT id,FLOOR(value/100) AS val FROM table_name GROUP BY id,val ORDER BY val
CREATE DATABASE database_name
Creates a database with the given name. The name can only contain letters,
numbers or the '_'
character. The max length of the database name is
32 characters.
All databases in MySQL are directories, so a CREATE DATABASE only
creates a directory in the MySQL database directory.
You can also create databases with mysqladmin
.
See section 12.1 Overview of the different MySQL programs
DROP DATABASE database_name
Drop all tables in the database and deleted the database.
You have to be VERY carefull with this command!
DROP DATABASE
returns how many files was removed from the directory.
Normally this is number of tables*3.
You can also drop databases with mysqladmin
.
See section 12.1 Overview of the different MySQL programs
CREATE TABLE table_name ( create_definition,... ) create_definition: column_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [ PRIMARY KEY ] [reference_definition] or PRIMARY KEY ( index_column_name,... ) or KEY [index_name] KEY( index_column_name,...) or INDEX [index_name] ( index_column_name,...) or UNIQUE [index_name] ( index_column_name,...) or FOREIGN KEY index_name ( index_column_name,...) [reference_definition] or CHECK (expr) type: TINYINT[(length)] [UNSIGNED] [ZEROFILL] or SMALLINT[(length)] [UNSIGNED] [ZEROFILL] or MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL] or INT[(length)] [UNSIGNED] [ZEROFILL] or INTEGER[(length)] [UNSIGNED] [ZEROFILL] or BIGINT[(length)] [UNSIGNED] [ZEROFILL] or REAL[(length,decimals)] [UNSIGNED] [ZEROFILL] or DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL] or FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL] or DECIMAL[(length,decimals)] [UNSIGNED] [ZEROFILL] or NUMERIC[(length,decimals)] [UNSIGNED] [ZEROFILL] or CHAR(length) [BINARY], or VARCHAR(length) [BINARY], or DATE or TIME or TIMESTAMP or DATETIME or TINYBLOB or BLOB or MEDIUMBLOB or LONGBLOB or TINYTEXT or TEXT or MEDIUMTEXT or ENUM(value1,value2,value3...) or SET(value1,value2,value3...) index_column_name: column_name [ (length) ] reference_definition: REFERENCES table_name [( index_column_name,...)] [ MATCH FULL | MATCH PARTIAL] [ ON DELETE reference_option] [ ON UPDATE reference_option] reference_option: RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT
See section 7.2 Column types.
The FOREIGN KEY, CHECK and REFERENCE syntax are only for compatibility. (To make it easier to port code from other SQL servers and run applications that create tables with references). They don't actually do anything. See section 5.2 What functionality is missing in MySQL.
If a column doesn't have a DEFAULT value and is not declared as NOT NULL, the default value is NULL.
INT(5) ZEROFILL
a value of 5 is retrieved as 00005
.
BINARY
means that the column will be compared case sensitive. The
default is that all strings are compared case insensitive according to
ISO-8859-1 Latin1. BINARY
is 'sticky' which means that if a column
marked BINARY
is used in a expression, the whole expression is
compared BINARY
.
column_name(length)
syntax one can specify an index which is only
a part of a string
column. This can make the index file much smaller.
BLOB
and TEXT
types.
isamchk
utility to
reorganise tables.
VARCHAR
columns with a length of one or two are changed to CHAR
. When using one
VARCHAR
column all CHAR
columns longer than 2 are changed to
VARCHAR
's. This doesn't affect the usage of the column in any way;
In MySQL VARCHAR
is just a different way to store characters.
MySQL
does the conversion because it will save space and make the
table faster.
See section 10.12 What are the different row formats? Or when to use VARCHAR/CHAR?
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.
NULL
value.
REGEXP
and RLIKE
) uses
ISO8859-1 (Latin1) when deciding the type of a character.
ALTER [IGNORE] TABLE table_name alter_spec [, alter_spec ...] alter_specification: ADD [COLUMN] create_definition or CHANGE [COLUMN] old_column_name create_definition or ALTER [COLUMN] column_name { SET DEFAULT literal | DROP DEFAULT } or ADD INDEX [index_name] ( index_column_name,...) or ADD UNIQUE [index_name] ( index_column_name,...) or DROP [COLUMN] column_name or DROP PRIMARY KEY or DROP INDEX key_name or RENAME [AS] new_table_name
ALTER TABLE
works by creating a temporary table and copying all
information to it and then the old table is deleted and the new one is
renamed. This is done in such a way that all updates are automatically
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.
IGNORE
isn't specified then the copy will be aborted and
rolled back if there exists any duplicated unique keys in the new
table. In case of duplicates the first found row will be used.
This is a MySQL extension.
CHANGE column_name
, DROP column_name
and DROP
INDEX
are MySQL extensions to ANSI SQL92.
COLUMN
is a pure noise word and can be omitted.
ADD
and CHANGE
takes the same create_definition as
CREATE TABLE
. See section 7.6 CREATE TABLE syntax..
ALTER COLUMN
sets a new default value or removes the old
default value for a column.
DROP INDEX
removes an index. This is a MySQL extension.
FOREIGN KEY
syntax in MySQL exists only for compatibility.
See section 5.2 What functionality is missing in MySQL.
DROP PRIMARY KEY
drops index named PRIMARY
or if no such
index exists, it drops the first UNIQUE
index in the table.
CHANGE
tries to convert data to the new format as good as possible.
mysql_info(MYSQL*)
one can retrieve how many records were
copied and how many records were deleted because of multiple indexes.
ALTER TABLE
one needs select, insert, delete,
update, create and drop privileges on the table.
ALTER TABLE table_name RENAME AS new_name
without any
other options, MySQL will only do a fast rename of table table.
Some examples of using ALTER TABLE:
CREATE TABLE t1 (a INTEGER,b CHAR(10)); INSERT INTO t1 VALUES(1,"testing"); ALTER TABLE t1 RENAME t2; ALTER TABLE t2 CHANGE a a TINYINT NOT NULL, CHANGE b c CHAR(20); ALTER TABLE t2 ADD d TIMESTAMP; ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a); ALTER TABLE t2 DROP COLUMN c; ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD INDEX (c); DROP TABLE t2;
DROP TABLE table_name [, table_name...]
Removes one or more tables. All the data and the definition are removed so take it easy with this command!
DELETE FROM table_name WHERE where_definition
Returns records affected.
If one does a delete without a WHERE
clause then the table is
recreated, which is much faster than doing a delete for each row. In
these cases, the command returns zero as affected records. MySQL
can't return the number of deleted row because the recreate is done without
opening the data files to make sure that one can recreate the table as
long as the table definition file table_name.frm
is valid.
SELECT [STRAIGHT_JOIN] [DISTINCT | ALL] select_expression,... [INTO OUTFILE 'file_name' ...] [ FROM table_references [WHERE where_definition ] [GROUP BY column,...] [HAVING where_definition] [ ORDER BY column [ASC | DESC] ,..] [LIMIT [offset,] rows] [PROCEDURE procedure_name]]
All used keywords must come in exactly the above order. For example
a HAVING
clause must come after any GROUP BY
and before any
ORDER BY
clause.
Strings are automatically converted to numbers and numbers to strings
when needed (a-la Perl). If in a compare operation ((=, <>, <= ,<,
>=, >)
) either of the arguments are numerical, the arguments are
compared as numbers, else the arguments are compared as strings. All
string comparisons are by default done case-independent by ISO8859-1
(The Scandinavian letter set which also works excellently with English).
select 1 > '6x'; -> 0 select 7 > '6x'; -> 1 select 0 > 'x6'; -> 0 select 0 = 'x6'; -> 1
HAVING
clause.
select concat(last_name,' ',first_name) as name from table order by name
LEFT OUTER JOIN
references.
See section 7.11 Join syntax
LIKE
expressions % and _ may be preceded with '\' to skip the
wildcard meaning and get a literal % or _.
IFNULL()
and IF()
return number or string value according to
use.
ORDER
and GROUP
columns may be given as column names,
column aliases or column numbers in SELECT
clauses.
HAVING
clause can take any column or alias in the
select_expressions. It is applied last, just before items are sent to
the client, without any optimisation. 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 user HAVING max(salary)>10
Change it to:
SELECT user,MAX(salary) AS sum FROM users GROUP BY user HAVING sum > 10
STRAIGHT_JOIN
forces the optimiser to join the tables in the same
order that the tables are given in the FROM
clause. One can use
this to get a query to be done more quickly if the optimiser joins the
tables in non-optimal order. See section 7.17 EXPLAIN syntax. Get information about a SELECT.
MySQL supports the following JOIN
syntaxes:
table_reference, table_reference table_reference [CROSS] JOIN table_reference table_reference LEFT [OUTER] JOIN table_reference ON conditional-expr table_reference LEFT [OUTER] JOIN table_reference USING (column-commalist) table_reference NATURAL LEFT [OUTER] JOIN table_reference { oj table_reference LEFT OUTER JOIN table_reference ON conditional-expr }
The last example is ODBC syntax.
table_reference AS alias
or
table_reference alias
.
,
and JOIN
are semantically identical. This does a full join
between the used tables. One normally specifies in the WHERE
condition how the tables should be linked.
ON
conditional is any WHERE
conditional. If there is no
matching record for the right table in a LEFT JOIN
a row with all
columns set to NULL will be used for the right table.
USING
column-list is a list of fields that must exists in both
tables. A LEFT JOIN B USING (C1,C2,C3...)
is defined to be semantically
identical to using an ON
expression
A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3...
.
NATURAL LEFT JOIN
of two tables is defined to be semantically
identical to a USING
with all column names that exist in both
tables.
LEFT JOIN
syntax exists only for compatibility with ODBC.
INSERT INTO table [ (column_name,...) ] VALUES (expression,...) or INSERT INTO table [ (column_name,...) ] SELECT ...
An expression may 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:
ORDER BY
clause.
INSERT
statement cannot appear in the FROM
clause of the query.
INSERT INTO ... SELECT ...
then one can get the following
info string with the C API function mysql_info()
.
Records: 100 Duplicates: 0 Warnings: 0
Duplicates are
rows which couldn't be written because some index would be
duplicated. Warnings are columns which were set to NULL, but have been
declared NOT NULL. These will be set to their default value.
In this case it's also forbidden in ANSI SQL to SELECT from the same table
that you are inserting into. The problem that there may be problems if
the SELECT finds records that is inserted at the same run. When using sub
selects the situation could easily be very confusing!
REPLACE INTO table [ (column_name,...) ] VALUES (expression,...) or REPLACE INTO table [ (column_name,...) ] SELECT ...
This works exactly like INSERT
, except that if there was some old
record in the table with the same unique index the old record or records
will be deleted before this record is inserted.
See section 7.12 INSERT syntax.
LOAD DATA INFILE
'text_file_name.text' [REPLACE
|
IGNORE
] INTO
TABLE
table_name [FIELDS
[TERMINATED BY
',' [OPTIONALLY
] ENCLOSED BY
'"'
ESCAPED BY
'\\' ]] [LINES TERMINATED BY
'\n'] [(Field1,
Field2...)]
This is used to read rows from a text file, which must be located on the
server, at a very high speed. The server-client protocol doesn't yet
support files over a connection. If you only have the file on the
client, use rcp or ftp to copy it, possibly compressed,
to the server before using LOAD DATA INFILE
. All paths to the text
file are relative to the database directory.
To write data to a text file, use the SELECT ... INTO OUTFILE
'interval.txt' fields terminated by ',' enclosed by '"' escaped by '\\'
lines terminated by '\n' FROM ...
syntax.
Normally you don't have to specify any of the text file type options. The
default is a compact text file with columns separated with tab
characters and all rows end with a newline. Tabs, newlines and \
inside fields are prefixed with a \
. NULLs are read and written as
\N.
FIELDS TERMINATED BY
has the default value of \t
.
FIELDS [OPTIONALLY] ENCLOSED BY
has the default value of "
.
FIELDS ESCAPED BY
has the default value of '\\'
.
LINES TERMINATED BY
has the default value of '\n'
.
FIELDS TERMINATED BY
and LINES TERMINATED BY
may be more
than one character.
If LINES TERMINATED BY
is an empty string and FIELDS
TERMINATED BY
is non-empty then lines are also terminated with
FIELDS TERMINATED BY
.
If FIELDS TERMINATED BY
and FIELDS ENCLOSED BY
both are
empty strings ("
) then this gives a fixed row format ("not delimited"
import format). With a fixed row size NULL values are output as a
blank string.
If you specify OPTIONALLY
in ENCLOSED BY
, then only
strings are enclosed in ENCLOSED BY
by the SELECT ... INTO
statement.
Duplicated ENCLOSED BY
chars are removed from strings that start
with ENCLOSED BY
. For example: With ENCLOSED BY '"'
:
"The ""BIG"" boss" -> The "BIG" boss The "BIG" boss -> The "BIG" boss
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 BY
is not empty then
\N
is also read as a NULL
value.
If REPLACE
is used, then the new row will replace all rows which
have the same unique index. If IGNORE
is used, the row will then
be skipped if a record already exists with an identical unique key.
If none of the above options are used an error will be issued. The
rest of the text file will be ignored if one gets a duplicate index error.
Some possible cases that are not supported by LOAD DATA
:
FIELDS TERMINATED BY
and FIELDS ENCLOSED
BY
both are empty) and BLOB columns.
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 the table. If a row has too few columns, the rest
of the columns are set to default values. TIMESTAMP
columns are only
set to the current time if there is a NULL value for the column or if
the TIMESTAMP
column is left out from the field list when the field
list is used.
For security reasons the text file must either reside in the database
directory or be readable by all. Each user that wants to use
LOAD DATA INFILE
must also have 'Y' in the 'File_priv' column
in the user privilege table!
See section 6.2 How does the privilege system work?
Because LOAD DATA INFILE
regards all input as strings you can't use
number values for enum
or set
columns as you can with
INSERT
statements. All enum
and set
must be given as
strings!
For more information about the escaped syntax, See section 7.1 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()
.
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
Warnings are 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. A warning is also given for any time, date, timestamp or datetime column that is set to 0.
An example that loads all columns:
LOAD DATA INFILE 'persondata.text' INTO TABLE persondata;
See section 10.8 How should I arrange my table to be as fast/small as possible?
UPDATE table SET column=expression,... WHERE where_definition
All updates are done from left to right. If one accesses a column in the expression, update will then use the current value (a given value or the default value) of the column.
UPDATE persondata SET count=count+1
SHOW DATABASES [LIKE wild] or SHOW TABLES [FROM database] [LIKE wild] or SHOW COLUMNS FROM table [FROM database] [LIKE wild] or SHOW INDEX FROM table [FROM database] or SHOW STATUS or SHOW VARIABLES [LIKE wild]
Gives information about databases, tables or columns. If the LIKE
wild
part is used the wild
string is a normal SQL wildcard (with
% and _). FIELDS
may be used as an alias for COLUMNS
and
KEYS
may be used as an alias for INDEXES
.
STATUS
gives status information from the server
like mysqladmin status
). The output may differ from the following:
Uptime | Running_threads | Questions | Reloads | Open_tables
|
119 | 1 | 4 | 1 | 3 |
VARIABLES
shows the values of the some of MySQL system variables. Most
of these variables can be changed by different options to mysqld
!
EXPLAIN SELECT select_options
Gives information about how and in which order tables are joined. With
the help of EXPLAIN
one can see when one has to add more indexes
to tables to get a faster select that uses indexes to find the
records. You can also see if the optimiser joins the tables in an
optimal order. One can force the optimiser to use a specific join order
with the STRAIGHT_JOIN
option to select.
The different join types are:
system
const
eq_ref
ref
range
all
Here is a example of a join which is optimised with the help of
EXPLAIN
.
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn, tt.ProjectReference, tt.EstimatedShipDate, tt.ActualShipDate, tt.ClientID, tt.ServiceCodes, tt.RepetitiveID, tt.CurrentProcess, tt.CurrentDPPerson, tt.RecordVolume, tt.DPPrinted, et.COUNTRY, et_1.COUNTRY, do.CUSTNAME FROM tt, et, et AS et_1, do WHERE tt.SubmitTime Is Null and tt.ActualPC = et.EMPLOYID and tt.AssignedPC = et_1.EMPLOYID and tt.ClientID = do.CUSTNMBR;
The EXPLAIN
returns the following:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 do ALL PRIMARY NULL NULL NULL 2135 et_1 ALL PRIMARY NULL NULL NULL 74 tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 range checked for each record (key map: 35)
In this case MySQL is doing a full join for all tables! This will take quite a long time as the product of the number of rows in each table must be examined! So if all tables had 1000 records MySQL has to look at 1000^4 = 1000000000000 rows. If the tables are bigger you can only imagine how long it would take...
In this case the first error is that MySQL can't yet use efficiently indexes on columns that are declared differently: (varchar() and char() are not different in this context)
In this case tt.ActualPC
is char(10)
and
et.EMPLOYID
is char(15)
.
Fix:
mysql> alter table tt change ActualPC ActualPC varchar(15);
And the above explanation shows:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used do ALL PRIMARY NULL NULL NULL 2135 range checked for each record (key map: 1) et_1 ALL PRIMARY NULL NULL NULL 74 range checked for each record (key map: 1) et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
Which is not perfect but much better. This version is executed in a couple of seconds.
After
mysql> alter table tt change AssignedPC AssignedPC varchar(15), change ClientID Clientid varchar(15);
You get the following from EXPLAIN
:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 tt ref AssignedPC,ClientID,ActualPC ActualPC 15 et.EMPLOYID 52 where used et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.Clientid 1
Which is 'almost' as good as it can get. The problem is that
MySQL assumes that tt.AcutalPC
is evenly distributed which
isn't the case in the tt.
Fortunately it is easy to tell MySQL about this:
shell> isamchk --analyze PATH_TO_MYSQL_DATABASE/tt shell> mysqladmin refresh
And now the join is 'perfect':
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1 et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.Clientid 1
(DESCRIBE | DESC) table [column]
Gives information about columns. This command is for Oracle compatibility. See section 7.16 SHOW syntax. Get information about tables, columns.... Column may be a column name or a string. Strings may contain wild cards.
LOCK TABLES
syntaxLOCK TABLES table_name [AS alias] READ|WRITE [, table_name READ|WRITE] ... UNLOCK TABLES
Locks tables for this thread. If a thread has a READ lock on a table, the thread (and all other threads) can only read from the table. If a thread has a WRITE lock one a table, then only this thread can READ and WRITE on the table. All threads waits until they get all locks (no timeouts).
When one uses LOCK TABLES
one must lock all tables one is going to use!
This policy ensures that table locking is deadlock free.
LOCK TABLES trans READ, customer AS c WRITE SELECT SUM(value) FROM trans WHERE customer_id= #some_id#; UPDATE customer SET total_value=#value_from_last_statement# WHERE customer_id=#some_id# UNLOCK TABLES
All tables are automatically unlocked when one issues another LOCK
TABLES
or if the connection to the server is closed.
Normally you don't have to lock tables. There is a couple of cases when you would like to lock tables anyway:
MySQL
doesn't support a transaction environment, you must use lock
tables if you want to ensure that no other thread comes between a read and a
update. For example the previous example requires LOCK TABLES
to be
safe! If one didn't use LOCK TABLES
there is a change that someone
inserts a new 'trans' row between the SELECT and UPDATE statements.
UPDATE customer set value=value+new_value
)
or the LAST_INSERT_ID() function you can avoid using LOCK TABLES
in many
cases.
You can also solve some cases by using user level locks: GET_LOCK() and RELEASE_LOCK(). These locks are saved in a hash table in the server and implemented with pthread_mutex for high speed. See section 7.3.11 Miscellaneous functions.
SET [OPTION] SQL_VALUE_OPTION=value, ...
The used options remain in effect for the whole current session.
The different options are:
SQL_SELECT_LIMIT=value
SQL_BIG_TABLES= 0 | 1
The table ### is full
for big selects that require a big temporary
table. The default value for a new connection is 0 (use in memory
temporary tables).
SQL_BIG_SELECTS= 0 | 1
WHERE
statement has been issued. A big query is defined as a SELECT
that
will probably have to examine more than max_join_size
rows. The
default value for a new connection is 0 (which will allow all SELECT's).
CHARACTER SET character_set_name | DEFAULT
cp1251_koi8
,
but one can easily add new mappings by editing the file
mysql_source_directory/sql/convert.cc
.
One can restore the default mapping by using DEFAULT
as the
character_set_name.
SQL_LOG_OFF= 0 | 1
TIMESTAMP= timestamp_value | DEFAULT
LAST_INSERT_ID= #
GRANT (ALL PRIVILEGES | (SELECT, INSERT, UPDATE, DELETE, REFERENCES (column list), USAGE)) ON table TO user,... [WITH GRANT OPTION]
This command doesn't do anything. It is only in MySQL for compatibility reasons. (To make it easier to port code from other SQL servers). Privileges in MySQL are handled with the MySQL grant tables. See section 6.2 How does the privilege system work?
CREATE [UNIQUE] INDEX index_name ON table_name ( column_name,... )
This function doesn't do anything. It is only in MySQL for
compatibility reasons. You can create a new index with ALTER TABLE
.
See section 7.7 ALTER TABLE syntax
DROP INDEX index_name
This always succeeds.
You can drop an index with ALTER TABLE
. See section 7.7 ALTER TABLE syntax
MySQL supports the # to end of line
and
/* multiple line */
comment
styles.
select 1+1; # This comment is to the end of line select 1 /* in-line-comment */ + 1; select 1+ /* This will be ignored */ 1;
MySQL doesn't support the --
ANSI SQL style comments.
See section 5.2.7 -- as start of a comment.
CREATE FUNCTION <function_name> RETURNS [string|real|integer] SONAME <name_of_shared_library> DROP FUNCTION <function_name>
User definable functions (UDF) is way to extend MySQL with new
functions that works as native MySQL functions like ABS()
and
concat()
. UDF's are written in C or C++ and require that dynamic
loading works on the operating system. The source distribution includes
the file `udf_example.cc' that defines 5 new functions.
The functions name, type and shared library is saved in the new system table 'func' in the 'mysql' database. To be able to create new functions one must have write privilege for the database 'mysql'. If one starts MySQL with --skip-grant-tables, then UDF initialization will also be skipped.
Each defined function may have a xxxx_init function and a xxxx_deinit function. The init function should alloc memory for the function and tell the main function about the max length of the result (for string functions), number of decimals (for double functions) and if the result may be a null value.
If a function sets the 'error' argument to 1 the function will not be called anymore and mysqld will return NULL for all calls to this instanse of the function.
All strings arguments to functions are given as string pointer + length to allow handling of binary data. Remember that all functions must be thread safe. This means that one is not allowed to alloc any global or static variables that changes! If one needs memory one should alloc this in the init function and free this on the __deinit function.
A dynamicly loadable file should be compiled sharable
(something like: gcc -shared -o udf_example.so myfunc.cc
).
You can easily get all switches right by doing:
cd sql ; make udf_example.o
Take the compile line that make writes, remove the '-c' near the end of
the line and add -o udf_example.so to the end of the compile line.
The resulting library (udf_example.so) should be copied to some dir
searched by ld, for example /usr/lib.
Some notes about the example functions:
metaphon
returns a metaphon string of the string argument.
This is something like a soundex string, but it's more tuned for English.
myfunc_double
returns summary of codes of all letters
of arguments divided by summary length of all its arguments.
myfunc_int
returns summary length of all its arguments.
lookup
returns the IP number for an hostname.
reverse_lookup
returns the hostname for a IP number.
The function may be called with a string "xxx.xxx.xxx.xxx" or
four numbers.
After the library is installed one must notify mysqld
about the new
functions with the commands:
CREATE FUNCTION metaphon RETURNS STRING SONAME "udf_example.so"; CREATE FUNCTION myfunc_double RETURNS REAL SONAME "udf_example.so"; CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so"; CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so"; CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so";
Functions should be created only once. The functions can be deleted by:
DROP FUNCTION metaphon; DROP FUNCTION myfunc_double; DROP FUNCTION myfunc_int; DROP FUNCTION lookup; DROP FUNCTION reverse_lookup;
The CREATE FUNCTION
and DROP FUNCTION
update the func
table. All active function will be reloaded on every restart of server
(if --skip-grant-tables is not given).
A common problem stems from trying to create a table with column names
timestamp
or group
, the names of datatypes and functions
built into MySQL. You're allowed to do it (for example,
ABS
is an allowed column name), but whitespace is not allowed
between a function name and the '('
when using the functions
whose names are also column names.
The following are explictly reserved words in MySQL. Most of
them (for example) group
, are forbidden by ANSI SQL92 as column
and/or table names. A few are because MySQL needs them and is
(currently) using a yacc parser:
action | add | all | alter
|
and | as | asc | auto_increment
|
between | bigint | bit | binary
|
blob | both | by | cascade
|
char | character | change | check
|
column | columns | create | data
|
database | databases | date | datetime
|
day | day_hour | day_minute | day_second
|
dayofweek | dec | decimal | default
|
delete | desc | describe | distinct
|
double | drop | escaped | enclosed
|
enum | explain | fields | float
|
float4 | float8 | foreign | from
|
for | full | grant | group
|
having | hour | hour_minute | hour_second
|
ignore | in | index | infile
|
insert | int | integer | interval
|
int1 | int2 | int3 | int4
|
int8 | into | is | join
|
key | keys | leading | left
|
like | lines | limit | lock
|
load | long | longblob | longtext
|
match | mediumblob | mediumtext | mediumint
|
middleint | minute | minute_second | month
|
natural | numeric | no | not
|
null | on | option | optionally
|
or | order | outer | outfile
|
partial | precision | primary | procedure
|
privileges | read | real | references
|
rename | regexp | repeat | replace
|
restrict | rlike | select | set
|
show | smallint | sql_big_tables | sql_big_selects
|
sql_select_limit | sql_log_off | straight_join | starting
|
table | tables | terminated | text
|
time | timestamp | tinyblob | tinytext
|
tinyint | trailing | to | use
|
using | unique | unlock | unsigned
|
update | usage | values | varchar
|
varying | varbinary | with | write
|
where | year | year_month | zerofill
|
At TcX, MySQL has worked without any problems in our projects since mid-1996. When released to a wider public we noticed that there were some pieces of 'untested code' in MySQL that were quickly found by the new user group who made queries in a different manner. Each new release has had fewer portability problems than the previous one, even though they have all had a lot of new features, and we hope that it will be possible to label one of the next releases 'stable'.
Each release of MySQL has been usable and there have only been problems when users start to use code from 'the gray zones'. Naturally, outside users can't know what the gray zones are and I hope this section will clarify those currently known.
Here we will try to answer some of the more important questions that seems to concern a lot of people and clarify some issues. This section has been put together from the information that has come forward in the mailing list which is very active in reporting bugs.
How stable is MySQL? Can I depend on MySQL in this project?
This is about the 3.21.x version of MySQL. All known and reported bugs are fixed in the latest version with the exception of the bugs listed in the BUGS file which are things that are 'design' related.
MySQL is written in multiple layers and different independent modules. Here is a list of the different modules and how tested each of them are.
--skip-locking
flag. Known
problems are some Linux systems and SunOS when using NFS-mounted file
systems.
--skip-locking
. Some people have reported lockup problems with the 0.5
release.
TcX provides email support for paying customers, but the MySQL mailing list usually provides answers to all common questions. Bugs are usually fixed right away with a patch that usually works and for serious bugs there is almost always a new release.
Well, MySQL is evolving quite rapidly here at TcX and we want to share this with other MySQL users. We try to make a release when we have a very useful feature that others seem to have a need for.
We also try to help out users who request features that are easy to implement. We also take note on what our licensed users want to have and we especially take notes of what our extended email supported customers want and try to help them out.
No one has to download a new release. The News section will tell you if the new release has something you really want. See section D MySQL change history.
If there is, by any chance, a fatal bug in a release we will make a new release as soon as possible. We would like other companies to do this too. :)
The 3.21.x version incorporates major portability changes for many different systems. When the 3.21 release is stable we will remove the alpha/beta suffix and move active development to 3.22. Bugs will still be fixed in the stable version. We don't believe in a complete freeze, as this also leaves out bug fixes and things that 'must be done'. 'Somewhat freezed' means that we will maybe add small things that 'almost surely will not affect anything thats already working'.
If you are running and old system and want to upgrade, but you don't want to take chances with 3.21 you should upgrade to 3.20.32. I have tried to only fix fatal bugs and make small, relatively safe changes in this version.
If you are trying MySQL for the first time or have a little time to test out that your current system, you should use 3.21.
If MySQL crashed (for example if the computer is turned off) when all data is not written to disk the tables may have become corrupted. To check a table use:
isamchk table_name
isamchk -e table_name
isamchk -e -i table_name
We at TcX run a cron job on all our important tables once a week.
35 0 * * 0 /path/to/isamchk -s /path/to/dbs/*/*.ISM
This prints out any crashed tables so we can go and examine and repair them when needed.
As we haven't had any unexpected crashes (without hardware trouble) tables for a couple of years now (this is really true), once a week is more than enough for us.
Of course, whenever the machine has done a reboot in the middle of a update one usually has to check all the tables that could have been affected. (This is an 'expected crashed table')
We recommend that to start with, one should do a isamchk -s
on all
updated tables each night until one comes to trust MySQL as much
as we do.
Naturally, one could add a check to safe_mysql that, if there is an old pid file left after a reboot, it should check all tables that have been modified the last 24 hours.
The file format that MySQL uses to store data has been extensively tested, but there are always instances (like a hard kill on the mysqld process in the middle of a write, a hardware error or a unexpected shutdown of the computer) when some tables may be corrupted.
The sign of a corrupted table is usually when queries abort unexpectedly and one gets errors like:
In these cases you have to repair your tables. The isamchk external utility can usually detect and fix most things that go wrong. See section 12.2 The MySQL table check, optimise and repair program.
If you are going to use isamchk on very large files, you should first decide how much memory you want to give to isamchk. More memory gives more speed. For example, if you have more than 32M ram, try:
isamchk -O sortbuffer=16M -O keybuffer=16M -O readbuffer=1M -O writebuffer=1M ....
shell> mysql database mysql> delete from table_name; mysql> quit
One can always move the MySQL form and data files between
different versions on the same architecture as long as one has the same
base version of MySQL. The current base version is of course
3. If one changes the character set (sort order) by recompiling
MySQL one has to do a isamchk -r -q
on all tables.
If you are paranoid and/or afraid of new versions you can always rename your old mysqld to something like mysqld-'old-version-number'. If your new mysqld then does something unexpected you can simple shut it down and restart with your old mysqld!
When you do a upgrade you should of course also take a backup of your old databases. Sometimes its good to be a little paranoid!
If you already have a version older than 3.20.28 running and want to switch to 3.21.# you need to do the following:
You can start the mysqld
3.21 server with safe_mysqld
--old-protocol
to use it with clients from the 3.20 distribution.
In this case the new client function, mysql_errno()
, will not
return any server error, only CR_UNKNOWN_ERROR
, (but it
works for client errors) and the server uses the old password() checking
instead of the new one.
If you are NOT using --old-protocol
:
scripts/add_long_password
must be run to convert the
password field in the 'mysql/user' table to char(16)
.
MySQL 3.20.28 and above can handle the new user table format without affecting clients. If you have a MySQL version below 3.20.28, passwords will not work on it anymore if you convert the user table. So to be safe, you should first upgrade to at least 3.20.28 and then upgrade to 3.21.#.
The new client code works with a 3.20.# mysqld server, so you can use the old 3.20.# server if you experience problems with 3.21.# without having to recompile the clients again.
If you are not using the option --old-protocol
to mysqld
,
old clients will issue the error message:
The new perl interface DBI/DBD also supports the old mysqlperl interface. The only change one has to do if one uses mysqlperl is to change the arguments to the connect() function. The new arguments are: host,database,user,password (the user & password arguments has changed places).
ERROR: Protocol mismatch. Server Version = 10 Client Version = 9
MySQL uses Unix times functions and has no problems with dates
until 2069; All 2 digit years are regarded to be in the range 1970-2069.
In MySQL 3.22 the new YEAR
column type can store years
0, 1901-2155 in 1 byte and display them with 2 or 4 digits.
mysqld
can give error messages in the following languages: Czech,
Dutch, English (default), French, German, Norwegian, Norwegian-ny,
Polish, Portuguese, Spanish and Swedish.
To start mysqld
with a language use one of the
--language=lang
or -L lang
switches:
mysqld --language=swedish
or
mysqld --language=/usr/local/share/swedish
Note that all the language names are in lowercase.
The language files are located (by default) in `mysql_base_dir/share/LANGUAGE/'.
By default, MySQL will use the ISO8859-1 (Latin1) character set. This is the character set used in the USA and western Europe.
The character set decides what characters are allowed in names and how
things are sorted by the ORDER BY
and GROUP BY
commands.
You may change this at compile time by the configure switch
--with-charset=charset
. See section 4.5.1 Quick installation overview..
When started with the --log-update=file_name
switch mysqld
makes a log file with all SQL command that update data. It results in a
file with name of file_name.#
where # is a number that is
increased for each refresh. If you do not give a file name the current
hostname is used.
The logging is smart since it only writes statements that really update
data. So an UPDATE
or a DELETE
with a WHERE
that finds no
rows is not written to the log. It even skips UPDATE
s that updates
a column to the value it had before.
If you want to update a database according from a update log you could do the following:
cat file-name.* | mysql
Currently a table is limited to the operation system file size. On Linux the current limit is 2G, on Solaris 2.5.1 the limit is 4G and on Solaris 2.6 the limit is going to be 1000G. To get more that 4G requires some changes to MySQL that are on the Todo. See section F List of things we want to add to MySQL in the future..
If your big table is going to be read_only, you could use pack_isam (See section 12.3 The MySQL compressed read only table generator) to merge and compress many tables to one. As pack_isam usually compresses a table by at least 50%, you can have much bigger tables.
Another solution can be the included MERGE library, which allows one to handle a collection of identical tables as one. Currently MERGE can only be used to scan a collection of tables because it doesn't support indexes. We will add indexes to this in the near future. Identical in this case means that all tables are created with identical column information.
You can get the current buffer sizes with:
> ./mysqld --help
This should result in a list of all mysqld options and configurable variables like the following.
Possibly variables to option --set-variable (-O) are: back_log current value: 5 join_buffer current value: 131072 key_buffer current value: 1048568 max_allowed_packet current value: 65536 max_connections current value: 90 max_join_size current value: 4294967295 max_sort_length current value: 1024 net_buffer_length current value: 8192 record_buffer current value: 131072 sort_buffer current value: 2097144 table_cache current value: 64 tmp_table_size current value: 1048576 thread_stack current value: 65536
back_log | How many outstanding connection requests may MySQL have. This comes into play when the main MySQL thread gets VERY many connection requests in a very short time. It then takes some time (but very short) for the main thread to check the connection and start a new thread. The back_log is how many connects can be stacked during this short time before MySQL momentarily stops answering new requests. You only need to increase this if you expect a large number of connections in a short period of time. In other words, the size of the listen queue for incoming tcp/ip connections. The manual page for the unix system call listen(2) should have more details. Check your OS documentation for the maximum value for this variable. |
join_buffer | This buffer is used for full joins (without indexes). It is allocated one time for each full join between two tables. Increase this to get a faster full join when adding indexes is not possible. Normally the best way to get fast joins is by adding indexes. |
key_buffer |
Buffers index blocks and are shared by all threads. You might want to
increase this when doing many delete/inserts on a table with lots of
indexes. To get even more speed use LOCK TABLES . See section 7.19 LOCK TABLES syntax.
|
max_allowed_packet |
Max size of one packet. This allows the message buffer to grow up to
this limit when needed (it is initiated to
net_buffer_length ). May be set very big because this is mainly to
find erroneous packets. You must increase this if you are using big
BLOBS. It should be as big as the biggest BLOB you want to use.
|
max_connections | How many simultaneous clients are allowed. If you increase this you probably has to increase the number of file descriptors mysqld has. This is Operating system depended so look at you OS documentation. |
max_join_size |
Joins that touch more records than max_join_size return an error. Set this if
you have users to tend to make joins without a WHERE that take a long
time and return millions of rows.
|
max_sort_length |
The number of bytes to use when sorting on BLOB or TEXT
columns.
|
net_buffer_length | The communication buffer is reset to this size between queries. This should not normally be changed, but if you have very little memory you can set it to the expected size of a query. |
record_buffer | Each thread that is doing a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans you may want to increase this. |
sort_buffer |
Each thread that needs to do a sort allocates a buffer of this
size. Increase this for faster ORDER BY or GROUP BY . A
sort also allocates one or two temporary files. The maximum disk-space
needed is (length_of_what_is_sorted + sizeof(database_pointer)) *
number_of_rows * 2 . sizeof(database_pointer) is usally 4 but may
grow in the future for really big tables.
|
table_cache | Number of open tables for all threads. If this is increased you must see to that the number of open file descriptor is also increased. MySQL needs two file descriptors for each unique table. |
tmp_table_size |
If a temporary table gets bigger than this a The table ### is
full error will be generated. Increase this if you do many advanced
GROUP BY queries.
|
thread_stack |
How big will each threads C stack be. A lot of the limits
detected by crash-me are dependent on this. The default is normally
enough.
|
> safe_mysqld -O key_buffer=16M -O table_cache=128 \ -O sort_buffer=4M -O record_buffer=1M &If you have little memory with lots of connections, use something like:
> safe_mysqld -O key_buffer=512k -O sort_buffer=100k -O record_buffer=100k &or even
> safe_mysqld -O key_buffer=512k -O sort_buffer=16k -O table_cache=32 \ -O record_buffer=8k -O net_buffer=1K &Note that if you change an option to
mysqld
it is only for that
instance of the server. To see the effects of a parameter change, do
something like this mysqld -O key_buffer=32m --help
.
You can check the parameters in effect with mysqladmin variables
.
If there are very many connections, 'swapping problems' may occur if
mysqld has not been configured to use very little memory for each
connection. It also works better if you have a enough memory for all
connections of course.
For example, for 200 open connections one should have a table cache of
at least 200 * (max_number of tables in join).
Most of the following test are done on Linux and with the MySQL benchmarks, but they should give some indication for other operating systems:
On Linux you will get the fastest code when compiling with pgcc and -O6. To compile sql_yacc.cc with these options one needs 180M memory as gcc/pgcc needs a lot of memory to make all functions inline.
The fastest code is when you link with -static and use Unix socket to connect to the database.
The MySQL-linux distribution that is distributed by TCX is compiled with pgcc and linked staticly.
net_buffer_length
).
mysqld
one can specify a key buffer. This will buffer
all indexes in all tables on a FIFO basis (variable key_buffer).
BLOB
s are stored on disk. One current
problem is that if the HEAP table exceeds the size of
tmp_table_size
, one will get the error: 'The table ### is full'.
In the future we will fix this by automatically changing the in memory
(HEAP) table to a disk based (NISAM) table if needed. To go around this
problem one can increase the -O tmp_table_size=#
option to mysqld
or use the SQL option SQL_BIG_TABLES
. See section 7.20 SET OPTION syntax.. In
MySQL 3.20
the maximum size of the temporary table was
recordbuffer*16
, so if you are using this version you have to
increase recordbuffer
. There also exists a patch to always store
temporary tables on disk, but this will affect the speed of all
complicated queries.
BLOB
s) is allocated. A BLOB
uses 5 to 8 bytes +length of blob data.
BLOB
s, a buffer is enlarged dynamically
to read in larger BLOB
s. If one scans a table there will be
a allocated buffer as large as the largest BLOB
.
mysqladmin refresh
closes all tables that are not in use and marks
all used tables to be closed when the running thread finishes. This will
effectively free most used memory. All log files are also closed and reopened.
When running mysqld ps
and other programs may report that
it uses a lot of memory. This may be caused by thread-stacks on different
memory addresses. For example, the Solaris ps calculates the unused memory
between stacks as used memory. You can verify this by checking available
swap with 'swap -s'. We have tested mysqld
with commercial
memory-leakage detectors so there should not be any memory leaks.
All indexes, PRIMARY
, UNIQUE
and INDEX()
, are stored
in B trees. Strings are automatically prefix- and end-space compressed.
INDEX(col1, col2)
creates a multiple index over the two columns.
The index can be seen as a concatenation of the given columns. If you use
INDEX(col1)
, INDEX(col2)
instead of INDEX(col1,col2)
you get two separate indexes instead.
SELECT * FROM table WHERE col1=# AND col2=#
In a case of INDEX(col1,col2)
the right row(s) can be fetched
directly. In a case of INDEX(col1)
, INDEX(col2)
the
optimiser decides which index will find fewer rows and this index will
be used to fetch the rows.
If the table has an index INDEX(col1,col2,col3...)
the prefix
of this can be used by the optimiser to find the rows. This means
that the above gives you search capabilities on: INDEX(col1)
and INDEX(col1,col2)
and INDEX(col1,col2,col3)
...
MySQL can't use a portion of an index to locate rows through an index.
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 indexes.
MySQL will also use indexes if the LIKE
argument is a
constant string that doesn't start with a wild character:
The following will use indexes:
SELECT * from table WHERE key_column like "Patrick%"; SELECT * from table WHERE key_column like "Pat%_ck%";
In the above cases only rows with Patrick <= key_column < Patricl
and
Pat <= key_column < Pau
will be considered.
The following selects will not use indexes:
SELECT * from table WHERE key_column like "%Patrick%"; SELECT * from table WHERE key_column like other_column;
(Incomplete, MySQL does a lot of optimisations.)
The first issue about making a slow SELECT ... WHERE
faster
is to check if one could add an index. All references between
different tables should usually be done with indexes. One can use
the EXPLAIN
command to check which indexes are used in a
select
. See section 7.17 EXPLAIN syntax. Get information about a SELECT.. See section 10.4 How does MySQL use indexes?
((a AND b) AND c OR
(((a AND b) AND (c AND d))))
-> (a AND b) OR (a AND b AND c AND d)
(a<b AND b=c) AND a=5
-> b>5 AND b=c AND a=5
(b>=5
AND b=5) OR (b=6 AND 5=5) OR (B=7 AND 5=6)
-> B=5 OR B=6
CONST(*)
on a single table without a WHERE
is retrieved
directly from the table. This is also done for any NOT NULL
expression under the same conditions.
HAVING
is merged with WHERE
if one doesn't use GROUP
BY
or group functions.
WHERE
is constructed to get a fast
WHERE
evaluation for each sub join and also to skip records as
soon as possible.
=
, >
,
>=
, <
, <=
, BETWEEN
and a LIKE
with
a character prefix like 'something%'.
AND
levels.
index = 1 or A = 10
-> NULL
(can't use index.)
index = 1 or A = 10 and index=2
-> index = 1 OR index = 2
index_part_1 = const and index_part_3 = const
-> index_part_1 =
const
const_table.index = constant
const_table.index_part_1 = const_table2.column and const_table.index_part_2 = constant
ORDER BY
and in GROUP
come from the same table, then this table is preferred first when joining.
HAVING
clause.
The cache of open tables can grow to a maximum of table-cache
(default 64, changeable with -O table_cache=#).
A table is never closed, except when the cache is full and another thread
tries to open a table or if one uses 'mysqladmin refresh'.
When the limit is reached, MySQL closes as many tables as possible, until the cache size has been reached or there are no more unused tables. This means that if all tables are in use by some threads, there will be more open tables than the cache limit, but the extra tables will be closed eventually. Tables are closed according to last-used order.
A table is opened (again) for each concurrent access. This means that
if one has two threads running on the same table or access the table
twice in the same query (with AS
) the table needs to be opened twice.
The first open of any table takes two file descriptors, each following
use of the table takes only one file descriptor.
If MySQL notices that a table is a symbolic linked it will resolve the symlink and use the table it points to instead. This works on all system that supports the realpath() call (At least Linux and Solaris supports realpath()! On system that doesn't supports realpath() you should not use the symlink and the table at the same time! The tables will be inconsistent after any update to the tables.
MySQL doesn't support linking of databases by default. Things will work fine as long as you don't make a symbolic link between databases. The following shows a case that DOES NOT work:
db2->db1 db1/
If you really need this you have to change in mysys/mf_format.c:
if (!lstat(to,&stat_buff)) /* Check if it's a symbolic link */ if (S_ISLNK(stat_buff.st_mode) && realpath(to,buff)) to if (realpath(to,buff))
Each table is actually three files. If you have many files in a directory open, close and create will be slow. If you also do selects on many different tables there will be a little overhead because when the table cache is full, for every table that has to be opened another has to be closed. One can make the overhead smaller by making the table cache larger.
All locking in MySQL is deadlock free. This is managed by always requesting all needed locks at once at query start and always locking the tables in the same order.
The locking method MySQL uses for WRITE
lock works as follows:
If there is no locks on the table, put a write lock on it, else put the lock in the write lock queue.
The locking method MySQL uses for READ
locks works as follows:
If there is no write locks on the table, put a read lock on it else put the lock in the read lock queue.
When a lock is released first use give the lock to the threads in the write lock queue and after this to the threads in the read lock queue.
This means that if you have many updates on the same table, select statements will be waiting until there is no more updates.
To fix this in the case where you do many inserts and many selects on the same table you could insert rows in another table and once in a while update the other table with all records from the temporary table.
This can be done with the following code:
LOCK TABLES real_table WRITE, insert_table WRITE insert into real_table select * from insert_table delete from insert_table UNLOCK TABLES
One could also change the locking code in mysys/thr_lock.c to use only one queue. In this case write locks would have the same priority that read locks and this could help some applications.
NOT NULL
if possible. It makes everything faster and you save one
bit per column.
MEDIUMINT
is often better than INT
.
VARCHAR
columns, a fixed size record format
will be used. This is much faster but may unfortunately waste some
space. See section 10.12 What are the different row formats? Or when to use VARCHAR/CHAR?.
isamchk --analyze
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 index on
average. Of course, this is always 1 for unique indexes.
isamchk --sort-index --sort-records=1
(if you want to sort on index 1). If you have a unique index from which
you want to read all records in numeric order, this is a good way to
make that faster.
LOAD DATA FROM INFILE
. This is
usually 20 times faster than using a lot of INSERT
s. If the text file
isn't on the server, rcp it to the server first. See section 7.14 LOAD DATA INFILE syntax.
You can even get more speed when loading data to tables with many indexes
by doing:
CREATE TABLE...
mysqladmin refresh
.
isamchk --keys-used=0 database/table_name
. This will remove all
usage of all indexes from the table.
LOAD DATA INFILE...
.
isamchk -r -q database/table_name
.
mysqladmin refresh
.
LOAD DATA FROM INFILE
and INSERT
is to enlarge the key buffer.
This can be done with the -O key_buffer=#
option to (safe)mysqld
.
For example 16M should be a good value if you have much RAM :)
SELECT ... INTO OUTFILE
. See section 7.14 LOAD DATA INFILE syntax.
LOCK TABLES
on the tables. ...FROM INFILE...
and
...INTO OUTFILE...
are atomic so you don't have to use
LOCK TABLES
when using these. See section 7.19 LOCK TABLES
syntax.
To check how you are doing, run isamchk -evi
on the .ISM
file. @c See section 12.2 The MySQL table check, optimise and repair program.
The time to insert a record consists of:
Where (number) is proportional time. This does not take into consideration the initial overhead to open tables (which is done once for each simultaneous running query).
The size of the table slows down the insert of indexes by N log N (B-trees).
A way of speeding up inserts is to lock your table during the inserts.
LOCK TABLES a WRITE; INSERT INTO a VALUES (1,23) INSERT INTO a VALUES (2,34) INSERT INTO a VALUES (4,33) INSERT INTO a VALUES (8,26) INSERT INTO a VALUES (6,29) UNLOCK TABLES;
The main speed difference is that the index buffer is only flushed once to disk for all inserts. Normally there would be as many index buffer flushes as there are inserts.
Locking will also lower the total time of multi-connection test but the maximum wait time for some threads will go up.
For example:
thread 1 does 1000 inserts thread 2, 3, and 4 does 1 insert thread 5 does 1000 inserts
If you don't use locking, 2, 3 and 4 will finish before 1 and 5. If you use locking 2,3,4 may finish before 1 or 5 but probably not, but the total time should be about 40% faster.
As INSERT
s, UPDATE
s and DELETE
s are very fast in
MySQL, one will obtain better overall performance by adding locks
around everything that does more than about 5 inserts/updates in a row.
If one does very many inserts in a row one could do a UNLOCK
TABLES
followed by a LOCK TABLES
once in a while (about each
1000 rows) to give other threads access to the table. This would still
give a nice performance gain.
Of course LOAD DATA INFILE
is much faster still.
The delete time of a record is exactly proportional to the number of indexes. To increase the speed of deletes you can increase the size of the index cache. The default index cache is 1M and to get faster deletes it should be increased by several factors (try 16M if you have enough memory).
mysqld
with the right options. More memory gives more speed
if you have it. See section 10.1 How does one change the size of MySQL buffers?.
SELECT
s faster. See section 10.4 How does MySQL use indexes?
NOT NULL
on all columns.
See section 10.8 How should I arrange my table to be as fast/small as possible?
--skip-locking
disables file locking between SQL requests. This gives a greater speed
but has the following consequences:
mysqladmin refresh
before
one tries to check/repair tables with isamchk
. (isamchk -d
table_name
is always allowed).
--skip-locking
is on by default when compiling with MIT threads.
This is because flock() isn't fully supported by MIT threads on all
platforms.
MySQL dosen't have true SQL VARCHAR() types.
MySQL has instead 3 different ways to store records and uses this to
emulate VARCHAR()
:
If one doesn't use any of the VARCHAR
, BLOB
or TEXT
column types a fixed row size is used, otherwise a dynamic row size is
used. CHAR()
and VARCHAR()
are treated identically from
the applications point of view; Both truncates end space from the column
when the column is accessed.
You can check the format used in a table with isamchk -d
.
MySQL has three different table formats:
VARCHAR
, TEXT
or BLOB
type in a table.
isamchk -r
from
time to time to get better performance.
Use isamchk -ei table_name
for some statistics.
isamchk
-ed
. All links may be removed with isamchk -r
.
MySQL can support different index types, but the normal one is NISAM. This is a B-tree index and one can roughly calculate the size for the index file as: sum over all keys:
(key_length+4)*0.67
(This is for the worst case when all keys are inserted in sorted order.
String index are space compressed and if the first index part is a string it will also be prefix compressed. This will usually make the index file smaller if the columns are not filled up to 100% or if there are many duplicates.
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.
As MySQL is multithreaded it may have many queries on the same table at once. To minimise 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 between all threads.
This should contain a technical description of the MySQL benchmark suite (and crash-me) but that description is not written yet. Currently see the code and results in the `bench' directory in the distribution. And of course on the web page.
It is meant to be a benchmark that will tell any user what things a given SQL implementation is good or bad at.
crash-me tries to find what a database supports by actually running queries. It find for example:
All MySQL clients that communicate with the server using the
mysqlclient
library use the following environment variables:
Name | Description |
MYSQL_UNIX_PORT | The default socket. Used with 'localhost'. |
MYSQL_TCP_PORT | The default TCP port. |
MYSQL_PWD | The default password. |
MYSQL_DEBUG | Debug-trace options when debugging. |
TMPDIR | Directory where temporary tables/files are created. |
mysql --help
.
mysql
mysql database < script.sql > output.tab
.
If you have a problem with that the memory in the client is not enough, use
the --quick
switch! This will force mysql to use
mysql_use_result()
instead of mysql_store_result()
to retrieve
the result set.
mysqlaccess
mysqladmin
mysqld
mysqldump
mysqlimport
LOAD DATA INFILE
. See section 7.14 LOAD DATA INFILE syntax
mysqlshow
mysqlbug
mysql_install_db
isamchk
make_binary_release
msql2mysql
mSQL
program to
MySQL. Doesn't handle all cases but gives a good start when
converting.
replace
replace a
b b a -- files
swaps a
and b
in the given files.
safe_mysqld
You can get all options for isamchk with isamchk --help
.
For information about how to use isamchk to repair a crashed table: See section 8.4 How to repair tables..
isamchk
doesn't use any more memory than you define with
the -O
options. The default is to use only about 2M to fix
things. By using bigger values you can get isamchk to operate faster.
Using -O sortbuffer=16M
should probably be enough for most cases.
But isamchk
uses temporary files in TMPDIR
. If
TMPDIR
points to a memory file system you may easily get out of
memory errors.
To get a description/statistics from a table use the methods below. We will explain some of the information in more detail later.
isamchk -d table_name
--skip-locking
isamchk
may report an error for a table that is updated while
isamchk runs, but there isn't any risk of destroying data.
isamchk -d -v table_name
isamchk -eis table_name
isamchk -eiv table_name
Example of isamchk -d
output:
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
Example of isamchk -d -v
output:
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 r 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
Example of isamchk -eis
output:
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
Example of isamchk -eiv
output:
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 are 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
Explanations for the things isamchk
prints:
ISAM file
Isam-version
Creation time
Recover time
Data records
Deleted blocks
Datafile: Parts
Data
records
.
Deleted data
Datafile pointer
Keyfile pointer
Max datafile length
.ISD
) get.
Max keyfile length
.ISM
) get.
Recordlength
Record format
Fixed
length
.
table description
Key
Start
Len
Index
unique
or multip.
. If one value can exist multiple times
in this index.
Type
C
data-type
with the options packed, stripped or empty.
Root
Blocksize
Rec/key
isamchk -a
. If this is not updated at all, a default
value of 30 is given.
Keyblocks used
Packed
CHAR
/VARCHAR
/DECIMAL
keys. For long strings like
names, this can significantly reduce the space used. In the above example
the 4th key is 10 characters long and gets a 60% reduction in space.
Max levels
Records
M.recordlength
Packed
Recordspace used
Empty space
Blocks/Record
isamchk
. See section 8.4 How to repair tables..
Recordblocks
Deleteblocks
Recorddata
Deleted data
Lost space
Linkdata
pack_isam
is an extra that you get when ordering more than 10
licenses or extended support. Since pack_isam
is distributed
binary only, pack_isam
is only available on some platforms.
Of course, all future updates to pack_isam
is included in the
price. pack_isam
may at some time be included as standard when
we get some kind of turnover for MySQL.
pack_isam
works by compressing each column in the table
separately. The information needed to decompress is read into memory
when the table is opened. This gives a much better performance when
accessing individual records as one only has to uncompress exactly one
record, not a much larger disk block like when using Stacker on MSDOS.
MySQL uses memory mapping (mmap) on compressed tables and falls back to normal read/write file usage if mmap doesn't work.
Usually, pack_isam
packs the datafile 40-70%.
There is currently two limitations with pack_isam
:
Fixing these limitations is on our TODO but with low priority.
pack_isam
options:
> pack_isam --help pack_isam Ver 5.0 for SOLARIS 2.5 on SPARCstation Copyright (C) 1994-1997 TcX AB & Monty Program KB & Detron HB. This is not free software. You must have a license to use this program This software comes with ABSOLUTELY NO WARRANTY Pack an ISAM-database to take much smaller space Keys are not updated, one must run isamchk -rq on datafile afterwards Usage: pack_isam [OPTIONS] -b, --backup Make a backup of the table as table_name.OLD -f, --force Force packing of table even if it's gets bigger or tempfile exists. -j, --join=# Join all given tables into table. All tables MUST be identical. -p, --packlength=# Force storage size of recordlength (1,2 or 3) -s, --silent Be more silent. -t, --test Don't pack table only test packing it -v, --verbose Write info about progress and packing result -w, --wait Wait and retry if table is in use -T, --tmp_dir=# Use temporary directory to store temporary table -#, --debug=... output debug log. Often this is 'd:t:o,filename` -?, --help display this help and exit -V, --version output version information and exit
Typical run:
(/my/monty/tmp) ls -l station.* -rw-rw-r-- 1 monty my 994128 Apr 17 19:00 station.ISD -rw-rw-r-- 1 monty my 53248 Apr 17 19:00 station.ISM -rw-rw-r-- 1 monty my 5767 Apr 17 19:00 station.frm (/my/monty/tmp) isamchk -dvv station ISAM file: station Isam-version: 2 Creation time: 1996-03-13 10:08:58 Recover time: 1997-02-02 3:06:43 Data records: 1192 Deleted blocks: 0 Datafile: Parts: 1192 Deleted data: 0 Datafilepointer (bytes): 2 Keyfile pointer (bytes): 2 Max datafile length: 54657023 Max keyfile length: 33554431 Recordlength: 834 Record format: Fixed length table description: Key Start Len Index Type Root Blocksize Rec/key 1 2 4 unique unsigned long 1024 1024 1 2 32 30 multip. text 10240 1024 1 column Start Length Type 1 1 1 2 2 4 3 6 4 4 10 1 5 11 20 6 31 1 7 32 30 8 62 35 9 97 35 10 132 35 11 167 4 12 171 16 13 187 35 14 222 4 15 226 16 16 242 20 17 262 20 18 282 20 19 302 30 20 332 4 21 336 4 22 340 1 23 341 8 24 349 8 25 357 8 26 365 2 27 367 2 28 369 4 29 373 4 30 377 1 31 378 2 32 380 8 33 388 4 34 392 4 35 396 4 36 400 4 37 404 1 38 405 4 39 409 4 40 413 4 41 417 4 42 421 4 43 425 4 44 429 20 45 449 30 46 479 1 47 480 1 48 481 79 49 560 79 50 639 79 51 718 79 52 797 8 53 805 1 54 806 1 55 807 20 56 827 4 57 831 4 Compressing station.ISD: (1192 records) - Calculating statistics normal: 20 empty-space: 16 empty-zero: 12 empty-fill: 11 pre-space: 0 end-space: 12 intervall-fields: 5 zero: 7 Original trees: 57 After join: 17 - Compressing file 87.14% (/my/monty/tmp) ls -l station.* -rw-rw-r-- 1 monty my 127874 Apr 17 19:00 station.ISD -rw-rw-r-- 1 monty my 55296 Apr 17 19:04 station.ISM -rw-rw-r-- 1 monty my 5767 Apr 17 19:00 station.frm (my/monty/tmp) isamchk -dvv station ISAM file: station Isam-version: 2 Creation time: 1996-03-13 10:08:58 Recover time: 1997-04-17 19:04:26 Data records: 1192 Deleted blocks: 0 Datafile: Parts: 1192 Deleted data: 0 Datafilepointer (bytes): 3 Keyfile pointer (bytes): 1 Max datafile length: 16777215 Max keyfile length: 131071 Recordlength: 834 Record format: Compressed table description: Key Start Len Index Type Root Blocksize Rec/key 1 2 4 unique unsigned long 10240 1024 1 2 32 30 multip. text 54272 1024 1 Field Start Length Type Huff tree Bits 1 1 1 constant 1 0 2 2 4 zerofill(1) 2 9 3 6 4 no zeros, zerofill(1) 2 9 4 10 1 3 9 5 11 20 table-lockup 4 0 6 31 1 3 9 7 32 30 no endspace, not_always 5 9 8 62 35 no endspace, not_always, no empty 6 9 9 97 35 no empty 7 9 10 132 35 no endspace, not_always, no empty 6 9 11 167 4 zerofill(1) 2 9 12 171 16 no endspace, not_always, no empty 5 9 13 187 35 no endspace, not_always, no empty 6 9 14 222 4 zerofill(1) 2 9 15 226 16 no endspace, not_always, no empty 5 9 16 242 20 no endspace, not_always 8 9 17 262 20 no endspace, no empty 8 9 18 282 20 no endspace, no empty 5 9 19 302 30 no endspace, no empty 6 9 20 332 4 allways zero 2 9 21 336 4 allways zero 2 9 22 340 1 3 9 23 341 8 table-lockup 9 0 24 349 8 table-lockup 10 0 25 357 8 allways zero 2 9 26 365 2 2 9 27 367 2 no zeros, zerofill(1) 2 9 28 369 4 no zeros, zerofill(1) 2 9 29 373 4 table-lockup 11 0 30 377 1 3 9 31 378 2 no zeros, zerofill(1) 2 9 32 380 8 no zeros 2 9 33 388 4 allways zero 2 9 34 392 4 table-lockup 12 0 35 396 4 no zeros, zerofill(1) 13 9 36 400 4 no zeros, zerofill(1) 2 9 37 404 1 2 9 38 405 4 no zeros 2 9 39 409 4 allways zero 2 9 40 413 4 no zeros 2 9 41 417 4 allways zero 2 9 42 421 4 no zeros 2 9 43 425 4 allways zero 2 9 44 429 20 no empty 3 9 45 449 30 no empty 3 9 46 479 1 14 4 47 480 1 14 4 48 481 79 no endspace, no empty 15 9 49 560 79 no empty 2 9 50 639 79 no empty 2 9 51 718 79 no endspace 16 9 52 797 8 no empty 2 9 53 805 1 17 1 54 806 1 3 9 55 807 20 no empty 3 9 56 827 4 no zeros, zerofill(2) 2 9 57 831 4 no zeros, zerofill(1) 2 9
You have two ways to add new functions to mysql:
To add a new native MySQL function (like SOUNDEX()
), you only
have to do the following:
sql_lex.cc
defining the function name in the
sql_functions
array.
sql_yacc.y
. On defines the preprocessor symbol
yacc can define (this should be added at the beginning of the
file). Then define the function parameters and create an 'item' with
these parameters. Check, for example, all occurrences of SOUNDEX in
sql_yacc.y
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.
void
Item_func_newname::fix_length_and_dec()
This should at least calcutate
max_length
based on the given arguments. max_length
is the
maximum number of chars the function may return. If the function can't
return a NULL
, one should set maybe_null = 0
.
About string functions:
String *str
argument provides a string
buffer that may be used to hold the result.
MySQL ODBC is a 32 bit ODBC (2.50) level 0 driver for Windows95 and NT. We hope somebody will port it to Windows 3.x.
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 add 4 to the 'Options' argument on the MyODBC connect/configure screen.
The log will be written to file `c:\tmp\myodbc.log'.
Most programs should work with MyODBC, but we we have tested these ourselves or got a confirmation from some user that is works:
SELECT concat(sunrise_time), concat(sunset_time) FROM sunrise_sunset;Values returned in this format (string) should be correctly recognised by Excel97 as time values. What
concat()
does in this case is that it fools ODBC to think
the column is of 'string type'. Without the 'concat()' ODBC knows the
column is of time type. Excel does not understand that.
Note that this is a bug in Excel because it automaticly converts a
string to a time. This would be great if the source was a text file, but
this is plain stupid when the source is a ODBC connection which reports
exact types for each column.
There are three possibilities for specifying the server name on Windows95:
ip hostname
For example:
194.216.84.21 my
Example of how to fill in the 'ODBC setup'.
Windows DNS name: test Description: This is my test database MySql Database: test Server: 194.216.84.21 User: monty Password: my_password Port:
The 'Windows DNS name' is any name that is unique in your windows ODBC setup.
When you fill in the values in the ODBC setup, these will be used as default values when prompting for a Driver connect. You don't have to give 'server', 'user' or 'password' in the ODBC setup screen.
When connecting to an ODBC source you have the option to change the server, user, password and port.
If port is not given the default port (3306) is used.
A common problem is how to get the value of an automatically-generated id
from an INSERT
. With ODBC you can do something like this:
INSERT INTO foo (auto,text) VALUES(NULL,'text') select LAST_INSERT_ID()
or if you are just going to insert in into another table:
INSERT INTO foo (auto,text) VALUES(NULL,'text') INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text')
MySQL server has gone away
error.
The most common reason for the MySQL server has gone away
error
is that the server closed the connection because of a timeout. By
default the server closes the connection after 8 hours if nothing has
happened.
If you have a script you just have to issue the query again for the client to do a automaticly reconnection.
One normally can get these error codes in this case: (Which one you get is OS dependent)
CR_SERVER_GONE_ERROR | The client couldn't send a question to the server. |
CR_SERVER_LOST | The client didn't get an error when writing to the server but it didn't get full answer (or any answer) to the question. |
-O max_query_size=#
(default 65536). The extra memory is allocated by demand, so mysqld will
only use more memory when you issue a big query or when mysqld must
return a big result row!
Can't connect to local MySQL server
error.A MySQL client can connect to the mysqld server in two different ways: Unix sockets, which connects trough a file in the file system, (default `/tmp/mysqld.sock'), or TCP/IP which connects trough a port number. Unix sockets are faster than TCP/IP but can only be used when connection to a server on the same computer. Unix sockets are used if one doesn't specify a hostname or if one specifies the special hostname 'localhost'.
Here follows some reasons to the error
Can't connect to local MySQL server
.
ps
.
You can check the server by trying these different connections: (the port and
socket may of course be different in your setup).
mysqladmin version mysqladmin -h `hostname` version mysqladmin -h `hostname` --port=3306 version mysqladmin --socket=/tmp/mysql.sock version
'mysqladmin -u `hostname` version
to check the
connection to the server.
mysqladmin version
and
check that the socket mysqladmin is trying to use really exists.
The fix in this case is to change the cron job not to remove mysqld.sock
or to place the socket somewhere else. You can move the socket by reconfiguring
mysqld with ./configure --with-unix-socket-path=/my-own-place/mysql.sock
or starting safe_mysqld with --socket=/my_own_place/mysqld.sock
and
setting the environment variable MYSQL_UNIX_PORT
to point at the socket
before starting your mysql clients.
--socket=...
.
If you change the socket you must also notify the clients about the new
path. You can do this by setting the environment variable
MYSQL_UNIX_PORT
to point at the socket or provide the socket as a
argument to the mysql clients. You can for example test the socket with
mysqladmin --socket=/path-to-socket version
.
If you do a query and get something like the following error:
mysql: Out of memory at line 42, 'malloc.c' mysql: neaded 8136 byte (8k), memory in use: 12481367 bytes (12189k)) ERROR 2008: MySQL client got out of memory
Note that the error refers to the MySQL client. The reason for this error is simply that the client does not have enough memory to store the whole result.
When the client gets a block bigger that net_buffer_length
it
issues a Packet too large
error.
If the mysql
client is used you may set a bigger buffer by
starting the client with mysql --set-variable=
net_buffer_length=1m
.
This error occurs when an in-memory temporary table gets bigger than
tmp_table_size
. To avoid this problem one can increase the
-O tmp_table_size=#
option to mysqld or use the SQL option
SQL_BIG_TABLES
before you do the problem query. See section 7.20 SET OPTION syntax..
One can also start mysqld with the option: --big-tables
.
This is exactly the same as using SQL_BIG_TABLES for all queries.
If you get Commands out of sync; You can't run this command now
in you client code you are calling clients functions in the wrong order!
This can for example happen if you are using 'mysql_use_result()' and try to execute a new query before you have done a 'mysql_free_result()'. This can also happen if you try to execute two queries, that returns data, without a mysql_use_result() or mysql_store_result() between.
On a disk full condition MySQL does the following:
mysqladmin kill
to the thread.
The thread will be aborted when it checks the disk next time (in 1 minute).
Access denied?
error.
See section 6.2 How does the privilege system work?. And especially See section 6.7 Why do I get this Access denied?
error..
mysqld (the MySQL server) can run as any user. In order to change mysqld to run as user USER, you'd have to the following:
shell> chown -R USER /your/path/to/mysql/var
You don't have to do anything to safe_mysqld to not run as root.
At this point, your mysqld process should be running fine and dandy as user 'USER'. One thing hasn't changed though - the access permissions. By default (right after running the permissions table install script), only user 'root' has access permission to the database. Unless you have changed that, it's still true. This shouldn't stop you from accessing MySQL when you're logged in under a user other than root, just specify -u root to the client program. Note that accessing MySQL as root, by supplying -u root in the command line, doesn't have ANYTHING to do with MySQL running as root, as a user or as anyone else. The access permissions and userbase of MySQL are completely separate from the UNIX users. The only connection to the UNIX users is if you don't use the -u option to clients. In this case the client will try to login into MySQL with your UNIX login name. If your UNIX box itself isn't secured, you should probably at least put a password on the root users in the MySQL access tables, since any johndoe user can run 'mysql -u root dbname' and do whatever he likes.
If you have problems with file permissions, for example when creating a table mysql gives: "ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)", then you might have the wrong value for environment variable UMASK. Default umask is 0664. Fix:
UMASK=432 export UMASK ./bin/safe_mysqld
If you get ERROR '...' not found (Errcode 23)
or any other error
with errcode 23
from MySQL this means that you haven't
allocated enough file descriptors for MySQL.
perror #
will give you the error message in a more readable form.
There is a commented line ulimit -n 256
in `safe_mysqld'. You
can remove this comment and of course increase or decrease the value if
you want. You can also make the table cache smaller with:
safe_mysqld -O table_cache=32
(the default is 64).
The format of DATE is 'YYYY-MM-DD'. According to ANSI SQL nothing else is
allowed. One should use this format to update or in the WHERE clause,
ie select * from table_1 where date >= '1997-05-05'
;
As a convenience, MySQL automatically converts the date to a
number if used in a number context. It is also smart enough to allow a
'relaxed' string form when updating and in a WHERE
with a compare
to a TIMESTAMP
, DATE
or a DATETIME
column.
The special date '0000-00-00' can be stored and retrieved as 0000-00-00. When using a '0000-00-00' date trough MyODBC it will automaticly be converted to NULL in MyODBC 2.50.12 and above, because ODBC can't handle this kind of dates.
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 ('97-05-05'); insert into table_1 (idate) values ('1997.05.05'); insert into table_1 (idate) values ('1997 05 05'); insert into table_1 (idate) values ('0000-00-00'); 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; select idate from table_1 where idate >= '19970505';
The following will not work:
select idate from table_1 where strcmp(idate,'19970505')=0; Because '19970505' is compared as a string to '1997-05-05'.
Note that MySQL does no checking if the date is correct. If you store a wrong date, like 1998-2-31, the wrong date will be stored. If the date is totally impossible a 0 is stored in the date field.. This is mainly a speed issue and we think it's up to the application to check the dates and not the server.
By default a MySQL column is case insensitive (although there are
some character sets that never are case insensitive). That means that if you
search with column like 'a%';
you will get all columns that start
with A
or a
. If you want to make this search case
sensitive use something like INDEX(column, "A")=0
to check a
prefix. Or STRCMP(column, "A") = 0
if the whole string should be
the same.
Simple compare operations >=, >, = , < , <=
, sorting and
grouping are done on the characters 'sort value'. Characters with
the same sort value (like E, e and й) are treated as the same character!
LIKE comparing is done on the uppercase value of each character (E == e but E <> й)
If you want column
to always be treated in a case sensitive manner,
declare it as BINARY
. See section 7.6 CREATE TABLE syntax..
If you are using Chinese data in the so-called big5 encoding you want to
make all character columns BINARY
. This works because the sorting
order of big5 encoding characters is based on the order of ascii codes.
A common confusion for newcomers to SQL is that they think that NULL is the same things as a empty string ". This is not the case! For example the following statements are compleatly different:
INSERT INTO my_table (name,phone) values ("my",NULL); INSERT INTO my_table (name,phone) values ("my","");
The first inserts a NULL value into address and the second inserts an empty string into address. The first can be regarded as 'phone number is not known' and the second can be regarded as 'she has no phone'.
In SQL NULL is a value that is always false when comparing to all other values, even NULL. An expression that contains NULL will always produce a NULL value if nothing else is mentioned. All following columns return NULL:
SELECT NULL,1+NULL,CONCAT('Invisible',NULL);
If you want to search for a column that has NULL, you must use the IS NULL test. The following shows how to find the NULL phone number and the empty phone number:
SELECT * from my_table where phone IS NULL; SELECT * from my_table where phone = "";
In MySQL, as in many other SQL servers, you can't index
columns that can have NULL
values. You have to declare such columns
NOT NULL
.
When reading data with LOAD DATA INFILE
empty columns are updated
with ". If you want a NULL value in a column you should use NULL or \N in
the textfile.
When using ORDER BY
NULL values are presented first (if not using DESC).
When using GROUP BY
all NULL values are regarded as equal.
To help with NULL handling you can use the functions: IS NULL
,
IS NOT NULL
and IFNULL()
The most general way to do database replication is using the update
log. See section 9.2 The Update log. This requires that one database acts as a master
(all data changes are done here) and one or more others as slaves. To
update a slave just run mysql < update_log
.
If you never do deletes, you can use timestamps.
It is possible to make a two-way updating system using both the update log (for deletes) and timestamps (on both sides). But in that case you must be able to handle confilicts when the same data has been changed in both ends. You probably want to keep the old version to help with deciding what has been updated.
Because replication in this case is done with SQL statements, you should not use the following functions in statements that updates the database, because they may return a different value in the other MySQL server:
All time functions are safe to use as the timestamp is sent to the mirror if needed. LAST_INSERT_ID() is also safe to use.
Since MySQL tables are stored as files it is easy to do a
backup. To get a consistent backup, do a LOCK TABLES
on the
relevant tables. See section 7.19 LOCK TABLES
syntax. You only need a read lock so other
threads can continue to query the tables while making a copy of the files
in the database directory. Or if you want to make a SQL level backup you
can use SELECT INTO OUTFILE
.
Another way is to use the mysqldump
program.
mysqldump --tab=some-dir
--lock-tables --quick
or simply by copying all table files (.frm, .ISM
and .ISD) while the server isn't updating anything.
mysqld
with --log-update
When you have to restore something (if isamchk -r
can't restore
all data as it can in 99.9% of all cases):
The ls in the last command is done to get all log files in the right order
You can also do selective backups with select * into outfile from
table
and restore with LOAD DATA FROM INFILE 'file_name' REPLACE
...
. To avoid duplicate records you need a PRIMARY KEY
in the
table. The REPLACE
means that if there is a 'duplicate index'
conflict when inserting new records the old record will be replaced with
the new one.
The C
API is distributed with MySQL. It is included in
the libmysqlclinet
library. It allows C
programs to access
a database.
Most of the other client APIs (all except Java) use this library to connect. So for example you can use the same environment variables.
The client has a maximum communication buffer size. This is automatically increased up to the maximum size (the default for this is 512Kb). As buffers are increased (but not decreased until close) on demand, it will not take any resources if one increases this. This size check is mostly a check for erroneous queries and communication packets.
The communication buffer must be big enough to contain a single SQL statement and one row of returned data (but of course not at the same time). Each thread's communication buffer is dynamically enlarged to handle any row or query up to the imposed limit.
So if you have BLOB
s that contains data up to 16M you must have
at least 16M as your communication buffer limit. See section 10.1 How does one change the size of MySQL buffers?.
MySQL shrinks each communication buffer to net_buffer_length
after each query.
mysql_affected_rows | Retrieves the number of affected rows by the last UPDATE, DELETE or INSERT. |
mysql_close | Closes a server connection. |
mysql_connect | Establish a connection to a MySQL server. |
mysql_create_db | Create a database. |
mysql_data_seek | Seeks to an arbitrary row in a query result set. |
mysql_drop_db | Drop a database. |
mysql_eof | Determine if last row has been read. |
mysql_escape_string | Escape a string for a SQL statement. See section 7.1 Literals. How do you write strings and numbers? |
mysql_error | The error message from last MySQL function. |
mysql_fetch_field | Find out what type a table field is. |
mysql_fetch_lengths | Returns the length of all columns in a query result set. |
mysql_fetch_row | Fetch the 'next' row in the query result. |
mysql_field_seek | Put the column cursor on column number field. |
mysql_free_result | Free memory used to store a query result. |
mysql_get_client_info | Return version information for the current client library. |
mysql_get_host_info | Returns name of server host. |
mysql_get_proto_info | Get protocol version used by connection. |
mysql_get_server_info | Returns the version number of the server. |
mysql_insert_id | Returns ID generated for a AUTO_INCREMENT field. |
mysql_list_dbs | Return matching database names. |
mysql_list_fields | Return matching field names. |
mysql_list_processes | Get a list of the current server threads. |
mysql_list_tables | Return matching table names. |
mysql_num_fields | Return the number of columns in a result set. |
mysql_num_rows | Returns the number of rows in result set. |
mysql_query | Executes a SQL query. |
mysql_real_query | Executes a SQL query with length information. |
mysql_reload | Reload the user permissions table in the server. |
mysql_select_db | Connect to a database. |
mysql_shutdown | Shut down the database server. |
mysql_stat | Return server status in a string. |
mysql_store_result | Reads a result set to the client. |
mysql_use_result |
Initiate a dynamic result set for each row. This uses much less memory than
mysql_store_result() but will put more strain on the server.
|
int mysql_affected_rows(MYSQL *mysql)
void mysql_close(MYSQL *mysql)
MYSQL *mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd)
int mysql_create_db(MYSQL *mysql, const char *db)
void mysql_data_seek(MYSQL_RES *res, uint offset)
int mysql_drop_db(MYSQL *mysql, const char *db)
int mysql_eof(MYSQL_RES *)
char *mysql_error(MYSQL *mysql)
uint mysql_escape_string(char *to,char *from,uint length)
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *handle)
BLOB
without retreving a result,
MySQL returns the 'default blob length', which is 8192, when
doing a select on the table. When one retrevies a result,
column_object->max_length contains the real max_length for the specific
query.
The 8192 size is chosen because MySQL doesn't know the max length
for the BLOB
. This should be made configurable sometime.
unsigned int *mysql_fetch_lengths(MYSQL_RES *mysql)
MYSQL_ROW mysql_fetch_row(MYSQL_RES *mysql)
void mysql_field_seek(MYSQL_RES *result, int field)
void mysql_free_result(MYSQL_RES *result)
char *mysql_get_client_info(void)
char *mysql_get_host_info(MYSQL *mysql)
int mysql_get_proto_info(MYSQL *mysql)
char *mysql_get_server_info(MYSQL *mysql)
int mysql_insert_id(MYSQL *mysql)
MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild)
MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
MYSQL_RES *mysql_list_processes(MYSQL *mysql)
MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild)
int mysql_num_fields(MYSQL_RES *result)
int mysql_num_rows(MYSQL_RES *result)
int mysql_query(MYSQL *mysql, const char *query)
int mysql_real_query(MYSQL *mysql, const char *query, uint length)
int mysql_reload(MYSQL *mysql)
int mysql_select_db(MYSQL *mysql, const char *db)
int mysql_shutdown(MYSQL *mysql)
char *mysql_stat(MYSQL *mysql)
MYSQL_RES *mysql_store_result(MYSQL *mysql)
MYSQL_RES *mysql_use_result(MYSQL *mysql)
mysql_query()
returns success, mysql_store_result()
sometimes returns NULL?It means one of the following:
INSERT
or UPDATE
or DELETE
).
You can always check if the statement should have given a result by
checking that mysql_num_fields(MYSQL *)
isn't 0. If this is 0
the last query was a statement that does not return values. For example
a INSERT
or a DELETE
.
You have got an error if mysql_error(MYSQL *)
isn't empty!
mysql_affected_rows(MYSQL *)
returns the number of affected
rows in the last query when doing an INSERT
, UPDATE
or
DELETE
. Except, if DELETE
is used without a WHERE
clause
then the table is truncated which is much faster! In this case it
returns the number of records affected as zero.
mysql_insert_id(MYSQL *)
returns the given ID of the last
query when inserting a row into a table with an AUTO_INCREMENT
index.
See section 17.1.3 How can I get the unique ID for the last inserted row?
Some queries, LOAD DATA INFILE...
and INSERT INTO
... SELECT ...
, return additional info. The result is returned in
mysql_info(MYSQL *)
. mysql_info()
returns a null pointer
if there is no additional information.
If you insert a record that has a AUTO_INCREMENT
index then you
can get the given id with mysql_insert_id(MYSQL *)
.
The last value is also stored in the server and can be retrieved with
the LAST_INSERT_ID()
function.
You can check if an auto_increment index is used by the following
code. This also checks if the query was an INSERT
with an
auto_increment
index.
if (mysql_error(MYSQL)[0] == 0 && mysql_num_fields(MYSQL_RESULT) == 0 && mysql_insert_id(MYSQL) != 0) used_id = mysql_insert_id(MYSQL);
The id that LAST_INSERT_ID()
returns is maintained in the server
per connection. It will not be botched by another client. It will not
even be changed if you update another auto_increment column with a non
magic value (that is a not NULL or 0).
mysql_use_result()
and mysql_store_result()
modes?
mysql_use_results
reads the result directly from the server without
storing it in a temporary table or local buffer. This is somewhat faster
and uses much less memory than mysql_store_result
. One shouldn't use
mysql_use_results
if there is a lot of processing being done 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). Doing this would tie up the server
and then other threads couldn't update the used tables. One can't
use mysql_data_seek
mysql_num_rows
or issue other queries
while using mysql_use_result
.
When using mysql_use_result
one must execute mysql_fetch_row()
until one gets a NULL pointer back, because else the next query would
get results from the previous query. The C API will give the error:
Commands out of sync; You can't run this command now
, if
you forget to do this!
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.
The client is 'almost' thread-safe. The biggest problem is that net.c (the subroutines that read from sockets) are not interrupt safe. This was done with the thought that one may want to have one's own alarm that can break a long read to a server.
The standard client libraries are not compiled with the thread options.
To get a thread safe client use the -lmysys
, -lstring
and
-ldbug
libraries and net_serv.o
that the server uses.
When using a threaded client I think one can have great use of the thr_alarm.c routine. If you are using the mysys routines, the only thing one has to remember is to call my_init() first!
All functions except mysql_connect() are currently thread safe.
To get connect thread_safe you have to do the following:
Recompile the client with:
CPPFLAGS=-DTHREAD_SAFE_CLIENT ./configure ...
You may get some errors because of undefined symbols when linking the standard client as the pthread libraries are not included by default.
The resulting libmysqld.a library is now thread safe.
Two threads can't use the same handle (returned by
mysql_connect()
) at the same time, even if two threads can use
different MYSQL_RES
handles that were created with
mysql_store_result()
.
When using a threaded client one can have great use of the thr_alarm.c routine. If you are using the mysys routines, the only thing one has to remember is to call my_init() first!
Since DBI/DBD
now is the recommended perl interface mysqlperl is
not documented here.
DBI
with DBD::mysql
DBI
is a generic interface for many databases. That means that
you can write a script what works with many different database engines
without change. You need a DataBase Driver (DBD) defined for each
database type. For MySQL, this driver is called
DBD::mysql
.
For more information on the Perl5 DBI, please visit DBIs web page and read the documentation. For more information on Object Oriented Programming (OOP) as defined in Perl5, see the perl OOP page.
Portable DBI methods.
connect | Establish a connection to a database server |
prepare | Get a SQL statement ready for execution |
do | Prepares and executes a SQL statement |
disconnect | Disconnect from the database server |
quote | Quote strings/blobs to be inserted |
execute | Executes prepared statements |
fetchrow_array | fetch the next row as an array of fields. |
fetchrow_arrayref | fetch next row as a reference array of fields |
fetchrow_hashref | fetch next row as a reference to a hashtable |
fetchall_arrayref | Get all data as a array of arrays |
finish | finish a statment and let the system free resources |
rows | Returns the number of rows affected |
data_sources | Return an array of databases available on localhost |
ChopBlanks | Shall fetchrow trim spaces |
NUM_OF_PARAMS | Number of placeholders in the prepared statement |
NULLABLE | Which columns can be NULL |
insertid | The latest auto_increment value |
is_blob | Which column ar BLOBs |
is_key | Which columns are keys |
is_num | Which columns are numeric |
is_pri_key | Which columns are primary keys |
is_not_null | Which columns can NOT be NULL. See NULLABLE |
length | Maximum theoretically possible column sizes |
max_length | Maximum physical present column sizes |
NAME | Column names |
NUM_OF_FIELDS | Number of fields returned. |
table | Table names in returned set |
type | All coulumn types |
_CreateDB | Create a database |
_DropDB | Drop a database. THIS IS DANGEROUS |
connect
$data_source
value should begin with
DBI:driver_name:
.
Example connect methods with the DBD::mysql
driver:
$dbh = DBI->connect("DBI:mysql:$database", $user, $password); $dbh = DBI->connect("DBI:mysql:$database:$hostname", $user, $password); $dbh = DBI->connect("DBI:mysql:$database:$hostname:$port", $user, $password);If the username and/or password are undefined, then the DBI will use the values of the
DBI_USER
, DBI_PASS
environment variables
respectively. If you don't specify a hostname, then it will default to
"localhost"
. If you don't specify a port, then it defaults to the
default mysql port (3306).
prepare
($sth)
which invokes the execute
method. Example:
$sth = $dbh->prepare($statement) or die "Can't prepare $statement: $dbh->errstr\n";
do
$rc = $dbh->do($statement) or die "Can't execute $statement: $dbh- >errstr\n";
disconnect
$rc = $dbh->disconnect;
quote
$sql = $dbh->quote($string)
execute
fetch_*
methods below to retrieve the data. Example:
$rv = $sth->execute or die "can't execute the query: $sth->errstr;
fetchrow_array
while(@row = $sth->fetchrow_array) { print qw($row[0]\t$row[1]\t$row[2]\n); }
fetchrow_arrayref
while($row_ref = $sth->fetchrow_arrayref) { print qw($row_ref->[0]\t$row_ref->[1]\t$row_ref->[2]\n); }
fetchrow_hashref
while($hash_ref = $sth->fetchrow_hashref) { print qw($hash_ref->{firstname}\t$hash_ref->{lastname}\t\ $hash_ref- > title}\n); }
fetchall_arrayref
my $table = $sth->fetchall_arrayref or die "$sth->errstr\n"; my($i, $j); for $i ( 0 .. $#{$table} ) { for $j ( 0 .. $#{$table->[$i]} ) { print "$table->[$i][$j]\t"; } print "\n"; }
finish
$rc = $sth->finish;
rows
$rv = $sth->rows;
NULLABLE
$null_possible = $sth->{NULLABLE};
NUM_OF_FIELDS
$nr_of_fields = $sth->{NUM_OF_FIELDS};
data_sources
@dbs = DBI->data_sources("mysql");
ChopBlanks
$sth->{'ChopBlanks') =1;
insertid
$new_id = $sth->{insertid};
is_blob
$keys = $sth->{is_blob};
is_key
$keys = $sth->{is_key};
is_num
$nums = $sth->{is_num};
is_pri_key
$pri_keys = $sth->{is_pri_key};
is_not_null
$not_nulls = $sth->{is_not_null};
max_length
length
$max_lengts = $sth->{max_length}; $lengts = $sth->{length};
NAME
$names = $sth->{NAME};
table
$tables = $sth->{table};
You can use the perldoc command to get more information about DBI.
perldoc DBI perldoc DBI::FAQ perldoc mysql
You can also use the pod2man
, pod2html
, etc.. tools to
translate to other formats.
And of course you can find the latest DBI information at
the DBI web page
.
Insert pointers/descriptions of JDBC.
Insert pointers/descriptions for C++.
Insert pointers/descriptions for Python.
Insert pointers/descriptions for TCL.
mSQL
This section has been written by the MySQL developers so it should be read with that in mind. But there are NO factual errors that we know of.
For a list of all supported limits, functions and types see the
crash-me web page.
mSQL
can get patalogically slow if you chage the order of tables
in a select. In the benchmark suite a time more that 15000 times slower
than MySQL was seen.
Because of no thread creation overhead, small parser, few features and
simple security mSQL
should be quicker at:
CREATE TABLE
and DROP TABLE
.
SELECT
one something that isn't an index. (A table scan is very
easy)
mSQL
and
most other SQL implementions on the following:
mSQL
all other
connections have to wait until the first, doesn't matter whether the
query is long or short, is executed and finished. After that the next
connection can be served, while all the others wait again, etc.
ORDER BY
and GROUP BY
.
DISTINCT
.
TEXT
or BLOB
columns.
GROUP BY
& HAVING
MySQL supports a full GROUP BY
with both HAVING
and the following functions count()
, avg()
, min()
,
max()
, sum()
and std()
. min()
and
max()
may take string arguments. count(*)
is optimised to
return very quickly if this is the only thing in the query. mSQL
does not support GROUP BY
at all.
INSERT
& UPDATE
with calculations.
MySQL can do calculations in a INSERT
or UPDATE
.
UPDATE SET x=x*10+y WHERE x<20;
SELECT
with functions
MySQL has too many functions to list here. See section 7.3 Functions for use in SELECT
and WHERE
clauses.
mSQL2
only has 4 types (char,text,int,real) it is hard to
get small tables.
mSQL
stability so we can not say
anything about that.
mSQL
and is also cheaper than
mSQL
. Remember to at least consider paying for a license or email
support for whatever product you choose to use. If you sell a product
with MySQL you are of course required to get a license for
this.
mSQL
with some
added features.
mSQL
has one but we have too little experience with
it to compare.
mSQL
, it has a lot of catching up
to do. To get some perspective on this you can view the mSQL
HISTORY file for the last year and compare it with the News
section. See section D MySQL change history. It should be pretty obvious which one has
developed most rapidly.
mSQL
and MySQL have a lot of interesting third-party
tools. Since it is very easy to port upwars (mSQL
->
MySQL) MySQL has almost all interesting mSQL
applications.
MySQL comes with a simple msql2mysql program that fixes the different
spelling of the most used functions. A conversion of a client program
from mSQL
to mySQL usually takes a couple of minutes.
mSQL
tools like msql-tcl, msqljava?
According to our experience it would just take a few hours to convert a
tool using the mSQL
C API to the MySQL C API.
The procedure:
Differences between the MySQL and mSQL
C API's.
mSQL
uses an
int
).
mSQL
only returns a text error
mSQL
are the MySQL client/server communications protocols?There are enough differences that it is impossible (at least not easy) to support both.
The greatest differences between MySQL and mSQL
are:
mSQL
2.0?CREATE TABLE
MySQL
UNSIGNED
option for all integer columns.
ZEROFILL
option for all integer columns.
AUTO_INCREMENT
option for all integer columns that also is a
PRIMARY KEY
. See section 17.1.3 How can I get the unique ID for the last inserted row?.
DEFAULT
value for all columns.
ENUM
type for one of a set of strings.
SET
type for many of a set of string.
BIGINT
type for 64 bit integers.
mSQL2
mSQL type | Corresponding MySQL type. |
char(len) | char(len) |
text(len) | text(len). len is the maximal length. And LIKE works.
|
int | int. With many more options! |
real | real. Or float. Both 4 and 8 bytes versions are available. |
uint | Unsigned integer. |
date | date. Takes ANSI SQL format instead of mSQL s own.
|
time | time |
money | decimal(12,2). A fixed point value with two decimals. |
MySQL
CREATE TABLE
. Indexes can not be
removed without recreating the table. See section 7.7 ALTER TABLE syntax.
mSQL
CREATE INDEX
clause. Indexes may be removed with DROP INDEX
.
MySQL
AUTO_INCREMENT
as a column type
specifier. See section 17.1.3 How can I get the unique ID for the last inserted row?.
mSQL
SEQUENCE
on a table and select the _seq
column.
MySQL
PRIMARY KEY
to the table.
mSQL
_rowid
column. Observe that _rowid
may change
depending on many factors.
MySQL
TIMESTAMP
column to the table. This column will automaticly
be updated to the current time if you don't give the column a value or
if you give it a NULL value in a UPDATE
or INSERT
statement.
mSQL
_timestamp
column.
=NULL
to IS NULL
when porting old code from mSQL to MySQL.
BINARY
attribute.
MySQL
LIKE
is case insensitive or case sensitive depending on the used
columns. If possible MySQL uses indexes if the like argument
doesn't start with a wildcard.
mSQL
CLIKE
.
MySQL
CHAR
and VARCHAR
columns. Currently use a TEXT
column if this behavior is
undesired.
mSQL
WHERE
statement?
MySQL
mSQL
behaviour in MySQL, use
parenthesis: 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
MySQL
mSQL
For a list of all supported limits, functions and types see the crash-me web page.
PostgreSQL has some more advanced features like user-defined types, triggers, rules and transactions. But it lacks a lot of the standard types and functions from ANSI SQL and ODBC. See the crash-me web page for a complete list of supported/unsupported types/function.
Normally PostgreSQL is much slower than MySQL. See section 11 MySQL benchmark suite.
Send any additions to this list to webmaster@tcx.se.
Many users of MySQL has contributed very useful support tools and addons.
Here is a list of what is available at http://www.tcx.se/Contrib (Or any mirror). The links below only works on the these pages.
Contributors to the MySQL distribution in somewhat random order:
mysqld
.
MISAM
library (A B-tree index file handler with index
compression and different record formats).
mSQL
tools like msqlperl, DBD/DBI and DB2mysql.
texi2html
. Also automatic website updating from
this manual.
Other contributors, bugfinders and testers: James H. Thompson, Maurizio Menghini, Wojciech Tryc, Luca Berra, Zarko Mocnik, Wim Bonis, Elmar Haneke, jehamby@lightside, psmith@BayNetworks.COM, duane@connect.com.au, "Ted Deppner <ted@psyber.com>, Mike Simons, Jaakko Hyvдtti.
And lots of bug report/patches from the folks on the mailing list.
And a big tribute to those that helps us answer question on the mysql@tcx.se mailing list.
REVERSE()
(by Zeev Suraski)
LEFT OUTER JOIN
.
LEFT
, NATURAL
,
USING
MYSQL_HOST
as the default host if it's defined.
SELECT column, SUM(expr)
now returns NULL
for column when
there are matching rows.
POWER()
, SPACE()
,
COT()
, DEGREES()
, RADIANS()
, ROUND(2 arg)
and TRUNCATE()
.
LOCATE()
parameters where
swapped according to ODBC standard. Fixed.
TIME_TO_SEC()
.
NOT NULL
fields.
UPDATE SET ...
if the timestamp was
used as.
BLOB
and TEXT
to
be compatible with mysqldump.
DATE '1997-01-01'
, TIME '12:10:10'
and
TIMESTAMP '1997-01-01 12:10:10'
formats required by ANSI SQL.
WARNING INCOMPATIBLE CHANGE!! This has the unfortunate
side-effect that one can't have columns named DATE
, TIME
or TIMESTAMP
anymore :( Old columns can only be accessed with
'tablename.columnname'!
REPLACE
, which works like INSERT
but
replaces conflicting records with the new record. REPLACE INTO
TABLE ... SELECT ...
works also.
CREATE DATABASE db_name
and DROP
DATABASE db_name
.
RENAME
option to ALTER TABLE
: ALTER TABLE name
RENAME AS new_name
.
net_write()
to my_net_write()
because of name
conflict with sybase.
DAYOFWEEK()
compatible with ODBC.
NULL
if the returned string should be longer than max_allowed_packet
.
INTERVAL
type to ENUM
, because
INTERVAL
is used in ANSI SQL.
TRIM()
function.
CURTIME()
.
ENCRYPT()
function by Zeev Suraski.
FOREIGN KEY
syntax skipping. New reserved words:
MATCH
, FULL
, PARTIAL
--bind-address
option.
NOT NULL
to be after the
DEFAULT
value as specified in the ANSI SQL standard. This will
make mysqldump with NOT NULL
and default values incompatible with
MySQL 3.20.
ALTER TABLE person ALTER COLUMN phone SET DEFAULT NULL
syntax.
TEXT
type. All
ODBC 2.5 functions is also supported (added REPAT). This gives better
portability.
TINYTEXT
, TEXT
, MIDDLETEXT
and
LONGTEXT
. These are actually blobs, but all searching is done
case independent.
BLOB
fields are now TEXT
fields. This only
changes that all searching on strings are case independent. One have to
do a ALTER TABLE and change the field to BLOB if one wants to have tests
done case dependent.
LOCK TABLES table_name [AS alias] (READ | WRITE), ...
mysqld --log-update
to get a log suitable for
incremental updates
FIELD_TYPE_TINY_BLOB
, FIELD_TYPE_MEDIUM_BLOB
,
FIELD_TYPE_LONG_BLOB
or FIELD_TYPE_VAR_STRING
(as
previously returned by mysql_list_fields). One should instead only use
FIELD_TYPE_BLOB
or FIELD_TYPE_STRING
. If one wants exact
types one should use the command SHOW FIELDS
.
0x######
which can be used as a string
(default) or a number.
FIELD_TYPE_CHAR
is renamed to FIELD_TYPE_TINY
.
DEFAULT
doesn't have to be NOT NULL
anymore.
INTERVAL
SET
Changes from 3.20.18 to 3.20.32b are not documented here since the the 3.21 release bransched here. And the relevant changes are also documented as changes to the 3.21 version.
max_allowed_packet
is now 65K for the server
and 512K for the client. This is mainly used to catch wrong packets that
could trash all memory. The server limit may be changed when it is
started.
ELT()
function is renamed to FIELD()
. The new
ELT()
function returns a value based on an index: FIELD()
is the invers of ELT()
Example: ELT(2,"A","B","C")
returns
"B"
. FIELD("B","A","B","C")
returns 2
;
LIKE
is always case insensitive.
SELECT id,lookup.text,sum(*) FROM test,lookup WHERE test.id=lookup.id group by id;
-lmysqlclient
. This is the only library that needs to be linked
with client applications. When using the binary releases one have to
link with -lmysql -lmysys -ldbug -lstrings
as before.
SELECT grp,COUNT(*) as c FROM table GROUP BY grp HAVING c > 1 instead of SELECT grp FROM table GROUP BY grp HAVING count(*) > 1
GROUP BY
or ORDER BY
or
DISTINCT
. Only the first max_sort_length
(default 1024)
are used when comparing blobs in these cases. This can be changed with
the -O max_sort_length
parameter to mysql. A workaround for most
cases is to use a substring: SELECT DISTINCT LEFT(blob,2048) FROM
table
.
bigint
or double
(both are
normally 64 bit long). It depends on the function which precision one
gets. The general rule is that bit functions are done with bigint
precision, IF, and ELT() with bigint or double precision and the rest
with double precision. One should try to avoid using bigger unsigned long
long values than 63 bits (9223372036854775807) for anything else than bit
fields!
SELECT * FROM table WHERE name = 'david '
For platform specific bugs see the sections about compiling and porting.
Everything in this list is in the order it will be done. If you want to affect the priority order, please register a licence or support us and tell us what you want to have done more quickly. See section 3 Licensing or When do I have/want to pay for MySQL?.
Time is given according to amount of work, not real time. TcX's main business is the use of MySQL not the development of it. But since TcX is a very flexible company and we have put a lot of resources into the development of MySQL.
LOCK
TABLES
/UNLOCK TABLES
but we will make this more automatic in the
future.
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 earlier versions are not good enough) and on Linux we use LinuxThreads by Xavier Leroy Xavier.Leroy@inria.fr.
The hard part of porting to a new UNIX variant without good native thread support is probably to port MIT threads. See `mit-pthreads/README' and Programming POSIX Threads.
The MySQL distribution includes a patched version of Provenzano's Pthreads from MIT (see MIT Pthreads web page). This can be used for some operating systems that does not have posix threads.
It is also possible to use another user level thread package named FSU Pthreads (see FSU pthread home page). This implementation is being used for the SCO port.
See the `thr_lock.c' and `thr_alarm.c' programs in the mysys directory for some tests/examples of these problems
Both the server and the client needs a working C++ compiler (we use gcc and have tried SparcWorks). Other compiler that is known to work is the IRIX cc.
To compile only the client use `./configure --without-server'
There currently no support for only compiling the server. Nor is it likly to be added unless someone has a good reason for it.
If you want/need to change any Makefile or the configure script you must get automake and autoconf. We have used autoconf-2.12 and automake-1.2.
All steps needed to remake everything from the most basic files.
/bin/rm */.deps/*.P /bin/rm -f config.cache aclocal autoheader aclocal automake autoconf ./configure --with-debug=yes --prefix='your installation directory' # The makefiles generated above needs GNU make (called gmake below) gmake clean all install init-db
If you have some very specific problem, you can always try to debug
MySQL. To do this you must configure MySQL with the option
--with-debug=yes
Start the mysql server with a trace log in /tmp/mysql.trace. The log file will get very BIG.
mysqld --debug
or you can start it with
mysqld --debug=d,info,error,query,general,where:O,/tmp/mysql.trace
which only prints information with the most interesting tags.
On most system (except Linux) you can also start mysqld in gdb
to get more information if mysqld crashes.
I have tried to use the RTS thread packages with MySQL but stumbled on the following problems:
They use old version of a lot of POSIX calls and it is very tedious to make wrappers for all functions. I am inclined to think that it would be easier to change the thread libraries to the newest POSIX specification.
Some wrappers are already written. Se mysys/my_pthread.c for more info.
At least the following should be changed:
pthread_get_specific should use on argument. sigwait should take two arguments. A lot of functions (at least pthread_cond_wait, pthread_cond_timedwait) should return the error code on error. Now they return -1 and set errno.
Another problem is that user level threads uses the ALRM signal and this aborts a lot of functions (read, write, open...). MySQL should do a retry on interrupt on all of these but it not that easy to verify it.
The biggest unsolved problem is the following:
To get thread_level alarms I changed mysys/thr_alarm.c to wait between alarms with pthread_cond_timedwait() but this aborts with error EINTR. I tried to debug the thread library why this happens but couldn't find any easy solution.
If someone wants to try MySQL with RTS threads I suggest the following:
Main thread: 1 Tread 0 (5) started Thread: 5 Waiting process_alarm Tread 1 (6) started Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Sleeped for 1 (1) sec Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Sleeped for 2 (2) sec Thread: 6 Simulation of no alarm needed Thread: 6 Sleeped for 0 (3) sec Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Sleeped for 4 (4) sec Thread: 6 Waiting process_alarm thread_alarm Thread: 5 Sleeped for 10 (10) sec Thread: 5 Waiting process_alarm process_alarm thread_alarm Thread: 6 Sleeped for 5 (5) sec Thread: 6 Waiting process_alarm process_alarm ... thread_alarm Thread: 5 Sleeped for 0 (1) sec end
MySQL is very dependent on the used thread package. So when choosing a good platform for MySQL the thread package is very important.
There are at least three types of thread packages.
In some systems kernel threads are managed by integrating user level threads in the system libraries. In such cases, the thread switching can only be done by the thread library and the kernel isn't really 'thread aware'.
Regular expressions are a powerful way of specifying complex searches.
MySQL uses regular Henry Spencers inplementation of regular expressions. And that is aimed to conform to POSIX 1003.2. MySQL uses the extended version.
To get more exact information see Henry Spencers regex.7 manual that is included in the source distribution. See section C Who has helped to make MySQL..
This is a simplistic reference that skips the details. From here on a regualr expressions is called a regexp.
A regular expression describes a set of strings. The simplest case is
one that has no special characters in it. For example the regexp
hello
matches hello
and nothing else.
Nontrivial regular expressions use certain special constructs so that
they can match more than one string. For example, the regexp
hello|word
matches either the string hello
or the string
word
.
And a more comples example regexp B[an]*s
matches any of the
strings Bananas
, Baaaaas
, Bs
and all other string
starting with a B
and continuing with any number of a
n
and ending with a s
.
The following special characters/constructs are known.
^
mysql> select "fo\nfo" regexp "^fo$"; -> 0 mysql> select "fofo" regexp "^fo"; -> 1
$
mysql> select "fo\no" regexp "^fo\no$"; -> 1 mysql> select "fo\no" regexp "^fo$"; -> 0
.
mysql> select "fofo" regexp "^f.*"; -> 1 mysql> select "fo\nfo" regexp "^f.*"; -> 1
a*
mysql> select "Ban" regexp "^Ba*n"; -> 1 mysql> select "Baaan" regexp "^Ba*n"; -> 1 mysql> select "Bn" regexp "^Ba*n"; -> 1
a+
mysql> select "Ban" regexp "^Ba+n"; -> 1 mysql> select "Bn" regexp "^Ba+n"; -> 0
a?
mysql> select "Bn" regexp "^Ba?n"; -> 1 mysql> select "Ban" regexp "^Ba?n"; -> 1 mysql> select "Baan" regexp "^Ba?n"; -> 0
de|abc
de
or abc
.
mysql> select "pi" regexp "pi|apa"; -> 1 mysql> select "axe" regexp "pi|apa"; -> 0 mysql> select "apa" regexp "pi|apa"; -> 1 mysql> select "apa" regexp "^(pi|apa)$"; -> 1 mysql> select "pi" regexp "^(pi|apa)$"; -> 1 mysql> select "pix" regexp "^(pi|apa)$"; -> 0
(abc)*
abc
.
mysql> select "pi" regexp "^(pi)+$"; -> 1 mysql> select "pip" regexp "^(pi)+$"; -> 0 mysql> select "pipi" regexp "^(pi)+$"; -> 1
{1}
{2,3}
a*
a{0,}
.
+
a{1,}
.
?
a{0,1}
.
i
and no comma matches a sequence of exactly i
matches of
the atom. An atom followed by a bound containing one integer i
and a comma matches a sequence of i
or more matches of the atom.
An atom followed by a bound containing two integers i
and
j
matches a sequence of i
through j
(inclusive)
matches of the atom.
Both arguments must 0 >= value <= RE_DUP_MAX (default 255)
, and
if there are two of them, the second must be bigger or equal to the
first.
[a-dX]
[^a-dX]
a
, b
,
c
, d
or X
. To include ]
it has to be written
first. To include -
it has to be written first or last. So
[0-9]
matches any decimal digit. All character that does not have
a defined mening inside a []
pair has no special meaning and
matches only itself.
mysql> select "aXbc" regexp "[a-dXYZ]"; -> 1 mysql> select "aXbc" regexp "^[a-dXYZ]$"; -> 0 mysql> select "aXbc" regexp "^[a-dXYZ]+$"; -> 1 mysql> select "aXbc" regexp "^[^a-dXYZ]+$"; -> 0 mysql> select "gheis" regexp "^[^a-dXYZ]+$"; -> 1 mysql> select "gheisa" regexp "^[^a-dXYZ]+$"; -> 0
[[.characters.]]
ch
collating element, then the RE [[.ch.]]*c
matches the first five
characters of chchcc
.
[=character-class=]
o
and (+)
are the members of an
equivalence class, then [[=o=]]
, [[=(+)=]]
, and
[o(+)]
are all synonymous. An equivalence class may not be an
endpoint of a range.
[:character_class:]
[:
and :]
stands for the list of all characters belonging
to that class. Standard character class names are:
alnum | digit | punct |
alpha | graph | space |
blank | lower | upper |
cntrl | xdigit |
mysql> select "justalnums" regexp "[[:alnum:]]+"; -> 1 mysql> select "!!" regexp "[[:alnum:]]+"; -> 0
mysql> select "a word a" regexp "[[:<:]]word[[:>:]]"; -> 1 mysql> select "a xword a" regexp "[[:<:]]word[[:>:]]"; -> 0
mysql> select "weeknights" regexp "^(wee|week)(knights|nights)$"; -> 1
Unireg is our tty interface builder, but it uses a low level connection to our NISAM (which is used by MySQL) and because of this it is very quick. It has existed since 1979 (on Unix in C since ~1986).
Unireg has the following components:
We update most of 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, HP/UX, 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 sources can be found in MySQL). Usually we compile the binary for the customer at their site.
All new development is concentrated to MySQL.
MySQL FREE PUBLIC LICENSE (Version 4, March 5, 1995)
Copyright (C) 1995, 1996 TcX AB & Monty Program KB & Detron HB Stockholm SWEDEN, Helsingfors FINLAND and Uppsala SWEDEN All rights reserved.
NOTE: This license is not the same as any of the GNU Licenses published by the Free Software Foundation. Its terms are substantially different from those of the GNU Licenses. If you are familiar with the GNU Licenses, please read this license with extra care.
This License applies to the computer program known as "MySQL". The "Program", below, refers to such program, and a "work based on the Program" means either the Program or any derivative work of the Program, as defined in the United States Copyright Act of 1976, such as a translation or a modification. The Program is a copyrighted work whose copyright is held by TcX Datakonsult AB and Monty Program KB and Detron HB.
This License does not apply when running "MySQL" on any Microsoft operating system. Microsoft operating systems include all versions of Microsoft Windows NT and Microsoft Windows.
BY MODIFYING OR DISTRIBUTING THE PROGRAM (OR ANY WORK BASED ON THE PROGRAM), YOU INDICATE YOUR ACCEPTANCE OF THIS LICENSE TO DO SO, AND ALL ITS TERMS AND CONDITIONS FOR COPYING, DISTRIBUTING OR MODIFYING THE PROGRAM OR WORKS BASED ON IT. NOTHING OTHER THAN THIS LICENSE GRANTS YOU PERMISSION TO MODIFY OR DISTRIBUTE THE PROGRAM OR ITS DERIVATIVE WORKS. THESE ACTIONS ARE PROHIBITED BY LAW. IF YOU DO NOT ACCEPT THESE TERMS AND CONDITIONS, DO NOT MODIFY OR DISTRIBUTE THE PROGRAM.
This document was generated on 10 May 1998 using the texi2html translator version 1.52 (extended by davida@detron.se).