分类: Mysql/postgreSQL
2008-05-11 18:49:59
本章讨论了使用MySQL编写SQL语句的下面元素时所使用的规则:
· 字符串和数字等文字值
· 识别符,例如表和列名
· 用户和系统变量
· 注释
· 保留字
该节描述了如何在MySQL中写文字值。包括字符串、数值、十六进制值、布尔值和NULL。本节还包括在MySQL中处理这些基本类型时会遇到的各种细微差别和“影印版”。
字符串指用单引号(‘'’)或双引号(‘"’)引起来的字符序列。例如:
'a string'
"another string"
如果SQL服务器模式启用了NSI_QUOTES,可以只用单引号引用字符串。用双引号引用的字符串被解释为一个识别符。
字符串可以有一个可选字符集引介词和COLLATE子句:
[_charset_name]'string' [COLLATE collation_name]
例如:
SELECT _latin1'string';
SELECT _latin1'string' COLLATE latin1_danish_ci;
关于这些字符串语法形式的详细信息,参见10.3.7节,“字符串文字字符集和校对”。
在字符串中,某些序列具有特殊含义。这些序列均用反斜线(‘\’)开始,即所谓的转义字符。MySQL识别下面的转义序列:
\0 |
ASCII 0(NUL)字符。 |
\' |
单引号(‘'’)。 |
\" |
双引号(‘"’)。 |
\b |
退格符。 |
\n |
换行符。 |
\r |
回车符。 |
\t |
tab字符。 |
\Z |
ASCII 26(控制(Ctrl)-Z)。该字符可以编码为‘\Z’,以允许你解决在Windows中ASCII 26代表文件结尾这一问题。(如果你试图使用mysql db_name < file_name,ASCII 26会带来问题)。 |
\\ |
反斜线(‘\’)字符。 |
\% |
‘%’字符。参见表后面的注解。 |
\_ |
‘_’字符。参见表后面的注解。 |
这些序列对大小写敏感。例如,‘\b’解释为退格,但‘\B’解释为‘B’。
‘\%’和‘\_’序列用于搜索可能会解释为通配符的模式匹配环境中的‘%’和‘_’文字实例。参见12.3.1节,“字符串比较函数”。请注意如果你在其它环境中使用‘\%’或‘\_’,它们返回字符串‘\%’和‘\_’,而不是‘%’和‘_’。
在其它转义序列中,反斜线被忽略。也就是说,转义字符解释为仿佛没有转义。
有几种方式可以在字符串中包括引号:
· 在字符串内用‘'’引用的‘'’可以写成‘''’。
· 在字符串内用‘"’引用的‘"’可以写成‘""’。
· 可以在引号前加转义字符(‘\’)。
· 在字符串内用‘"’引用的‘'’不需要特殊处理,不需要用双字符或转义。同样,在字符串内用‘'’引用的‘"’也不需要特殊处理。
下面的SELECT语句显示了引用和转义如何工作:
mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello';
+-------+---------+-----------+--------+--------+
| hello | "hello" | ""hello"" | hel'lo | 'hello |
+-------+---------+-----------+--------+--------+
mysql> SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello";
+-------+---------+-----------+--------+--------+
| hello | 'hello' | ''hello'' | hel"lo | "hello |
+-------+---------+-----------+--------+--------+
mysql> SELECT 'This\nIs\nFour\nLines';
+--------------------+
| This
Is
Four
Lines |
+--------------------+
mysql> SELECT 'disappearing\ backslash';
+------------------------+
| disappearing backslash |
+------------------------+
如果你想要在字符串列内插入二进制数据(例如BLOB),必须通过转义序列表示下面的字符:
NUL |
NUL字节(ASCII 0)。用‘\0’表示该字符(反斜线后面跟一个ASCII‘0’字符)。 |
\ |
反斜线(ASCII 92)。用‘\\’表示该字符。 |
' |
单引号(ASCII 39)。用‘\'’表示该字符。 |
" |
双引号(ASCII 34)。用‘\"’表示该字符。 |
当编写应用程序时,在包含这些特殊字符的字符串用于发送到MySQL服务器的SQL语句中的数据值之前,必须对它们正确进行转义。可以用两种方法来完成:
· 用转义特殊字符的函数处理字符串。例如,在C程序中,可以使用mysql_real_escape_string() C API函数来转义字符。参见25.2.3.52节,“mysql_real_escape_string()”。Perl DBI接口提供一个quote方法来将特殊字符转换为正确的转义序列。参见25.4节,“MySQL Perl API”。
· 显式转义特殊字符,许多MySQL API提供了占位符功能,允许你在查询字符串中插入特殊标记,然后当你发出查询时将数据值同它们绑定起来。在这种情况下,API关注转义值中的特殊字符。
整数用一系列阿拉伯数字表示。浮点数使用‘.’作为十进制间隔符。两种类型的数值均可以在前面加一个‘-’来表示负值。
合法整数的例子:
1221
0
-32
合法浮点数的例子:
294.42
-32032.6809e+10
148.00
整数可以用在浮点环境中;它被解释为与浮点数等效。
MySQL支持十六进制值。在数字上下文中,十六进制数如同整数(64位精度)。在字符串上下文,如同二进制字符串,每对十六进制数字被转换为一个字符:
mysql> SELECT x'4D7953514C';
-> 'MySQL'
mysql> SELECT 0xa+0;
-> 10
mysql> SELECT 0x5061756c;
-> 'Paul'
十六进制值的默认类型是字符串。如果想要确保该值作为数字处理,可以使用CAST(...AS UNSIGNED):
mysql> SELECT 0x41,CAST(0x41 AS UNSIGNED);
-> 'A',65
0x语法基于ODBC。十六进制字符串通常用于ODBC以便为BLOB列提供值。x’hexstring’语法基于标准SQL。
可以用HEX()函数将一个字符串或数字转换为十六进制格式的字符串:
mysql> SELECT HEX('cat');
-> '636174'
mysql> SELECT 0x636174;
-> 'cat'
常量TRUE等于1,常量FALSE等于0。常量名可以写成大写或小写。
mysql> SELECT TRUE,true,FALSE,false;
-> 1,1,0,0
可以使用b'value'符号写位字段值。value是一个用0和1写成的二进制值。
位字段符号可以方便指定分配给BIT列的值:
mysql> CREATE TABLE t (b BIT(8));
mysql> INSERT INTO t SET b = b'11111111';
mysql> INSERT INTO t SET b = b'1010';
+------+----------+----------+----------+
| b+0 | BIN(b+0) | OCT(b+0) | HEX(b+0) |
+------+----------+----------+----------+
| 255 | 11111111 | 377 | FF |
| 10 | 1010 | 12 | A |
+------+----------+----------+----------+
NULL值表示“没有数据”。NULL可以写成大写或小写。
请注意NULL值不同于数字类型的0或字符串类型的空字符串。参见A.5.3节,“与NULL值有关的问题”。
对于用LOAD DATA INFILE或SELECT ...INTO OUTFILE执行的文本文件导入或导出操作,NULL用序列\N表示。参见13.2.5节,“LOAD DATA INFILE语法”。
数据库、表、索引、列和别名是识别符。该节描述了在MySQL中识别符的允许的语法。
下面的表描述了每类识别符的最大长度和允许的字符。
识别符 |
最大长度(字节) |
允许的字符 |
数据库 |
64 |
目录名允许的任何字符,不包括‘/’、‘\’或者‘。’ |
表 |
64 |
文件名允许的任何字符,不包括‘/’、‘\’或者‘。’ |
列 |
64 |
所有字符 |
索引 |
64 |
所有字符 |
别名 |
255 |
所有字符 |
除了表内注明的限制,识别符不可以包含ASCII 0或值为255的字节。数据库、表和列名不应以空格结尾。在识别符中可以使用引号识别符,尽管应尽可能避免这样使用。
识别符用Unicode(UTF8)保存。在.frm文件中保存的表定义的识别符和在mysql数据库中的授权表保存的识别符也用Unicode(UTF8)保存。在MySQL 5.1中授权表(和其它表)的字符串列的大小等于字符个数;这说明(不象以前版本的MySQL)你可以在这些列保存的值中使用多字节字符而不需要降低字符个数。
识别符可以引起来也可以不引起来。如果识别符是一个保留字或包含特殊字符,无论何时使用,必须将它引起来。关于保留字的列表参见9.6节,“MySQL中保留字的处理”。特殊字符指那些当前字符集、‘_’和‘$’之外的文字数字字符集。
识别符的引用符是反勾号(‘`’):
mysql> SELECT * FROM `select` WHERE `select`.id > 100;
如果SQL服务器模式包括ANSI_QUOTES模式选项,还可以用双引号将识别符引起来:
mysql> CREATE TABLE "test" (col INT);
ERROR 1064: You have an error in your SQL syntax. (...)
mysql> SET sql_mode='ANSI_QUOTES';
mysql> CREATE TABLE "test" (col INT);
Query OK, 0 rows affected (0.00 sec)
如果你引用识别符,可以在识别符内包括识别符引用符。如果识别符内包括的字符与引用识别符的字符相同,则需要用双字符。下面的语句创建一个名为a`b包含列c"d的表:
mysql> CREATE TABLE `a``b` (`c"d` INT);
建议不要使用XeX模式的名,例如1e或2e2,因为类似1e+1的表达式比较模糊。根据上下文,它可以解释为表达式1e + 1或数字1e+1。
使用MD5产生表名时应仔细,因为它可能产生不合法的表名,如上所述。
MySQL允许使用由单个识别符或多个识别符组成的名字。多部分名各组件之间应以句点(‘.’)间隔开。多部分名的开头部分作为限定词,后面的识别符被解释。
在MySQL中可以引用下面形式的列:
列参考 |
含义 |
col_name |
列col_name,查询中使用的表包含有此名字的列。 |
tbl_name.col_name |
默认数据库中的表tbl_name的列col_name。 |
db_name.tbl_name.col_name |
数据库db_name中的表tbl_name的列col_name。 |
如果多部分名的组件需要引用,应分别将它们引起来而不要将整个名引起来。例如,`my-tables`.`my-column` 有效,而`my-tables.my-column`无效。
不需要在语句中为列指定tbl_name或db_name.tbl_name前缀,除非列会很模糊。假定表t1和t2各包含一个列c,你使用SELECT语句在t1和t2中搜索c。在这种情况下,c很模糊,因为它在语句中使用的表内不唯一。你必须用表名t1.c或t2.c限定它,表示指哪个表。同样,要想用同一语句搜索数据库db1中的表t和数据库db2中的表t,你必须将那些表中的列指为db1.t.col_name和db2.t.col_name。
限定名中句点后面的字必须为一个识别符,因此不需要将它引起来,即使是一个保留字。
语法.tbl_name表示当前数据库中的tbl_name。该语法与ODBC兼容,因为某些ODBC程序在表名前面加前缀‘.’字符。
在MySQL中,数据库对应数据目录中的目录。数据库中的每个表至少对应数据库目录中的一个文件(也可能是多个,取决于存储引擎)。因此,所使用操作系统的大小写敏感性决定了数据库名和表名的大小写敏感性。这说明在大多数Unix中数据库名和表名对大小写敏感,而在Windows中对大小写不敏感。一个显著的例外情况是Mac OS X,它基于Unix但使用默认文件系统类型(HFS+),对大小写不敏感。然而,Mac OS X也支持UFS卷,该卷对大小写敏感,就像Unix一样。参见1.8.4节,“MySQL对标准SQL的扩展”。
注释:尽管在某些平台中数据库名和表名对大小写不敏感,不应在同一查询中使用不同的大小写来引用给定的数据库或表。下面的查询不会工作,因为它同时引用了表my_tables和as MY_tables:
mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;
列、索引、存储子程序和触发器名在任何平台上对大小写不敏感,列的别名也不敏感。
默认情况,表别名在Unix中对大小写敏感,但在Windows或Mac OS X中对大小写不敏感。下面的查询在Unix中不会工作,因为它同时引用了别名a和A:
mysql> SELECT col_name FROM tbl_name AS a
-> WHERE a.col_name = 1 OR A.col_name = 2;
然而,该查询在Windows中是可以的。要想避免出现差别,最好采用一致的转换,例如总是用小写创建并引用数据库名和表名。在大多数移植和使用中建议使用该转换。
在MySQL中如何在硬盘上保存和使用表名和数据库名由lower_case_tables_name系统变量确定,可以在启动mysqld时设置。lower_case_tables_name可以采用下面的任一值:
值 |
含义 |
0 |
使用CREATE TABLE或CREATE DATABASE语句指定的大写和小写在硬盘上保存表名和数据库名。名称比较对大小写敏感。在Unix系统中的默认设置即如此。请注意如果在大小写不敏感的文件系统上用--lower-case-table-names=0强制设为0,并且使用不同的大小写访问MyISAM表名,会导致索引破坏。 |
1 |
表名在硬盘上以小写保存,名称比较对大小写敏感。MySQL将所有表名转换为小写以便存储和查找。该行为也适合数据库名和表的别名。该值为Windows和Mac OS X系统中的默认值。 |
2 |
表名和数据库名在硬盘上使用CREATE TABLE或CREATE DATABASE语句指定的大小写进行保存,但MySQL将它们转换为小写以便查找。名称比较对大小写敏感。注释:只在对大小写不敏感的文件系统上适用! InnoDB表名以小写保存,例如lower_case_tables_name=1。 |
在Windows和Mac OS X中,lower_case_tables_name的 默认值是1。
如果只在一个平台上使用MySQL,通常不需要更改lower_case_tables_name变量。然而,如果你想要在对大小写敏感不同的文件系统的平台之间转移表,会遇到困难。例如,在Unix中,my_tables和MY_tables是两个不同的表,但在Windows中,这两个表名相同。要想避免由于数据库或表名的大小写造成的数据转移问题,可使用两个选项:
· 在任何系统中可以使用lower_case_tables_name=1。使用该选项的不利之处是当使用SHOW TABLES或SHOW DATABASES时,看不出名字原来是用大写还是小写。
· 在Unix中使用lower_case_tables_name=0,在Windows中使用lower_case_tables_name=2。这样了可以保留数据库名和表名的大小写。不利之处是必须确保在Windows中查询总是用正确大小写引用数据库名和表名。如果将查询转移到Unix中,由于在Unix中大小写很重要,如果大小写不正确,它们不工作。
例外:如果你正使用InnoDB表,在任何平台上均应将lower_case_tables_name设置为1,以强制将名转换为小写。
请注意在Unix中将lower_case_tables_name设置为1之前,重启mysqld之前,必须先将旧的数据库名和表名转换为小写。