mysql数据库基本操作

mysql数据库基本操作

SQL概述

SQL 是于 1974 年由 Boyce 和 Chamberlin 提出的, 并在 IBM 公司研制的关系数据库管理系统原型 System R 上实现。 由于 SQL 功能丰富、简单易学、使用方便, 深受用户和计算机工业界的欢迎, 被数据库厂商所广泛采用。

SQL的特点

SQL 是一个综合的、功能强大的且简洁易学的语言,它与诸如 Java、 C 等程序设计语言不同,是由很少的词构成, 这些词称为关键字,每个 SQL 语句都是由一个或多个关键字所组成。 SQL 的目的就是要能够很好地提供一种从数据库中读写数据的简单而有效的方法。

SQL 具有如下特点。

1) SQL 不是某个特定数据库供应商专有的语言。 几乎所有重要的关系数据库管理系统都支持 SQL, 所以掌握 SQL 可以帮助用户与几乎所有的关系数据库进行交互。

2) SQL 简单易学。 它的语句全都是由具有很强描述性的英语单词所组成, 而且这些单词的数目不多。

3) SQL 尽管看上去很简单,但它实际上是一种强有力的语言,灵活使用其语言元素,可以进行非常复杂和高级的数据库操作。

需要注意的是: SQL 语句不区分大小写。 许多 SQL 开发人员习惯于对所有 SQL 关键字使用大写,而对所有列和表的名称使用小写,这样的书写方式可使代码更易于阅读和调试,本书列举的实例也将遵照这个方式

SQL的组成

SQL 集数据查询 ( Data Query )、 数据定义 ( Data Definition )、 数据操纵 ( Data Manipulation)和数据控制 (Data Control) 四大功能于一体,其核心主要包含有以下几个部分。

  1. 数据定义语言 ( Data Definition Language , DDL )
    数据定义语言主要用于对数据库及数据库中的各种对象进行创建、删除、修改等操作。其中,数据库对象主要有表、默认约束、规则、视图、触发器、存储过程等。
    数据定义语言包括的主要 SQL 语句有以下三个。
    1) CREATE: 用于创建数据库或数据库对象。
    2) ALTER: 用于对数据库或数据库对象进行修改。
    3) DROP: 用于册除数据库或数据库对象。
    对于不同的数据库对象,这三个 SOL语句所使用的语法格式有所不同。
  2. 数据操纵语言 (Data Manipulation Language : DML )
    数据操纵语言主要用于操纵数据库中各种对象,特别是检索和修改数据。数据操纵语言包括的主要 SQL 语句如 下。
    1) SELECT: 用于从表或视图中检索数据, 其是数据库中使用最为频繁的 SQL 语句之-。
    2) INSERT: 用于将数据插入到表或视图中。
    3) UPDATE:用于修改表或视图中的数据,其既可修改表或视图中一行数据,也可同时修改多行或全部数据。
    4) DELETE: 用于从表或视图中删除数据, 其中可根据条件删除指定的数据。
  3. 数据控制 语言 ( Data Control Langua ge , DCL )
    数据控制语言主要用于安全管理, 例如确定哪些用户可以查看或修改数据库中的数据。数据控制语言包括的 主要 SOL 语包如 下
    1) GRANT: 用于授予权限, 可把语句许可或对象许可的权限授予其他用户和角色。
    2) REVOKE:用于收回权限,其功能与 GRANT 相反,但不影响该用户或角色从其他角色中作为成员继承许可权限。
  4. 嵌入式和动态 SQL 规则
    嵌入式和动态 SQL 规则规定了 SQL 语句在高级程序设计语言中使用的规范方法, 以便适应较为复杂的应用。
  5. SOL 调用和会话规则
    SQL 调用包括 SQL 例程和调用规则 ,以便提高 SQL 的灵活性、有效性、共享性以及使 SQL 具有更多的高级语言的特征。 SQL 会话规则则 可使应用程序连接到多个 SQL 服务器中的某一个, 并与之交互。 这一部分内容, 本书不作介绍。

MySQL预备知识

MySQL 是一个关系数据库管理系统(RDBMS),它具有客户/服务器体系结构,最初是由瑞典 MySQL AB 公司开发。由于其具有体积小、速度快、开放源代码、遵循 GPL (GNU 通用公共许可证) 等特点,许多中、小型网站为了降低网站总体拥有成本而选择 MySQL 作为网站数据库。尽管与其他诸如 Oracle、DB2、 SQL Server 等大型关系数据库相比, MySQL 还有一些不足之处, 但是这丝毫不影响它受欢迎的程度,如今 MySQL 已被广泛应用于 Intermet 上各类中、小型网站与信息管理系统的开发。因此,本书是以 MySQL 作为相关知识学习的实例数据库。

MySQL使用基础

目前,使用 MySQL 数据库管理系统构建各种信息管理系统或互联网网站的应用环境,主要有如下两种构架方式。

1 ) LAMP ( Linux +Apache+ MySQL+PHP/Perl/Python ), 即使用 Linux 作为操作系统, Apache 作为 Web 服务器, My SQL 作为数据库管理系统, PHP、 Perl 或 Python 语言作为服务器端脚本解释器。

2) WAMP ( Windows +Apache+ My SQL+PHP/Perl/Python ), 即 使用 Windows 作为 操作系统, Apache 作为 Web 服务器, My SQL 作为数据库管理系统, PHP、 Perl 或 Python 语言作为服务器端脚本解释器。

MySQL中的SQL

MySQL 作为 一种关系型数据库管理系统, 遵循 SQL 标准,提供了 对数据定义语言 DDL ( 如 CREATE 、 ALTER 、 DROP )、 数 据 操 纵 语 言 DML ( 如 SELECT 、 INSERT、 UPDATE、 DELETE )、 数据控制语言 DCL ( 如GRANT、 REVOKE ) 的支持, 井且同样支持关系数据库的三级模式结构。其外模式包括视图 ( View) 和部分基本表( Table), 数据库模式包括若干基本表,内模式则包括若干存储文件。其中,基本表是本身独立存在的表,在 MySQL 中一个关系对应一个基本表, 一个或多个基本表对应一个存储文件,一个表可以有若干索引,索引 也存放在存储文件中,其中存储文件的逻辑结构组成了 MySQL 的内模式,并且存储文件的物理结构对最终用户是隐蔽的:而视图则是从一个或几个基本表导出的表,尽管它也是关系,但其本身不独立存储在数据库中,即数据库中只存储视图的定义而不存储视图对应的数据,这些数据仍存储在导出视图的基本表中,因此视图是一个虚表,并且用户可以在视图上再定义视图。

此外,为方便用户编程, MySQL 在 SQL 标准的基础上增加了部分扩展的语言要素。这些语言要素包括常量、变量、运算符、表达式、函数、流程控制语句和注解等。

(1) 常量

常量是指在程序运行过程中值不变的量,也称为字面值或标量值。常量的使用格式取决于值的数据类型,可分为字符串常量、数值常量、十六进制常量、时间日期常量、位字段值、布尔值和 NULL 值。

· 字符串常量是指用单引号或双引号括起来的字符序列, 分为 ASCII 字符串常量和

Unicode 字符串常量。

· 数值常量可以分为整数常量和浮点数常量。其中, 整数常量是不带小数点的十进制

数:浮点数常量则是使用小数点的数值常量。

·一个十六进制值通常指定为一个字符串常量,每对十六进制数字被转换为一个字

符, 其最前面有一个大写字母 "X" 或小写字"x "。

·日期时间常量是用单引号将表示日期时间的字符串括起来而构成的。

·可以使用 b'value格式符号书写位字段值。 其中, value 是一个用 0 或1 书写的二进制

值。位字段符号可以方便地指定分配给 BIT 列的值。

2) 变量

变量用于临时存储数据: 变量中的数据可以随着程序的运行而变化: 变量有名字和数据类型两个属性。 其中, 变量的名字用于标识变量, 变量的数据类型用于确定变量中存储数值的格式和可执行的运算。

在 MySQL 中, 变量分为用户变量和系统变量。 在使用时, 用户变量前常添加一个符号"@ ", 用于将其与列名区分开: 而大多数系统变量应用于其他 SQL 语句中时, 必须在系统变量名称前添加两个 "@" 符号。

(3) 运算符

MySQL提供了如下几类编程语言中常用的运算符。

●算术运算符有:+(加)、-(减)、*(乘)、/(除)和%(求模)5种运算。

●位运算符有:&(位与)、丨(位或)、(位异或)、~(位取反)、>>(位右移)、<<

(位左移)。

比较运算符有:=(等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等

于)、(不等于)、!=(不等于)、<=>(相等或都等于空)。

·逻辑运算符有:NOT或!(逻辑非)、AND或&&(逻辑与)、OR或(逻辑或)

XOR(逻辑异或)

(4)表达式

表达式是常量、变量、列名、复杂计算、运算符和函数的组合。一个表达式通常可以得到一个值。与常量、变量一样,表达式的值也具有某种数据类型,可能的数据类型有字符类型、数值类型、日期时间类型。因而,根据表达式的值的数据类型,表达式可分为字符型表达式,数值型表达式和日期表达式。

(5) 内置函数

在编写 My SQL 数据库程序时,通常可直接调用系统提供的内置函数,来对数据库表进行相关操作。MySQL 中包含了 100 多个函数,基本分为如下几类:

· 数学函数, 例如 ABS()函数、 SORT()函数;

· 聚合函数, 例如 COUNT函数;

字符串函数, 例如 ASCII函数、 CHAR函数;

· 日期和时间函数, 例如 NOW 函数、 YEAR函数:

· 加密函数, 例如 ENCODE函数、 ENCRY PT函数;

· 控制流程函数, 例如 IFO函数、 IFNULL函数;

· 格式化函数, 例如 FORMAT函数;

· 类型转换函数, 例如 CAST函数;

· 系统信息函数,例如 USER函数、 VERSION函数。

数据定义、

关系数据库系统支持三级模式结构, 其模式、 外模式和内模式中的基本对象有数据库模式、表、索引、视图等。相应地, SQL 的数据定义功能包括数据库模式定义、表定义、索引定义和视图定义。 本节主要介绍使用相关的 SQL 语句实现数据库模式, 表和索引的定义。

其罗列了 SQL 标准所提供的数据定义语句 。 需要注意的是: SQL 标准不提供修改数据库模式定义和修改视图定义的操作,用户如果需要修改这些对象,可先将它们删除然后再重建,或者也可以使用具体的关系数据库管理系统所提供的扩展语句来实现,例如 My SQL 数据库中 的 ALTER SCHEMA、 ALTER VIEW 等语句: 另外, SQL 标准也没有提供索引相关的语句, 但为了提高查询效率, 商用关系数据库管理系统通常都提供了索引机制和相关语句 , 例如使用 MySQL 数据库中的 CREATE INDEX 语句 、 DROP INDEX 语句和 A LTER INDEX 语句分别实现创建、 删除和修改索引。

数据库模式的定义

数据库模式的定义包含数据库的创建、选择、修改、删除、查看等操作。

  1. 创建数据库
    在 MySQL 中, 可 以使用 CREATE DATABASE 或 CREATE SCHEMA 语句创建数据库,其语法格式是:
SQL 复制代码
CREATE{DATABASE|SCHEMA}[IF NOT EXISTS] db_name
[DEFAULT]CHARCTER SET [=] charset_name|[DEFAULT]COLLATE [=]collation_name

在此语法中:"\[\] "标示其内容为可选项:"" 用于分隔花括号中的选择项,表示可任选其中一项来与花括号外的语法成分共同组成 SQL 语句命令,即选项彼此间是"或" 的关系;"db _name " 用于标示具体的数据库命名, 且该数据库名必须符合操作系统文件夹命名规则,而在 MySQL 中则不区分大小写: 关键字" DEFAULT " 用于指定默认值:关键字" CHARACTER SET" 用于指定数据库字符集 ( Charset): 关键字 " COLLATE " 用于指定字符集的校对规则; 关键字"IF NOT EXISTS" 用于在创建数据库前进行判断,只有该数据库目前尚不存在时才执行 CREATE DATABASE 操作, 即此选项可以避免出现数据库已经存在而再新建的错误

SQL 复制代码
MariaDB [(none)]> CREATE DATABASE mysql_test;
ERROR 1007 (HY000): Can't create database 'mysql_test'; database exists
  1. 选择数据库
    在 My SQL 中, 使用 USE 语句可以实现从一个数据库"跳转" 到另一个数据库(一般用于数据库客户端或CLI), 在用 CREATE DATABASE 语句创建了数据库之后, 该数据库不会自动成为当前数据库, 需要用这条 USE 语句来指定, 其使用语法是:
SQL 复制代码
USE db_name;

只有使用 USE 命令指定某个数据库为当前数据库之后,才能对该数据库及其存储的数据对象执行各种后续操作

  1. 修改数据库
    在 MySQL 中,可以使用 ALTERDATABASE 或 ALTER SCHEMA 语句, 来修改已被创建的数据库的相关
SQL 复制代码
ALTER{DATABASE|SCHEMA}[db_name]
SQL 复制代码
MariaDB [(none)]> ALTER DATABASE mysql_test DEFAULT CHARACTER SET gb2312 DEFAULT COLLATE gb2312_chinese_ci;
Query OK, 1 row affected (0.001 sec)
  1. 删除数据库
    在 MySQL 中, 当需要删除已创建的数据库时, 可使用 DROP DATABASE 或 DROP SCHEMA 语句,其语法格式是:
SQL 复制代码
DROP  D ATABASE | CHEMA F E XISTS] db_name
SQL 复制代码
MariaDB [(none)]> DROP DATABASE mysqltest;
Query OK, 0 rows affected (0.002 sec)
MariaDB [(none)]> DROP DATABASE mysqltest;
ERROR 1008 (HY000): Can't drop database 'mysqltest'; database doesn't exist

由此可见, 可选项 " IF EXISTS " 可 以避免删除不存在的数据库时出现的 MySQL 错误信息。 另外, 需要注意 的 是: 使用 DROP DATABASE 或 DROP SCHEMA 语句会删除指定的整个数据库, 该数据库中的所有表 (包括其中的数据) 也将水久删除, 因而使用该语句时,需谨慎, 以免错误刪除

  1. 查看数据库
    在 MySQL 中, 可 使用 SHOW DATABASES 或 SHOW SCHEMAS 语句查看可用数据库列表,其语法格式是:
SQL 复制代码
SHOW  {}DATABASES | SCHEMAS }[LIKE ' pattem ' | WHERE expr]`
``
在此语法中: 可选项 " LIKE" 关键字用于匹配指定的数据库名称: 可选项 " WHERE "从句用于指定数据库名称查询范围的条件。
需要注意的是: 使用 SHOW DATABASES 或 SHOW SCHEMAS 语句, 只会列出当前用户权限范围内所能查看到的所有数据库名称。


```SQL
MariaDB [(none)]> SHOW DATABASES
    -> ;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mybatis            |
| mysql              |
| mysql_test         |
| performance_schema |
+--------------------+
5 rows in set (0.003 sec)

表定义

只有成功创建数据库之后, 才能在数据库中创建数据表。 数据表是关系数据库中最重要、最基本的数据对象,也是数据存储的基本单位。若没有表,数据库中其他的数据对象则没有意义。

数据表被定义为字段的集合,数据在表中是按照行和列的格式来存储的,每一行代表一条记录,每一列代表记录中一个字段的取值。创建数据表的过程,实质上就是定义每个字段的过程,同时也是实施数据完整性约束的过程。其中,确定表中每个字段的数据类型是创建表的重要步骤,而字段的数据类型则是定义该字段所能存储的数据值的类型。

下面,通过使用 SQL 语句在 MySQL 数据库中实现表的创建、更新、重命名、复制、删除和查看等操作,

  1. 创建表
    在 MySQL 中, 可以使用 CREATE TABLE 语句创建表。
    CREATE TABLE 语句的语法内容较多, 主要由表创建定义 (create definition)、 表选项(table options ) 和分区选项 (partition options) 等内容所构成。 其中,表创建定义是由表列的名字、列的定义以及可能的一个空值声明、一个完整性约束或表索引 项等组成,而表索引项则主要定义表的索引、主键、外键等。实际的表定义(包含所有列)均被括在圆括号中,各列彼此间用逗号分隔,每列的定义以列名 (在该表中必须是唯一的)开始,后跟列的数据类
    型以及可选参数。 因此, 通常使用该语句的基本语法格式是:
SQL 复制代码
CREATE [TEMPORARY] TABLE tab_name
(
	字段名1 数据类型 [列级完整性约束条件][默认值]
	[,字段名2 数据类型 [列级完整性约束条件][默认值]]
	[,.....]
	[,表级完整性约束条件]
) [ENGINE = 引擎类型]
SQL 复制代码
mysql> USE mysql test;
Database changed
my sql> CREA TE TABLE customers
->(
->cust id INT NOT NULL AUTO INCREMENT,
->cust_name CHAR(50) NOT NULL
->cust_sex CHAR(I) NOT NULL DEFAULT 0,
->cust_address CHAR(50) NULL,
->cust_contact CHAR(50) NULL,
->PRIMARY KEY (cust_id)
->);
Ouery OK  0 rows affected (0.1 1 sec)

(1) 临时表与持久表

在创建表的 CREATE TABLE 语句中, 若添加可选项 "TEMPORARY " 关键字, 则表示使用该语句创建的表为临时表, 而若不选用该关键字创建的表则为持久表 (通常, 简称表)。在数据库中,持久表一旦创建, 则将一直存在, 多个用户或者多个应用程序可以同时使用该持久表: 而在有些应用场景中,用户存在需要临时存放数据的需求,比如临时存储复杂的 SELECT 语句的查询结果, 尔后可能需要重复地使用这个结果, 但这个结果又不希望被永久保存,那么此时可以使用临时表。

在表的实际使用过程中,用户可以如同操作持久表一样,操作临时表,只是临时表的生命周期较短, 而且只能对创建它的用户可见, 当断开与该数据库的连接时, MySQL 会自动删除它们,这意味着两个不同的连接可以使用相同的临时表名称,同时两个临时表不会互相冲突,也不与原有的同名的非临时表冲突。

(2) 数据类型

数据类型是指系统中所允许的数据的类型。 数据库中每个列都应有适当的数据类型,用于限制或允许该列中存储的数据。 例如, 如果列中存储的为数字,则相应的数据类型应该为数值类型:如果列中存储的是日期、文本、注释、金额等,则应该用恰当的数据类型规定出来。数据类型可帮助正确地排序数据,并在优化磁盘使用方面起着重要的作用。因此,在创建表时必须为每个表列指定正确的数据类型及可能的数据长度。

在 MySQL 中, 主要的数据类型包括数值类型 ( 例如 I , 整型 int、 浮点型 double、 布尔型 bool)、日期和时间类型 (例如 ,日 期型 date、时间戳 timestamp 、时间型 time)、字符串类型(例如, 定长字符类型 char、 可变长字符类型 varchar )、 空间数据类型等。

(3) 关键字 AUTO INCREMENT

在 CREATE TABLE 语句中 , 使用关键字 " AUTO _ INCREMENT ", 可以为表中数据类型为整型的列设置自增属性, 从而能实现当插入 NULL 值或数字 0 到一个 AUTO INCREMENT 列中时, 该列的值会被自动设置为 "此前表中该列的最大值加 1"。 其中, AUTO _INCREMENT 顺序是从数字 1 开始, 同时每个表只能有 一个 AUTO _INCREMENT 列, 并且它必须被索引。

另外, 当一个表列被指定为 AUTO _INCREMENT 后, 其值是可以被覆盖的, 即可以简单地在表数据插入语句(INSERT 语句)中为该列指定一个值,只要该值是唯一的(尚未使用过),那么这个值将被用来替代系统自动生成的值,并且后续的增量将基于该手工插入的值。

(4)指定默认值

默认值是指在向表插入数据时,如果没有明确给出某个表列所对应的值,则 DBMS 此时允许为此表列指定的一个值。 在 MySQL 中, 默认值是用 CREATE TABLE 语句的列定义中关键字 " DEFAULT " 来指定。 如例 , 给 cust_sex 列的描述添加 " DEFAULT 0 ",用于指示 MySQL在未给出用户性别的情况下,使用默认值0 (代表"男")。

如果没有为列指定默认值, My SQL 会自动地为其分配一个。 如若该s列可以取 NULL 值, 则默认值为 NULL, 而如若该列被定义为 NOT NULL, 则默认值取决于该列的类型:对于没有声明 AUTO INCREMENT 属性的数字类型, 默认值是 0: 对于一个 AUTO INCREMENT 列,默认值是在顺序中的下一个值: 对于除 TIMESTAMP 以外的日期和时间类型,默认值是该类型适当的 "零" 值;对于表中第一个 TIMESTAMP 列,默认值是当前的日期和时间。

(5) NULL 值

NULL 值是指没有值或缺值,其在 MySQL 中是通过关键字 " NULL " 来指定的。 允许 NULL 的列,可以在插入行时不给出该列的值:而不充许 NULL 值的列,则不接受该列没有值的行,即在插入或更新行时,该列必须要有值。

在 MySQL 中 , 每个表列要么是 NULL 列, 要么是 NOT NULL 列, 这种状态在创建时由表的定义所规定。 NULL 为默认设置,如果不指定 NOT NULL, 则认为指定的是 NULL。 每个表列均都指定了是否为 NULL 列, 这将会通过返回错误和插入失败的方式, 来阻止在 NOT NU LL 列中插入没有值的列。

值得注意的是:不能将 NULL 值与空串相混淆,NULL 值是没有值, 它不是空串。如果指定" (两个单引号,其间没有字符), 这在 NOT NULL 列中是允许的,因为空串是一个有效的值, 它不是无值, 所以 NULL 值用关键字 " NULL " 而不是空串指定。

(6) 主键

在 CREATE TABLE 语句中, 主键是通过 PRIMARY KEY 关键字来指定的, 如 PRIMARY KEY (custid), 它指定用户的 id 号 cust_id 作为该表的主键。 主键值必须唯一,即表中的每个行必须具有唯一的主键值, 而且主键一定要为 NOT NULL。 如果主键使用单个列, 则它的值必须唯一: 如果使用多个列,则这些列的组合值也必须唯一。

  1. 更新表

为实现数据库中表规范化设计的目的,有时需要对之前已经创建的表做进一步的结构修改与调整。 在 MySQL 中, 可以使用 ALTER TABLE 语句来更改原有表的结构, 例如可以增加或删减列、创建或取消索引 、更改原有列的数据类型、重新命名列或表,还可以更改表的评注和表的引擎类型等,甚至还可以使用该语句为表重新创建触发器、存储过程、索引和外键等。

下面,通过在 ALTER TABLE 语句中使用不同的子句,分别介绍在 MySQL 数据库中更新表的相关操作。

(1) ADD COLUMN子句

如若需要向表中增加新列, 可在 ALTER TABLE 语句中添加 ADDCOLUMN子句来实现, 且其可同时增加多个列。

SQL 复制代码
MariaDB [mysql_test]> alter table mysql_test.customers add column cus_city char(10) NOT NULL DEFAULT 'Wuhan' AFTER sex;
Query OK, 0 rows affected (2.282 sec)
Records: 0  Duplicates: 0  Warnings: 0

例 4.6 中通过关键字 " AFTER " 在原表 cust _ sex 列之后添加了 一个新列 cust _ city, 也可通过关键字 "FIRST " 将新列 cust_city 作为原表的第 一列, 若不指定这两个关键字, 则新列会添加到原表的最后。另外, 此例中对表名的指定采用的是完全限定的表名方式, 即" db_name.tbl _name " 的表名格式。

类似地, 可以在 ALTER TABLE 语句中通过使用 ADDPRIMARY KEY 子句、 ADD FOREIGN KEY 子句、ADD INDEX 子句为原表添加一个主键、外键和索引等。

(2) CHANGE COLUMN 子句

如若需要修改表中列的名称或数据类型, 可在 ALTER TABLE 语句中添加 CHANGE COLUMN子句。 CHANGE COLUMN 子句可同时修改表中指定列的名称和数据类型, 且在 ALTER TABLE 语句中可 以同时放入多个 CHANGE COLUMN子句 , 只需彼此间用逗号分隔。

SQL 复制代码
MariaDB [mysql_test]> ALTER TABLE mysql_test.customers
    -> CHANGE COLUMN sex cust_sex char(1) NULL DEFAULT 'M';
Query OK, 0 rows affected (1.229 sec)
Records: 0  Duplicates: 0  Warnings: 0

需要注意的是: 如果将列原有的数据类型更换为另外 一种类型, 可能会丢失该列原有的数据: 如果试图改变的数据类型与原有数据类型不兼容, SOL 命令则不会被执行, 且系统会提示错误: 而在类型兼容的情况下, 该列的数据可能会被截断, 例如, 一个列的数据类型若从字符长度为 10 个字符的可 变长 字符类型 varchar(10)改为字符长度为 1 的定长字符数据类型 char(1), 则 该列 中的数据 " Wuhan " 将被截取成 " W "

(3 ) ALTER COLUMN 句

如若需要修改或删除表中指定列的默认值, 可在 ALTER TABLE 语句中添加 ALTER COLUMN 于 句。

SQL 复制代码
MariaDB [mysql_test]> ALTER TABLE mysql_test.customers
    -> ALTER COLUMN cust_city SET DEFAULT 'Beijing';
Query OK, 0 rows affected (0.002 sec)
Records: 0  Duplicates: 0  Warnings: 0

(4) MODIFY COLUMN 子句

与 CHANGE COLUMN子句有所不 同, 在 ALTER TABLE 语句中 添加 MODIFY COLUMN子句只会修改指定列的数据类型,而不会干涉它的列名。另外, MODIFY COLUM N子句还可 以 通过关键字 " FIRST" 或 "AFTER " 修改指定列在表中的位置。

SQL 复制代码
MariaDB [mysql_test]> ALTER TABLE mysql_test.customers
    -> MODIFY COLUMN cust_name char(20) FIRST;
Query OK, 0 rows affected (0.002 sec)
Records: 0  Duplicates: 0  Warnings: 0

(5) DROP COLUMN 子句

数据表中的列越多,DBMS 的工作负荷会增大,数据库所占用的空间也会相应增加,因而必要时需要规范化数据表, 并卸除表中多余的列, 此时可通过在 ALTER TABLE 语句中添加 DROP COLUMN子句来完成操作。

SQL 复制代码
MariaDB [mysql_test]> ALTER TABLE mysql_test.customers
    -> DROP COLUMN cust_contact;
Query OK, 0 rows affected (4.089 sec)
Records: 0  Duplicates: 0  Warnings: 0

另外,需要注意的是:一旦卸除列,原本存储在该列中的一切内容都会跟着被卸除,所

以在使用 DROP COLUMN子句时, 必须格外小心 。 类似地, 也可分别通过在 ALTER TABLE 语句中添 加 DROP PRIMARY KEY 子句 、 DROP FOREIGN KEY 子句、 DROP INDEX 子句卸除原表的主键、外键和索引等。

(6) RENAME TO 子句

在 ALTER TABLE 语句中,可以添加 RENAME TO子句为表重新赋予一个表名。

SQL 复制代码
MariaDB [mysql_test]> ALTER TABLE mysql_test.customers
    -> RENAME TO mysql_test.backup_customers;
Query OK, 0 rows affected (0.726 sec)
  1. 重命名表
    除了使用前面的 ALTER TABLE 语句, 还可 以直接用 RENAME TABLE 语句来更改表的名字,并可同时重命名多个表,其语法格式是:
SQL 复制代码
MariaDB [(none)]> RENAME TABLE mysql_test.backup_customers TO mysql_test.customers;
Query OK, 0 rows affected (0.665 sec)
  1. 删除表
    如若需要删除数据库中一个已存在的表,可以通过使用 DROP TABLE 语句来实现,其语法格式是:
SQL 复制代码
DROP [TEMPORARY ] TABLE [IF EXISTS]
tbl _ name [, tbl_name] ...
[RESTRICT | CASCADE]

需要注意的是: DROP TABLE 语句可以同时删除多个表 (包括临时表), 但操作者必须拥有该命令的权限:当表被删除时,其中存储的数据和分区信息均会被删除,所以使用该语句须格外小心,但操作者在该表上的权限并不会自动被删除。

  1. 查看表
    (1) 显示表的名称
    在 MySQL 中, 可以使用 SHOW TABLES 语句来显示指定数据库中存放的所有表名,其语法格式是:
SQL 复制代码
SHOW [FULL] TABLES [{FROM | IN } db _name ]
[LIKE 'XXXX'| WHERE expr]
SQL 复制代码
MariaDB [mysql_test]> show tables;
+----------------------+
| Tables_in_mysql_test |
+----------------------+
| customers            |
| seller               |
+----------------------+
2 rows in set (0.001 sec)

(2) 显示表的结构

在 MySQL 中,可以使用 SHOW COLUMNS 语句来显示指定数据表的结构,其语法格式是:

SQL 复制代码
SHOW [FULL] COLUMNS {FROM|IN ) tbl_name [FROM|IN] db_name [LIKE 'pattern'|WHERE expr]

或者, 使用 DESCRIBE 语句来完成,其语法格式是:

{DESCRIBE | DESC } tbl_name [col_name|wild ]

说明: MySQL 支持用 DESCRIBE 作为 SHOW COLUMNS FROM 的一种快捷方式。

SQL 复制代码
MariaDB [mysql_test]> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field        | Type     | Null | Key | Default | Extra          |
+--------------+----------+------+-----+---------+----------------+
| cust_name    | char(20) | YES  |     | NULL    |                |
| cust_id      | int(11)  | NO   | PRI | NULL    | auto_increment |
| cust_sex     | char(1)  | YES  |     | M       |                |
| cus_city     | char(10) | NO   |     | Wuhan   |                |
| cust_city    | char(50) | NO   |     | Beijing |                |
| cust_address | char(50) | YES  |     | NULL    |                |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.003 sec)

索引定义

所谓索引,就是 DBMS 根据表中的一列或若干列按照一定顺序建立的列值与记录行之间的对应关系表,因而索引实质上是一张描述索引列的列值与原表中记录行之间一一对应关系的有序表。在列上创建了索引之后,查找数据时可以直接根据该列上的索引 找到对应记录行的位置,从而快速地查找到数据。例如,图书管理员将图书名称与存放该图书的具体位置(如书架) 写在一张小卡片上,并按照图书名称的拼音顺序将所有的卡片排序,如此一来,在查找一本书名为 "数据库系统原理" 的书籍时,就可以根据拼音的顺序迅速找到记录有该书名及其具体位置的小卡片,从而根据卡片上记载存放该书的具体位置快速地找到所要查找的书籍,而这些小卡片就是索引。如若没有索引I, DBMS 则会通过表扫描方式逐个读取指定表中的数据记录来进行访问,这样的查找方式如同在图书馆里为查找一本书时将馆内所有的书籍都找寻一遍,如此查询的效率毫无疑问是非常低的。

由此可见,索引是提高数据文件访问效率的有效方法。目前,索引技术已经在各种数据库系统中得到了广泛应用。尽管索引可以大大加快数据查询的速度,但过多地使用索引也会增加系统的开销, 这是因为索引存在着一些弊端。

1) 索引是以文件的形式存储的, DBMS 会将一个表的所有索引保存在同一个索引文件中, 索引文件需要占用磁盘空间。 如果有大量的索引,索引文件可能会比数据文件更快地达到最大的文件尺寸。特别是如果在一个大表上创建了多种组合索引 ,索引 文件会膨胀得非常快。

2) 索引 在提高查询速度的同时,却会降低更新表的速度。在更新表中索引 列上的数据时,索引会被自动更新,以确保索引树与表中的内容保持一致,这可能需要重新组织一个索引。 如果表中的索引I很多, 这会 非常浪费时间, 由此会降低 INSERT、 UPDATE、DELETE 和其他写入操作的效率。表中的索引 越多,则更新表的时间就会越长。

因此,如果数据库中存在大量的表, 则需要认真研究建立更加优秀的索引 ,或者优化查询语句。根据具体用途, 索引在逻辑上通常包含有如下几类。

(1) 普通索引 (INDEX)

这是最基本的索引 类型, 它没有任何限制。 创建普通索引时, 通常使用的关键字是 INDEX 或 KEY 。

(2) 唯一性索引I (UNIQUE)

这类索引 和普通索引 基本相同, 只是有一点区别, 即索引 列中的所有值都只能出现一次, 必须是唯一的。 创建唯一性索引时, 通常使用的关键字 UNIQUE。

(3) 主键 ( PRIMARY KEY )

主键是 一种唯 一性索引I。 创建主键时, 必须指定关键字 PRIMARY KEY , 且不能有空值。主键一般是在创建表的时候指定,也可以通过修改表的方式添加主键,并且每个表只能有一个主键。

在实际使用中, 索引通常被创建成单列索引 和组合索引 。 其中, 单列索引 就是一个索引只包含原表中的一个列: 而组合索引 也称复合索引或多列索引, 就是原表中多个列共同组成一个索引。 一个表可以有多个单列索引, 但这些索引 不是组合索引。 按照最左边前缀的法则,一个组合索引 实质上为表的查询提供了多个索引 ,以此来加快查询速度。例如,若在一个表上创建了一个组合索引 (coll, col2, col3), 那么在实际的查询中, 可以被系统用来加快查询速度的索引 实际上有这样三个, 即单列索引 (col1) 、 多列索引 (coll, col2) 和多列索引( col l, col2, col3 )

  1. 索引的创建
    通过使用 SQL 语句, 在 MySQL 数据库中, 分别有三种方式来创建索引。
    (1 ) 使用 CREATE INDEX 语句创 建索引
    可以使用专 门用于创建索引I的 CREATE INDEX 语句在一个已有的表上创建索引I, 但该语句不能创建主键。 这个 SQL 语句的常用语法格式是:
SQL 复制代码
CREATE[UNIQUE|INDEX index_name]
ON tbl_name(index_col_name,...)

其中,index_col_name的格式为:

col_name[(length)][ASC|DESC]

在此语法中: 可选项 " UNIQUE " 关键字用于指定创建唯一性索引:"index name " 用于指定索引名,一个表可以创建多个索引 ,但每个索引在该表中的名称必须是唯一的:"tbl _name " 用于指定要建立索引的表名: "index _ col _name" 是关于索引列的描述。

其中,关于索引列的描述可包含这样三个语法要素:"col_name" 用于指定要创建索引的列名, 通常可考虑将查询语句中在 WHERE 子句和 JION 子句里出现的列来作为索引 列:可选项 "length",用于指定使用列的前 length 个字符来创建索引 , 使用列的一部分创建索引有利于减小索引文件的大小, 节省磁盘空间: 关键字"ASC "或" DESC " 是可选项, 用于指定索引I按升序 (ASC) 还是降序 (DESC) 来排列 , 默认时为 ASC

SQL 复制代码
MariaDB [(none)]> CREATE INDEX index_cust
    -> ON mysql_test.customers(cust_name,cust_id);
Query OK, 0 rows affected (2.182 sec)
Records: 0  Duplicates: 0  Warnings: 0

该语句成功执行后, 接着输入语句 SHOW INDEX F ROM mysql_ test.customers 即可查看到已建立的索引。

SQL 复制代码
MariaDB [(none)]> CREATE INDEX index_customers ON mysql_test.customers(cust_name(3) ASC);
Query OK, 0 rows affected (1.340 sec)
Records: 0  Duplicates: 0  Warnings: 0

(2) 使用 CREATE TABLE 语句创建索引

索引可以在创建表的同时一起被创建。 具体使用方法是, 可在 CREATE TABLE 语句语法中的表创建定义 (create definition) 部分添加以下语法成分中的某一项或几项:

i) 语法项CONSTRAINT \[symbol] PRIMARY KEY (index_col _name), 用于表示在创建新表的同时创建该表的主键:

ii) 语法项 {INDEX|KEY } index_name (index _col_name."), 用于表示在创建新表的同时创建该表的索引:

ii) 语法项CONSTRAINT \[symbol ] UNIQUE INDEX\|KEY index _name (index _col _ name""), 用于表示在创建新表的同时创建该表的唯一性索引:

iv ) 语法项CONSTRAINT \[symbol] FOREIGN KEY index _name (index _col _ name, ),用于表示在创建新表的同时创建该表的外键

其中, 关键字 " KEY " 是关键字 INDEX 的同义词: 关键字 " CONSTRAINT " 用于为主键、 UNIQUE 键、外键定义一个名字: 在使用 CREATE TABLE 语句定义列选项的时候,可以通过直接在某个列定义后面添加关键字 " PRIMARY KEY " 的方式来创建主键, 而当主键是由多个列组成的多列索引时, 则不能使用这种方法, 只能通过在语句最后加上一个 PRIMARY KEY(col_name, ...) 子句的 方式来实现 。

SQL 复制代码
MariaDB [mysql_test]> CREATE TABLE seller
    -> (
    -> seller_id int NOT NULL AUTO_INCREMENT,
    -> seller_name char(50) NOT NULL,
    -> seller_address char(50) NULL,
    -> seller_contact char(50) NULL,
    -> product_type int(5) NULL,
    -> sales int NULL,
    -> PRIMARY KEY(seller_id,product_type),
    -> INDEX index_seller(sales)
    -> );
Query OK, 0 rows affected (1.217 sec)

(3) 使用 ALTER TABLE 语句创 建索引

在使用 ALTER TABLE 语句修改表的同时, 可以向己有的表中添加索引。 具体使用方法是,可在 ALTER TABLE 语句语法中添加以下语法成分中的某一项或几项:

i) 语法项 ADD {INDEX|KEY } index _name(index_col _name,), 用于表示在修改表的同时为该表添加索引:

ii) 语法项 ADD CONSTRAINT \[symbol PRIMARY KEY (index _col _ name,...), 用 于表示在修改表的同时为该表添加主键:

iii)语法项 ADD CONSTRAINT \[symboljUNIQUE INDEX\|KE Y index _name (index _ col_name,...), 用于表示在修改表的同时为该表添加唯一性索引:

iv)语 法项 ADD CONSTRAINT \[symbolJFOREIGN KEY index _ name (index _col name,...), 用于表示在修改表的同时为该表添加外键。

SQL 复制代码
MariaDB [mysql_test]> ALTER TABLE mysql_test.seller
    -> add index index_seller_name(seller_name);
Query OK, 0 rows affected (1.259 sec)
Records: 0  Duplicates: 0  Warnings: 0
  1. 索引的查看
    如果需要查看表中 创建的索引 的情况, 可以使用 SHOW INDEX 语句, 其语法格式是:
SQL 复制代码
SHOW {INDEX | INDEXES | KEYS )
{FROM | IN} tbl name
[{FROM | IN} db _ name]
[WHERE expr]
  1. 索引的查看
    如果需要查看表中创建的索引I 的情况, 可以使用 SHOW INDEX 语句, 其语法格式是:
SQL 复制代码
SHOW {INDEX | INDEXES | KEYS)
{FROM | IN} tbl _ name
[{FROM | IN} db name]
[WHERE expr]
  1. 索引的删除
    当一个索引不再需要时, 可以使用 DROP INDEX 语句或 ALTER TABLE 语句来进行删除。
    (1) 使用 DROP INDEX 语句删除索引
    该语句的使用非常简单,其语法格式是:
SQL 复制代码
DROP INDEX index _name ON tbl _name

其中,"index _name " 用于指定要删除的索引名,"tbl_name " 用于指定该索引所在的表。

SQL 复制代码
MariaDB [mysql_test]> DROP INDEX index_cust ON mysql_test.customers;
Query OK, 0 rows affected (0.905 sec)
Records: 0  Duplicates: 0  Warnings: 0

(2) 使用 ALTER TABLE 语句删除索引

ALTER TABLE 语句也可以用于对索引 的删除。 其使用方法是,在 ALTER TABLE 语句中指定以下子句中的某一项:

i) 选用 DROP PRIMARY KEY 子句用于删除表中的主键, 由于一个表中只有一个主键, 其也是一个索引;

ii) 选用 DROP INDEX子句用于删除各种类型的索引:

ii) 选用 DROP FOREIGN KEY 子句用于删除外键。

数据更新

数据更新操作有三种: 向表中添加若干行数据、修改表中的数据和删除表中的若干行数据。在 SQL 中有三类相应的语句,分别是插入数据 (INSERT)、修改数据 (UPDATE) 和删除数据 (DELETE)。

插入数据

在 MySQL 中,可以使用 INSERT 语句, 向数据库中一个已有的表插入一行或多行元组数据。 INSERT 语句有三种语法形式, 分别对应的是 INSERT·· VALUES 语句、 INSERT SET 语句和 INSERT. SELECT 语句。

  1. 使用 INSERT VAL UES 语句插入单行或多 行元组数据
    在 My SQL 中, 使用 INSERT VALUES 语句插入单行或多行元组数据的语法格式是:
SQL 复制代码
INSERT [INTO] tbl_name [col_name,...]
	{VALUES|VALUE}({expr|DEFAULT},...),(....),...

在此语法中:

1)"tbl _name" 指定欲被插入数据的表名。

2)"col _name " 指定需要插入数据的列名列表。如果要向表中所有列插入数据,则全部列名均可省略, 尽管这种不必指定所有列名的语法非常简单,但它却高度依赖于表中所有列的定义次序,因而在表的结构有可能发生改变时就会显得特别不安全,所以应尽量总是使用明确指定所有列名的列表。如果只是向表的部分列插入数据, 则需要明确指定这些列的列名,而对于那些没有被指定的列, 它们的值可根据列的默认值或相关属性来确定, 通常 MySQL 是按照下列原则进行处理的:

i) 对于具有标志 (IDENTITY) 属性的列, 系统会自动生成序号值来唯一标志该列 :

ii) 具有默认值的列, 其值可通过在 INSERT 语句中指定关键字 " DEFAULT " 将其设为默认值:

ii) 没有默认值的列, 若允许为空值, 则其值可通过在 INSERT 语句中指定关键字" NULL " 将其设为空值, 若不允许为空值, 则 INSERT 语句执行出错:

iv ) 对于类型为 TIMESTAMP 的列, 系统会为其自动赋值:

V ) 由于 AUTO _ INCREMENT 属性列的值是在表中其他列被赋值之后生成的, 所以在对表中其他列做任何赋值操作 (如 INSERT 语句) 时, 对该 AUTO INCREMENT 属性列的引用只会返回数字 0。

3)通过关键字"VALUES "或" VALUE"引导的子句,其包含各列需要插入的数据清单。数据清单中数据的顺序必须与列的顺序相对应,同时该子句中的值可以是:

i) "expr ", 表示一个常量、 变量或一个表达式, 也可以是空值 NULL, 其值的数据类型要与列的数据类型一致,如果表达式的类型与列值不匹配, 这样做会造成类型转化或插入语句出错, 另外当列值为字符型时, 需要用单引号括起:

iI) 关键字 " DEFAULT", 即用于指定此列值为该列的默认值, 前提是该列之前已经明确指定了默认值: 否则插入语包会出错

SQL 复制代码
MariaDB [(none)]> INSERT INTO mysql_test.customers VALUES('zhangsan',901,'F','beijing','zhangyangqu');
Query OK, 1 row affected (0.317 sec)

--给的是0但是902
MariaDB [(none)]> INSERT INTO mysql_test.customers
    -> VALUES('LISI',0,DEFAULT,'WUHAN',NULL);
Query OK, 1 row affected (1.442 sec)

MariaDB [(none)]> select * from mysql_test.customers;
+-----------+---------+----------+-----------+--------------+
| cust_name | cust_id | cust_sex | cust_city | cust_address |
+-----------+---------+----------+-----------+--------------+
| zhangsan  |     901 | F        | beijing   | zhangyangqu  |
| LISI      |     902 | M        | WUHAN     | NULL         |
  1. 使用 INSERT*SET 语句插入部分列值数据
    在 MySQL 中,可以使用 INSERTSET 语句直接给表中的某(些)列指定对应的列值,即要插入数据的列名在 SET 子句中指定,这种方式会更加灵活,其语法格式是:
SQL 复制代码
INSERT INTO tbl_name
	SET col_name = {expr|DEFAULT},...
	
MariaDB [(none)]> INSERT INTO mysql_test.customers SET cust_name='李四',cust_address='武汉市',cust_sex=DEFAULT;
Query OK, 1 row affected (0.356 sec
  1. 使用 INSERT SE LECT 语句插入子查询数据
    子查询不仅可以嵌套在 SELECT 语句中, 用于构造父查询的条件, 也可以嵌套在 INSERT 语句中, 用于生成要批量插入的数据。 在 My SQL 中, 可 以使用 INSERT SELECT 语句来实现,其语法格式是:
SQL 复制代码
INSERT [INTO] tbl _ name [(col_name,.")]
SELECT ...

在此语法中: SELECT 子句用于快速地从一个或多个表中取出数据, 并将这些数据作为行数据插入到另一个表中, SELECT 子句返回的是一个查询到的结果集,INSERT 语句将这个结果集插入到指定表中,其中结果集中每行数据的字段数、字段的数据类型必须与被操作的表完全一致。

删除数据

SQL 复制代码
DELETE FROM tbl_name
[WHERE where _condition]
[ORDER BY ..]
[LIMIT row _count]

在此语法中: "tbl_name " 指定要删除数据的表名: 可选项 WHERE 子句表示为删除操作限定删除条件, 从而删除特定的行,若省略 WHERE 子句, 则表示删除该表中的所有行,但表的定义仍在数据字典中, 即 DELETE 语句删除的是表中的数据, 而不是关于表的定义: 可选项 ORDER BY 子句表示各行将按照子句中 指定的顺序进行册除: 可选项 LIMIT 子句用于告知服务器在控制命令被返回到客户端前被删除的行的最大值。

sql 复制代码
MariaDB [mysql_test]> DELETE FROM mysql_test.customers WHERE cust_name = 'LISI';
Query OK, 1 row affected (0.185 sec)

修改数据

SQL 复制代码
UPDATE tbl name
SET col_namel = {expr1|DEFAULT) [, col_name2= {expr2|DEFAULT}]
[WHERE where_condition]
[ORDER BY....]
[LIMIT row_count]

在此语法中: "tbl_ name " 指定要修改的表的名称: SET 子句用于指定表中要修改的列名及其列值,其中每个指定的列值可以是表达式,也可以是该列所对应的默认值,如果指定的是默认值, 则用关键字 " DEFAULT " 表示列值: 可选项 WHERE 子句用于限定表中要修改的行, 若不指定此子句, 则 UPDATE 语句会修改表中所有的行: 可选项 ORDER BY 子句用于限定表中的行被修改的次序: 可选项 LIMIT 子句用于限定被修改的行数。

SQL 复制代码
MariaDB [mysql_test]> UPDATE customers  SET cust_address='武汉' WHERE cust_name = 'zhangsan';
Query OK, 1 row affected (0.274 sec)
Rows matched: 1  Changed: 1  Warnings: 0

此外, 需要注意的是: 使用 UPDATE 语句可同时修改数据行的多个列值, 只需其彼此间用逗号分隔即可:如若删除表中某个列的值,在允许该列可为空值的前提下,可将它设置为 NULL 来实现。

数据查询

数据查询是 SQL 语言的核心功能, 也是数据库中使用得最多的操作, 其用途是从数据库的一张或多张表 (或视图) 中检索出满足条件的数据信息。通常,查询的结果是由 0 行(没有满足条件的数据) 或多行记录组成的一个记录集合,并允许选择一个或多个字段作为输出字段

SQL 是提供 SELECT 语句进行数据查询,该功能强大、使用灵活,其数学理论基础是关系数据模型中对表对象的组关系运算即选择,投影和连接

SELECT语句

使用 SELECT 语句可以在需要时从数据库中快捷方便地检索、统计或输出数据。 该语句的执行过程是从数据库中选取匹配的特定行和列, 并将这些数据组织成一个结果集,然后以张临时表的形式返回。 在 MySQL 中, SELECT 语句的常用语法格式是:

SQL 复制代码
[ALL | DISTINCT | DISTINCTROW ]
select_expr [ select_expr ]
FROM table_references
[WHERE where_condition ]
[GROUP BY {col_name | expr | position}
[ASC | DESC], " [ WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC],...]
[LIMIT [offset,] row_count | row_count OFFSET offset}]

在此语法结构中, SELECT 子句用于指定输出的字段: FROM 子句用于指定数据的来源: WHERE 子句用于指定数据的选择条件: GROUP BY 子句用于对检索到的记录进行分组:HAVING 子句用于指定组的选择条件: ORDER BY 子句用于对查询的结果进行排序。在这些子句中, SELECT 子句和 FROM 子句是必需的, 其他子句都是可选的, 并且在 SELECT 语句的使用中, 所有被添加选用的子句必须依照 SELECT 语句的语法格式所罗列的顺序来使用, 例如, 一个 HAVING 子句必须位于 GROUP BY 子句之后, 并位于 ORDER BY 子句之前,

此外, 在 SELECT 语句的语法结构中, 三个关键字 ALL DISTINCT DISTINCTROW 为可选项,用于指定是否应返回结果集中的重复行。若没有指定这些选项,则默认为 ALL,即 SELECT 操作中所有匹配的行, 包括可能存在的重复行, 都将被返回: 若指定选项 DISTINCT 或 DISTINCTROW , 则 会 消 除 结 果集 中 的 重 复 行 , 其中 DISTINCT 或 DISTINCTROW 为同义词, 且这两个关键字应用于 SELECT 语句中所指定的所有列, 而不仅仅是前置某个列。

列的选择与指定

在 SELECT 语句的使用 中 , 最简单的形式是 " SELECT aelect _expr" 使用这种最简单的 SELECT 语句, 可以进行数据库系统所 支持的任何运算, 例如, 执行语句 " SELECT 1+1"系统会返回数值 2。

在 SELECT 语句中, 语法项 " select_expr " 主要用于指定需要查询的内容, 其指定方法通常有以下几种。

  1. 选择指定的列
    选择一个或多个表中的某个或某些列作为 SELECT 语句的查询列 。 若查询列有多个, 则各个列名之间需要用逗号进行分隔, 且查询结果返回时, 结果集中各列的次序是依照 SELECT 语句中指定列的次序给出的: 若查询一个表中的所有列, 则可在 SELECT 语句指定列的位置上直接使用星号 ( *) 通配符, 而不必逐个列出所有列名, 此时结果集中各列的次序一般是这些列在表定义中出现的次序。另外, 列名的指定可以采用直接给出该列的名称的方式, 也可以使用完全限定的列名方式, 即 " tbl name.col_name " 的列名格式。
SQL 复制代码
MariaDB [mysql_test]> select cust_name,cust_sex,cust_address from mysql_test.customers;
+-----------+----------+--------------+
| cust_name | cust_sex | cust_address |
+-----------+----------+--------------+
| zhangsan  | F        | 武汉         |
| 李四      | M        | 武汉市       |
+-----------+----------+--------------+
2 rows in set (0.001 sec)


MariaDB [mysql_test]> SELECT * FROM customers;
+-----------+---------+----------+-----------+--------------+
| cust_name | cust_id | cust_sex | cust_city | cust_address |
+-----------+---------+----------+-----------+--------------+
| zhangsan  |     901 | F        | beijing   | 武汉         |
| 李四      |     903 | M        | Beijing   | 武汉市       |
+-----------+---------+----------+-----------+--------------+
2 rows in set (0.001 sec)

2.定义并使用列的别名

在系统输出查询结果集中某些列或所有列的名称时,若希望这些列的名称显示为自定义的列名, 而非原表中的列名, 则可以在 SELECT 语句中添加 AS 子句到指定的列名之后, 以此来修改查询结果集中列的别名。其具体使用方法是将 SELECT 语句的语法项 " select expr" 指定为如下语法格式:

column_name [AS] column_alias

SQL 复制代码
MariaDB [(none)]> select cust_name,cust_address AS 地址 from mysql_test.customers;
+-----------+-----------+
| cust_name | 地址      |
+-----------+-----------+
| zhangsan  | 武汉      |
| 李四      | 武汉市    |
+-----------+-----------+
2 rows in set (0.001 sec)
  1. 替换查询结查集中的数据
    在对表进行查询时,若希望得到对某些列的查询分析结果,而不是由查询得到的原始具体数据,则可以在SELECT语句中替换这些列,其中需要用到CASE表达式。其具体使用方法是可将SELECT语句的语法"select_expr"
SQL 复制代码
CASE 

WHEN 条件1 THEN 表达式1
WHEN 条件2 THEN 表达式2
...
ELSE 表达式

END [AS] column_alias
SQL 复制代码
MariaDB [mysql_test]> select cust_name ,case when cust_sex='M' THEN '男' when cust_sex='F' THEN '女' END AS 性别 FROM customers;
+----------------+--------+
| cust_name      | 性别   |
+----------------+--------+
| zhangsan       | 女     |
| 李四           | 男     |
| Barbara Thomas | 男     |
+----------------+--------+
3 rows in set (0.001 sec)
  1. 计算列值
    使用 SELECT 语句对列进行查询时, 在结果集中可以输出对列值计算后的值, 其具体使用方法是将 SELECT 语句的语法项 " select_expr " 指定为对应列参与计算的表达式。
SQL 复制代码
MariaDB [mysql_test]> SELECT  cust_name,cust_sex,cust_id+100
    -> FROM mysql_test.customers;
+----------------+----------+-------------+
| cust_name      | cust_sex | cust_id+100 |
+----------------+----------+-------------+
| zhangsan       | F        |        1001 |
| 李四           | M        |        1003 |
| Barbara Thomas | M        |        1004 |
+----------------+----------+-------------+
3 rows in set (0.002 sec)
  1. 聚合函数
    SELECT 语句的语法项 " select_expr " 也可以指定为聚合函数。 聚合函数通常是数据库系统中一类系统内置函数,常用于对一组值进行计算,然后返回单个值。 它通常与 GROUP BY 子句一起使用, 如果 SELECT 语句中有一个 GROUP BY 子句, 则这个聚合函数对所有列起作用,如果没有, 则 SELECT 语句只产生一行作为结果。 另外, 除 COUNT 函数外,聚合函数都会忽略空值。

FROM子句与多表连接查询

SELECT 语句的查询对象是由 FROM 子句指定的, 其可根据用户的查询需求实现单表或多表查询。中介绍的实例都是针对一个表进行的,但在实际查询中往往需要从多个表中获取信息,此时的查询就会涉及多张表。若一个查询同时涉及两个或两个以上的表,则称之为多表连接查询,也称多表查询或连接查询。

在关系数据库的设计中,为了减少数据的冗余,以及增强数据库的稳定性和灵活性,通常会基于关系规范化原则,将物理世界中的数据信息分解成多个表,实现一类数据一个表,并且在表与表之间通过设置 "键" (如主键,外键)的方式来保持多表之间的关联关系。 与之相反,在关系数据库的应用中,需要通过对表对象的连接运算,实现数据库中数据信息的组合,而这种数据组合的需求,在 SQL 中正是通过多表连接查询来实现的。因此,这种分解与组合数据的方法, 使得数据库系统能够更有效地存储数据,更方便地处理数据, 且可获得更大的可伸缩性。

多表连接查询是关系数据库中最主要的查询。 通过在 FROM 子句中指定多个表时, SELECT 操作会使用 "连接" 运算将不同表中需要查询的数据组合到一个结果集中, 并同样以一个临时表的形式返回,其连接方式主要包括交叉连接、内连接和外连接。

  1. 交叉连接
    交叉连接, 又称笛卡尔积。 在 MySQL 中, 它是通过在 FROM 子句中使用关键字"CROSS JOIN " 来连接两张表,从而实现一张表的每一行与另一张表的每一行的笛卡尔乘积, 并返回两张表的每一行相乘的所有可能的搭配结果 , 供 SELECT 语句中其他语法元素(如 WHERE 子句 、 GROUP BY 子句等) 进行过滤和筛选操作。
SQL 复制代码
SELECT * FROM tb1 CROSS JOIN  tbl2;

在 FROM子句中也可以省略关键字 CROSS JOIN,而使用逗号分隔交叉联接的两张表。由此下面等同的 SQL 语句形式:

SQL 复制代码
SELECT * FROM tb1,tab2;

需要注意的是: 交叉连接返回的查询结果集的记录行数,等于其所连接的两张表记录行数的乘积。 例如, tbl1 的记录行数为 100 条, 表 tbl2 的记录行数为 200 条, 则结果集的记录行数将是 100×200-20000 条。 由此可见,倘若所连接的两张表的记录行数很多时,交叉联接的查询结果会非常庞大,且查询执行时间非常长,甚至有可能会因为返回的数据过多而造成系统的停滞不前。因而,对于存在大量数据的表,应该避免使用交叉连接。

  1. 内连接
    内连接是一种最常用的连接类型,它是通过在查询中设置连接条件的方式,来移除查询结果集中某些数据行之后的交叉连接。具体而言,内连接就是利用条件判断表达式中的比较运算符来组合两张表中的记录, 其目的是为了消除交叉连接中的某些数据行。
    在 My SQL 中, 可以通过在 FROM 子句中使用关键字 " INNER JOIN " 连接两张表,并使用 ON 子句设置连接条件的方式来实现内连接,其语法格式是:
SQL 复制代码
SELECT some_columns
FROM table1 
INNER JOIN 
table2
ON some_conditions;

在此语法中: " some_columns " 用于指定需要检索的列的名称或列别名: " table1 " 和" table2 " 用于指定进行内连接的两张表的表名或表别名: ON 子句通过事先设定的连接条件" some_conditions", 来指定两张表按什么条件进行连接, 且连接条件中可采用任何一种比较运算符。其中,连接条件 "some _conditions " 一般使用的语法格式是:

[<table>.]<列名或列别名><比较运算符>[<table2>.]<列名或列别名>

SQL 复制代码
SELECT * FROM  tb_student INNER JOIN tb_score
ON tb_student.studentNO = tb_score.studentNo;

由于内连接是系统默认的表连接, 因而在 FROM 子句中可以省略关键字 " INNER ", 而只用关键字 " JOIN" 连接表。 在 FROM 子句中, 也可以在多个表之间连续使用关键字" INNER JOIN" 或关键字 "JOIN", 如此可以同时实现多个表的内连接。 此外, 关于内连接的使用,通常有如下三种情形。

(1) 等值连接

在 FROM 子句中使用关键字"INNER JOIN " 或"JOIN" 连接两张表时,如若在 ON子句的连接条件中使用运算符 "= " (即等号), 即进行相等性测试,则此连接方式称为等值连接, 也称为相等连接。 通常, 在等值连接的条件设置中会包舍 一个主键和一个外键。

(2) 非等值连接

在 FROM 子 句中 使用 关键字 " INNER JOIN " 或 " JOIN " 连接两张表时, 如若在 ON子句的连接条件中使用除运算符 "-" 之外的其他比较运算符 即进行不相等性测试, 则此连接方式称为非等值连接, 也称为不等连接。

(3) 自连接

在 FROM 子句中使用关键字 "INNER JOIN" 或"JOIN" 连接表时, 可以将一 个表与它自身进行连接,这种连接方式称为自连接。 自连接是一种特殊的内连接,若需要在一个表中查找具有相同列值的行,则可以考虑使用自连。使用自连接时,需要为表指定两个不同的别名, 且对所有查询列的引I 用均必须使用表别名限定, 否则 SELECT 操作会失败。

  1. 外连接
    内连接是在交叉连接的结果集上返回只满足条件的记录,但有时也会存在输出那些不满足连接条件的元组信息的查询需求,这种情况就需要使用外连接来实现。
    外连接是首先将连接的两张表分为基表和参考表,然后再以基表为依据返回满足和不满足条件的记录。外连接可以在表中没有匹配记录的情况下仍返回记录。外连接要比内连接更加注重两张表之间的关系,其根据连接表的顺序,可分为左外连接和右外连接两种。
    (1) 左外连接
    左外连接, 也称左连接, 它的使用语法格式与内连接大致相同,区别仅在于它在 FROM 子句中使用关键字 "LEFT OUTER JOIN " 或关键字 " LEFT JOIN" 来连接两张表, 而不是使用关键字 "INNER JOIN " 或 "JOIN ", 如此可用于接收关键字 " LEFT OUTER JOIN " 或"LEFT JOIN " 左边表 (也称为基表) 的所有行, 并用这些行与该关键字右边表 (也称为参考表)中的行进行匹配,即匹配左表中的每一行及右表中符合条件的行。
    这种连接方式特别适合当左表与右表具有一对多关系的情形。在左外连接的结果集中除了匹配的行之外,还包括左表中有的,但在右表中不匹配的行,对于这样的行,从右表中被选择的列的值被设置为 NULL。 也就是说,左外连接的结果集中的 NULL 值表示右表中没有找到与左表相符的记录。
    (2) 右外连接
    右外连接,也称右连接,它的使用语法格式与内连接大致相同,区别仅在于它在 FROM 子句中使用关键字 " RIGHT OUTER JOIN " 或关键字 " RIGHT JOIN " 来连接两张表, 而不是使用关键字 "INNER JOIN " 或 " JOIN "。
    右外连接是以右表为基表,其连接方法与左外连接完全一样。在右外连接的结果集中除了匹配的行之外,还包括右表中有的,但在左表中不匹配的行,对于这样的行,从左表中被选择的列的值被设置为 NULL
SQL 复制代码
SELECT * FROM tb_student LEFT JOIN tb_score ON tb_student.studentNo = tb.score.studentNo;

WHERE 子句与条件查询

在 SELECT 语句中, 可以使用 WHERE 子句指定过滤条件 (也称搜素条件或查询条件), 从 FROM 子句的中间结果中选取适当的数据行, 实现数据的过滤。 下面介绍 WHERE

1.比较运算

比较运算用于比较两个表达式的值。其中, MySQL 支持列出的所有比较运算符。当两个表达式的值均不为 NULL 时, 除了 "<=>" 运算符, 其他比较运算返回逻辑值 TRUE (真) 或 FALSE (假): 而当两个表达式值中有一个为空值或都为空值时, 则将返回 UNKNOWN。对于运算符 "<=>", 当两个表达式彼此相等或都等于空值时, 比较的结果值为 TRUE, 若其中有一个空值或者都是非空值但却不相等时, 则为 FALSE, 不会出现值为 UNKNOWN 的情况

SQL 复制代码
SELECT * FROM mysql_test.customers WHERE cust_sex = 'M'
  1. 判定范围
    在 W HERE 子句中, 用于范围判定的关键字有 " BETWEEN " 和 "IN" 两个。
    (1) BET WEEN.AND
    当查询的过滤条件被限定在值的某个范围时,可以使用关键字 " BETWEEN "。 它的使用语法格式是:
SQL 复制代码
expression[NOT]BETWEEN expression1 and expression2

其中, 表达式 expressionl 的值不能大于表达式 expression2 的值。 当不使用关键字" NOT " 时, 如果表达式 expression 的值在表达式 expressionl 与 expression2 之间 (包括这两个值), 则返回 TRUE, 否则返回 FALSE: 如果使用关键字 NOT 时, 其返回值正好相反

SQL 复制代码
SELECT * FROM mysql_test.customers WHERE cust_id BETWEEN 903 912;

(2) IN

使用关键字" IN "可以指定一个值的枚举表,该表中会列出所有可能的值,其使用语法格式是:

SQL 复制代码
expression IN (expression[,...n])

当要判定的值能与该表中任意会返回结果 TRUE,否则返回 FALSE 注意,尽管关键字'IN'可用于范围判定,但其最主要的作用是表达子查询

SQL 复制代码
SELECT * FROM mysql_test.customers WHERE cust_id IN(903,906,908)

3.判定空值

当需要判定一个表达式的值是否为空值时, 可以使用关键字"IS NULL" 来实现,其使用语法格式是:

SQL 复制代码
expression IS [NOT] NULL

其中,当不使用关键字 " NOT " 时, 如果表达式 expression 的值为空值, 则返回 TRUE, 否则返 回 FALSE: 而当使用关键字 " NOT " 时, 其结果正好相反。

SQL 复制代码
SELECT cust_name FROM mysql_test.customers WHERE cust_contact IS NULL;
  1. 子查询
    通常, 可以使用 SELECT 语句创建子查询, 即可嵌套在其他 SELECT 查询中的 SELECT 查询。在 MySQL 中,区分如下四类子查询。
    i) 表子查询,即子查询返回的结果集是一个表。
    i) 行子查询,即子查询返回的结果集是带有一个或多个值的一行数据。
    ii) 列子查询,即子查询返回的结果集是一列数据,该列可以有一行或多行,但每行只有一个值。
    iv ) 标量子查询, 即子查询返回的结果集仅仅是一个值。
    在指定查询条件的 WHERE 子句中,可以使用子查询的结果集作为过滤条件的一部分,并且子查询通常会与关键字 "IN ""EXIST" 和比较运算符结合使用。
    (1) 结合关键字 "IN " 使用的子查询
    结合关键字 "IN " 所使用的子查询主要用于判定一个给定值是否存在于在子查询的结果集中,其使用语法格式是:
SQL 复制代码
expression [NOT] IN (subquery)

在此语法中: subquery 用于指定子查,通常这里的子查询只能返回一列数据, 而对于比较复杂的查询要求,则可以使用 SELECT 语句实现子查询的多层嵌套: expression 用于指定表达式,当表达式与子查询返回的结果集中某个值相等时,过滤条件返回 TRUE,否则返回 FALSE, 若使用了关键字 " NOT", 则返回的值正好相反。

(2) 结合比较运算符使用的子查询

结合比较运算符所使用的子查询主要用于将表达式的值与子查询的结果进行比较运算,其使用语法格式是:

SQL 复制代码
expression {=|<|<=|>|>=|<=>|<>|!=} {ALL|SOME|ANY}(subquery)

在此语法中: 三个关键字 " ALL " SOME " 或 " ANY " 为选择项, 用于指定对比较运算的限制。 其中, 关键字 "ALL " 用于指定表达式需要与子查询结果集中的每个值都进行比较, 当表达式与每 个值都满足 比较关系时, 会返回 TRUE , 否则返回 FALSE: 关键字" SOME " 和 "ANY " 是同义词, 表示表达式只要与子查询结果集中的某个值满足比较关系时, 就返回 TRUE, 否则返 回 FALSE。

(3) 结合关键字 " EXIST " 使用的子查询

结合关键字 " EXIST " 所使用的子查询主要用于判定子查询的结果集是否为空。 它的使用语法格式是:

SQL 复制代码
EXIST(subquery)

其中, 如果子查询的结果集不为空, 则返回 TRUE, 否则返回 FALSE。

需要注意的是,在实际应用中,子查询通常可以改写成通过表的连接方式来实现,只是两者的执行性能会有所差异。

GROUP BY 子句与分组数据

在 SELECT 语句中, 允许使用 GROUP BY 子句, 将结果集中的数据行根据选择列的值进行逻辑分组,以便能汇总表内容的子集,即实现对每个组的聚集计算。因而, GROUP BY 子句可指示 DBMS 分组数据:然后对每个组而不是对整个结果集进行聚合。

GROUP BY 子句的使用语法格式是:

SQL 复制代码
GROUP BY {col_name | expr | position}[ASC | DESC],...[WITH ROLLUP]

i) col_name: 指定用于分组的选择列。 可以指定多个列,彼此间用逗号分隔。 注意, GROUP BY 子句中的各选择列 必须也是 SELECT 语句的选择列表清单中的一项。

ii) expr: 指定用于分组的表达式。该表达式通常与聚合函数一块使用,例如可将表达式 " COUNT(*) AS '人数" 作为 SELECT 语句的选择列表清单中的一项。

ii) position: 指定用于分组的选择列在 SELECT 语句结果集中的位置, 通常是一个正整数。 例如, 使用 GROUP BY 3 表示根据 SELECT 语句中列清单上的第 3 列的值进行逻辑分组。

iv ) ASC 丨 DESC: 关键字" ASC " 表示按升序分组: 关键字" DESC " 表示按降序分组。其中,默认值为 ASC。这两个关键字必须位于对应的列名、表达式、列的位置之后。

v) WITH ROLLUP: 此关键字为可选项,用于指定在结果集中不仅包含由 GROUP BY 子句分组后的数据行,还包含各分组的汇总行,以及所有分组的整体汇总行。因此,使用该关键字,可以得到每个分组以及每个分组汇总级别的值。

SQL 复制代码
SELECT cust_address,cust_sex,COUNT(*) AS '人数' 
FROM mysql_test.customers
GROUP BY cust_address.cust_sex;


SELECT cust_address,cust_sex,COUNT(*) AS '人数' 
FROM mysql_test.customers
GROUP BY cust_address.cust_sex
WITH ROLLUP;
---会出现没有cust_address,cust_sex值的汇总行。

由上述两个例子的执行结果可以看出, 在 GROUP BY 子句中添加了可选项 " WITH ROLLUP " 后, 将对 GROUP BY 子句中所指定的各列再次生成汇总行, 其汇总规则是: 按列的排列的逆序依次进行汇总,并且在生成的同一逻辑组的汇总行中,对于具有不同列值的字段值将被设置为 NU LL

此外,对于 GROUP BY 子句的使用, 需要注意以下几点。

i) GROUP BY 子句可以包含任意数目的列,使得其可对分组进行嵌套,为数据分组提供更加细致的控制。

i) 如果在 GROUP BY 子句中嵌套了 分组,那么将按 GROUP BY 子句中列的排列顺序的逆序方式依次进行汇总,并将在最后规定的分组上进行一个完全汇总。

) GROUP BY 子句中列出的每个列都必须是检索列或有效的表达式 , 但不能是聚合函数。如果在 SELECT 语句中使用表达式,则必须在 GROUP BY 子句中指定相同的表达式。注意,不能使用别名。

iv ) 除聚合函数之外, SELECT 语句中的每个列都必须在 GROUP BY 子句中给出。

V) 如果用于分组的列中含有 NULL 值,则 NULL 将作为一个单独的分组返回:如果该列中存在多个 NULL 值,则将这些NULL 值所在的行分为一组。

HAVING 子句

在 SELECT 语句中,除了能使用 GROUP BY 子句分组数据之外,还可以使用 HAVING子句来过滤分组, 即在结果集中规定包含哪些分组和排除哪些分组。

HAVING 子句的使用语法格式是:

SQL 复制代码
HAVING where_condition

其中, where _condition 用于指定过滤条件。

HAVING 子句与 WHERE 子句 非常相似, HAVING 子 句支持 WHERE 子句中所有的操作符和句法,但两者之间仍存在以下儿点差异。

i) WHERE 子句主要用于过滤数据行,而 HAVING 子句主要用于过滤分组, 即 HAVING 子句可基于分组的聚合值而不是特定行的值来过滤数据。

i) HAVING 子句中的条件可以包含聚合函数, 而 WHERE 子句中则不可以。

) WHERE 子句会在数据分组前进行过滤, HAVING 子句则会在数据分组后进行过滤。 因而, WHERE 子句排除的行不包含在分组中 , 这就会可能改变计算值, 从而影响 HAVING 子句基于这些值过滤掉的分组。

SQL 复制代码
nysql> SELECT cust_nane,cust _address
FROM nysql_test.custoners
GROUP BY cust_address,cust _nane
HAVING COUNT(*)<=3 ;

ORDER BY子句

在 SELECT 语句中, 可以使用 ORDER BY 子句将结果集中的数据行按一定的顺序进行排列,否则结果集中数据行的顺序是不可预料的。

ORDER BY 子句的使用语法格式是:

SQL 复制代码
ORDER BY {col_name | expr | position } [ASC | DESC],...

在此语法格式中:

i) col_name:指定用于排序的列。可以同时指定多个列,列名彼此间用逗号分隔。

ii) expr:指定用于排序的表达式。

ii) position: 指定用于排序的列在 SELECT 语句结果集中的位置,通常是一个正整数。例如,使用 ORDER BY 2 表示对 SELECT 语句中列清单上的第 2 列进行排序。

iv) ASC | DESC: 关键字 " ASC " 表示按升序排列: 关键字 " DESC " 表示按降序排列。其中,默认值为 ASC。 这两个关键字必须位于对应的列名 、表达式、列的位置之后。

SQL 复制代码
SELECT cust_name,cust_sex FROM mysql_test.customers
ORDER BY cust_name DESC,cust_address DESC;

此外, 关于 ORDER BY 子句的使用,需要注意以下儿点。

i ) ORDER BY 子句中可 以包含子查询。

ii) 当对空值进行排序时, ORDER BY 子句会将该空值作为最小值来对待。 即,若按升序排列结果集, 则 ORDER BY 子句会将该空值所在的数据行置于结果集的最上方: 若是使用降序排序, 则会将其置于结果集的最下方。

ii)若在 ORDER BY 子句中指定多个列进行排序,则在 MySQL 中会按照这些列从左至右所罗列的次序依次进行排序。

iv) 在使用 GROUP BY 子句时, 通常也会同时使用 ORDER BY 子句

LIMIT 子句

当使用 SELECT 语句返回的结果集中行数很多时,为了便于用户对结果数据的浏览和操作,可以使用 LIMIT 子句来限制被 SELECT 语句返回的行数。

LIMIT 子句的使用语法格式是:

LIMIT {[offset,]row_count|row_count OFFSET offset}

在此语法格式中:

i) offset: 为可选项, 默认为数字 0, 用于指定返回数据的第一行在 SELECT 语句结果集中的偏移量, 其必须是非负的整数常量。 注意, SELECT 语句结果集第一行 (初始行)的偏移量为0 而不是 1。

i) row _count: 用于指定返回数据的行数,其也必须是非负的整数常量。若这个指定行数大于实际能返回的行数时, 在 MySQL 中将只返回它能返回的数据行。

iii) row_count OFFSET offset: 从第 offset+ 1 行开始, 取 row _count 行。

SQL 复制代码
SELECT cust_id,cust_name FROM mysql_test.customers
OREER BY cust_id
LIMIT 4,3;

SELECT cust_id,cust_name FROM mysql_test.customers
OREER BY cust_id
LIMIT 3 OFFSET 4;

视图

从数据库的三级模式中,可以看到模式 (对应到基本表)是数据库中全体数据的逻辑结构,当不同的用户需要基本表中不同的数据时,可以为这些不同的用户建立不同的外模式。外模式中的内容来自于模式,它是模式的部分数据或重构的数据。外模式对应到数据库中的概念就是视图 (View )。

视图是数据库中的一个对象, 它是数据库管理系统提供给用户的以多种角度观察数据库中数据的一种重要机制。视图是从一个或多个表或者其他视图中通过查询语句导出的表,它也包含一系列带有名称的数据列和若干条数据行, 并有自己的视图名, 由此可见视图与基本表十分类似。然而,视图仍不同于数据库中真实存在的基本表,它们存在以下区别。

i) 视图不是数据库中真实的表,而是一张虚拟表,其结构和数据是建立在对数据库中真实表的查询基础上的。

ii) 视图的内容是由存储在数据库中进行查询操作的 SQL 语句来定义的, 它的列数据与行数据均来自于定义视图的查询所引用的真实表,并且这些数据是在引用视图时动态生成的。

iii)视图不是以数据集的形式存储在数据库中,它所对应的数据实际上是存储在视图所引用的真实表 (基本表)中。

iv) 视图是用来查看存储在别处的数据的一种虚表,而其自身并不存储数据。

尽管视图与数据库中的基本表存在着本质上的不同,但但视图一经定义后,可以如同使用基表一样,对视图进行查询,修改、删除和更新操作,并且使视图还具有如下一些优点。

i) 集中分散数据。当用户所需的数据分散在数据库多个表中时,通过定义视图可以将这些数据集中在一起,以方便用户对分散数据的集中查询处理。

ii) 简化查询语句。 通过定义视图可为用户屏蔽数据库的复杂性,使其不必详细了解数据库中复杂的表结构和表连接: 因而能简化用户对数据库的查询语句。 例如, 即便是底层数据库表发生了更改, 也不会影响到上层用户对数据库的正常使用, 只需数据库编程人员重新定义视图的内容即可。

iii) 重用 SQL 语句。 视图提供的是一种对查询操作的封装, 它本身不包含数据, 其所呈现的数据是根据视图的定义从基本表中检索出来的, 如若基本表中的数据被新增或更改,视图所呈现的则是更新后的数据。 因此, 通过定义视图,编写完所需查询后,可以方便地重用该视图, 而不必了解它的具体查询细节。

iv) 保护数据安全。通过只授予用户使用视图的权限,而不具体指定使用表的权限,来保护基础数据的安全性。

v) 共享所需数据。 通过使用视图,每个用户不必都定义和存储自己所需的数据,可以共享教据库中的数据,从而同样的数据只需存储一次。

vi) 更改数据格式。通过使用视图,可以重新格式化检索出的数据,并组织输出到其他应用程序中去。

创建视图

在 MySQL 中,可以使用 CREAT其常用的语法格式是:

SQL 复制代码
CREATE VIEW view_name[column_list]
AS select_statement
[WITH[CASCADED|LOCAL] CHECK OPTION]

在此语法结构中:

i) view _name 用于指定视图的名称, 且该名称在数据库中必须是唯一的, 不能与其他表或规图同名。

ii) column list 是可选项, 用于为视图中的每个列指定明确的名称, 且列名的数目必须等于 SELECT 语句检索出的结果数据集的列数, 同时每个列名间用逗号分隔。 如若省略 column_list,则新建视图使用与基本表或源视图中相同的列名。
iii) select
statement 用于指定创 建视图的 SELECT 语句。 这个 SELECT 语句给出 了 视图的定义, 它可用于查询多个基本表或源视图。

iv) WITH CHECK OPTION 是可选项, 用于指定在可更新视图上所进行的修改都需要符合 select_statement 中所指定的限制条件,这样可以确保数据修改后,仍可以通过视图看到修改后的数据。 当视图是根据另一个视图定义时, 关键字 " WITH CHECK OPTION " 给出两个参数, 即 CASCADED 和 LOCAL, 它们决定检查测试的范围。 其中, 关键字 " CASCADED "为选项默认值, 它会对所有视图进行检查, 而关键字 " LOCAL " 则使 CHECK OPTION 只对定义的视图进行检查。

SQL 复制代码
CREATE OR REPLACE VIEW mysql_test.customers_view
AS 
SELECT * FROM mysql_test.customers
WHERE cust_sex='M'
WITH CHECK OPTION

二 删除视图

在 MySQL 中,可以使用 DROP VIEW 语句来删除视图,其语法格式是:

SQL 复制代码
DROP VIEW [IF EXISTS]
view_name[,view_name]
[RESTRICT|CASCADE]

使用 DROP VIEW 语句可以一次删除多个视图,但必须在每个视图上拥有 DROP 权限。同时, 为防止因删除不存在的视图而出错, 需要在 DROP VIEW 语句中添加关键字 "F EXISTS ".

三 修改视图定义

在 MySQL 中, 可以使用 ALTER VIEW 语句来对已有视图的定义 (结构) 进行修改,其常用的语法格式是:

SQL 复制代码
ALTTER view_name [column_list]
AS select_statement
[WITH[CASCADE|LOCAL] CHECK OPTION]

由此可见,ALTER VIEW 语句与 CREATE VIEW 语句的使用语法相似。 此外,修改视图的定义,也可以通过先使用 DROP VIEW 语句,再使用 CREATE VIEW 语句的过程来实现。

四 查看视图定义

在 MySQL 中,可以使用 SHOW CREATE VIEW 语句来查看已有视图的定义 (结构),其语法格式是:

SQL 复制代码
SHOW CREATE VIEW view_name

五 更新视图数据

由于视图是一个虚拟表,所以通过插入、修改和删除等操作方式来更新视图中的数据,实质上是在更新视图所引用的基本表中的数据。然而,视图的更新操作是受一定限制的,并非所有的视图都可 以进行 INSERT、UPDATE 或 DELETE 等更新操作,只有满足可更新条件的视图才能进行更新,否则可能会导致系统出现不可预期的结果。对于可更新的视图,需要该视图中的行和基本表中的行之问具有一对一的关系。

  1. 使用 INSERT 语句通过视图向基本表插入数据
SQL 复制代码
INSERT INTO mysql_test.custmoers_view
VALUES('909','周明','M','武汉市','洪山区')

这条插入语句能够成功执行, 是因为在创建视图 customers_view 的语句中添加了 WITH CHECK OPTION 子句。 WITH CHECK OPTION 子句会在更新数据时,检查新数据是否符合视图定义中 WHERE 子句的条件, 并且 WITH CHECK OPTION 子句只能和可更新视图一起使用。若插入的新数据不符合 WHERE 子句的条件,则数据插入操作无法成功,因而此时视图的数据插入操作受限了。另外,当视图所依赖的基本表有多个时,也不能向该视图插入数据,这是因为在 My SQL 中不能正确地确定要被更新的基本表。

  1. 使用 UPDATE 语句通过视图修改基本表的数据
SQL 复制代码
UPDATE mysql_test.customers_view
SET cust_address = '上海市';

注意,若一个视图依赖于多个基本表,则一次视图数据修改操作只能改变一个基本表中的数据。

  1. 使用 DELETE 语句通过视图删除基本表的数据
SQL 复制代码
DELETE FROM mysql_test.customers_view 
WHERE cust_name = '周明';

注意,对于依赖多个基本表的视图,也是不能使用 DELETE 语句的。

六、查询视图数据

视图一经定义后,就可以如同查询数据库中的真实表一样,对视图进行数据查询检索:这也是对视图使用最多的一种操作。视图用于查询检索,主要体现在这样一些应用:利用视图简化复杂的表连接:使用视图重新格式化检索出的数据:使用视图过滤不想要的数据。

SQL 复制代码
SELECT cust_name,cust_addrss 
FROM mysql_test.customers_view
WHERE cust_id = 908
相关推荐
2603_965148111 小时前
电商选品调研:通过关键词搜索API获取市场热销商品,结合商品详情API分析竞品卖点与定价
开发语言·数据库·人工智能·python·信息可视化
土豆.exe1 小时前
nf_tables 的 verdict 被读了两次:一个十年未闭合的位域错配
java·数据库·网络安全·缓存
缓慢更新2 小时前
表单引擎的存储建模:宽表与文档库的取舍
运维·服务器·网络·数据库·低代码·oracle·适配器模式
Web3&Basketball4 小时前
实测Gemini4Argon:ERQA 87%登顶长程任务榜
数据库·python·大模型·多模态·gemini·长上下文·推理优化
xiaogai_gai4 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
注塑机数据采集联网4 小时前
注塑机数据采集网关对接MES系统数字化技术方案
大数据·网络·数据库·物联网·数据挖掘·数据分析
像风一样自由20204 小时前
56.实战PostgreSQL-pgvector-FastAPI构建轻量级RAG
数据库·人工智能·postgresql·大模型·fastapi·智能体
User_芊芊君子5 小时前
KFS异构同步_260条链路DDL自动转换解析
数据库·ai·大模型
xiancai_xianyu5 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架