本章主要介绍一下MySQL中的SQL语法
1. 数据库操作
数据库操作主要包括:
1)创建数据库
创建数据库的基本语法如下:
CREATE DATABASE
用于创建一个指定名字的数据库。要想使用该SQL语句,要求用户具有CREATE
权限。其中create_specification用于指定所创建数据库的字符集特性。数据库的字符集特性会被存储在数据库目录的db.opt
文件中。
在MySQL中,一个数据库对应着一个目录,数据库中的每一个表(table)都有相应的文件对应。因为在数据库刚建立的时候并没有表(table),因此目录下仅有一个文件db.opt
。
假如你在MySQL的数据目录下创建一个目录,MySQL会认为其是一个数据库。
2) 删除数据库
删除数据库的基本语法如下:
DROP DATABASE
会删除数据库和数据库中的所有表数据。要删除数据库,你必须要有DROP
权限。语句执行后的返回结果为所删除的表的数目。
3) 选择数据库
选择数据库语法如下:
4) 查看所有数据库
查看所有数据库语法如下:
5) 查看当前所使用的数据库
6) 修改数据库
这里一般只用于修改字符集与校对集。
2. 表操作
表的操作主要包括:
2.1 创建数据库表
基本语法如下:
例如,下面创建名为runoob
的表:
1) 索引和外键
在创建表的时候可以指定索引和外键,在这里我们介绍一下相关的内容:
-
CONSTRAINT symbol: 用于指定约束名称。假如在创建表时添加了CONSTRAINT symbol
子句并且指定了symbol
的话,则symbol在整个数据库中必须是唯一的。如果有重复的symbol,则会产生相应的错误。而如果并未指定symbol,那么MySQL或默认帮我们产生一个。
-
PRIMARY KEY: 是一个unique索引,并且所有的列必须被定义为NOT NULL
。假如我们并没有显示的指定NOT NULL
,那么MySQL会隐式的帮我们指定。一个表只能有一个PRIMARY KEY
。
对于存储索引为InnoDB
的表,建议尽量保持PRIMARY KEY
足够的短以减少存储占用的空间,这是因为InnoDB
表的二级索引是存储主键列的。
在创建表的时候,请将PRIMARY KEY
放在最开始,然后是UNIQUE
索引,再接着是noneunique
索引。这可以帮助MySQL优化器选择优先使用哪个索引,并且能够更快速的检测到重复的unique值。
一个PRIMARY KEY
可以是一个多列(multi-column)索引,对于一个多列索引的话,你并不能够在创建列的时候直接在后面指定PRIMARY KEY
,你可以在一个单独的PRIMARY KEY(key_par,...)
子句中指定。
-
KEY/INDEX: 在这里KEY
通常等价于INDEX
。主要为了兼容其他的数据库系统。
-
UNIQUE: 唯一索引会创建一个约束要求索引中的所有值都是唯一的。对于所有存储引擎来说,一个UNIQUE
索引是允许存在多个NULL
值的(假设该列允许的话)。
-
FULLTEXT: 全文索引是一种特殊类型的索引,主要用于全文搜索。只有InnoDB
和MyISAM
这两个存储引擎支持全文索引。它们只能够针对CHAR
、VARCHAR
和TEXT
列来创建全文索引。
-
SPATIAL: 对于spatial类型数据,你可以创建SPATIAL
索引。并且只有MyISAM
类型表的非空
列才支持SPATIAL
索引。
-
FOREIGN KEY
: MySQL支持外键,以允许你跨表参考(reference)相关的数据。并且由于foreign key
的约束,可以使得数据传播上的一致性。
2) 创建表时生成的文件
在数据库的对应目录中,每一个表的格式文件是以.frm
结尾的,而其他的文件根据存储引擎的不同会略有些差异。
对于InnoDB
存储引擎来说,存储文件是由innodb_file_per_table
配置选项所控制的。在创建InnoDB表时,如果此选项被打开,表数据以及所关联的索引都会存储在一个.ibd
文件中。而如果该选项被关闭的话,所有的InnoDB
表数据和索引数据都会被存放在系统表空间(system tablespace)中。
对于MyISAM
表,存储引擎会创建数据文件和索引文件。对于每一个MyISAM
表tbl_name,都会在硬盘上存在如下三个文件:
-
tbl_name.frm: 表格式文件
-
tbl_name.MYD: 数据文件
-
tbl_name.MYI: 索引文件
2.2 删除数据表
删除表的语法如下:
DROP TABLE
用于移除一个或多个表,对于每一个表你必须具有DROP
权限。
2.3 修改表
修改表的基本语法如下:
ALTER TABLE
用于改变表的结构。例如,你可以添加或删除一列,创建或销毁索引,更改已存在列的类型,重命名列或表。
下面给出一些示例,假如我们通过如下语句创建了表t1
:
- 将列
a
从INTEGER
类型转换为TINYINT NOT NULL
类型,并且将列b
从CHAR(10
类型转换为CHAR(20)
类型,且将列b
的名称由b更改为c
- 在列
d
上增加一个索引,在列a
上增一个UNIQUE
索引
3. 视图操作
视图操作主要包括:
3.1 创建视图
创建视图语法如下:
CREATE VIEW
语句用于创建一个新的视图,或者替换一个老的视图(假如指定了OR REPLACE
)。假如视图不存在,CREATE OR REPLACE VIEW
等价于CREATE VIEW
;假如视图已经存在,则CREATE OR REPLACE
会替换该视图。
select_statement
是一个SELECT
子句,用于体统视图的定义。说明: select_statement可以从一个基础表中查询,也可以从另一个视图中查询。
说明: MySQL数据库视图在创建的时候就已经固定下来了(即创建时视图就处于frozen
状态),并不会受到后续底层表定义的影响。例如,假如在一个表上通过SELECT *
定义了一个视图,假如后面再在表中增加了一列,那么其并不会成为该视图的一部分;而如果后续删除了表的一列,那么在查看视图的时候将会产生错误。
下面给出一个示例:
3.2 修改视图
修改视图的基本语法如下:
上述语句用于修改一个视图(视图必须已经存在)。执行该语句时,必须要有CREATE VIEW
以及DROP VIEW
的权限。
3.3 删除视图
删除视图语法如下:
用于删除一个或多个视图。
4. 索引操作
索引操作主要包括:
4.1 创建索引
创建索引语法如下:
通常你会在使用CREATE TABLE
语句创建表时同时创建出该表上的所有索引。这里CREATE INDEX
允许向一个已存在的表中添加索引。可以通过SHOW INDEX FROM tbl_name
来查看一个表上的索引。
实际上,CREATE INDEX
会被映射成一个ALTER TABLE
语句来创建索引。注意,CREATE INDEX
并不能被用于创建一个PRIMARY KEY
。
1) UNIQUE INDEX
可以在一个表上创建UNIQUE
索引,FULLTEXT
索引,SPATIAL
索引。这里我们主要介绍一下唯一索引
。一个UNIQUE
索引会创建约束:要求索引上的值都是唯一的。假如你向表中插入一个新的行,若造成UNIQUE
索引列的值重复,则会产生相应的错误。假如你在一列上创建一个前缀UNIQUE
索引,那你需要保证在前缀长度范围内数据是唯一的。注: 对于UNIQUE
索引,如果该列本身允许NULL
,则允许有重复的NULL。
假如在一个表的一个单独
的列上(要求该列的数据类型为整数类型
)创建PRIMARY KEY
或UNIQUE NOT NULL
索引,那么你可以在SELECT
语句中使用_rowid
来引用索引列:
-
假如PRIMARY KEY
索引对应的列是一个单独的列
,并且列的数据类型是整数类型
,那么你可以使用_rowid
来引用该列;假如有一个PRIMARY KEY
索引,并且该索引列并不是一个单独的整数类型列,那么_rowid
并不能被使用。
-
否则,可以使用_rowid
来引用第一个类型为整数的单独UNIQUE NOT NULL
索引列。假如第一个UNIQUE NOT NULL
索引列并不是单独的整数类型列
,那么_rowid
将不能被使用。
2) 索引类型(index_type)
在创建索引时,底层一般都是用BTREE
或者HASH
来作为数据结构。一般来说,对于InnoDB
以及MyISAM
底层是采用BTREE
来做索引的;对于MEMORY
以及NDB
存储引擎,底层可以采用BTREE
来做索引,也可以采用HASH
来做索引。
4.2 删除索引
删除索引语法如下:
上面表示从表tbl_name
上删除名称为index_name
的索引。注意,对于PRIMARY KEY
这样的索引,其index_name
为PRIMARY
。
5. 数据操作
表的数据操作这里我们主要介绍:
-
表数据的插入
-
表数据的删除
-
表数据的更新
-
表数据的查询
另外,其实也包括调用存储过程
以及一些其他的操作。关于MySQL存储过程,我们后面的章节再进行讲解。
5.1 数据插入
插入的基本语法如下:
INSERT
用于插入一条新的数据到一个已存在的表中。INSERT ... VALUES
和INSERT ... SET
形式的的插入语句显示的指定要插入的值,而INSERT ... SELECT
形式的插入语句插入从另外一个表中查询出来的结果。而INSERT
后跟ON DUPLICATE KEY UPDATE
子句的话,如果在插入时导致一个UNIQUE
索引或PRIMARY KEY
重复的话,则该重复的值会被更新。
在进行表插入时需要具有该表的INSERT
权限。而假如ON DUPLICATE KEY UPDATE
子句被使用的话,那么还要求具有UPDATE
权限。
5.2 数据删除
删除的基本语法如下:
DELETE
删除语句用于从表tbl_name
删除数据,并且返回删除的行数。删除的可选条件WHERE
用于指定删除哪些满足条件的行,假如并未指定WHERE
条件的话,则所有的数据均会被删除。假如LIMIT
子句被指定的话,则会最多删除指定的行数。
假如ORDER BY
子句被指定的话,则会按照指定的顺序来进行删除。这在搭配LIMIT
一起使用时很有效。例如,下面的语句首先查找到匹配WHERE
条件的记录,然后再按timestamp_column
列对这些行进行排序,最后再删除第一个元素(oldest):
DELETE FROM somelog WHERE user = 'jcole'
ORDER BY timestamp_column LIMIT 1;
5.3 数据更新
UPDATE
是一个数据库操作语句(DML),用于修改一个表中的记录:
UPDATE
语句用于更新一个表中已存在的列。假如一个UPDATE
语句包含了一个ORDER BY
子句的话,则会依照指定的顺序更新行记录,这在一些特性情形下是很有用的(如果不按顺序,可能会导致错误)。假设有一个表t
包含了一个UNIQUE
索引列id
,下面的更新语句则可能会导致duplicate-key
错误:
UPDATE t SET id = id + 1;
例如, 假设该表含有id
为1和2的两条记录,假如在2被更新为3之前将1更新为2,则会产生错误。为了避免这个问题,增加一个ORDER BY
语句使得id更大的记录优先被更新:
UPDATE t SET id = id + 1 ORDER BY id DESC;
5.4 数据查询
数据查询语法如下:
SELECT
用于从一个或多个表中查询数据。针对SELECT
最常用的子句有如下:
-
每一个select_expr
用于指示想要获取的列。必须至少有一列
-
table_reference
用于指定要从那个(些)表中查询数据。关于JOIN
的查询语法我们后边会进行介绍
-
假如指定了WHERE
子句的话,其用于指示查询条件。
此外,SELECT
也能够被用于查询行值
来进行计算,而不需要指定任何一个表。例如:
在这种不需要指定表的情况下,也允许通过指定一个Dummy 表DUAL
:
一般情况下,SELECT
子句的顺序必须严格按照上面的语法顺序。例如HAVING
子句必须在GROUP BY
子句之后并且在ORDER BY
子句之前。
1) select_expr
select_expr
用于指明要查询哪些列,其可以是一列
,或者是一个表达式
,或者是*
(表示查询所有):
- 假若查询列表只是一个单独的
*
,表示用于查询所有表的所有列
- 在其他形式下,使用一个未限定的
*
可能会造成SQL语法解析错误,为了避免这个问题,请使用限定的tbl_name.*
来引用
- 可以使用
AS alias_name
来为select_expr
指定一个别名,该别名可以被后续的GROUP BY
、ORDER BY
以及HAVING
子句所使用。例如:
其实你也可以使用tbl_name AS alias_name
来对table进行重命名。例如:
- 在
ORDER BY
、GROUP BY
子句中,可以使用列名(column names)、列的别名(column aliases)、或列号(column position)来引用SELECT
查询出的列。列号(column position)从1
开始:
这里如果要逆向排序的话,可以在ORDER BY
子句的列名后面添加DESC
关键字。
GROUP BY
子句允许你增加一个WITH ROLLUP
修饰符,以使在分组
的基础上有一个更高层的总结视图
2) SELECT … INTO 语法
SELECT ... INTO
形式使得SELECT
能够将查询结果存入变量或文件:
-
SELECT … INTO var_list: 用于查询列并将查询值存入变量
-
SELECT … INTO OUTFILE: 将查询到的值写入一个文件。可以指定列和行的结束符以格式话输出到文件。注意这里是将查询出来的数据写入到MySQL server
机器上的某一个文件中,文件必须要存在并且能够被访问。另外,假如你想要将查询出的结果保存到一个远程客户端,那么你必须在远程客户端使用MySQL Client
软件连接上SQL Server,然后通过mysql -e "SELECT ..." > file_name
来将文件保存在客户端宿主机上。关于更详细的数据导入导出相关语法我们后序会进行介绍,这里只给出一个例子:
- SELECT … INTO DUMPFILE: 将查询出来的
单独一行
数据写入到文件,不进行任何格式化
6. 示例
6.1 GROUP BY的使用
GROUP BY
语句根据一个或多个列对结果进行分组。在分组的列上我们可以使用COUNT、SUM、AVG等函数。
1) 构建示例表
将下面的语句写入到文件employee_tbl.sql
:
然后登录数据库,导入employ_tbl.sql
,从而创建测试表:
2) 使用GROUP BY语句分组查询
3) 使用WITH ROLLUP
WITH ROLLUP
可以实现分组统计数据基础上再进行相同的统计(SUM/AVG/COUNT)。例如我们将以上的数据表按名字进行分组,再统计每个人登录的次数:
其中记录NULL
表示所有人的登录次数。我们可以使用coalesce
来设置一个可取代NULL
的名称, coalesce
的语法:
select coalesce(a,b,c);
参数说明: 如果a==NULL,则选择b; 如果b==NULL,则选择c;如果都为NULL,则返回NULL
以下实例中如果名字为NULL,我们使用总数
来替代:
6.2 MySQL NULL值处理
我们已经知道,MySQL使用SQL SELECT 命令及WHERE子句来读取数据表中的数据,但是当提供的查询条件字段为NULL
时,该命令可能就无法正常工作。为了处理这种情况,MySQL提供了三大运算符:
-
IS NULL: 当列的值为NULL,此运算符返回true
-
IS NOT NULL: 当列的值不为NULL,此运算符返回true
-
<=>: 安全的NULL比较操作符(不同于=
运算符),当比较两个NULL值时返回true
在MySQL中,NULL通过=
运算符与任何数比较都返回NULL
:
1) 示例
尝试以下实例:
如下我们可以看到,=
与!=
运算符是不起作用的:
要查找表中的数据必须使用IS NULL
或IS NOT NULL
或<=>
操作符:
6.3 MySQL复制表
如果我们要完全复制MySQL的数据表,包括表的结构、索引、默认值等。这里我们介绍一下如何完整的复制MySQL数据表,步骤如下:
1) 获取数据表的完整结构
2) 创建新表
采用上面的获取到的表结构元数据
,我们来创建新表clone_tbl
:
3) 克隆旧表中的数据
执行完上面的步骤之后,我们通过INSERT INTO ... SELECT
来将旧表中的数据拷贝到新表:
[参看]:
- MySQL教程