/*
DML语句
DML操作是指对数据库中标记录的操作,主要包括表记录的插入(insert)、更新(update)、删除(delete)、查询(select)
这里介绍mysql中的
*/
--先准备一张表
create table Student
(
)
--插入数据
/*一个概念,自增。
注意:
mysql中的自增长好像只可以设置标志种子而不可以设置每一次自增的量。
一个表中好像只能设置一个字段自增,如果设置多个字段自增,报错。
一个表中的自增长的列只能是一个,数据类型要是整数类型,必须是主键或者unique约束,且注意,对于任意任何想要做自增的键,必须加非空约束。指的是它必须不能为空,主键自带,unique需要声明
*/
--there can be only one auto column and it must be defined as a key
create table Student(
id int primary key,
age int auto_increment
)
create table Student(
id int primary key auto_increment,
age int auto_increment
)
--前面两个都是错误的例子
--两种设置自增的方式:1、在建表的时候设置
create table teaA
(
id int primary key auto_increment,
name varchar(20)
)
insert into teaA(name) values('ni');--设置自增成功,插入成功
select * from teaA;
drop table teaA;
--这里每一次都是从1开始的,怎么设置从某一个特定的数开始呢?
create table teaA
(
id int primary key auto_increment,
name varchar(20)
)
alter table teaA auto_increment=1000;--这里设置了
--第二种设置自增,通过后面修改表的对应主键项使得表自增
create table teaA
(
id int primary key,
name varchar(20)
);
alter table teaA modify id int auto_increment;--前面定义了主键,你在这里不能加主键
alter table teaA auto_increment=1000;
drop table teaA;
/*
再来一个概念,默认值。
有些列可以设定如果你不给值的话,它会自动使用默认值。
如何设定默认值?
建表时:create table tablename (columnname datatype default defaultvalue);
已建表修改:alter table tablename alter column columnname set default defaultvalue;
*/
/*
再来一个概念,允许空值。只要你没有设置非空约束,没有主键约束。它就是可以为空的,你就可以不在该列中插入值或者插入null值
插入数据的基本语法: insert into 表名(列名1,列名2,。。。) values (属性值1,属性值2,。。。)
注意:
第一个括号里面写所有的要插入的项,后面的括号里面的值与前面的一一对应
如果主键是自增,插入的项中不需要给主键赋值
*/
insert into teaA (name) values ('guozhen');
/*如果有某些列允许空值,可以不给那些赋值,就是在列名的括号中不写它或者在列名中的有了但是在后面赋值的时候给他赋空值*/
alter table teaA add column age int; --增加一项
insert into teaA(name,age) values('liuli',null);
insert into teaA(name) values('wuc');
--其实前面的列名也可以省略,表示给该表中的所有列赋值。但是那样的话,有自增的是不能搞定的。
create table student (id int primary key,name varchar(20),sex varchar(2));--新增一个表
insert into student values(1,'guozhen','0');
--如何一次插入多条数据呢? 语法: insert into 表名(列名1,列名2,...) values (属性值1,属性值2,...) ,(属性值1,属性值2,...)...;,当然也可以省略列名
insert into student values(2,'liuli','0'),(3,'xuyu','0');
/*
删除数据
两种方式delete语句和truncate语句 delete from 表名 [where ...],后面如果不加表名,默认删除的是表的所有数据
truncate与delete的区别:
delete删除的数据,你不commit是不会保存操作的,truncate删除的数据,是直接删除数据,释放空间
delete删除数据可以指定where条件,删除部分数据,truncate清空整个表格
*/
delete from student where id=1;
truncate student;
select * from student;
/*
修改数据
update语句 update 表名 set 字段名=属性值 [where...]
可以修改多个属性项,使用逗号连接,如果不是用where语句,则默认修改整个表。
*/
update student set sex='1';
select * from student;
update student set name='guozhen1',sex='0' where id=1;
/*
查询语句select
select * from 表名 查询某表所有信息
select 列名1,。。。 from 表名
select * from 表名 where ...
select 列名1,。。。 from 表名 where... 查询指定列满足某个条件的所有数据
*/
select * from student;
select name from student;
select name,sex from student;
select * from student where id=2;
--查询不重复的记录,使用distinct关键字
insert into student values(4,'liuli',1);--插入重复数据
select name,sex from student;--可以看到重复现在
select distinct name,sex from student; --成功去除重复
/*条件查询,where语句
where 后面的条件可以是比较运算符,例如>、< >= <= != =,也可以是逻辑运算符 in or and 等
*/
select * from emp;
select * from emp where deptno=1; --查询所有deptno为1的记录
/*
模糊查询
like语句 通配符“_”表示一个字符,“%”表示任意个字符。如果前后没有通配符表示以某个字符开头或者以某个字符结尾
in关键字 表示一个固定范围之间,类似于枚举类型
between ... and在一个区间,相当于 >=XXX and <XXX 元素要是有可比性的,一般字符串按照hashCode比较
*/
select * from emp where ename like 'han%';
select * from emp where ename like '%zhe_'
select * from emp where ename between 'g' and'j';
--对查询的结果进行排序,order by 关键字,asc表示升序,desc表示降序,可以有多个排序条件,使用逗号分隔,默认的排序方式是升序
select * from emp order by sal asc;
select * from emp order by sal desc,deptno desc;
--限制语句。在不同数据库中的限制语句不同。记忆中oracle是使用rownum sql server是使用top,mysql使用的是limit关键字,limit的语法: select ..[limit offset_start,length]
select * from emp limit 3;--如果不写前面的offset_start则表示从前面的0号下标位置开始,查询前n条记录
select * from emp limit 2,2;
/*
常见的聚合函数:sum(求和)、count(*)(记录数)、max(最大值)、min(最小值)、avg(x)求平均值
分组:group by语句,如果需要依据多个条件进行分组,使用逗号隔开
注意:group by 是根据 后面的字段分组,即该字段相同的记录只会显示一行,除非你后面跟的字段的值是唯一 ,才会全部显示,group by 通常会用于统计 如 count( ) sum() 等。
使用聚合后如何使用条件判断呢?where?having?
where和having的区别
select ··· from ···
where ···(只能对分组前的属性进行筛选)
group by ···
having ···(只能对分组后的每个组的整体属性进行筛选,用聚合函数体现)
····
--不使用group by就默认表的整体为一组
意义都一个样,
速度上:where更快
使用上:1、having先分组后计算,where反之 2、having后面跟聚合函数,where不可以。
前面是我百度来的答案,我总结下:
where是针对整个查询出来的结果进行选择,having是在查询出结果后分组的结果进行选择。having是在分组后再计算,所以速率就不用说了
having后面的选择条件可以是聚合函数,但是where遇救不可以
*/
select * from emp;
select count(ename) from emp;
select avg(sal) from emp;
select * from emp group by deptno;
select * from emp group by deptno,sal,hiredate;
select count(*) from emp group by deptno; --这里我感觉聚合函数的参照物指的是每一组的数据,默认一组所以直接使用得到的是count=4,但是分组后就分开了
select ename,avg(sal) from emp group by ename;
select ename,avg(sal) from emp where ename in ('guozhen','hanxiaowen') group by ename ; --排序和聚合是在查询出的数据的基础上进行操作的,所以where字句应该在group by字句之前
select ename,avg(sal) from emp group by ename having ename in ('guozhen','hanxiaowen');
select ename from emp where avg(sal) >2500;--报错
select ename from emp where avg(sal) >2500 group by ename;--报错
select ename,avg(sal) from emp group by ename having avg(sal) >2500; --正确的
select * from emp where sal>2000 group by hiredate;
/*
表连接
当需要同时显示多个表中的字段时,就可以使用表连接来实现这样的功能。
表连接分为两类:
内连接:仅选出两张表中互相匹配的记录
inner join ... on
外连接:会选择其中不匹配的记录
left join ... on 包含左边表中的记录甚至是右边表中没有和他匹配的记录
right join ... on
*/
select * from emp;
select * from dept;
insert into emp values('xiongda','1987-09-12',8000,5);
select * from emp inner join dept on emp.deptno=dept.deptno;
select * from emp left join dept on emp.deptno=dept.deptno;
select * from emp right join dept on emp.deptno=dept.deptno;
/*
子查询
在某些情况下,当进行查询的时候,需要的条件是另一个select语句的结果的时候,就要用到子查询。所以说,内连接查询可以使用子查询替换
用于子查询的关键字有in、not in、= 、!=、exists、not exists等,如果查询的记录唯一,可以使用=替代in
*/
select * from emp where deptno in (select deptno from dept where deptname in ('hanxiaowen','fin'));
/*记录联合 union 和union all*/
/*关于sql union操作符号
union操作符用于合并两个或者多个select语句的结果集
注意:
union内部的的select语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条select语句中列的顺序必须相同
union结果集中的列名总是等于union中第一个select语句中的列名
sql union语法的结果集没有重复值,只能用于查询语句
union all就保留重复值
*/
select * from customers
union
select * from orders;
create table usera(
name varchar(20),
password varchar(20)
);
/*刚刚使用add加到后面了,无奈只能重新修改到最前面去*/
alter table usera modify column id int first;
alter table userb modify column id int first;
create table userb(
name varchar(40),
password varchar(40)
);
insert into usera values (1,'zhang','hua'),(2,'wang','wei'),(3,'carter','tomas'),(4,'yang','ming'),(5,'zhang','hua');
insert into userb values (1,'adams','john'),(2,'bush','george'),(3,'carter','thomas'),(4,'gates','bill');
/*抄错数据了*/
update usera set password='thomas' where name='carter';
select name,password from usera
union
select name,password from userb
/*测试发现union会去重复,相当于将两个表中查出来的数据当成一个表然后去重复*/
select name,password from usera
union all
select name,password from userb
/**/
--使用左外连接的小例子-------------
create database others;
create table Customers
(
customerid char(5) not null primary key,
city varchar(10) not null
);
drop table customers;
insert into customers
values ('FISSA','Madrid'),('FRNDO','Madrid'),('KRLOS','Madrid'),('MRPHS','Zion');
create table Orders
(
orderid int not null primary key,
customerid char(5) null references customers(customerid)
)
insert into Orders values (1,'FRNDO'),(2,'FRNDO'),(3,'KRLOS'),(4,'KRLOS'),(5,'KRLOS'),(6,'MRPHS'),(7,null);
select * from customers;
select * from orders;
/*题目:来自Madrid且订单数少于3的消费者 */
/*
先分析一下吧:
首先查找的是消费者
来自Madrid
查找订单数小于三的customerid
*/
select distinct * from customers;
select distinct * from customers where city='Madrid';
select customerid from orders group by customerid having count(*)<3;
/*多表连接查询,应该是默认的内连接inner join*/
select distinct a.customerid '消费者',count(*) '数量' from customers a,orders b where a.customerid=b.customerid group by a.customerid having count(*)<3;
/*别人的做法,子查询*/
select distinct customerid as '消费者',count(customerid) as '订单数' from Orders where customerid in (select distinct customerid from orders group by customerid having count(*)<3) group by customerid;
/*其实前面全部都有问题,查询的少了一个数据,就是没有一个消费的消费者FISSA,因为它没有消费,所以再消费表中找不到记录*/
/*多表左外连接连接查询,count里面*少用,最好用标识列*/
select distinct a.customerid '消费者',count(b.orderid) '消费数量' from customers a left join orders b on a.customerid=b.customerid group by a.customerid having count(b.orderid)<3;
/*左外连接,右外连接,内连接的区别:
内连接查询的是两个表中的所有有共性的数据,
左外连接查询的是左边表中的所有数据和右表中有共性的数据
右外连接查询的是左表中的有共性的数据和右表中的所有数据
当然,三个查询都需要满足基本的查询条件
*/