MySQL数据库与JDBC编程(一)

JDBC基础

JDBC的全称是Java Database Connectivity,即数据库连接,它是一种可以执行SQL语句的JavaAPI。程序可通过JDBC API连接到关系数据库,并使用结构化查询语言(SQL,数据库标准的查询语言)来完成对数据库的查询、更新。

JDBC简介

通过使用JDBC,就可以使用同一种API访问不同的数据库系统。
JDBC驱动示意图
在这里插入图片描述
正是通过JDBC驱动的转换,才使得使用相同JDBC API编写的程序,在不同的数据库系统上运行良好。Sun提供的JDBC可以完成以下三个基本工作。

  1. 与数据库建立连接
  2. 执行SQL语句
  3. 获得SQL语句的执行结果

通过JDBC的这三个功能,应用程序就可以使用JDBC来操作数据库系统了

JDBC驱动程序

数据库驱动程序是JDBC程序和数据库之间的转换层,数据库驱动程序负责将JDBC调用映射成特定的数据库调用。

    	              JDBC访问示意图

在这里插入图片描述

ODBC的全称是Open Database Connectivity,即开放数据库连接。ODBC和JDBC很像,严格地说,应该说JDBC模仿了ODBC的设计。ODBC也允许应用程序通过一组通用的API访问不同的数据库管理系统,从而使得基于ODBC的应用程序可以在不同的数据库之间切换。同样,ODBC也需要各数据库厂商提供相应的驱动程序,而ODBC则负责管理这些驱动程序。

SQL语法

SQL语句是对所有关系数据库都通用的命令语句,而JDBC API则是执行SQL语句的工具,JDBC允许对不同的平台、不同的数据库采用相同的编程接口来执行SQL语句。

关系数据库基本概念和MySQL基本命令

严格来说,数据库仅仅是存放用户数据的地方。当用户访问、操作数据库中的数据时,就需要数据库管理系统的帮助。数据库管理系统的全称是Database Management System,简称DBMS。我们常常会把数据库和数据库管理系统笼统地称为数据库,通常所说的数据库既包括存储用户数据的部分,也包括管理数据库的管理系统。

MySQL数据库的一个实例(Server Instance)可以同时包含多个数据库,MySQL使用如下命令来查看当前实例下包含多少个数据库

SHOW DATABASES;

删除指定数据库

DROP DATABASE 数据库名;

创建新的数据库,其中IF NOT EXISTS是可选的,如果加上则代表数据库不存在时才会创建

CREATE DATABASE [IF NOT EXISTS] 数据库名;
建立了数据库之后,如果想操作该数据库,则需要进入该数据库

进入指定数据库命令

use 数据库名;

查询该数据库下包含多少个数据表

SHOW TABLES;

查看指定数据表的表结构

DESC 表名;

连接远程主机的MySQL服务命令

mysql -p 密码 -u 用户名 -h 主机名

执行上面命令时可以省略-p后面的密码,执行该命令后系统会提示输入密码

MySQL数据库通常支持如下两种存储机制
  1. MyISAM:这是MySQL早期默认的存储机制,对事务支持不够好
  2. InnoDB:InnoDB提供事务安全的存储机制。InnoDB通过建立行级锁来保证事务完整性,并以Oracle风格的共享锁来处理select语句。系统默认启动InnoDB存储机制

SQL语句基础

SQL的全称是Structured Query Language,也就是结构化查询语言。SQL是操作和检索关系数据库的标准语言,标准的SQL语句可用于操作任何关系数据库。

使用SQL语句可以完成如下任务

  1. 在数据库中检索信息
  2. 对数据库的信息进行更新
  3. 改变数据库的结构
  4. 更改系统的安全设置
  5. 增加用户对数据库或表的许可权限

在上面的5个任务中,一般程序员可以管理前3个任务,后面2个任务通常由DBA来完成。

标准的SQL语句通常可分为如下几种类型

  • 查询语句:主要由select关键字完成,查询语句是SQL语句中最复杂、功能最丰富的语句
  • DML(Data Manipulation Language,数据操作语言)语句:主要由insetupdatedelete三个关键字完成
  • DDL(Data Definition Language,数据定义语言)语句:主要由createalterdroptruncate四个关键字完成
  • DCL(Data Control Language,数据控制语言)语句:主要由grantrevoke两个关键字完成
  • 事务控制语句:主要由commitrollbacksavepoint三个关键字完成

DDL语句

DDL语句是操作数据库对象的语句,包括创建(create)、删除(drop)和修改(alter)数据库对象

常见的数据库对象
在这里插入图片描述

建表语句示例
create table test(
	# 整型通常用int
	test_id int,
	# 小数点数
	test_price decimal,
	# 普通长度文本,使用default指定默认值
	test_name varchar(255) default 'xxx',
	# 大文本类型
	test_desc text,
	# 图片
	test_img blob,
	test_date datetime
);

建表时需要指定每列的数据类型,不同数据库所支持的列类型不同,这需要查阅不同数据库的相关文档。
MySQL支持的列类型
在这里插入图片描述

使用子查询建表语句,可以在建表的同时插入数据
# 创建haha数据表,该数据表和user_inf完全相同,数据也完全相同
create table haha 
as
select * from user_inf;

当数据表创建成功后,MySQL使用information_schema数据库里的TABLES表来保存该数据库实例中的所有数据表,可以通过查询TABLES表来获取该数据库的表信息

修改表结构的语法

修改表结构使用alter table,修改表结构包括增加列定义、修改列定义、删除列、重命名列等操作。
增加列定义语法

# 为hehe数据表增加一个hehe_id字段,该字段的类型为int
# 如果只是增加一列,则可以省略圆括号
alter table hehe
add hehe_id int;

# 为hehe数据表增加aaa、bbb字段,两个字段的类型都为varchar(255)
alter table hehe
add(
	aaa varchar(255) default 'xxx',
	bbb varchar(255)
);

修改列定义语法

# 将hehe表的hehe_id列修改成varchar(255)类型
alter table hehe
modify hehe_id varchar(255);

# 将hehe表的bbb列修改成int类型
alter table hehe 
modify bbb int;

删除列定义语法

# 删除hehe表中的aaa字段
alter table hehe
drop aaa;

重命名数据表的语法

# 将hehe数据表重命名为wawa
alter table hehe
rename to wawa;

完全改变列定义

# 将wawa数据表的bbb字段重命名为ddd
alter table wawa
change bbb ddd int;

对比change和modify连个选项,不难发现:change选项比modify选项多了一个列名,因为change选项可以改变列名,所以它需要两个列名。一般而言,如果不需要改变列名,使用alter table的modify选项即可,只有当需要修改列名时才会使用change选项。

删除表的语法

# 删除数据表
drop table wawa;

删除表的效果如下

  • 表结构被删除,表对象不再存在
  • 表里的所有数据也被删除
  • 该表所有相关的索引、约束也被删除
truncate表

对于大部分数据库而言,truncate都被当成DDL处理,truncate被称为截断某个表,它的作用是删除该表里的全部数据,但保留表结构。相对于DML里的delete命令而言,truncate的速度要快得多,而且truncate不像delete可以删除指定的记录,truncate只能一次性删除整个表的全部记录。

truncate 表名;

数据库约束

约束是在表上强制执行的数据校验规则,约束主要用于保证数据库里数据的完整性。除此之外,当表中数据存在相互依赖性时,可以保护相关的数据不被删除。

大部分数据库支持下面5种完整性约束

  1. NOT NULL:非空约束,指定某列不能为空
  2. UNIQUE:唯一约束,指定某列或者几列组合不能重复
  3. PRIMARY KEY:主键,指定该列的值可以唯一地标识该条记录
  4. FOREIGN KEY:外键,指定该行记录从属于主表中的一条记录,主要用于保证参照完整性
  5. CHECK:检查,指定一个布尔表达式,用于指定对应列的值必须满足该表达式

虽然大部分数据库都支持上面5种约束,但MySQL不支持CHECK约束,虽然MySQL的SQL语句也可以使用CHECK约束,但这个CHECK约束不会有任何作用。

虽然约束的作用只是用于保证数据表里数据的完整性,但约束也是数据库对象,并被存储在系统表中,也拥有自己的名字。根据约束对数据列的限制,约束分为如下两类

  1. 单列约束:每个约束只约束一列
  2. 多列约束:每个约束可以约束多个数据列

为数据表指定约束有如下两个时机

  1. 在建表的同时为相应的数据列指定约束
  2. 建表后创建,以修改表的方式来增加约束

MySQL使用information_schema数据库里的TABLE_CONSTRAINTS表来保存该数据库实例中所有的约束信息

NOT NULL约束
建表时为指定列指定非空约束,只要在列定义后增加not null即可

create table hehe(
	# 建立了非空约束,这意味着hehe_id不可以为null
	hehe_id int not null,
	# MySQL的非空约束不能指定名字
	hehe_name varchar(255) default 'xyz' not null,
	# 下面列可以为空,默认就是可以为空
	hehe_gender varchar(2) null
);

也可以在使用alter table修改表时增加或删除非空约束

# 增加非空约束
alter table hehe
modify hehe_gender varchar(2) not null;

# 取消非空约束
alter table hehe 
modify hehe_name varchar(255) null;

# 取消非空约束,并指定默认值
alter table hehe
modify hehe_name varchar(255) default 'abc' null;

UNIQUE约束
唯一约束用于保证指定列或指定列组合不允许出现重复值。虽然唯一约束的列不可以出现重复值,但可以出现多个null值(因为在数据库中null不等于null)。

同一个表内可建多个唯一约束,唯一约束也可由多列组合而成。当为某列创建唯一约束时,MySQL会为该列相应地创建唯一索引。如果不给唯一约束起名,该唯一约束默认与列名相同。

使用列级约束语法建立唯一约束非常简单,只要简单地在列定义后增加unique关键字即可。

# 建表时创建唯一约束,使用列级约束语法建立约束
create table unique_test(
	# 建立了非空约束,这意味着test_id不可以为null
	test_id int not null,
	# unique就是唯一约束,使用列级约束语法建立唯一约束
	test_name varchar(255) unique
);

如果需要为多列组合建立唯一约束,或者想自行指定约束名,则需要使用表级约束语法。

# 建表时创建唯一约束,使用表级约束语法建立约束
create table unique_test2(
	# 建立了非空约束,这意味着test_id不可以为空
	test_id int not null,
	test_name varchar(255),
	test_pass varchar(255),
	# 使用表级约束语法建立唯一约束
	unique(test_name),
	# 使用表级约束语法建立唯一约束,而且指定约束名
	constraint test2_uk unique(test_pass)
);

我们还可以为多列组合建立唯一约束

# 建表时创建唯一约束,使用表级约束语法建立约束
create table unique_test3(
	# 建立了非空约束,这意味着test_id不可以为空
	test_id int not null,
	test_name varchar(20),
	test_pass varchar(50),
	# 使用表级约束语法建立唯一约束,指定两列组合唯一
	constraint test3_uk unique(test_name,test_pass)
);

也可以在修改表结构时使用add关键字来增加唯一约束

# 增加唯一约束
alter table unique_test3
add unique(test_name,test_pass);

对于大部分数据库而言,删除约束都是在alter table语句后使用drop constraint 约束名语法来完成的,但MySQL并不使用这种方式,而是使用drop index 约束名的方式来删除约束

# 删除unique_test3表上的test3_uk唯一约束
alter table unique_test3
drop index test3_uk;

PRIMARY KEY约束
主键约束相当于非空约束和唯一约束,即主键约束的列既不允许出现重复值,也不允许出现null值;如果对多列组合建立主键约束,则多列里包含的每一列都不能为空,但只要求这些列组合不能重复。

每一个表中最多允许有一个主键,但这个主键约束可由多个数据列组合而成,主键是表中能唯一确定一行记录的字段或字段组合。

当创建主键约束时,MySQL在主键约束所在列或列组合上建立对应的唯一索引。

建表时创建主键约束,使用列级约束语法

create table primary_test(
	# 建立了主键约束
	test_id int primary key,
	test_name varchar(255)
);

建表时创建主键约束,使用表级约束语法

create table primary_test2(
	test_id int not null,
	test_name varchar(255),
	test_pass varchar(255),
	# 指定主键约束名为test2_pk,对大部分数据库有效,但对MySQL无效
	# MySQL数据库中该主键约束名依然是PRIMARY
	constraint test2_pk primary key(test_id)
);

建表时创建主键约束,以多列建立组合主键,只能使用表级约束语法

create table primary_tese3(
	test_name varchar(255),
	test_pass varchar(255),
	# 建立多列组合的主键约束
	primary key(test_name,test_pass)
);

删除指定表的主键约束

# 删除主键约束
alter table primary_test3
drop primary key;

很多数据库对主键列都支持一种自增长的特性,如果某个数据列的类型是整型,而且该列作为主键列,则可指定该列具有自增长功能。

create table primary_test4(
	# 建立主键约束,使用自增长
	test_id int auto_increment primary key,
	test_name varchar(255),
	test_pass varchar(255)
);

FOREIGN KEY 约束
外键约束主要用于保证一个或两个数据表之间的参照完整性,外键是构建于一个表的两个字段或者两个表的两个字段之间的关系。外键确保了相关的两个字段的参照关系:子(从)表外键列的值必须在主表被参照列的值范围之内,或者为空(也可以通过非空约束来约束外键列不允许为空)。

当主表的记录被从表记录参照时,主表记录不允许被删除,必须先把从表里参照该记录的所有记录全部删除后,才可以删除主表的该记录。还有一种方式,删除主表记录时级联删除从表中所有参照该记录的从表记录。

从表外键参照的只能是主表主键列或者唯一键列,这样才可保证从表记录可以准确定位到被参照的主表记录。同一个表内可以拥有多个外键。

建立外键约束时,MySQL也会为该列建立索引。

建立外键约束同样可以采用列级约束语法和表级约束语法。如果仅对单独的数据列建立外键约束,则使用列级约束语法即可;如果需要对多列组合创建外键约束,或者需要为外键约束指定名字,则必须使用表级约束语法。

采用列级约束语法建立外键约束直接使用references关键字,references指定该列参照哪个主表,以及参照主表的哪一列。

# 为了保证从表参照的主表存在,通常应该先建主表
create table teacher_table1(
	# auto_increment:代表数据库的自动编号策略,通常用作数据表的逻辑主键
	teacher_id int auto_increment,
	teacher_name varchar(255),
	primary key(teacher_id)
);

create table student_table1(
	# 为本表建立主键约束
	student_id int auto_increment primary key,
	student_name varchar(255),
	# 指定java_teacher参照到teacher_table1的teacher_id列
	java_teacher int references teacher_table1(teacher_id)
);

注意,虽然MySQL支持使用列级约束语法来建立外键约束,但这种列级约束语法建立的外键约束不会生效,MySQL提供这种列级约束语法仅仅是为了和标准的SQL保持良好的兼容性。因此,如果要使MySQL中的外键约束生效,则应使用表级约束语法。

# 为了保证从表参照的主表存在,通常应该先建主表
create table teacher_table(
	teacher_id int auto_increment,
	teacher_name varchar(255),
	primary key(teacher_id)
);

create table student_table(
	student_id int auto_increment primary key,
	student_name varchar(255),
	# 指定java_teacher参照到teacher_table的teacher_id列
	java_teacher int,
	foreign key(java_teacher) references teacher_table(teacher_id)
);

如果使用表级约束语法,则需要使用foreign key来指定本表的外键列,并使用references来指定参照哪个主表,以及参照到主表的哪个数据列。使用表级约束语法可以为外键约束指定约束名,如果创建外键约束时没有指定约束名,则MySQL会为该外键约束命名为table_name_ibfk_n,其中table_name是从表的表名,而n是从1开始的整数。

# 为了保证从表参照的主表存在,通常应该先建主表
create table teacher_table2(
	teacher_id int auto_increment,
	teacher_name varchar(255),
	primary key(teacher_id)
);

create table student_table2(
	student_id int auto_increment primary key,
	student_name varchar(255),
	java_teacher int,
	# 使用表级约束语法建立外键约束
	# 指定外键约束的约束名为student_teacher_fk
	constraint student_teacher_fk 
	foreign key(java_teacher) references teacher_table(teacher_id)
);

如果需要建立多列组合的外键约束,则必须使用表级约束语法

# 为了保证从表参照的主表存在,通常应该先建主表
create table teacher_table3(
	teacher_name varchar(50),
	teacher_pass varchar(50),
	# 以两列建立组合主键
	primary key(teacher_name, teacher_pass)
);

create table student_table3(
	# 为本表建立主键约束
	student_id int auto_increment primary key,
	student_name varchar(255),
	java_teacher_name varchar(50),
	java_teacher_pass varchar(50),
	# 使用表级约束语法建立外键约束,指定两列的联合外键
	foreign key(java_teacher_name, java_teacher_pass) references teacher_table3(teacher_name, teacher_pass)
);


删除外键约束

# 删除student_table3表上名为student_table3_ibfk_1的外键约束
alter table student_table3
drop foreign key student_table3_ibfk_1;

增加外键约束通常使用add foreign key命令

# 修改student_table3数据表,增加外键约束
alter table student_table3
add foreign key(java_teacher_name, java_teacher_pass) references teacher_table3(teacher_name, teacher_pass);

外键约束不仅可以参照其他表,而且可以参照自身,这种参照自身的情况通常被称为自关联。

# 使用表级约束语法建立外键约束键,且直接参照自身
create table foreign_test(
	foreign_id int auto_increment primary key,
	foreign_name varchar(255),
	# 使用该表的refer_id参照到本表的foreign_id列
	refer_id int,
	foreign key(refer_id) references foreign_test(foreign_id)
);

如果想定义当删除主表记录时,从表记录也会随之删除,则需要在建立外键约束后添加on delete cascade或添加on delete set null,第一种是删除主表记录时,把参照该主表记录的从表记录全部级联删除;第二种是指定当删除主表记录时,把参照该主表记录的从表记录的外键设为null。

create table teacher_table4(
	teacher_id int auto_increment,
	teacher_name varchar(255),
	primary key(teacher_id)
);

create table student_table4(
	student_id int auto_increment primary key,
	student_name varchar(255),
	java_teacher int,
	foreign key(java_teacher) references teacher_table4(teacher_id)
	on delete cascade # 也可用on delete set null
);

CHECK约束

create table check_test(
	emp_id int auto_increment,
	emp_name varchar(255),
	emp_salary decimal,
	primary key(emp_id),
	# 建立CHECK约束
	check(emp_salary>0)
);

虽然上面的SQL语句建立的check_test表中有CHECK约束,CHECK约束要求emp_salary大于0,但这个要求实际上并不会起作用。

索引

索引是存放在模式(schema)中的一个数据库对象,虽然索引总是从属于数据表,但它和数据表一样属于数据库对象。创建索引的唯一作用就是加速对表的查询,索引通过使用快速路径访问方法来快速定位数据,从而减少了磁盘的I/O。

索引作为数据库对象,在数据字典中独立存在,但不能独立存在,必须属于某个表。

MySQL使用information_schema数据库里的STATISTICS表来保存该数据库实例中的所有索引信息

创建索引有两种方式
  1. 自动:当在表上定义主键约束、唯一约束和外键约束时,系统会为该数据列自动创建对应的索引
  2. 手动:用户可以通过create index语句来创建索引

对单个列创建索引

create index emp_last_name_idx
on employees(last_name);

对多列建立索引

# 下面语句为employees的first_name和last_name两列同时建立索引
create index emp_last_name_idx2
on employees(first_name, last_name);

删除索引

drop index 索引名 on 表名

有些数据库删除索引时无须指定表名,因为它们要求建立索引时每个索引都有唯一的名字,例如Oracle就采用这种策略。但MySQL只要求同一个表内的索引不能同名,所以删除索引时必须指定表名。

索引的好处是可以加速查询。但索引也有如下两个坏处

  1. 与书的目录类似,当数据表中的记录被添加、删除、修改时,数据库系统需要维护索引,因此有一定的系统开销
  2. 存储索引信息需要一定的磁盘空间

视图

视图看上去非常像一个数据表,但它不是数据表,因为它并不能存储数据。视图只是一个或多个数据表中数据的逻辑显示。
使用视图有如下几个好处

  • 可以限制对数据的访问
  • 可以是复杂的查询变得简单
  • 提供了数据的独立性
  • 提供了对相同数据的不同显示

因为视图只是数据表中数据的逻辑显示,也就是一个查询结果,所以创建视图就是建立视图名和查询语句的关联

create or replace view 视图名 
as 
subquery

通过建立视图的语法规则不难看出,所谓视图的本质,其实就是一条被命名的SQL查询语句。

一旦建立了视图以后,使用该视图与使用数据表就没有什么区别了,但通常只是查询视图数据,不会修改视图里的数据,因为视图本身没有存储数据。

为了强制不允许改变视图的数据,MySQL允许在创建视图时使用with check option子句,使用该子句创建的视图不允许修改

create or replace view view_test
as
select teacher_name from teacher_table
# 指定不允许修改该视图的数据
with check option;

删除视图

drop view 视图名

DML语句用法

DML语句由insert into、update和delete from 3个命令组成。

insert into语句
insert into 表名(列名...) values(...);

如果省略列名则默认插入所有列的值

update语句
update table_name 
set column1=value1[,column2=value2]...
[where condition];
delete from语句

delete from语句用于删除指定数据表的记录。使用delete from语句删除时不需要指定列名,因为总是整行地删除。

delete from table_name
[where condition];

单表查询

单表查询的select语句的语法格式如下

select column1,column2...
from 数据源
[where condition];

select后的不仅可以是数据列,还可以是表达式,还可以是变量、常量等。

# 数据列实际上可当成一个变量
select teacher_id + 5
from teacher_table;
# 查询出teacher_table表中teacher_id * 3大于4的记录
from teacher_table
where teacher_id * 3 > 4;
# 数据列实际上可当成一个变量
select 3*5, 20 
from teacher_table;

# 选择出teacher_name和'xx'字符串连接后的结果
select concat(teacher_name, 'xx')
from teacher_table;

MySQL提供了一种扩展语法,允许select语句后没有from子句

select 4 + 5;
distinct
# 去除重复行
select distinct student_name,java_teacher
from student_table;

使用distinct去除重复行时,distinct紧跟select关键字。它的作用是去除后面字段组合的重复值,而不管对应记录在数据库里是否重复。例如,(1, ‘a’, ‘b’)和(2, ‘a’, ‘b’)两条记录在数据库里是不重复的,但如果仅选择后面两列,则distinct会认为两条记录重复。

SQL中判断两个值是否相等的比较运算符是单等号,判断不相等的运算符是<>;SQL中的赋值运算符不是等号,而是冒号等号 :=

SQL语句中可以使用两个通配符:下划线(_)和百分号(%),其中下划线可以代表一个任意的字符,百分号可以代表任意多个字符。

查询出所有学生中名字以“孙”开头的学生

select * from student_table
where student_name like '孙%';

查询出名字为两个字符的所有学生

select * from student_table
# 下面使用两个下划线代表两个字符
where student_name like '__';

在某些特殊的情况下,查询的条件里需要使用下划线或百分号,不希望SQL把下划线和百分号当成通配符使用,这就需要使用转义字符,MySQL用反斜线(\)作为转义字符

# 选出所有名字以下划线开头的学生
select * from student_table
where student_name like '\_%';

判断是否为空用 is null

select * from student_table
where student_name is null;

如果需要按多列排序,则每列的asc、desc必须单独设定。如果指定了多个排序列,则第一个排序列是首要排序列,只有当第一列中存在多个相同的值时,第二个排序列才会起作用。如下SQL语句先按java_teacher列的降序排列,当java_teacher列的值相同时按student_name列的升序排列。

select * from student_table
order by java_teacher desc,student_name asc;

数据库函数

下面直接通过一些例子来介绍MySQL单行函数的用法

# 选出teacher_table表中teacher_name列的字符长度
select char_length(teacher_name)
from teacher_table;

# 计算teacher_name列的字符长度的sin值
select sin(char_length(teacher_name))
from teacher_table;

# 计算1.57的sin值,约等于1
select sin(1.57);
# 为指定日期添加一定的时间
# 在这种用法下interval是关键字,需要一个数值,还需要一个单位
select DATE_ADD('1998-01-02', interval 2 MONTH);
# 这种用法更简单,单位是日
select ADDDATE('1998-01-02', 60);
# 获取当前日期
select CURDATE();

# 获取当前时间
select CURTIME();

# 下面的MD5是MD5加密函数
select MD5('test');

MySQL提供了如下几个处理null的函数

如果expr1为null,则返回expr2,否则返回expr1

IFNULL(expr1,expr2)

如果expr1和expr2相等,则返回null,否则返回expr1

NULLIF(expr1,expr2)

类似于三目运算符,如果expr1为true,则返回expr2,否则返回expr3

`IF`(expr1,expr2,expr3)

判断expr是否为null,如果为null则返回true,否则返回false

ISNULL(expr)

MySQL还提供了一个case函数,该函数是一个流程控制函数。case函数有两个用法,case函数第一个用法的语法格式如下

case value
when compare_value1 then result1
when compare_value2 then result2
...
else result
end
# 如果java_teacher为1,则返回‘Java老师’,为2返回‘Ruby老师’,否则返回‘其他老师’
select student_name, case java_teacher
when 1 then 'Java老师'
when 2 then 'Ruby老师'
else '其他老师'
end
from student_table;

case函数第二个用法的语法格式如下

case
when condition1 then result1
when condition2 then result2
...
else result
end

在第二个用法中,condition1、condition2都是返回一个boolean值的条件表达式,因此这种用法更加灵活。

# id小于3的为初级班,3~6的为中级班,其他的为高级版
select student_name,case
when student_id <= 3 then '初级班'
when student_id <= 6 then '中级班'
else '高级班'
end
from student_table;

虽然我们介绍了MySQL常用函数的简单用法,但通常不推荐在Java程序中使用特定数据库的函数,因为这将导致程序代码与特定数据库耦合;如果需要把该程序移植到其他数据库系统上时,可能需要打开源程序,重新修改SQL语句。

分组和组函数

组函数也就是多行函数,组函数将一组记录作为整体计算,没组记录返回一个结果,而不是每条记录返回一个结果。常用的组函数有如下5个

计算多行expr的平均值,其中,expr可以是变量、常量或数据列,但其数据类型必须是数值型。还可以在变量、列前使用distinct或all关键字,如果使用distinct,则表明不计算重复值;all用和不用的效果完全一样,表明需要计算重复值。

AVG([DISTINCT] expr)

计算多行expr的总条数,其中,expr可以是变量、常量或数据列,其数据类型可以是任意类型;用星号(*)表示统计该表内的记录行数;distinct表示不计算重复值

COUNT(DISTINCT expr,[expr...])

计算多行expr的最大值,其中expr可以是变量、常量或数据列,其数据类型可以是任意类型

MAX(expr)

计算多行expr的最小值,其中expr可以是变量、常量或数据列,其数据类型可以是任意类型

MIN(expr)

计算多行expr的总和,其中,expr可以是变量、常量或数据列,但其数据类型必须是数值型;distinct表示不计算重复值

SUM([DISTINCT] expr)
# 计算student_table表中的记录条数
select count(*)
from student_table;
# 计算java_teacher列总共有多少个值
select count(distinct java_teacher)
from student_table;
# 统计所有student_id的总和
select sum(student_id)
from student_table;
# 计算的结果是20 * 记录的行数
select sum(20)
from student_table;
# 选出student_table表中student_id最大的值
select max(student_id)
from student_table;
# 选出teacher_table表中teacher_id最小的值
select min(teacher_id)
from teacher_table;
# 因为sum里的expr是常量34,所以每行的值都相同
# 使用distinct强制不计算重复值,所以下面计算结果为34
select sum(distinct 34)
from student_table;
# 使用count统计记录行数时,null不会被计算在内
select count(student_name)
from student_table;

对于可能出现null的列,可以使用ifnull函数来处理该列

# 计算java_teacher列所有记录的平均值
select avg(ifnull(java_teacher, 0))
from student_table;

在默认情况下,组函数会把所有记录当成一组,为了对记录进行显式分组,可以在select语句后使用group by子句,group by子句后通常跟一个或多个列名,表明查询结果根据一列或多列进行分组,当一列或多列组合的值完全相同时,系统会把这些记录当成一组。

# count(*)将会对没组得到一个结果
select count(*)
from student_table
# 将java_teacher列值相同的记录当成一组
group by java_teacher;

如果对多列进行分组,则要求多列的值完全相同才会被当成一组。

select count(*)
from student_table
# 当java_teacher、student_name两列的值完全相同时才会被当成一组
group by java_teacher,student_name;

使用having子句对组进行过滤

select * 
from student_table
group by java_teacher
# 对组进行过滤
having count(*) > 2;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章