wenni4
级别: 论坛版主
UID: 7
精华: 1
发帖: 80
威望: 83 点
金钱: 820 RMB
贡献值: 0 点
注册时间:2007-05-17
最后登录:2008-12-20
楼主  发表于: 2007-07-30 22:37

 MySQL 语言参考之语言结构篇

6.1.1.1 字符串
字符串是多个字符组成的一个字符序列,由单引号(“'”) 或双引号 (“"”) 字符包围。(但在 ANSI 模式中运行时只能用单引号)。

例如:

'a string'
"another string"

在一个字符串中,如果某个序列具有特殊的含义,每个序列以反斜线符号 (“\”)开头,称为转义字符。 MySQL 识别下列转义字符:

\0
一个 ASCII 0 (NUL) 字符。
\'
一个 ASCII 39 单引号 (“'”) 字符。
\"
一个 ASCII 34 双引号 (“"”) 字符。
\b
一个 ASCII 8 退格符。
\n
一个 ASCII 10 换行符。
\r
一个 ASCII 13 回车符。
\t
一个 ASCII 9 制表符(TAB)。
\z
ASCII(26) (Control-Z)。这个字符可以处理在 Windows 系统中 ASCII(26) 代表一个文件的结束的问题。(当使用 mysql database < filename 时 ASCII(26) 可能会引起问题产生。)
\\
一个 ASCII 92 反斜线 (“\”) 字符。
\%
一个 ASCII 37 “%” 字符。它用于在正文中搜索“%”的文字实例,否则这里“%”将解释为一个通配符。查看章节 6.3.2.1 字符串比较函数。
\_
一个 ASCII 95 “_” 字符。它用于在正文中搜索“_”的文字实例,否则这里“_”将解释为一个通配符。查看章节 6.3.2.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 |
+--------------------+


如果你想要把二进制数据插入到一个字符类型的字段中(例如BLOB),下列字符必须由转义序列表示:

NUL
ASCII 0,你应该用 “\0”(一个反斜线和一个ASCII “0”字符)表示它。
\
ASCII 92,反斜线。需要用 “\\” 表示。
'
ASCII 39,单引号。需要用 “\'” 表示。
"
ASCII 34,双引号。需要用 “\"” 表示。
如果你写 C 代码,你可以使用 C API 函数mysql_real_escape_string() 来为 INSERT 语句转义字符。查看章节 8.1.2 C API 函数概述。在 Perl 中,你可以使用 DBI 包中的 quote 方法来将这些特殊字符转换成适当的转义序列。查看章节 8.5.2 DBI 接口。

你应该在任何可能包含上述特殊字符的字符串中使用转义函数!

另外,很多 MySQL API 提供了一些占位符处理能力,这允许你在查询语句中插入特殊标记,然后在执行查询时对它们绑定数据值。这样,API 会自动为你从数值中转换它们。

wenni4
级别: 论坛版主
UID: 7
精华: 1
发帖: 80
威望: 83 点
金钱: 820 RMB
贡献值: 0 点
注册时间:2007-05-17
最后登录:2008-12-20
1楼  发表于: 2007-07-30 22:37
6.1.1.2 数字

整数被表示为一个数字序列。浮点数使用 “.” 作为一个十进制的分隔符。这两种类型的数字可以前置 `-' 以表示一个负值。

有效整数的例子:

1221
0
-32

有效浮点数的例子:

294.42
-32032.6809e+10
148.00

一个整数可以在浮点语境中使用;它被解释为等值的浮点数。

6.1.1.3 十六进制值

MySQL 支持十六进制数值。在数字的语境中,它们表现类似于一个整数(64位精度)。在字符串的语境中,它们表现类似于一个二进制的字符串,每一对十六进制数字被转换为一个字符:

mysql> SELECT x'4D7953514C';
        -> MySQL
mysql> SELECT 0xa+0;
        -> 10
mysql> SELECT 0x5061756c;
        -> Paul

表达式 x'hexstring' (4.0 中新加入) 是基于 ANSI SQL 的,表达式 0x 是基于 ODBC 的。十六进制的字符串通常被 ODBC 用于为 BLOB 类型字段赋值。你可以通过 HEX() 将一个字符串或一个数值转化为十六进制格式。
wenni4
级别: 论坛版主
UID: 7
精华: 1
发帖: 80
威望: 83 点
金钱: 820 RMB
贡献值: 0 点
注册时间:2007-05-17
最后登录:2008-12-20
2楼  发表于: 2007-07-30 22:38
6.1.1.4 NULL 值

NULL 值并不意味着“无数据”,并且是不同于例如数字类型的 0 或字符串类型的空串。查看章节 A.5.3 NULL 值问题。

当使用文本文件导入与导出格式时 (LOAD DATA INFILE,SELECT ... INTO OUTFILE),NULL 可以用 \N 来描述。查看章节 6.4.9 LOAD DATA INFILE 句法.

6.1.2 数据库、表、索引、列和别名

数据库、表、索引、列和别名都需遵守 MySQL 同样的规则。

注意,从 MySQL 3.23.6 开始,规则发生改变了,此时引进了用“`”引用标识符(数据库、表和字段名)。如果你以 ANSI 模式运行,“"” 也可以用于引用标识符。查看章节 1.8.2 以 ANSI 模式运行 MySQL。

标识符  最大长度  允许的字符 
数据库  64  一个目录名中允许的任何字符,除了“/”、“\” 或 “.”。
表  64  一个文件名中允许的任何字符,除了 “/” 或 “.”。
列  64  所有的字符。
别名  255  所胡的字符。

注意,除了上面的,在一个标识符中还不能有 ASCII(0) 或 ASCII(255) 或引用字符。

注意,如果标识符是一个受限掉的词或包含特殊的字符,当使用它时,必须以一个 ` (backtick) 来引用它。

mysql> SELECT * FROM `select` WHERE `select`.id > 100;

查看章节 6.1.7 MySQL 对保留字挑剔吗?。

在 MySQL 3.23.6 以前的版本中,命名规则如下:

一个名字可以由当前字符集中包含的文字与数字字符以及 “_” 和 “$” 组成。缺省字符集为 ISO-8859-1 Latin1;这可以通过改变 mysqld 的 --default-character-set 的选项来改变。查看章节 4.6.1 用于数据和排序的字符集。
一个名字可以以在名字中合法的任何字符开始。特别地,一个名字可以以一个数字开始(这不同于许多其它的数据库系统!)。但一个名字不能 仅仅 以数字组成。
不能在名字中使用 “.” 字符,因为它是用于扩充格式的,你可以用它引用列(见下面)。
建议不要使用象 1e 这样的名字,因为一个表达式 1e+1 是存在二义性的。它可以被解释为表达式 1e + 1 或数字 1e+1。

在 MySQL 中,你可以使用下列表格中的任一种方式引用一个列:

列引用  含义 
col_name  列 col_name 来自查询所用的任何一个表中对应字段 
tbl_name.col_name  列 col_name 来自当前数据库中的表 tbl_name 
db_name.tbl_name.col_name  列 col_name 来自数据库 db_name 中的表 tbl_name。这个形式从 MySQL 3.22 或以后版本开始可用。
`column_name`  该字段是一个关键词或包含特殊字符。 

在一条语句中的列引用中,不需要明确指定一个 tbl_name 或 db_name.tbl_name 前缀,除非这个引用存在二义性。例如,假设表 t1 和 t2 均包含一个字段 c,当用一个使用了 t1 和 t2 的 SELECT 检索 c 时。在这种情况下,c 存在二义性,因为它在这个语句所使用的表中不是唯一的,因而必须通过写出 t1.c 或 t2.c 来指明你所需的是哪个表。同样的,如果从数据库 db1 的表 t 和数据库 db2 的表 t 中检索,你必须用db1.t.col_name 和 db2.t.col_name 来指定引用哪个库表的列。

句法 .tbl_name 意味着表 tbl_name 在当前数据库中。这个句法是为了与 ODBC 兼容,因为一些 ODBC 程序以一个 “.” 字符作为表名的前缀。
wenni4
级别: 论坛版主
UID: 7
精华: 1
发帖: 80
威望: 83 点
金钱: 820 RMB
贡献值: 0 点
注册时间:2007-05-17
最后登录:2008-12-20
3楼  发表于: 2007-07-30 22:38
6.1.3 名字的大小写敏感性

在 MySQL 中,数据库和表对就于那些目录下的目录和文件。因而,操作系统的敏感性决定数据库和表命名的大小写敏感。这就意味着数据库和表名在 Windows 中是大小写不敏感的,而在大多数类型的 Unix 系统中是大小写敏感的。一个特例是 Mac OS X,当缺省的 HFS+ 文件系统使用时。然而 Mac OS X 还支持 UFS 卷,那些在 Mac OS X 是大小写敏感的就如他们在任一 Unix 上一样。查看章节 1.8.3 MySQL 对 ANSI SQL92 的扩展。

注意:尽管在 Windows 中数据库与表名是忽略大小写的,你不应该在同一个查询中使用不同的大小写来引用一个给定的数据库和表。下面的查询将不能工作,因为它以 my_table 和 MY_TABLE 引用一个表:

mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;

列名与列的别名在所有的情况下均是忽略大小写的。

表的别名是区分大小写的。下面的查询将不能工作,因为它用 a 和 A 引用别名:

mysql> SELECT col_name FROM tbl_name AS a
    ->                WHERE a.col_name = 1 OR A.col_name = 2;

如果记忆数据库和表名的字母大小写有困难,建议采用一个一致一约定,例如总是以小写字母创建数据库和表。

避免这个问题的另一个办法就是以 -O lower_case_table_names=1 参数启动 mysqld。缺省地在 Windows 中这个选项为 1 ,在 Unix 中为 0。

如果 lower_case_table_names 为 1 ,MySQL 将在存储与查找时将所有的表名转换为小写字线。(从 MySQL 4.0.2 开始,这个选项同样适用于数据库名。) 注意,当你更改这个选项时,你必须在启动 mysqld 前首先将老的表名转换为小写字母。

如果将 MyISAM 从 Windows 移动到一个 Unix 磁盘中,在某些情况下你可能需要使用 “mysql_fix_extensions” 工具来修正指定数据库目录下的文件扩展名(小写字母 “.frm”,大写字母 “.MYI” 和 “.MYD”)。“mysql_fix_extensions” 存放在 “scripts” 子目录下。
wenni4
级别: 论坛版主
UID: 7
精华: 1
发帖: 80
威望: 83 点
金钱: 820 RMB
贡献值: 0 点
注册时间:2007-05-17
最后登录:2008-12-20
4楼  发表于: 2007-07-30 22:38
6.1.4 用户变量

MySQL 支持连接特定(connection-specific)的用户变量,用 @variablename 句法表示。一个变量名可以由当前字符集中包含的文字与数字字符以及 “_”、“$” 和 “.” 组成。缺少的字符集为 ISO-8859-1 Latin1;这可以通过改变 mysqld 的--default-character-set 的选项来改变。查看章节 4.6.1 用于数据和排序的字符集。

变量不必被初始化。缺省地,他们的值为 NULL 并可以存储一个整数、实数或字符串值。当连接线程退出时,这个线程的所有变量将会自动地被释放。

你可以通过 SET 句法来设置一个变量:

SET @variable= { integer expression | real expression | string expression }
[,@variable= ...].

在语句中除了 SET 之外还可以直接为一个变量赋值。然而在这各情况下,赋值操作符为 := 而不是 =,因为 = 在非 SET 语句中是用于比较的:

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 的子句中。

注意:在一个 SELECT 语句中,各个表达式只有在它被送到客户端时才能被求值。这就意味着,在 HAVING、GROUP BY 或 ORDER BY 子句中,你不能使用一个包含在 SELECT 部份所设置变量的表达式。例如:下面的语句将不会按预期的运作:

mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM table_name HAVING b=5;

原因是因为 @aa 不会是当前行的值,而是前一个符合条件的行的 id 值。

规则就是在同一语句中决不赋值 和 使用同一个变量。
wenni4
级别: 论坛版主
UID: 7
精华: 1
发帖: 80
威望: 83 点
金钱: 820 RMB
贡献值: 0 点
注册时间:2007-05-17
最后登录:2008-12-20
5楼  发表于: 2007-07-30 22:39
6.1.5 系统变量

从 MySQL 4.0.3 开始,我们提供了对大量的系统变量和连接变量的更好的访问方式。你可以不需要关闭服务器就可以更改其中的大部变量值。

系统变量可分为两种类型:线程特定(Thread-specific)或称为连接特定(connection-specific)变量,它们是当前连接唯一的;全局变量,它们用于设置全局事件。全局变量也同样被用于设置一个新连接的相应线程特定变量的初始值。

当 mysqld 启动时,所有的全局变量以命令行参数和选项文件内容初始化。可以通过 SET GLOBAL 命令更改这些值。当一个新的连接线程被建立时,将以全局变量值初始化线程特定变量,直到你执行一个新的 SET GLOBAL 命令时,线程特定变量才会改变。

为了设置一个 全局(GLOBAL) 变量值,可以使用下面的任一句法:(在这里,我们以 sort_buffer_size 变量作为一个示例)

SET GLOBAL sort_buffer_size=value;
SET @@global.sort_buffer_size=value;

为了设置一个 会话(SESSION) 变量的值,可以使用下面任一句法:

SET SESSION sort_buffer_size=value;
SET @@session.sort_buffer_size=value;
SET sort_buffer_size=value;

如果你没有明确指定 GLOBAL 或 SESSION,那么默认地将是设置 SESSION。查看章节 5.5.6 SET 句法。

LOCAL 是 SESSION 的同义词。

通过下面的任一命令可以检索到一个 全局(GLOBAL) 变量值:

SELECT @@global.sort_buffer_size;
SHOW GLOBAL VARIABLES like 'sort_buffer_size';

通过下面的任一命令可以检索到一个 会话(SESSION) 变量值:

SELECT @@session.sort_buffer_size;
SHOW SESSION VARIABLES like 'sort_buffer_size';

当 检索 一个变量值时使用 @@variable_name 句法,或没有指定 GLOBAL 或 SESSION 时,如果线程特定(thread-specific)的 (SESSION) 值存在,MySQL 将返回它。如果不存在,那么 MySQL 将返回全局变量值。

在设置 全局(GLOBAL) 变量而不是在检索他们的时候需要使用 GLOBAL ,是为了在之后引用一个同名的线程特定(thread-specific)变量或删除同名的一个线程特定(thread-specific)变量时不至发生问题。在这种情况下,你可能无意间改变整个服务器的状态而不是你自己的连接。

下面的列表是你可以使用 GLOBAL 或 SESSION 对它们进行更改和检索的所有变量。

变量名  变量值类型  变量类型 
autocommit  bool  SESSION 
big_tables  bool  SESSION 
binlog_cache_size  num  GLOBAL 
bulk_insert_buffer_size  num  GLOBAL | SESSION 
concurrent_insert  bool  GLOBAL 
connect_timeout  num  GLOBAL 
convert_character_set  string  SESSION 
delay_key_write  OFF | ON | ALL  GLOBAL 
delayed_insert_limit  num  GLOBAL 
delayed_insert_timeout  num  GLOBAL 
delayed_queue_size  num  GLOBAL 
error_count  num  LOCAL 
flush  bool  GLOBAL 
flush_time  num  GLOBAL 
foreign_key_checks  bool  SESSION 
identity  num  SESSION 
insert_id  bool  SESSION 
interactive_timeout  num  GLOBAL | SESSION 
join_buffer_size  num  GLOBAL | SESSION 
key_buffer_size  num  GLOBAL 
last_insert_id  bool  SESSION 
local_infile  bool  GLOBAL 
log_warnings  bool  GLOBAL 
long_query_time  num  GLOBAL | SESSION 
low_priority_updates  bool  GLOBAL | SESSION 
max_allowed_packet  num  GLOBAL | SESSION 
max_binlog_cache_size  num  GLOBAL 
max_binlog_size  num  GLOBAL 
max_connect_errors  num  GLOBAL 
max_connections  num  GLOBAL 
max_error_count  num  GLOBAL | SESSION 
max_delayed_threads  num  GLOBAL 
max_heap_table_size  num  GLOBAL | SESSION 
max_join_size  num  GLOBAL | SESSION 
max_sort_length  num  GLOBAL | SESSION 
max_tmp_tables  num  GLOBAL 
max_user_connections  num  GLOBAL 
max_write_lock_count  num  GLOBAL 
myisam_max_extra_sort_file_size  num  GLOBAL | SESSION 
myisam_max_sort_file_size  num  GLOBAL | SESSION 
myisam_sort_buffer_size  num  GLOBAL | SESSION 
net_buffer_length  num  GLOBAL | SESSION 
net_read_timeout  num  GLOBAL | SESSION 
net_retry_count  num  GLOBAL | SESSION 
net_write_timeout  num  GLOBAL | SESSION 
query_cache_limit  num  GLOBAL 
query_cache_size  num  GLOBAL 
query_cache_type  enum  GLOBAL 
read_buffer_size  num  GLOBAL | SESSION 
read_rnd_buffer_size  num  GLOBAL | SESSION 
rpl_recovery_rank  num  GLOBAL 
safe_show_database  bool  GLOBAL 
server_id  num  GLOBAL 
slave_compressed_protocol  bool  GLOBAL 
slave_net_timeout  num  GLOBAL 
slow_launch_time  num  GLOBAL 
sort_buffer_size  num  GLOBAL | SESSION 
sql_auto_is_null  bool  SESSION 
sql_big_selects  bool  SESSION 
sql_big_tables  bool  SESSION 
sql_buffer_result  bool  SESSION 
sql_log_binlog  bool  SESSION 
sql_log_off  bool  SESSION 
sql_log_update  bool  SESSION 
sql_low_priority_updates  bool  GLOBAL | SESSION 
sql_max_join_size  num  GLOBAL | SESSION 
sql_quote_show_create  bool  SESSION 
sql_safe_updates  bool  SESSION 
sql_select_limit  bool  SESSION 
sql_slave_skip_counter  num  GLOBAL 
sql_warnings  bool  SESSION 
table_cache  num  GLOBAL 
table_type  enum  GLOBAL | SESSION 
thread_cache_size  num  GLOBAL 
timestamp  bool  SESSION 
tmp_table_size  enum  GLOBAL | SESSION 
tx_isolation  enum  GLOBAL | SESSION 
version  string  GLOBAL 
wait_timeout  num  GLOBAL | SESSION 
warning_count  num  LOCAL 
unique_checks  bool  SESSION 

以 num 标记的变量可以设置一个数字值。以 bool 标记的变量可以设置 0、1、ON 或 OFF。enum 类型的变量通常是设置为该变量的某一个可用值,但也可以设置为相对应的数字。(enum 的第一个值为 0)。

下面是某些变量的描述:

变量  描述 
identity  last_insert_id 的别名 (Sybase 兼容) 
sql_low_priority_updates  low_priority_updates 的别名 
sql_max_join_size  max_join_size 的别名 
delay_key_write_for_all_tables  如它与 delay_key_write 一起被设置,那么所有新打开的 MyISAM 表将使用 delayed key writes. 
version  VERSION() 的别名 (Sybase (?) 兼容) 

在启动选项章节中可以找到其它的变量的描述,SHOW VARIABLES 的描述在 SET 部分。查看章节 4.1.1 mysqld 命令行选项。查看章节 4.5.6.4 SHOW VARIABLES。查看章节 5.5.6 SET 句法。
wenni4
级别: 论坛版主
UID: 7
精华: 1
发帖: 80
威望: 83 点
金钱: 820 RMB
贡献值: 0 点
注册时间:2007-05-17
最后登录:2008-12-20
6楼  发表于: 2007-07-30 22:39
6.1.6 注释句法


MySQL 服务器支持 # 到该行结束、-- 到该行结束 以及 /* 行中间或多个行 */ 的注释方格:

mysql> SELECT 1+1;    # 这个注释直到该行结束
mysql> SELECT 1+1;    -- 这个注释直到该行结束
mysql> SELECT 1 /* 这是一个在行中间的注释 */ + 1;
mysql> SELECT 1+
/*
这是一个
多行注释的形式
*/
1;

注意 -- (双长划) 注释风格要求在两个长划后至少有一个空格!

尽管服务器理解刚才描述的注释句法,但 MySQL 客户端的语法分析在 /* ... */ 注释方式上还有所限止:

单引号和双引号被用来标志一个被引用字符串的开始,即使是在一个注释中。如果注释中的引号没有另一个引号与之配对,那和语法分析程序就不会认为注释结束。如果你以交互式运行 mysql,你会产生困惑,因为提示符从 mysql> 变为 '> 或 ">。
一个分号被用于指出当前 SQL 语句的结束并且跟随它的任何东西表示下一行的开始。
不论你是以交互式运行 mysql 还是将命令放在一个文件中,然后以 mysql < some-file 告诉 mysql 读取它的输入,这个限制均存在。

MySQL 支持 `--' ANSI SQL 注释风格,但在两个长划后必须跟有一个空格。查看章节 1.8.4.7 `--' 作为一个注释的开始。