🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 第9章:语言结构 ** 目录** [ 9.1. 文字值](#)[ 9.1.1. 字符串](#)[ 9.1.2. 数值](#)[ 9.1.3. 十六进制值](#)[ 9.1.4. 布尔值](#)[ 9.1.5. 位字段值](#)[9.1.6. NULL值](#)[ 9.2. 数据库、表、索引、列和别名](#)[ 9.2.1. 识别符限制条件](#)[ 9.2.2. 识别符大小写敏感性](#)[ 9.3. 用户变量](#)[ 9.4. 系统变量](#)[ 9.4.1. 结构式系统变量](#)[ 9.5. 注释语法](#)[ 9.6. MySQL中保留字的处理](#) 本章讨论了使用MySQL编写SQL语句的下面元素时所使用的规则: ·         字符串和数字等文字值 ·         识别符,例如表和列名 ·         用户和系统变量 ·         注释 ·         保留字 ### 9.1. 文字值 [ 9.1.1. 字符串](#)[ 9.1.2. 数值](#)[ 9.1.3. 十六进制值](#)[ 9.1.4. 布尔值](#)[ 9.1.5. 位字段值](#)[9.1.6. NULL值](#) 该节描述了如何在MySQL中写文字值。包括字符串、数值、十六进制值、布尔值和NULL。本节还包括在MySQL中处理这些基本类型时会遇到的各种细微差别和“影印版”。 ### 9.1.1. 字符串 字符串指用单引号(‘'’)或双引号(‘"’)引起来的字符序列。例如: ~~~ '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节,“字符串文字字符集和校对”](# "10.3.7. Character String Literal Character Set and Collation")。 在字符串中,某些序列具有特殊含义。这些序列均用反斜线(‘\’)开始,即所谓的*转义字符*。MySQL识别下面的转义序列: <table border="1" cellpadding="0" id="table1"><tr><td> <p> <span>\0</span><span> </span></p></td> <td> <p><span>ASCII 0(</span><span>NUL</span><span>)</span>字符。</p></td> </tr><tr><td> <p> <span>\'</span><span> </span></p></td> <td> <p>单引号<span>(</span>‘<span>'</span>’<span>)</span>。</p></td> </tr><tr><td> <p> <span>\"</span><span> </span></p></td> <td> <p>双引号<span>(</span>‘<span>"</span>’<span>)</span>。</p></td> </tr><tr><td> <p> <span>\b</span><span> </span></p></td> <td> <p>退格符。</p></td> </tr><tr><td> <p> <span>\n</span><span> </span></p></td> <td> <p>换行符。</p></td> </tr><tr><td> <p> <span>\r</span><span> </span></p></td> <td> <p>回车符。</p></td> </tr><tr><td> <p> <span>\t</span><span> </span></p></td> <td> <p><span>tab</span>字符。</p></td> </tr><tr><td> <p> <span>\Z</span><span> </span></p></td> <td> <p><span>ASCII 26(</span>控制(<span>Ctrl</span>)<span>-Z)</span>。该字符可以编码为‘<span>\Z</span>’,以允许你解决在<span>Windows</span>中<span>ASCII 26</span>代表文件结尾这一问题。<span>(</span>如果你试图使用<span>mysql <i>db_name</i> &lt; <i>file_name</i></span>,<span>ASCII 26</span>会带来问题)<span>。</span></p></td> </tr><tr><td> <p> <span>\\</span><span> </span></p></td> <td> <p>反斜线<span>(</span>‘<span>\</span>’<span>)</span>字符。</p></td> </tr><tr><td> <p> <span>\%</span><span> </span></p></td> <td> <p>‘<span>%</span>’字符。参见表后面的注解。</p></td> </tr><tr><td> <p> <span>\_</span><span> </span></p></td> <td> <p>‘<span>_</span>’字符。参见表后面的注解。</p></td> </tr></table> 这些序列对大小写敏感。例如,‘\b’解释为退格,但‘\B’解释为‘B’。 ‘\%’和‘\_’序列用于搜索可能会解释为通配符的模式匹配环境中的‘%’和‘_’文字实例。参见[12.3.1节,“字符串比较函数”](# "12.3.1. String Comparison Functions")。请注意如果你在其它环境中使用‘\%’或‘\_’,它们返回字符串‘\%’和‘\_’,而不是‘%’和‘_’。 在其它转义序列中,反斜线被忽略。也就是说,转义字符解释为仿佛没有转义。 有几种方式可以在字符串中包括引号: ·         在字符串内用‘'’引用的‘'’可以写成‘''’。 ·         在字符串内用‘"’引用的‘"’可以写成‘""’。 ·         可以在引号前加转义字符(‘\’)。 ·         在字符串内用‘"’引用的‘'’不需要特殊处理,不需要用双字符或转义。同样,在字符串内用‘'’引用的‘"’也不需要特殊处理。 下面的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),必须通过转义序列表示下面的字符: <table border="1" cellpadding="0" id="table2"><tr><td> <p> <span>NUL</span></p></td> <td> <p> <span>NUL</span>字节<span>(ASCII 0)</span>。用‘<span><span>\0</span><span>’</span></span>表示该字符<span>(</span>反斜线后面跟一个<span>ASCII</span>‘<span>0</span>’字符<span>)</span>。</p></td> </tr><tr><td> <p> <span>\</span></p></td> <td> <p>反斜线<span>(ASCII 92)</span>。用‘<span>\\</span>’表示该字符。</p></td> </tr><tr><td> <p> <span>'</span></p></td> <td> <p>单引号<span>(ASCII 39)</span>。用‘<span>\'</span>’表示该字符。</p></td> </tr><tr><td> <p> <span>"</span></p></td> <td> <p>双引号<span>(ASCII 34)</span>。用‘<span>\"</span>’表示该字符。</p></td> </tr></table> 当编写应用程序时,在包含这些特殊字符的字符串用于发送到MySQL服务器的SQL语句中的数据值之前,必须对它们正确进行转义。可以用两种方法来完成: ·         用转义特殊字符的函数处理字符串。例如,在C程序中,可以使用mysql_real_escape_string() C API函数来转义字符。参见[25.2.3.52节,“mysql_real_escape_string()”](# "25.2.3.52. mysql_real_escape_string()")。Perl DBI接口提供一个quote方法来将特殊字符转换为正确的转义序列。参见[25.4节,“MySQL Perl API”](# "25.4. MySQL Perl API")。 ·         显式转义特殊字符,许多MySQL API提供了占位符功能,允许你在查询字符串中插入特殊标记,然后当你发出查询时将数据值同它们绑定起来。在这种情况下,API关注转义值中的特殊字符。 ### 9.1.2. 数值 整数用一系列阿拉伯数字表示。浮点数使用‘.’作为十进制间隔符。两种类型的数值均可以在前面加一个‘-’来表示负值。 合法整数的例子: ~~~ 1221 ~~~ ~~~ 0 ~~~ ~~~ -32 ~~~ 合法浮点数的例子: ~~~ 294.42 ~~~ ~~~ -32032.6809e+10 ~~~ ~~~ 148.00 ~~~ 整数可以用在浮点环境中;它被解释为与浮点数等效。 ### 9.1.3. 十六进制值 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' ~~~ ### 9.1.4. 布尔值 常量TRUE等于1,常量FALSE等于0。常量名可以写成大写或小写。 ~~~ mysql> SELECT TRUE,true,FALSE,false; ~~~ ~~~         -> 1,1,0,0 ~~~ ### 9.1.5. 位字段值 可以使用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        | ~~~ ~~~ +------+----------+----------+----------+ ~~~ ### 9.1.6. NULL值 NULL值表示“没有数据”。NULL可以写成大写或小写。 请注意NULL值不同于数字类型的0或字符串类型的空字符串。参见[A.5.3节,“与NULL值有关的问题``”](# "A.5.3. Problems with NULL Values")。 对于用LOAD DATA INFILE或SELECT ...INTO OUTFILE执行的文本文件导入或导出操作,NULL用序列\N表示。参见[13.2.5节,“LOAD DATA INFILE语法”](# "13.2.5. LOAD DATA INFILE Syntax")。 ### 9.2. 数据库、表、索引、列和别名 [ 9.2.1. 识别符限制条件](#)[ 9.2.2. 识别符大小写敏感性](#) 数据库、表、索引、列和别名是识别符。该节描述了在MySQL中识别符的允许的语法。 下面的表描述了每类识别符的最大长度和允许的字符。 <table border="1" cellpadding="0" id="table3"><tr><td> <p><strong><span>识别符</span></strong></p></td> <td> <p><strong><span>最大长度<span>(</span>字节<span>)</span></span></strong></p></td> <td> <p><strong><span>允许的字符</span></strong></p></td> </tr><tr><td> <p>数据库</p></td> <td> <p><span>64</span></p></td> <td> <p>目录名允许的任何字符,不包括‘<span style="font-size: 10.0pt; ">/</span>’、‘<span>\</span>’或者‘<span>。</span>’</p></td> </tr><tr><td> <p>表</p></td> <td> <p><span>64</span></p></td> <td> <p>文件名允许的任何字符,不包括‘<span style="font-size: 10.0pt; ">/</span>’、‘<span>\</span>’或者‘<span>。</span>’</p></td> </tr><tr><td> <p>列</p></td> <td> <p><span>64</span></p></td> <td> <p>所有字符</p></td> </tr><tr><td> <p>索引</p></td> <td> <p><span>64</span></p></td> <td> <p>所有字符</p></td> </tr><tr><td> <p>别名</p></td> <td> <p><span>255</span></p></td> <td> <p>所有字符</p></td> </tr></table> 除了表内注明的限制,识别符不可以包含ASCII 0或值为255的字节。数据库、表和列名不应以空格结尾。在识别符中可以使用引号识别符,尽管应尽可能避免这样使用。 识别符用Unicode(UTF8)保存。在.frm文件中保存的表定义的识别符和在mysql数据库中的授权表保存的识别符也用Unicode(UTF8)保存。在MySQL 5.1中授权表(和其它表)的字符串列的大小等于字符个数;这说明(不象以前版本的MySQL)你可以在这些列保存的值中使用多字节字符而不需要降低字符个数。 识别符可以引起来也可以不引起来。如果识别符是一个保留字或包含特殊字符,无论何时使用,*必须*将它引起来。关于保留字的列表参见[9.6节,“MySQL中保留字的处理”](# "9.6. Treatment of Reserved Words in 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) ~~~ 参见[5.3.2节,“SQL服务器模式”](# "5.3.2. The Server SQL Mode")。 *如果*你引用识别符**,可以在识别符内包括识别符引用符。如果识别符内包括的字符与引用识别符的字符相同,则需要用双字符。下面的语句创建一个名为a`b包含列c"d的表: ~~~ mysql> CREATE TABLE `a``b` (`c"d` INT); ~~~ 建议不要使用*X*e*X*模式的名,例如1e或2e2,因为类似1e+1的表达式比较模糊。根据上下文,它可以解释为表达式1e + 1或数字1e+1。 使用MD5产生表名时应仔细,因为它可能产生不合法的表名,如上所述。 ### 9.2.1. 识别符限制条件 MySQL允许使用由单个识别符或多个识别符组成的名字。多部分名各组件之间应以句点(‘.’)间隔开。多部分名的开头部分作为限定词,后面的识别符被解释。 在MySQL中可以引用下面形式的列: <table border="1" cellpadding="0" id="table4"><tr><td> <p><strong><span> 列参考</span></strong></p></td> <td> <p><strong><span>含义</span></strong></p></td> </tr><tr><td> <p><span><i> <span>col_name</span></i></span></p></td> <td> <p>列<span><i><span>col_name</span></i></span>,查询中使用的表包含有此名字的列。</p></td> </tr><tr><td> <p><span><i> <span> tbl_name.col_name</span></i></span></p></td> <td> <p>默认数据库中的表<span><i><span>tbl_name</span></i></span>的列<span><i><span>col_name</span></i></span>。</p></td> </tr><tr><td> <p><span><i> <span> db_name.tbl_name.col_name</span></i></span></p></td> <td> <p>数据库<span><i><span>db_name</span></i></span>中的表<span><i><span>tbl_name</span></i></span>的列<span><i><span>col_name</span></i></span>。</p></td> </tr></table>   如果多部分名的组件需要引用,应分别将它们引起来而不要将整个名引起来。例如,`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程序在表名前面加前缀‘.’字符。 ### 9.2.2. 识别符大小写敏感性 在MySQL中,数据库对应数据目录中的目录。数据库中的每个表至少对应数据库目录中的一个文件(也可能是多个,取决于存储引擎)。因此,所使用操作系统的大小写敏感性决定了数据库名和表名的大小写敏感性。这说明在大多数Unix中数据库名和表名对大小写敏感,而在Windows中对大小写不敏感。一个显著的例外情况是Mac OS X,它基于Unix但使用默认文件系统类型(HFS+),对大小写不敏感。然而,Mac OS X也支持UFS卷,该卷对大小写敏感,就像Unix一样。参见[1.8.4节,“MySQL对标准SQL的扩展”](# "1.8.4. MySQL Extensions to Standard 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可以采用下面的任一值: <table border="1" cellpadding="0" id="table5"><tr><td> <p><strong><span>值</span></strong></p></td> <td> <p><strong><span>含义</span></strong></p></td> </tr><tr><td> <p> <span>0</span></p></td> <td> <p>使用<span>CREATE TABLE</span>或<span>CREATE DATABASE</span>语句指定的大写和小写在硬盘上保存表名和数据库名。名称比较对大小写敏感。在<span>Unix</span>系统中的默认设置即如此。请注意如果在大小写不敏感的文件系统上用<span>--lower-case-table-names=0</span>强制设为<span>0</span>,并且使用不同的大小写访问<span>MyISAM</span>表名,会导致索引破坏。</p></td> </tr><tr><td> <p> <span>1</span></p></td> <td> <p>表名在硬盘上以小写保存,名称比较对大小写敏感。<span>MySQL</span>将所有表名转换为小写以便存储和查找。该行为也适合数据库名和表的别名。该值为<span>Windows</span>和<span>Mac OS X</span>系统中的默认值。</p></td> </tr><tr><td> <p> <span>2</span></p></td> <td> <p>表名和数据库名在硬盘上使用<span>CREATE TABLE</span>或<span>CREATE DATABASE</span>语句指定的大小写进行保存,但<span>MySQL</span>将它们转换为小写以便查找。名称比较对大小写敏感。<strong><span>注</span><span>释:</span></strong><em><span>只</span></em>在对大小写不敏感的文件系统上适用<span>! </span> <span>InnoDB</span>表名以小写保存,例如<span>lower_case_tables_name=1</span>。</p></td> </tr></table> 在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**之前,必须先将旧的数据库名和表名转换为小写。 ### 9.3. 用户变量 可以先在用户变量中保存值然后在以后引用它;这样可以将值从一个语句传递到另一个语句。*用户变量与连接有关*。也就是说,一个客户端定义的变量不能被其它客户端看到或使用。当客户端退出时,该客户端连接的所有变量将自动释放。 用户变量的形式为@*var_name*,其中变量名*var_name*可以由当前字符集的文字数字字符、‘.’、‘_’和‘$’组成。 默认字符集是cp1252 (Latin1)。可以用**mysqld**的--default-character-set选项更改字符集。参见[5.10.1节,“数据和排序用字符集”](# "5.10.1. The Character Set Used for Data and Sorting")。用户变量名对大小写不敏感。 设置用户变量的一个途径是执行SET语句: ~~~ SET @var_name = expr [, @var_name = expr] ... ~~~ 对于SET,可以使用=或:=作为分配符。分配给每个变量的*expr*可以为整数、实数、字符串或者NULL值。 也可以用语句代替SET来为用户变量分配一个值。在这种情况下,分配符必须为:=而不能用=,因为在非SET语句中=被视为一个比较 操作符: ~~~ mysql> SET @t1=0, @t2=0, @t3=0; ~~~ ~~~ mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3; ~~~ ~~~ +----------------------+------+------+------+ ~~~ ~~~ | @t1:=(@t2:=1)+@t3:=4 | @t1  | @t2  | @t3  | ~~~ ~~~ +----------------------+------+------+------+ ~~~ ~~~ |                    5 |    5 |    1 |    4 | ~~~ ~~~ +----------------------+------+------+------+ ~~~ 用户变量可以用于表达式中。目前不包括明显需要文字值的上下文中,例如SELECT语句的LIMIT子句,或者LOAD DATA语句的IGNORE number LINES子句。 如果使用没有初始化的变量,其值是NULL。 如果用户变量分配了一个字符串值,其字符集和校对规则与该字符串的相同。用户变量的可压缩性(coercibility)是隐含的。(即为表列值的相同的可压缩性(coercibility)。 **注释:**在SELECT语句中,表达式发送到客户端后才进行计算。这说明在HAVING、GROUP BY或者ORDER BY子句中,不能使用包含SELECT列表中所设的变量的表达式。例如,下面的语句不能按期望工作: ~~~ mysql> SELECT (@aa:=id) AS a,(@aa+3) AS b 从tbl_name HAVING b=5; ~~~ HAVING子句中引用了SELECT列表中的表达式的别名,使用@aa。不能按期望工作:@aa不包含当前行的值,而是前面所选的行的id值。 一般原则是不要在语句的一个部分为用户变量分配一个值而在同一语句的其它部分使用该变量。可能会得到期望的结果,但不能保证。 设置变量并在同一语句中使用它的另一个问题是变量的默认结果的类型取决于语句前面的变量类型。下面的例子说明了该点: ~~~ mysql> SET @a='test'; ~~~ ~~~ mysql> SELECT @a,(@a:=20) FROM tbl_name; ~~~ 对于该 SELECT语句,MySQL向客户端报告第1列是一个字符串,并且将@a的所有访问转换为字符串,即使@a在第2行中设置为一个数字。执行完SELECT语句后,@a被视为下一语句的一个数字。 要想避免这种问题,要么不在同一个语句中设置并使用相同的变量,要么在使用前将变量设置为0、0.0或者''以定义其类型。 未分配的变量有一个值NULL,类型为字符串。 ### 9.4. 系统变量 [ 9.4.1. 结构式系统变量](#) MySQL可以访问许多系统和连接变量。当服务器运行时许多变量可以动态更改。这样通常允许你修改服务器操作而不需要停止并重启服务器。 **mysqld**服务器维护两种变量。全局变量影响服务器整体操作。会话变量影响具体客户端连接的操作。 当服务器启动时,它将所有全局变量初始化为默认值。这些默认值可以在选项文件中或在命令行中指定的选项进行更改。服务器启动后,通过连接服务器并执行SET GLOBAL *var_name*语句,可以动态更改这些全局变量。要想更改全局变量,必须具有SUPER权限。 服务器还为每个连接的客户端维护一系列会话变量。在连接时使用相应全局变量的当前值对客户端的会话变量进行初始化。对于动态会话变量,客户端可以通过SET SESSION *var_name*语句更改它们。设置会话变量不需要特殊权限,但客户端只能更改自己的会话变量,而不能更改其它客户端的会话变量。 对于全局变量的更改可以被访问该全局变量的任何客户端看见。然而,它只影响更改后连接的客户的从该全局变量初始化的相应会话变量。不影响目前已经连接的客户端的会话变量(即使客户端执行SET GLOBAL语句也不影响)。 可以使用几种语法形式来设置或检索全局或会话变量。下面的例子使用了sort_buffer_sizeas作为示例变量名。 要想设置一个GLOBAL变量的值,使用下面的语法: ~~~ mysql> SET GLOBAL sort_buffer_size=value; ~~~ ~~~ mysql> SET @@global.sort_buffer_size=value; ~~~ 要想设置一个SESSION变量的值,使用下面的语法: ~~~ mysql> SET SESSION sort_buffer_size=value; ~~~ ~~~ mysql> SET @@session.sort_buffer_size=value; ~~~ ~~~ mysql> SET sort_buffer_size=value; ~~~ LOCAL是SESSION的同义词。 如果设置变量时不指定GLOBAL、SESSION或者LOCAL,默认使用SESSION。参见[13.5.3节,“SET语法”](# "13.5.3. SET Syntax")。 要想检索一个GLOBAL变量的值,使用下面的语法: ~~~ mysql> SELECT @@global.sort_buffer_size; ~~~ ~~~ mysql> SHOW GLOBAL VARIABLES like 'sort_buffer_size'; ~~~ 要想检索一个SESSION变量的值,使用下面的语法: ~~~ mysql> SELECT @@sort_buffer_size; ~~~ ~~~ mysql> SELECT @@session.sort_buffer_size; ~~~ ~~~ mysql> SHOW SESSION VARIABLES like 'sort_buffer_size'; ~~~ 这里,LOCAL也是SESSION的同义词。 当你用SELECT @@*var_name*搜索一个变量时(也就是说,不指定global.、session.或者local.),MySQL返回SESSION值(如果存在),否则返回GLOBAL值。 对于SHOW VARIABLES,如果不指定GLOBAL、SESSION或者LOCAL,MySQL返回SESSION值。 当设置GLOBAL变量需要GLOBAL关键字但检索时不需要它们的原因是防止将来出现问题。如果我们移除一个与某个GLOBAL变量具有相同名字的SESSION变量,具有SUPER权限的客户可能会意外地更改GLOBAL变量而不是它自己的连接的SESSION变量。如果我们添加一个与某个GLOBAL变量具有相同名字的SESSION变量,想更改GLOBAL变量的客户可能会发现只有自己的SESSION变量被更改了。 关于系统启动选项和系统变量的详细信息参见[5.3.1节,“**mysqld**命令行选项”](# "5.3.1. mysqld Command-Line Options")和[5.3.3节,“服务器系统变量”](# "5.3.3. Server System Variables")。在[5.3.3.1节,“动态系统变量”](# "5.3.3.1. Dynamic System Variables")中列出了可以在运行时设置的变量。 ### 9.4.1. 结构式系统变量 结构式变量在两个方面不同于常规系统变量: ·         其值是一个含组件的结构,可以指定服务器参数,一般紧密相关。 ·         可能是给定类型的结构式变量的几个实例。每个实例有一个不同的名,指向服务器维护的不同的资源。 MySQL 5.1支持结构式变量类型,可以指定监控键值缓存操作的参数。键值缓存结构式变量有以下组件: ·         key_buffer_size ·         key_cache_block_size ·         key_cache_division_limit ·         key_cache_age_threshold 该节描述了引用结构式变量的语法。在语法的例子中使用了键值缓存变量,但关于键值缓存如何操作的具体详情在其它章节中,如 [ 7.4.6节,“MyISAM键高速缓冲”](# "7.4.6. The MyISAM Key Cache")。 要引用结构式变量实例的组件,可以使用instance_name.component_name格式的复合名。例如: ~~~ hot_cache.key_buffer_size ~~~ ~~~ hot_cache.key_cache_block_size ~~~ ~~~ cold_cache.key_cache_block_size ~~~ 对于每个结构式系统变量,总是预定义名为default的一个实例。如果不使用任何实例名引用结构式变量的一个组件,default实例被使用。这样,default.key_buffer_size和key_buffer_sizeboth均指向同一系统变量。 结构式变量实例和组件的命名规则为: ·         对于给定类型的结构式变量,每个实例必须有一个在该类变量中唯一的一个名。但是,在不同类型的结构式变量中实例名不需要唯一。例如,每个结构式变量有一个实例default,因此在不同的变量类型中default不是唯一的。 ·         每个结构式变量类型的组件名在所有系统变量名中必须是唯一的。如果不是这样(也就是说,如果两个不同类型的结构式变量能够共享组件成员名),将不清楚使用哪个默认结构式变量来用作没有使用实例名限定的成员名。 ·         如果结构式变量实例名作为未引起来的识别符不合法,将它用反勾号引起来作为识别符。例如,hot-cache不合法,但`hot-cache`合法。 ·         global、session和local不是合法实例名。这样可以避免与引用非结构式系统变量的符号的冲突,例如@@global.*var_name*。 目前,这前两个规则不可能违背,因为唯一的结构式变量类型是键值缓存。在将来创建其它类型的结构式变量,这些规则将有重要的意义。 一个例外是,可以在可能出现简单变量名的上下文中使用复合名引用结构式变量组件。例如,可以使用一个命令行选项未某个结构式变量分配一个值: ~~~ shell> mysqld --hot_cache.key_buffer_size=64K ~~~ 在选项文件中,使用: ~~~ [mysqld] ~~~ ~~~ hot_cache.key_buffer_size=64K ~~~ 如果用该选项启动服务器,除了默认大小为8MB的默认键值缓存,还创建一个名为hot_cache的键值缓存,大小为64KB。 假定你这样启动服务器: ~~~ shell> mysqld --key_buffer_size=256K \ ~~~ ~~~          --extra_cache.key_buffer_size=128K \ ~~~ ~~~          --extra_cache.key_cache_block_size=2048 ~~~ 在这种情况下,服务器将默认键值缓存的大小设定为256KB。(也可以写成--default.key_buffer_size=256K)。 并且,服务器创建一个名为extra_cache的第2个键值缓存,大小为128KB,缓存表索引块的块缓存区的大小设置为2048字节。 在下面的例子中,用3个不同的键值缓存(大小比例为3:1:1)启动服务器: ~~~ shell> mysqld --key_buffer_size=6M \ ~~~ ~~~          --hot_cache.key_buffer_size=2M \ ~~~ ~~~          --cold_cache.key_buffer_size=2M ~~~ 也可以在运行时设置和检索结构式变量值。例如,要想将名为hot_cache的一个键值缓存的大小设置为10MB,使用下面任何一个语句: ~~~ mysql> SET GLOBAL hot_cache.key_buffer_size = 10*1024*1024; ~~~ ~~~ mysql> SET @@global.hot_cache.key_buffer_size = 10*1024*1024; ~~~ 要想检索缓存大小,执行: ~~~ mysql> SELECT @@global.hot_cache.key_buffer_size; ~~~ 但是,下面的语句不工作。变量不解释为一个复合名,而是解释为LIKE模式匹配操作的简单字符串: ~~~ mysql> SHOW GLOBAL VARIABLES LIKE 'hot_cache.key_buffer_size'; ~~~ 这是一个在可能出现简单的变量名时使用结构式变量名的例子。 ### 9.5. 注释语法 MySQL服务器支持3种注释风格: ·         从‘#’字符从行尾。 ·         从‘-- ’序列到行尾。请注意‘-- ’(双破折号)注释风格要求第2个破折号后面至少跟一个空格符(例如空格、tab、换行符等等)。该语法与标准SQL注释语法稍有不同,后者将在[1.8.5.7, “‘--’作为注释起始标记”](# "1.8.5.7. '--' as the Start of a Comment")中讨论。 ·         从/*序列到后面的*/序列。结束序列不一定在同一行中,因此该语法允许注释跨越多行。 下面的例子显示了3种风格的注释: ~~~ mysql> SELECT 1+1;     # This comment continues to the end of line ~~~ ~~~ mysql> SELECT 1+1;     -- This comment continues to the end of line ~~~ ~~~ mysql> SELECT 1 /* this is an in-line comment */ + 1; ~~~ ~~~ mysql> SELECT 1+ ~~~ ~~~ /* ~~~ ~~~ this is a ~~~ ~~~ multiple-line comment ~~~ ~~~ */ ~~~ ~~~ 1; ~~~ 上述的注释语法适用于**mysqld**服务器如何分析SQL语句。发送到服务器之前,**mysql客户**程序也执行部分语句解析。(例如,它通过解析来确定在多语句行中的语句边界)。 在MySQL 5.1中,**mysql**解析/* ...*/注释的唯一局限性是结合该风格的注释定界符使用的叹号标记了有条件执行的SQL语句部分。适用于交互式运行**mysql**和将命令放入一个文件中,并以批处理模式使用**mysql**来处理**mysql < *****file_name***的文件。详细信息和例子参见[1.8.4节,“MySQL对标准SQL的扩展”](# "1.8.4. MySQL Extensions to Standard SQL")。 ### 9.6. MySQL中保留字的处理 尝试使用一个识别符,例如使用嵌入式MySQL数据类型或函数名作为表名或列名,例如TIMESTAMP或GROUP,会造成一个常见问题。允许你这样操作(例如,ABS可以作为一个列名)。但是,默认情况下,在数调用中在函数名和后面的‘(’字符之间不允许有空格。该要求使函数调用与列名引用不同。 该行为的不利结果是在某些上下文中省略一个空格会使识别符解释为函数名。例如,该语句合法: ~~~ mysql> CREATE TABLE abs (val INT); ~~~ 但省略abs后面的空格会造成语法错误,因为省略后该语句好像要调用ABS()函数: ~~~ mysql> CREATE TABLE abs(val INT); ~~~ 如果SQL服务器模式包括IGNORE_SPACE模式值,服务器允许函数调用时在函数名和后面的‘(’字符之间有空格。这样使函数名被视为保留字。结果是,与函数名相同的识别符必须按照[9.2节,“数据库、表、索引、列和别名”](# "9.2. Database, Table, Index, Column, and Alias Names")中所描述的引起来。SQL服务器模式按照[5.3.2节,“SQL服务器模式”](# "5.3.2. The Server SQL Mode")中所描述的进行控制。 限定名中句点后面的字必须为一个识别符,因此不需要将它引起来,即使它是一个保留字。 在MySQL中,下表中的字显式被保留。其中大多数字进制被标准SQL用作列名和/或表名(例如,GROUP)。少数被保留了,因为MySQL需要它们,(目前)使用**yacc**解析程序。保留字被引起来后可以用作识别符。 | ADD | ALL | ALTER | |-----|-----|-----| | ANALYZE | AND | AS | | ASC | ASENSITIVE | BEFORE | | BETWEEN | BIGINT | BINARY | | BLOB | BOTH | BY | | CALL | CASCADE | CASE | | CHANGE | CHAR | CHARACTER | | CHECK | COLLATE | COLUMN | | CONDITION | CONNECTION | CONSTRAINT | | CONTINUE | CONVERT | CREATE | | CROSS | CURRENT_DATE | CURRENT_TIME | | CURRENT_TIMESTAMP | CURRENT_USER | CURSOR | | DATABASE | DATABASES | DAY_HOUR | | DAY_MICROSECOND | DAY_MINUTE | DAY_SECOND | | DEC | DECIMAL | DECLARE | | DEFAULT | DELAYED | DELETE | | DESC | DESCRIBE | DETERMINISTIC | | DISTINCT | DISTINCTROW | DIV | | DOUBLE | DROP | DUAL | | EACH | ELSE | ELSEIF | | ENCLOSED | ESCAPED | EXISTS | | EXIT | EXPLAIN | FALSE | | FETCH | FLOAT | FLOAT4 | | FLOAT8 | FOR | FORCE | | FOREIGN | FROM | FULLTEXT | | GOTO | GRANT | GROUP | | HAVING | HIGH_PRIORITY | HOUR_MICROSECOND | | HOUR_MINUTE | HOUR_SECOND | IF | | IGNORE | IN | INDEX | | INFILE | INNER | INOUT | | INSENSITIVE | INSERT | INT | | INT1 | INT2 | INT3 | | INT4 | INT8 | INTEGER | | INTERVAL | INTO | IS | | ITERATE | JOIN | KEY | | KEYS | KILL | LABEL | | LEADING | LEAVE | LEFT | | LIKE | LIMIT | LINEAR | | LINES | LOAD | LOCALTIME | | LOCALTIMESTAMP | LOCK | LONG | | LONGBLOB | LONGTEXT | LOOP | | LOW_PRIORITY | MATCH | MEDIUMBLOB | | MEDIUMINT | MEDIUMTEXT | MIDDLEINT | | MINUTE_MICROSECOND | MINUTE_SECOND | MOD | | MODIFIES | NATURAL | NOT | | NO_WRITE_TO_BINLOG | NULL | NUMERIC | | ON | OPTIMIZE | OPTION | | OPTIONALLY | OR | ORDER | | OUT | OUTER | OUTFILE | | PRECISION | PRIMARY | PROCEDURE | | PURGE | RAID0 | RANGE | | READ | READS | REAL | | REFERENCES | REGEXP | RELEASE | | RENAME | REPEAT | REPLACE | | REQUIRE | RESTRICT | RETURN | | REVOKE | RIGHT | RLIKE | | SCHEMA | SCHEMAS | SECOND_MICROSECOND | | SELECT | SENSITIVE | SEPARATOR | | SET | SHOW | SMALLINT | | SPATIAL | SPECIFIC | SQL | | SQLEXCEPTION | SQLSTATE | SQLWARNING | | SQL_BIG_RESULT | SQL_CALC_FOUND_ROWS | SQL_SMALL_RESULT | | SSL | STARTING | STRAIGHT_JOIN | | TABLE | TERMINATED | THEN | | TINYBLOB | TINYINT | TINYTEXT | | TO | TRAILING | TRIGGER | | TRUE | UNDO | UNION | | UNIQUE | UNLOCK | UNSIGNED | | UPDATE | USAGE | USE | | USING | UTC_DATE | UTC_TIME | | UTC_TIMESTAMP | VALUES | VARBINARY | | VARCHAR | VARCHARACTER | VARYING | | WHEN | WHERE | WHILE | | WITH | WRITE | X509 | | XOR | YEAR_MONTH | ZEROFILL | MySQL允许部分关键字用做未引起来的识别符,因为许多人以前曾使用过它们。下面列出了一些例子: - ACTION - BIT - DATE - ENUM - NO - TEXT - TIME - TIMESTAMP 这是MySQL参考手册的翻译版本,关于MySQL参考手册,请访问[dev.mysql.com.](http://dev.mysql.com/doc/mysql/en)。原始参考手册为英文版,与英文版参考手册相比,本翻译版可能不是最新的。