相信看了一会第十三章 MySQL数据库的你一定一头雾水把?太抽象了也没有什么详细的学习,根本无从下手,这篇特殊的文章照顾了一下零基础的小伙伴,也是纯实机演示。
本文章参照了 尚硅谷MySQL基础学习视频教学!
安装数据库的步骤还是非常简单的,只要网速好去官方下载msi的安装包既可。
安装过程比较简单,这边设置不建议复杂,因为学习初期的阶段。
#sql专用代码栏
#打开数据库的方法其实很多我们挑选一种常用既可
#首先先大概介绍一下登入的关键字
# mysql[数据库] -u[用户名] -h[主机名] -P[端口] -p[密码]
mysql -h localhost -u root -P 3306 -p
#这里mysql指定了数据库
#-h localhost 表示输入主机名 localhost代表本地的意思
#-u root 代表用户名 默认用户名为 root
#-P 3306 端口 端口默认为3306
#-p 密码 输入完回车会要求输入密码 Enter password:
我们看执行详细流程。
首先按下电脑快捷键 win+R 调出运行并输入 'cmd’打开命令提示符,显示窗口后输入:
mysql -h localhost -u root -P 3306 -p
回车后会要求输入密码,输入完密码看到如图的内容代表成功进入数据库。
#显示数据库
show databases;
#打开/进入 指定的数据库
use mysql;
#显示当前数据库所有的表
show table;
#实现不退出或不切换数据显示其他数据库表格
show tables from sys;
#显示当前所在数据库
select database();
上面的数据库比如:
这些都是系统的数据库并不推荐在里面做练习或者修改数据,所以我们通过如下代码创建一个空的数据库进行学习:
#这里的 'database'关键字大小写效果一致
create DATABASE test;
create database test;
#删除数据库
drop database test;
我们学习了打开数据库、创建数据库、显示数据库里的表格等基本指令,现在我们组合这些操作一口气创建一个表。
#登入
mysql -h localhost -u root -P 3306 -p
#显示所有的数据库
show databases;
#打开指定的数据库
use sys;
#显示当前数据库的表
show tables;
#显示其它数据库的表
show tables from mysql;
#显示当前所在的数据库
select database();
#创建数据库
create database test;
create DATABASE testtow;
#删除指定的数据库
#显示所有数据库观察执行结果
show databases;
#打开/进入 test数据库
use test;
#显示当前所有表
show tables;
#显示当前所在数据库
select database();
#创建表
create table stuinfo(
#整形
id int,
#字符型
name varchar(20)
);
#这里的声明其实和Java变量差不多 暂时这么理解
#显示表结构
desc stuinfo;
这里就完成了一个最简单的完整流程操作,继续看基本指令的学习:
#创建一个表
create table stuinfo(
id int,
name varchar(20)
);
#显示表结构
desc stuinfo;
Field代表字段、Type代表类型,后面代表的是一些其他的约束,先不看这些。
#查看表数据
select * from stuinfo;
这里表现的为没有数据的结果,因为只是创建了表的字段没有赋值。
#插入数据
insert into stuinfo (id,name) values(1,'洛天依');
这时候我们再次使用显示数据的指令来访问数据。
可以看到如上的手动添加的内容。
通过小键盘的 上键 ↑来调用上次指令记忆,找到插入数据的代码再次添加一条数据。
insert into stuinfo (id,name) values(2,'乐正绫');
不小心添加了重复的数据?看如下操作
#修改数据
update stuinfo set name = '乐正绫' where id = 2;
#删除指定数据
delete from stuinfo where id = 3;
查看客户端的版本
#客户端内查看
mysql>select version();
#客户端外查看
#这里不用分号 因为是doc命令
C:\Users\YueDie>mysql --version
#简写
C:\Users\YueDie>mysql -V
show databases;
use 库名
show tables;
show tables from 库名;
create table 表名(
列名 列类型,
列名 列类型,
...
)
desc 表名
#方式一:
#在服务端内
select version();
#方式二:
#在服务端外
#注意在服务单外于是系统指令不用加分号
mysql --version
#方式三:
#在服务端外
mysql -V
我们现在登入方式改为:
mysql -u root -p
不分区大写小,但建议关键字大写,表名和列名小写
show databases;
SHOW DATABASES;
最好每条命令以分号结尾
use test;
select*from stuinfo;
SELECT*FROM stuinfo\g
create table stuinfo(id int,name varchar(20));
第一种单行注释:#注释内容
第二种单行注释:-- 注释内容
多行注释:/*注释内容*/
好,上面就是我们入门第十三章的小练习,也是作为基础铺垫的内容,接下来开始尝试学习文章里的MySQL内容!
#注意这里test后面的一定是()圆括号不要是大括号
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
);
#语法:
create table [模式名.]表名[column[,column...]]
as subquery;
#创建hehe数据表,该数据表和test完全相同,数据也完全相同
create table hehe
as
select*from test;
alter table 表名
add(
#可以有多个列定义
column_name1 datatype [default expr],
...
);
上面语法格式中的圆括号部分与建表语法的圆括号部分完全相同,只是此时圆括号里的列定义是追加到已有表的列定义后面。还有一点需要指出,如果只是新增一列,则可以省略圆括号,仅在add后紧跟一个列定义既可。为数据表增加字段的SQL语句如下:
#为hehe数据表增加一个hehe_id字段,该字段的类型为int
alter table hehe
add hehe_id int;
#这里也是对应了上面的:如果只是新增一列,则可以省略圆括号
#这里如果是修改新增多列就不可以忽略圆括号
alter table hehe
add(
aaa varchar(255) default 'xxx',
bbb varchar(255)
);
上面第二条SQL语句增加aaa字段时,为该字段指定默认值为’xxx’,值得指出的是,SQL语句中的字符串值不是用双引号引起的,而是用单引号引起的。
alter table 表名
modify column_name datatype[default expr][first|after col_name];
上面语法中first或者after col_name指定需要将目标修改到指定位置。
修改前的hehe_id列
代码执行
#将hehe表的hehe_id列修改成varchar(255)类型
alter table_hehe
modify hehe_id varchar(255);
alter table hehe
modify bbb int;
从上面代码中不难看出,使用SQL修改数据表里列定义的语法和为数据表里增加一个列定义的语法几乎完全一样,关键是增加列定义所使用的add关键字,而修改列定义使用modify(修改)关键字(alter直译为 改变)。还有一点需要指出,add新增的列名必须是源表表中不存在的,而modify修改的列名必须是原表中已存在的。
MySQL的一个modify命令不支持修改多个列定义,其他数据库支持,比如Oracle支持一个modify命令修改多个列,一个modify命令修改多个列定义的语法和一个add命令增加多个列定义的语法非常相似,也是需要使用圆括号将多个列定义括起来。如果需要修改多行列定义,只需要在alter table后使用多个modify命令即可。
从数据表中删除列的语法比较简单。
alter table 表名
drop column_name
删除列只要在drop后竟跟需要删除的列名即可。例如:
#删除hehe表中的aaa字段
alter table hehe
drop aaa;
重命名数据表的语法格式如下:
alter table 表名
rename to 新表名
#将hehe数据表重命名为wawa:
alter table hehe
rename to wawa;
MySQL为alter table提供了change选项,该选项可以改变列名。change选项的语法格式如下:
alter table 表名
change old+column_name new_cloumn_name type[default expr] [first[after col_name]]
通过对比不难发现 change和modify两个选项:change选项比modify选项多了一个列名,因为change可以改变列名,所以它需要两个列名。一般而言,如果不需要改变列名使用alter table 的 modify 选项即可,只有当需要修改列名时才会使用change选项。语句如下:
#将wawa的bbb字段重命名为ddd
alter table wawa
change bbb ddd int;
#关键字 旧字段名 新字段名 类型
像这种不小心使用 insert into 插入了新数据的情况下就应该将其多余的内容删除掉。
通过如下操作删除
删除表的语法格式如下:
drop table 表名;
如下SQL语句将会把数据库中已有的表删除:
#删除数据表
drop table wawa;
先看处理上面的语句
#删除数据表的数据
delete from wawa;
insert into
现在我们试试上面的 drop table wawa;
这里直接删除了wawa数据表,而非删除里面的数据列。
上面的结果差距很大
看例子
delete : delete from 表名 where 条件
delete选中指定表的内容删除,删除的是数据
drop : alter table 表名 drop 字段 drop table 表
drop删除的是表
相当于drop直接删除了表,释放了内存,所以drop速度大于delete,所以使用drop也一定要慎重,虽然可以恢复但是很麻烦,使用delete也一定要带上where子句。
删除数据表的效果如下:
对于大部分数据库而言,truncate都被当成DDL处理(和drop一列),truncate被称为“截断”某个表——它的作用是删除该表里全部数据,但保留表结构,相对于DML里的delete命令而言,truncate的速度要快的多,而且truncate不像delete可以删除指定的记录,truncate只能一次性删除整个表的全部记录。
truncate命令的语法如下:
truncate 表名
这里做实验也很简单,我们再次创建wawa表
#这里起码要在 test表里
show tables;
use test;
select database();
#这里表列我们就不搞那么复杂了
create table wawa(
id int,
name varchar(255)
);
desc wawa;
#插入一列数据
insert into wawa (id,name) values(1,'洛天依');
select*from wawa;
truncate wawa;
show tables;
desc wawa;
MySQL对truncate的处理比较特殊——如果使用非InnoDB存储机制,truncate比delete速度要快;如果使用InnoDB存储机制,在MySQL5.0.3之前,truncate和delete完全一样,在5.0.3之后,truncate table比delete效率高,但如果该表被建外约束所参照,truncate又变为delete操作。在5.0.13之后,快速truncate总是可用,即比delete性能要好。
约束更好保证了数据表里数据的完整性。约束时在表上强行执行的数据校验规则,约束主要还用于保证数据的完整性。除此之外,当表中数据存在互相依赖性时,可以保护相关的数据不被删除。
大部分数据库支持下面5种完整性约束。
虽然大部分数据库都支持上面5种约束,但MySQL不支持CHECK约束,虽然MySQL的SQL语句也可以使用CHECK约束,但这个CHECK约束不会有任何作用。
虽然约束的作用只是保证数据表里数据的完整性,但约束也是数据库对象,被存储在系统表中,也拥有自己的名字。根据约束对数据列的限制,约束分为如下两类。
为数据表指定约束有如下两个时机:
非口约束用于确保指定列不允许为空,非空约束是比较特殊的约束,它只能作为列级约束使用,只能使用列级约束语法定义。这里要介绍一下SQL中的null值,SQL的null不区分大小写。SQL中的null具有如下特征。
如果需要在建表时为指定列指定非空约束,只要在列定义后面增加 not null即可。建表语句如下:
#如果是跟着我的文章走的,那现在test表中肯定有个wawa,现在我们给它删掉
#删掉wawa表和test表
drop table test;
drop table wawa;
#使用函数来确定自己是否处于test数据库
select database();
create table hehe(
#建立了非空约束,这意味着hehe_id不可以为nul
hehe_id int not null,
#MySQL的非空约束不能指定名字
hehe_name varchar(255) default 'xyz' not null,
#下面可以为空,默认就是为空
hehe_gender varchar(2) null
);
除此之外,也可以在使用alter table 修改表时增加或删除非空约束,SQL命令如下:
#增加非空约束
alter table hehe
modify hehe_gender varchar(2) not null;
#取消非空约束
alter table hehe
modify hehe_name varchar(2) null;
#取消非空约束,并指定默认值
alter table hehe
modify hehe_name varchar(255) default 'abc' null;
唯一约束用于保证指定列或指定列组合不允许出现重复值。虽然唯一约束的列不可以出现重复值,但可以出现多个null值(因为在数据库中null不等于null)。
一个表内可创建多个唯一约束,当为某列创建唯一约束时,MySQL会为该列相应的创建唯一索引,如果不给唯一索引起名,则该唯一约束默认与列名相同。
当建立唯一约束时,MySQL在唯一约束所在列或列组合上建立对应的唯一索引。
使用列级约束语法建立唯一约束非常简单,只要简单地在列定义后增加unique关键字即可。SQL语句如下:
create table unique_test(
#建立了非空约束,这意味着test_id不可以为null
test_id int not null,
#unique就是唯一索引,使用列级约束语法建立唯一索引
test_name varchar(255) unique
);
如果需要为多列组合建立唯一约束,或者向自行指定约束名,则需要使用表级约束语法。表级约束语法格式如下:
[constraint 约束名] 约束定义
上面的表级约束语法格式既可以放在 create table 语句中与列定义并列,也可以放在 alter table 语句中使用 add关键字来添加约束。SQL语句如下:
create table unique_test2(
#建立了非空约束,这意味着test_id 不可以为null
test_id int not null,
test_name varchar(255),
var_pass varchar(255),
#使用表级约束语法建立唯一约束
unique(test_name),
#使用表级约束语法建立唯一约束,而且指定约束名
constraint test2_uk unique(test_pass)
);
上面的建表语句为test_name、test_pass分别建立了唯一约束,这意味着这两列都不能出现重复值。除此之外,还可以为这两列组合建立唯一约束,SQL语句如下:
@建表时创建唯一约束,使用表级约束语法建立约束
create table unique_test3(
#建立了非空约束,这意味着test_id不可以为null
test_id int not null,
test_name varchar(255),
test_pass varchar(255),
#使用表级约束语法建立唯一约束,指定两列组合不允许重复
constraint test3_uk unique(test_name,test_pass)
);
对于上面的unique_test2和unique_test3两个表,都是对test_name、test_pass建立唯一约束,其中unique_test2要求test_name、test_pass都不能出现重复值,而unique_test3只要求test_name、test_pass两列值组合不能重复。
也可以在修改表结构时使用add关键字来增加唯一约束,SQL语句㛍:
#增加唯一约束
alter table unique_test3
add unique(test_name,test_pass);
还可以在修改表时使用 modify关键字,为单列采用列级约束语法来增加唯一约束,代码如下
#为unique test3表的test_name增加唯一约束
alter table unique_test3
add unique(test_name,test_pass);
对于大部分数据库而言,删除约束都是在alter table 语句后使用 "drop constraint 约束名"语法来完成的,但MySQL并不使用这种方式,而是使用 "drop index 约束名"的方式来删除约束。例如如下SQL语句:
#删除unique_test3表上的test3_uk唯一约束
alter table unique_test3
drop index test3_uk;
主键约束相当于非空约束和唯一约束,即主键约束的列既不允许出现重复值,也不允许出现null值;如果对多列组合建立主键约束,则多列里包含的每一列都不能为空,但只要求这些列组合不能重复。主键列的值可用于唯一地标识表中的一条记录。
每一个表只允许有一个主键,但这个主键可以由多个数据列组合而成,主键是表中能唯一确定一行记录的字段或字段组合,和唯一约束的语法相似,建立主键约束使用 primary key。
练习结束就可以删掉之前的数据库了减少内存和碍眼。
记得use数据库哦。
#列级语法
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_test3
(
test_id varchar(255),
test_pass varchar(255),
#建立多列组合的主键约束
primary key(test_name,test_pass)
);
如果需要删除指定表的主键约束,则在alter table 语句后使用 drop primary key子句即可。SQL语句如下:
#删除主键约束
这里不小心删除了,少打了个3
如果需要为指定表增加主键约束,既可通过modify修改列定义来增加主键约束,这将采用列级约束语法来增加主键约束;也可以通过add来增加主键约束,这将采用表级约束语法来增加主键约束。SQL语句如下:
#使用表级约束语法来增加主键约束
alter table primary_test3
add primary key(test_name,test_pass);
如果只是为单独的数据列增加主键约束,则可使用modify修改列定义来实现。SQL语句如下:
注意,如果报错了,原因大概率是字母打错和重复添加主键看下面示意图
#使用列级约束语法来增加主键约束
alter table primary_test3
modify test_name varchar(255) primary key;
这里因为上面误删了 primary_test的test_id的主键约束可以补回来
不要连续执行上面两条SQL语句,因为上面两条SQL语句都是为primary_test3增加主键约束,而同一个表里最多只能有一个主键约束,所以连续执行上面两条SQL语句肯定出现错误。为了避免这个问题,可以在成功执行了第一条增加主键约束的SQL语句之后,先将primary_test3里的主键约束删除后再执行第二条增加主键约束的SQL语句。
很多数据库对主键列都支持一种自增长的特性——如果某个数据列的类型是整形,而且该列作为主键列,则可指定该列具有自增长功能。指定自增长功能通常用于设置逻辑主键列——该列的值没有任何物理意义,仅仅用于标识每行记录。MySQL使用auto_increment来设置自增长,SQL语句如下:
SQL最后的一行不用 , 直接以)结尾即可
一旦指定了某列具有自增长特性,则向该表插入记录时不可为该列指定值,该列的值由数据库系统自动生成。
外键约束主要用于保证一个或两个数据表之间的参照完整性,外键是构建与一个表的两个字段或者两个表的两个字段之间的参照关系。外键确保了相关的两个字段的参照关系:子(从)表外键列的值必须在主表被参照列的值范围之内,或者为空(也可以通过非空约束来约束外键列不允许为空)。
当删除主表记录时不允许直接删除,而是需要删除从表里参照该记录的所有记录,全部删除后才可以删除主表的该记录。或者删除主表记录时级联从表中的所有参照该记表的从表记录。
#为了保证从表参照的主表存在,通常应该先建主表
create table teacher_table(
#auto_increment:代表数据库的自动编号策略,通常用作数据表的逻辑主键
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 references teacher_table(teacher_id)
);
值得指出的是,虽然MySQL支持使用列级约束语法来建立外键约束,但这种列级约束语法建立的外键约束不会生效,MySQL提供这种列级约束语法仅仅是为了和标准SQL保持良好的兼容性,因此,如果要使MySQL中的外键约束生效,则应使用表级约束语法。
#为了保证从表参照的主表存在,通常应该先建主表
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,
foreign key(java_teacher) references teacher_table1(teacher_id)
);
如果使用表级约束语法,则需要使用foregin key来指定本表的外键列,并使用references来指定参照哪个主表,以及参照到主表的哪个数据列。如果没有创建约束名,则MySQL会为该外键约束命名为 table_name_ibfk_n,其中table_name是从表的表名,而n是从1开始的整数。
如果需要显式指定外键约束的名字,则可使用constraint来指定名字。SQL语句如下:
#为了保证从表参照的主表存在,通常应该先建主表
create table teacher_table2(
#auto_increment:代表数据库的自动编号策略,通常用作数据表的逻辑主键
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_table2(teacher_id)
);
#为了保证从表参照的主表存在,通常应该先建立主表
create table teacher_table3(
teacher_name varchar(255),
teacher_pass varchar(255),
#以两列建立组合
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(255),
java_teacher_pass varchar(255),
#使用表级约束语法建立外键约束,指定两列的联合外键
foreign key(java_teacher_name,java_teacher_pass) references teacher_table3(teacher_name,teacher_pass)
);
删除外键约束的语法很简单,在alter table 后面增加“drop foreign key 约束名”子句即可。代码如下:
#删除student_table3表上名为student_table3_ibfk_1的外键约束
alter table student_table3
drop foreign key student_table3_ibfk_1;
增加外键约束通常使用add foreign key命令。SQL语句如下:
#修改student_table3数据表,增加外键约束
alter table student_table3
add foreign key(java_teacher_name,java_teacher_pass)
references teacher_table3(teacher_name,teacher_pass);
值得支出的是,外键约束不仅可以参照其他表,而且可以参照自身,这种参照自身的通常被称为自关联。例如,如果一个包保存某个公司的所有员工记录,员工之间有部门经理和普通员工之分,部分经理和普通员工之间存在一对多的关联关系,但他们都是保存在同一个数据表里的记录,这就是典型的自关联。下面的SQL语句用于建立自关联的外键约束。
#使用表级约束语法建立外约束键,且直接参照自身
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。SQL语句如下:
#为了保证从表参照的主表存在,通常应该先建立主表
create table teacher_table4(
#auto_increment:代表数据库的自动编号策略,通常用作数据表的逻辑主键
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
);
当前版本的MySQL支持建表时使用CHECK约束,但是这个CHECK约束不会有任何作用。建立CHECK约束的语法很简单,只要在建表时列定义后增加check(逻辑表达式)即可。SQL语句如下:
create table check_test(
emp_id int auto_increment,
emp_name varchar(255),
emp_salary decimal not null,
primary key(emp_id),
#建立CHECK约束
check(emp_salary>0)
);
虽然上面的SQL语句建立的CHECK_test表中有CHECK约束,CHECK约束要求emp_salary大于0,但实际上并不会起作用。
MySQL作为一个开源、免费的数据库系统,对有些功能支持确实不太好,如果读者确实希望MySQL创建数据表有CHECK约束,甚至有更复杂的完整性约束,则可借助于MySQL的触发器机制。本阶段(Java基础)不会介绍,可期待下一阶段(MySQL)文章。
关于约束学习的总结,其实约束这个内容不是很难,只是现在刚刚学习MySQL基础操作语句还很抽象,我也不清楚约束具体作用,这些都需要慢慢的学习去完善认知和使用以及学习!
索引是存在在模式中的一个数据库对象,它加速了查询,减少了磁盘的I/O。
索引作为数据库对象,在数据字典中独立存在,但不能独立存在,必须属于某个表。
MySQL使用information_schema数据库里的STATISTICS表来保存该数据库实例中的所有索引信息,用户可通过查询该表来获取该数据库的索引信息。
创建索引有两种方式.
删除索引也有两种方式。
索引的作用类似于书的目录,几乎没有一本书没有目录,因此几乎没有一个表没有索引。一个表中可以有多个索引列,每个索引都可以用于加速该列的查询速度。
创建索引的语法格式如下:
create index index_name
on table_name (column[,column]...);
下面的索引将会提供对employees表基于last_name字段的查询速度。
变绿在cmd原始状态下输入 color a 就行了 也可以直接输入color调出提示。
#这里我们先创建一个只有含有一个 last_name字段的表
create table employees(
last_name varchar(255)
);
创建employees表中last_name的索引
create index emp_last_name_idx
on employees(last_name);
也可同时对多列建立索引,SQL语句如下:
先删掉原来的employees表
drop table employees;
create table employess(
#这次多了一列 first_name
first_name varchar(255),
last_name varchar(255)
);
#下面语句为employees的first_name和last_name两列同时建立索引
create index emp_last_name_idx
on employees(first_name,last_name);
删除索引需要指定表:
drop index 索引名 on 表名
如下SQL语句删除了employees表上的emp_last_name_idx索引:
drop index emp_last_name_idx
on employees;
有些数据库删除索引时无须指定表名,因为它们要求建立索引时每个索引都有唯一的名字,所以无须指定表名,例如Oracle就采用这种策略。但MySQL只要求同一个表内的索引不能同名,所以删除索引时必须指定表名。
索引的好处是可以加速查询。但索引也有如下两个坏处。
视图看上去很像一个数据表,但它不是数据表,因为它不能存储数据。视图只是一个或多个数据表中数据的逻辑显示。使用视图有如下几个好处。
create or replace view 视图名
as
subquery
从上面语法可以看出,创建、修改视图都可使用上面语法。上面语法的含义是,如果该视图不存在则创建视图;如果指定视图名的视图已经存在,则使用新视图替换原有视图。后面的subquery就是一个查询语句,这个查询可以非常复杂。
通过建立视图的语法规则不难看出,所谓视图的本质,其实就是一条被命名的SQL查询语句。
一旦建立了视图以后,使用该视图与使用数据表就没有上面区别了,但通常只是查询视图数据,不会修改视图里的数据,因为视图本身没有存储数据。
如下SQL语句就创建了一个简单的视图:
这里因为删除了之前的 teacher_table,所以重新建立一个
create table teacher_table(
teacher_name varchar(255) default '视图测试',
teacher_pass varchar(255)
);
创建视图
create or replace view view_test
as
select teacher_name,teacher_pass from teacher_table;
我们来看结果
可以看到,我们通过 desc关键字查询两者时,显示的数据毫无区别。
通常不推荐直接改变视图的数据,因为视图并不存储数据,它只是相当于一条命名的查询语句而已。为了强制不允许改变视图的数据,MySQL允许在创建视图时使用with check option子句,使用该子句创建的视图不允许修改,如下所示。
这里删除视图的语句就不再是
drop table view_test;
而是
drop view view_test;
create or replace view view_test
as
select teacher_name from teacher_table
#指定不允许修改该视图的数据
with check option;
大部分数据库都采用 with check option来强制不允许修改数据库的数据,但Oracle采用 with read olny 来强制不允许修改视图的数据。
删除视图语句如下:
drop view 视图名
上面删除过了一次 view_test视图
drop view view_test;
与DDL操作数据库对象不同,DML主要操作数据表里的数据,使用DML可以完成如下三个任务。
DML语句由insert into、update 和 delete from三个命令组成。
其实这三个文章刚开始就都讲过了,所以只要前面的实例跟着做过,再学这个还是非常简单的,包括会了前面文章的所有内容。不过注意,文章刚开始确实讲过这三个关键字但是都是使用,并没有将很多细节,所以主要学习的时候才是最重要的,提前实习只是打下基础。
insert into 用于向指定数据表中插入数据。对于标准的SQL语句而言,每次只能插入一条记录。insert into语句的语法格式如下:
insert into table_name [(column[,column...])]
values(value[,value...]);
执行插入操作时,表名后可以用括号列出所有需要插入值的列名,而values后用括号列出对应需要插入的值。
如果省略了表名后面的括号及括号里的列名列表,默认将为所有列都插入值,则需要为每一列都指定一个值。如果既不想在表名后列出列名,又不想为所有列都指定值,则可以为那些无法确定值的列分配null。下面SQL语句示范了如何向数据表中插入记录。
只有在数据库中已经成功创建了数据表之后,才可以向数据表中插入记录。下面的SQL语句以前面外键约束时所创建的teacher_table2和student_table2为列来介绍数据插入操作。
在表名后使用括号列出所有需要插入值的列:
如果之前把前面的实例删了,就再创建一下两个表。
这里应该使用 select查询表中数据,而不再是 desc
insert into teacher_table2(teacher_name) values('xyz');
select*from teacher_table2;//查询语句
insert into teacher_table2
#使用null代替主键列的值
values(null,'abc');
从上面中看到 abc记录的主键列的值是2,而不是SQL语句插入的NULL,因为主键列是自增长的,系统自动分配值。
根据前面介绍的外键约束规则:外键列里的值必须是被参照列里已有的值,所以向表中插入记录之前,通常应该先向主表中插入记录。否则从表记录的外键列只能为null、现在主表teacher_table2中已有了2条记录,现在可以向从表student_table2中插入记录了,SQL语句如下:
inserto into student_table2
#当向外键列里插值时,外建列的值必须是被参照列里已有的值
values(null,'张三',2);
外键约束保证被参照的记录存在,但并不保证必须有被参照记录,即外建立可以为null,如果想保证每条记录必须存在对应的主表记录,则应使用非空、外键两个约束。
在一些特殊的情况下,可以使用带子查询的插入语句,带子查询的插入语句可以一次插入多条记录,SQL语句如下:
insert into student_table2(student_name)
#使用子查询的值来插入
select teacher_name from teacher_table2;
正如上面的SQL语句所示,带子查询的插入语句甚至不要求查询数据的源表和插入数据的目标表是同一个表,它只要求选择出来的数据列和插入目的表的数据列个数相等、数据类型匹配既可。
MySQL甚至提供了一种扩展的语法,通过这种扩展的语法也可以一次插入多条记录。MySQL允许在values后使用多个括号包含多条记录,表示多条记录的多个括号之间以英文逗号格式。SQL语句如下:
insert into teacher_table2
#同时插入多个值
values(null,"Yeeku"),(null,"Sharyfly");
这个文章初期也有讲过,修改语句。
update语句用于修改数据表的记录,每次可以修改多条记录,通过使用where子句限定修改哪些记录。where子句是一个条件表达式,该条件表达式类似于Java语句的if,只有符合该条件的记录才会被修改。没有where子句以意味着where表达式的值总是true。即该表的所有记录都会被修改。update语句的语法格式如下。
update table_name
set column1 = value1[,column2 = value2]...
[WHERE condition];
使用update语句不仅可以一次修改多条记录,也可以一次修改多列。修改多列都是通过在set关键字后使用 cloumn1 = value1,column2 = value2…来实现的,修改多列之间的值以英文逗号隔开。
下面的SQL语句将把teacher_table2表中的所有记录的teacher_name列的值都改为’孙悟空’。
update teacher_table2
set teacher_name= '孙悟空';
也可以通过添加where条件来指定值修改特定记录,SQL语句如下。
delete from语句用于删除指定数据表的记录。使用delete from语句删除时不需要指定列名,因为总是整行地删除。
使用delete from语句可以一次删除多行,删除哪些行采用where子句限定,只删除满足where条件的记录。没有where子句限定将会把表中的全部记录删掉。
delete from语句的语法格式如下:
delete from table_name
[WHERE condition];
如下SQL语句将会把student_table2表的记录全部删除
delete from student_table2;
也可以使用where条件来限定只删除指定记录,SQL语句如下:
delete from teacher_table2
where teacher_id>2;
当主表记录被从表记录参照时,主表记录不能被餐厨,只有先将从表中参照主表记录的所有记录全部删除后,才可以删除主表记录。还有一种情况,定义外键约束时定义了主表记录和从表记录之间的级联删除 on delete cascade,或者使用 on delete set null 用于指定当主表记录被删除时,从表中参照该记录的从表记录被外键列的值设为null。
有示意图,但是不展示了,光看示意图看不懂,看介绍。
select语句的功能就是查询数据,select语句也是SQL中最丰富的语句,select语句不仅可以执行单表查询,而且可以执行多表连接查询,还可以进行子查询,select语句用于从一个胡哦多个数据表中选出特定行、特定列的交集。
select后的列用于确定选择哪些列,where条件用于确定选择哪些行,只有满足where条件的记录才会被选择出来;如果没有where条件,则默认选出所有行。如果想选择出所有列,则可使用星号代表所有列。
下面的SQL语句将会选择出teacher_table表中的所有行、所有列的数据。
select*from teacher_table;
为了能看到查询结果,必须准备数据表,并向数据表中插入一些数据,因此在运行本节的select之前准备好之前的数据表 student_table。
如果增加where条件,则只选择出符合where条件的记录。如下SQL语句将选择出student_table表中java_teacher值大于3的记录的student_name列的值。
select student_name from student_table
where java_teacher>3;
先添加好数据,再执行上面的内容:
当使用select语句进行查询时,还可以在select语句中使用算术运算符(+、-、*、/),从而形成算术表达式。使用算术表达式的规则如下:
不论从哪个角度来看,数据列都很像一个变量,只是这个变量值具有指定的范围——逐行计算表中的每条记录时,数据列的值依次变化。因此能使用变量的地方,基本上都可以使用数据列。
下面的select语句中使用了算术运算符。
#数据列实际上可以当成一个变量
select teacher_id +5
from teacher_table;
#查询出teacher_table表中teacher_id*3大于4的记录
select*from teacher_table where teacher_id *3 >4;
需要指出的是,select后的不仅可以是数据列,也可以是表达式,还可以是变量、常量等。例如:
#在select后直接使用表达式或常量
select 3*5,20
from teacher_table;
SQL语句中算术运算符的优先级与Java语言中的运算符优先级完全相同,乘法和除法的优先级高于加法和减法,同级运算的顺序是从左到右,表达式中使用括号可以强行改变优先级的运算顺序。
MySQL中没有提供字符串连接运算符,即无法使用加号(+)将字符串常量、字符串变量或字符串列连接起来。MySQL使用concat函数来进行字符串连接运算。
SQL语句如下:
#选择出teacher_name和'xx'字符串连接后的结果
select concat(teacher_name,'xx')
from teacher_table;
MySQL的算术表达式中也可以使用null,但是会导致整个算术表达式的返回结果都为null,使用字符串连接也是null。
select concat(teacher_name,null)
from teacher_table;
如果不希望直接使用列名作为列标题,则可以为数据列或表达式起一个别名,为数据列或表达式起别名时,别名紧跟数据列,中间以空格隔开,或者使用as关键字隔开。SQL语句如下:
select teacher_id +5 as MY_ID
from teacher_table;
可以看出,为列起别名,可以改变列的标题头,用于标识计算结果的具体含义。如果列别名中使用特殊字符(如空格),或者强制大小写敏感,都可以通过为别名添加双引号来实现。SQL语句如下:
#可以为选出的列起别名,别名中包括单引号字符,所以把别名用双引号引起来
select teacher_id +5 "MY'id"
from teacher_table;
如果要选择多列,并未多列起名,则列与列之间以逗号隔开,但列与列名之间以空格隔开。
select teacher_id +5 MY_ID,teacher_name 老师名
也可以为表起别名,为表起别名的语法和为列或表达式起别名的语法完全一样。
select teacher_id + 5 MY_ID,teacher_name 老师名
#为teacher_table其别名
from teacher_table t;
前面已经提到,列名可以当成变量处理,所以运算符也可以在多列之间进行运算,SQL语句如下。
select teacher_id +5 MY_ID,concat(teacher_name,teacher_id)teacher_name from
teacher_table
where teacher_id * 2 >3;
甚至可以在select、where子句中都不出现列名,SQL语句如下:
select 5+4
from teacher_table
where 2<9;
这种情况这叫特殊:where语句后的表达式总是true,所以会把teacher_table表中的每条记录都选择出来)但SQL语句没有选择任何列,仅仅选择了一个常量,所以SQL会把该常量当成一列,teacher_table表中有多少条记录,该常量就会出现多少次。
对于选择常量的情形,指定数据表可能没有太大的意义,所以MySQL提供了一种扩展语法,允许select语句后没有from子句,即可写成如下形成。
select 5+4;
上面语句并不是标准的SQL语句,例如,Oracle就提供了一个名为dual的虚标(最新的MySQL数据库也支持dual虚标),它没有任何意义,仅仅相当于from后的占位符。如果选择常量,则可使用如下语句。
select 5+4 from dual;
select默认会把所有的符合条件的记录全部选出来,即使两行记录完全一样。如果想除去重复行,则可以使用distinct关键字从查询结果中清除重复行。
额实际上,没有重复行,去了个寂寞
但是可以手动添加一个:
再次执行如上指令。
这里看到了,查询到了重复的值。
看去除重复行的效果
#去除重复行查询
select distinct student_name,java_teacher
from student_table;
使用ddistinct去除重复行时,distinct紧跟select关键字。它的作用是去除后面字段组合的重复值,而不管对应记录在数据库里是否重复。例如,(1,‘a’,‘b’)和(2,‘a’,‘b’)两条记录在数据库里是不重复的,但如果仅选择后面两列,则distinct会认为两条记录重复。
前面已经看到了where子句的作用——可以控制只选择指定的行,因为where子句里包含的是一个条件表达式,所以可以使用 >、>=、<、<=、=和<>等基本的比较运算符。SQL中比较运算符不仅可以比较数值之间的大小,也可以比较字符串、日期之间的大小。
SQL中判断两个值是否相等的比较运算符是单等号,判断不相等的运算符是<>;SQL中的赋值运算符不是等号,而是冒号等号(:=)。
除此之外,SQL还支持如下表所示的特殊比较运算符。
可能有点看不清楚
概念只是个人理解不一定正确。
下面的SQL语句选出student_id 大于等于2,且小于等于4的所有记录。
select*from student_table
where student_id between 2 and 4;
使用betwwen val 1 and val2必须保证val1小于val2,否则将选不出任何记录。此处之外,between val1and val2中的两个值不仅可以是常量,也可以是变量,或者是列名也行。如下SQL语句选出java_teacher小于等于2,student_id大于等于2的所有记录
select*from student_table
where 2 between java_teacher and student_id;
使用in比较运算符时,必须在in后的括号里列出一个或多个值,它要求指定列必须与in括号里任意一个值相等,SQL语句如下:
#选出student_id为2或4的记录
select*from student_table
where student_id in(2,4);
与此类似的是,in括号里的值既可以是常量,也可以是变量或者列名,SQL语句如下:
select*from student_table
where 2 in (student_id,java_teacher);
运行结果也就那几个,详细使用还是等到JDBC吧。
like运算主要用于模糊查询,例如:查 ‘张开头的记录’
这就需要使用模糊查询了,比如查找 '张’姓名开头的学生。
SQL有两个通配符:下画线(_)和百分号(%),其中下画线可以代表任意一个字符,百分号可以代表多个字符。
下面语句查询名为张的学生。
这里比较坑,得自己再加点数据了
通过结构显示可以知道有3个数值,而id是自动增长,所以可以直接null让系统自动分配,name是我们这次主要的内容
我就新建这么多的数据,主要看查询结果。
select*from student_table
where student_name like '张%';
下面SQL语句将查询名为两个字符的所有学生。
select*from student_table
where student_name like '__';
在某些特殊情况下,查询的条件里需要使用下画线或百分号,不希望SQL把下画线和百分号当成通配符使用,这就需要使用转义字符,MySQL使用反斜线(\)作为转义字符,SQL语句如下:
这里再次自导自演一次,添加带有_下画线的数据
查询带有下画线的数据:
这里大意了
标准SQL语句并没有提供反斜线(\)的转义字符,而是使用escape关键字显式进行转义。例如,为了实现上面的功能需要使用SQL语句。
这里就不要再执行这个代码了,有奇怪的BUG。
is null用于判断某些值是否为空,判断是否为空不要用=null来判断,因为SQL中 null=null返回null,如下SQL语句将选择出student_table表中student_name为null的所有记录。
select*from student_table
where student_name is null;
如果where子句后有多个条件需要组合,SQL提供了and和or逻辑运算符来组合两个条件,并提供了not来对逻辑表达式求否。如下SQL语句将选出学生名字为2个字符,且student_id大于3的所有记录。
select*from student_table
where student_name like '__' and student_id >3;
select*from student_table
where student_name like '__' or student_id >3;
select*from student_table
where not student_name like '\_%';
下面示意了逻辑运算符的优先级。
如果SQL代码需要改变优先级默认顺序,则可以使用括号,括号的优先级比所有的运算符都高
select*from student_table
where(student_id > 3 or student_name >'张')and java_teacher>1;
执行查询后的查询结果默认按插入顺序排列;如果需要查询结果按某列值大小进行排序,则可以使用 order by 子句。 order by 子句的语法格式如下:
order by column_name1 [desc],column_name2 ...
进行排序时默认按升序排列,如果强制按降序排列,则需要在列后使用desc关键字(与之对应的是asc关键字,用不用该关键字的效果完全一样,因为默认就是按升序排序的)。
上面语法中设定排序列时可采用列名、序列名和列别名。如下SQL语句选出student_table表中所有记录,选出后按java_teacher列的升序排列。
如果需要按多列排序,则每列的asc、desc必须单独设定,如果指定了多个排序列,则第一个排序了是首要排序列,只有当第一列中存在多个相同的值时,第二个排序列才会起作用。如下SQL语句先按java_teacher列的降序排列,当java_teacher列的相同值同时按student_name列的升序排列。
select*from student_table
order by java_teacher desc,student_name;
前面看到的连接字符串使用的concat函数,每个数据库都会在标准的SQL基础上扩展一些函数,这些函数用于进行数据处理和复杂计算,它们通过对一组数据进行计算,得到最终需要输出的结果。
函数一般都会有一个或者多个输入,这些输入被称为函数的参数,函数内部会对这些参数进行判断和计算,最终只有一个值作为返回值。函数可以出现在SQL语句中的各个位置,比较常用的位置是select之后和where子句之中。
根据函数对多行数据的处理方式,函数被分为单行函数和多行函数,单行函数对每行输入值单独计算,每行得到一个计算结果返回给用户,多行函数对多行输入值整体计算,最后只会得到一个结果。
SQL中的函数和Java语言中的方法有些相似,但SQL中的函数是独立的程序单元,也就是说,调用函数时无须使用任何类、对象作为调用者,而是直接执行函数。执行函数的语法如下:
function_name(arg1,arg2...)
多行函数也称为聚集函数、分组函数,主要用于完成一些统计计算,在大部分数据库中基本相同。但不同数据库中的单行函数差别非常大,MySQL中的单行函数具有如下特征。
MySQL数据库的数据类型大致分为数值型、字符串和日期时间型,所以MySQL提供了对应的函数。转换函数主要负责完成类型转换。其他函数又大致分为如下几类。
每个数据库都包含了大量的单行函数,这些单行函数的用法也存在一些差异,但是有一点是相同的——每个数据库都会为一些常用计算功能提供相应的函数,这些函数的函数名可能不同,用法可能有差异,但所有数据库提供的函数库所能完成的功能大致相似。
MySQL单行函数的用法。
这里代码比较多
#选出teacher_table表中teacher_name列的字符长度
select char_length(teacher_name);
#计算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',3);
#获取当前日期
select CURDATE();
#获取当前时间
select curtime();
#下面的MD5是MD5加密函数
select MD5('testing');
MySQL提供了如下几个处理null的函数
#如果student_name列等于'张三',则返回null
select nullif(student_name,'张三')
from student_table;
#如果student_name列为null,则返回'没有名字',否则返回'有名字'
select if(isnull(student_name),'没有名字','有名字')
from student_table;
MySQL还提供了一个case函数,该函数是一个流程控制函数。case函数有两个用法,case函数第一个用法的语法格式如下:
case value
when compare_value1 then result1
when compare_value2 then result2
...
else result
end
case函数用value和后面的compare_value1、compare_value2、…依次比较,如果value和指定的compare_value1相等,则返回对应的result1,否则返回else后的result。
#如果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个
#计算student_table表中的记录条数
select count(*) from student_table;
#计算java_teacher列总共有多少个值
select count(distinct java_teacher) from student_table;
select sum(student_id) 'student_id的所有总和'
from student_table;
#上面是别名的应用
#计算的结果是20*记录的行数
select sum(20) from student_table;
#选出student_table表中最大的id值
select max(student_id) from student_table;
#选出teacher_table表中teacher_id最小的值
select min(teacher_id) from student_table;
#因为sum里的expr是常量34,所以每行的值都相同
#使用distinct强制不计算重复值,所以下面的计算结果为34
select sum(distinct 34)
from student_table;
select count(student_name) from student_table;
对于可能出现null的列,可以使用ifnull函数来处理该列。
#计算java_teacher列所有记录的平均值
select avg(ifnull(java_teacher,0))
from student_table;
值得支出的是,distinct和*不同时使用,如下SQL语句有错误
select count(distinct *)
from student_table;
在默认情况下,组函数会把所有记录当一组,为了对记录进行显式分组,可以在select语句后使用group by子句,group by子句后通常会跟一个或多个列名,表明查询结果根据一列或多列进行分组——当一列或多列组合的值完全相同时,系统会把这些记录当成一组。SQL语句如下:
#count(*)将会对每组得到一个结果
select count(*)
from student_table
#将java_teacher列值相同的记录当成一组
group by java_teacher;
如果对多列进行分组,则要求多列的值完全相同才会被当成一组。SQL语句如下:
select count(*)
from student_table
#当java_teacher、student_name两列的值完全相同时才会被当成一组
group by java_teacher,student_name;
很多时候,需要选择的数据并不是来自一个表,而是来自多个数据表,这就需要使用多表连接查询,例如,对于上面的student_table和teacher_table两个数据表,如果希望查询出所有学生以及他的老师名字,这就需要从两个表中取数据。
多表连接查询有两种规范,较早的SQL92规范支持如下几种多表连接查询。
SQL92的多表连接查询语法比较简洁。多个表都放在from之后,多个表以逗号可开,连接条件在where之后,与查询条件之间用and逻辑运算符连接。如果连接条件要求两列值相等,则称为等值连接,否则称为非等值连接;如果没有任何连接条件,则被称为广义笛卡儿积,SQL92中多表连接查询的语法格式如下:
select column1,colum2...
from table1,table2...
[where join_coondition]
多表连接查询中可能出现两个或多个数据列具有相同的列名,则需要在这些同名列之间使用表名前缀或表别名前缀作为限制,避免系统混淆。
如果只是单表查询是不可能重复的,但是多表查询应该加上前缀或表别名。
如下SQL语句查询出所有学生的资料以及对应的老师姓名。
实际上,多表查询的过程可以理解成一个嵌套循环。这个嵌套循环的伪码如下:
//依次遍历teacher_table表中的每条记录
for t in teacher_table{
//遍历student_table表中的每条记录
for s in student_table{
//当满足连接条件时,输出两个表连接后的结果
if(s.java_teacher = t.teacher_id)
output s + t
}
}
#不使用连接条件,得到广义笛卡儿积
select s.*,teacher_name
#指定多个数据表,并指定表别名
from student_table s,teacher_table t;
与此类似的是,非等值连接的执行结果可以使用上面的嵌套循环来计算,SQL语句如下:
select s.*,teacher_name
#指定多个数据表,并指定表别名
from student_table s,teacher_table t
#使用where指定连接条件,并指定student_name列不能为null
where s.java_teacher = t.teacher_id and student_name is ot null;
SQL不支持SQL 92的左外连接、右外连接。
自连接只是连接的一种用法,并不是一种连接类型,不管是SQL92还是SQL99栋可以使用自连接查询。自连接本质就是把一个表当两个表来用。
下面的SQL语句建立了一个自连接的数据表,并向表中插入了4条数据。
create tabl emp_table(
emp_id int auto_increment priamry key,
emp_name varchar(255),
manager_id int,
foreign key(manager_id) references emp_table(emp_id));
insert into emp_table
values(null,'唐僧',null),
(null,'孙悟空',1),
(null,'猪八戒',1),
(null,'沙僧',1);
如果需要查询该数据表中的所有员工名,以及每个员工对应的经理名,则必须使用自连接查询。所谓自连接就是把一个表当成两个表来用,这就需要为一个表起两个别名,而且查询中用的所有数据列都要加表别名前缀,因为两个表数据完全一样。下面的自连接查询可以查询出所有的员工名,以及对应的经理名。
select emp.emp_id,emp.emp_name 员工名, mar.emp_name 经理名
from emp_table emp,emp_table mgr
where emp.manager_id = mgr.emp_id;
SQL99的连接查询与SQL 92的连接查询原理基本相似,不同的是SQL99连接查询的可读性更强——查询用多个数据表显式使用 xxx join连接,而不是直接依次排列在from之后,from后只需要放一个数据表;连接条件不再放在where之后,而是提供了专门的连接条件子句。
select s.*,teacher_name
#SQL99多表连接查询的from后只有一个表名
from student_table s
#cross join 交叉连接,相当于广义笛卡儿积
cross join teacher_table t;
select s.*,teacher_name
from student_table s
natural join teacher_table t;
运行上面语句将出现一个错误,因为student_table表中并不存在名为teacher_id的列,也就是说,如果使用using子句来指定连接条件,则两个表必须有同名列,否则将会出现错误。
select s.*,teacher_name
#SQL99多表连接查询的from后只有一个表名
from student_table s
#join连接另一个表
join teacher_table t
#使用on来指定连接条件
on s.java_teacher = t.teacher_id;
使用on子句的连接完全可以替代SQL92的等值连接、非等值连接,因为on子句的连接条件除等值条件之外,也可以是非等值条件。如下SQ语句就是SQL99中的非等值连接。
select s.*,teacher_name
#SQL 99多表连接查询的from后只有一个表名
from student_table s
#join连接另一个表
#使用on来指定连接条件;非等值连接
on s.java_teacher>t.teacher_id;
select s.*,teacher_name
#SQL 99多表连接查询的from后只有一个表名
from student_table s
#right join 右外连接另一个表
right join teacher_table t
#使用on来指定连接条件,使用非等值连接
on s.java_teacher<t.teacher_id;
select s.*,teacher_name
from student_table s
left join teacher_table t
on s.java_teacher>t.teacher_id;
不难发现SQL99与SQL92外连接恰好相反,SQL99左外连接会把左边表中所有不满足连接条件的记录全部列出;SQL99右外连接将会把右边表中所有不满足条件的记录全部列出。
下面的SQL语句使用全外连接,连接条件是等值连接。
会出错误,因为MySQL并不支持全外连接。
这些查询我也懵,到了JDBC多练练就行了,现在有点抽象
子查询就是指定查询语句中嵌套另一个查询,子查询可以支持多层嵌套。对于一个普通的查询语句而言,子查询可以出现在两个位置。
对于把子查询当成数据表是完全把子查询当做数据表来用,只是把之前的表名变成子查询(也可为子查询起别名),其他部分与普通查询没有任何区别。下面SQL语句示范了把子查询当数据表的用法。
select*
#把子查询当数据表
from(select*from student_table) t
where t.java_teacher>1;
把子查询当数据表的用法更准确地说是当成视图,可以把上面的SQL语句理解成在执行查询时创建了一个临时视图,该视图名为t,所以这种临时创建的视图被称为行内视图。
还有一种情形:把子查询当where条件中的值,如果子查询返回单行、单列值,则被当成一个标准量使用,也就是可以单行记录比较运算符。例如如下SQL语句:
先加一个数据
select *from student_table
where java_teacher > (select teacher_id from teacher_table
where teacher_name = 'Yeeku'
);
#显示student_table的值(java_teacher大于teacher_id)
这里因为前面都是相等的,所以只有最后几列输出了出来。比如容易误导。
上面查询语句中的子查询将返回一个单行、单列值(该值就是1),如果把上面查询语句的括号部分换位1,那么这条语句就再简单不过了——实际上,这就是这种子查询的实质,单行、单列子查询被当成标准量处理。
如果子查询返回多个值,则需要使用in、any和all等关键字,in可以单独使用,与前面介绍比较运算符所讲的in完全一样,此时可以把子查询返回的多个值当成一个值列表。
select*from student_table
where student_id in (select teacher_id from teacher_table);
上面查询语句中的子查询将返回多个值,这多个值将被当成一个值列表,只要student_id与该值列表的任意一个值相等,就可以选中这条记录。
any和all可以与>、>=、<、<=、<>、=等运算符结合使用,与any结合使用分表表示大于、大于等于、小于、小于等于、不等于、等于其中任意一个值;与all结合使用分别表示大于、大于等于、小于、小于等于、不等于、等于全部值。从上面介绍可以看出,=any的作用与in的作用相同。如下语句使用=any来替代上面的in。
select*from student_table where student_id>
all(select teacher_id from teacher_table);
还有一种子查询可以返回多行、多列,此时where子句中应该有对应的数据列,并使用圆括号将多个数据列组合起来。SQL语句如下:
查了个寂寞,我们直接看集合运算然后看JDBC基础入门。
select语句查询的结果是一个包含多条数据的结果级,类似于数学里的集合,还可以进行交(intersect)、并(union)和差(minus)运算,select查询得到的结果集也可能需要进行这三种运算。
为了对两个结果集进行集合运算。这两个结果集必须满足如下条件。
union运算的语法格式如下:
select 语句 union select 语句
下面的SQL语句查询出所有教师的信息和主键小于4的学生信息。
#查询结果集包含两列,第一列为int类型,第二列为varchar类型
select*from teacher_table
union
#这个结果集的数据列必须与前一个结果集的数据列一一对等
select student_id,student_name from student_table;
minus运算的语法格式如下:
select 语句 minus select 语句
上面的语法格式十分简单,不过很遗憾,MySQL并不支持使用minus运算符们只能借助于子查询来“曲线”实现上面的minus运算。
假如向从所有学生记录中“减去”与老师记录的ID相同、姓名相同的记录,则可进行如下的minus运算
MySQL并不支持这种运算。但可以通过如下子查询来实现上面的运算。
intersect运算的语法格式如下:
select 语句 intersect select 语句
上面的语法格式十分简单,不过很遗憾,MySQL并不支持使用intersect运算符,因此只能借助于多表连接查询来“曲线”实现上面的intersect运算。
假如想找出学生记录中与老师记录中的ID相同、姓名相同的记录,则可以进行如下的intersect运算。
select student_id,student_name from student_table
intersect
#两个结果级的数据列的数量必须相等,数据类型一一对应,可以进行intersect运算
select teacher_id,teacher_name from teacher_table;
不过MySQL并不支持这种运算。但可以通过如下多表连接查询来实现上面运算。
select student_id ,student_name from student_table
join teacher_table
on(student_id=teacher_id and student_name = teacher_name);
需要指出的是,如果进行intersect运算的两个select子句中都包括了where条件,那么将intersect运算改成多表连接查询后还需要将两个where条件进行and运算。假如有如下intersect运算的SQL语句:
上面语句改写如下;
某种意义上来说 没有数据就是查询了个寂寞。
重头戏来了。
连接方式
准备好驱动JAR包即可
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class ConnMySql {
public static void main(String[] args)throws Exception {
//1.加载驱动,使用反射知识,现在记住这么写
Class.forName("com.mysql.cj.jdbc.Driver");
try(
//2.使用DriverManger获取数据库连接
//其中返回的Connection就代表了Java程序和数据库的连接
//不同数据库的URL写法需要查驱动问道,用户名、密码由DBA分配
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?useSSL=false&serverTimezone=UTC",
"root","123456789");
//3.使用Connection来创建一个Statement对象
Statement stmt = conn.createStatement();
//4.执行SQL语句
/*
Statement有三种执行SQL语句的方法:
1.excute()可执行任何SQL语句-返回一个boolean值
如果执行后第一个结果是ResultSet,则返回true,否则返回false
2.excuteQuery()执行select语句-返回查询到的结果级
3.excuteUpdate()用于执行DML语句-返回一个整数
*/
ResultSet rs = stmt.executeQuery("select*from teacher_table"))
{
//ResultSet有一系列的getXxx(列索引|列名)方法,用于获取记录指针
//指定行、特定列的值,不断地使用next()将记录指针下移一行
//如果移动之后记录指针依然指向有效行,则next()方法返回true
while(rs.next()){
System.out.print("老师编号:"+rs.getInt("teacher_id")+" ");
System.out.println("老师名称:"+rs.getString("teacher_name"));
}
}
}
}
本文章就此结束了,加油哦。