SQL表中支持很多固有类型,包括:
类型 |
含义 |
char(n) |
存放固定长度的字符串,用户指定长度为n。如果没有使用n个长度则会在末尾添加空格。 |
varchar(n) |
可变长度的字符串,用户指定最大长度n。char的改进版,大多数情况下我们最好使用varchar。 |
int |
整数类型 |
smallint |
小整数类型 |
numeric(p,d) |
定点数,精度由用户指定。这个数有p位数字(包括一个符号位)d位在小数点右边。 |
real ,double precision |
浮点数和双精度浮点数。 |
float(n) |
精度至少位n位的浮点数 |
SQL中用很多关键字来表达CRUD的操作(增删改查)。在这之外有很多特殊的关键字用来表示一些其他的含义,在总结SQL之前我们有必要进行一些了解。
类型 |
含义 |
示例 |
primary key |
主键,后面括号中是作为主键的属性 |
primary key(student_id) |
foreign key references |
外键,括号中为外键,references后为外键的表 |
foreign key(course_id) references Course |
not null |
不为空,前面为属性的定义 |
name varchar(10) not null |
SQL语法使用最多的就是查询,除了查找语句之外,其他的语句内容都很少。
类型 |
含义 |
create table |
创建一张表 |
insert into…values |
向表中插入一条信息 |
delete from |
从表中删除一条信息 |
update…set…where |
在where的位置,更新内容为set的值 |
drop table |
删除表 |
alter table…add |
向表中添加某个属性 |
alter table…drop |
将表中的某个属性删除 |
create table Student(
ID varchar(20) not null,
name varchar(10) not null,
age int,
class varchar(50),
primary key (ID));
创建一张叫做Student的表,表中有四个属性,ID,姓名,年龄和班级,么个属性都有各自的类型。在这张表中主键是ID。
insert into Student(ID,name,class)
values(10152510302,"Tom","class 1");
向表中添加一行信息,一个名叫Tom的学生的信息,因为age值不是not null,也就不是必须的,所以我们不添加age属性也没有问题。
delete form Student
where name="Tom";
从表中删除所有名字叫做Tom的信息。如果delete from不写where查询条件表示清空这张表。
update Student
set age=18
where name="Tom";
将所有名字叫做Tom的信息的年龄设置为18。
drop table Student;
删除Student这张表。
alter table Student
add sex varchar(5);
向表中添加性别属性,并且将表中以存放的信息的sex值设为null。所有通过这种方式添加的属性都不能被设置为not null类型。
alter table Student
drop class;
从表中将class这一列属性删除。
SQL最为常用的就是查询,我们使用数据库并从中查找出我们希望的内容。在这个过程中,我们可能要编写很复杂的语句。这里我们分类别详细的总结具体的查询情况。
单关系查询是指只一张表中的内容查询有关信息,不涉及其他的表,这是查询中最为基本的一种情况。我们通过这种情况来总结一些基本的SQL语句编写方法。下面先给出一些涉及到的关键字。
类型 |
含义 |
select |
表示要查找出的表所含有的属性 |
from |
表示要操作的表 |
where |
判断条件,根据该判断条件选择信息 |
distinct |
在select后加入关键字distinct表示将结果去重 |
all |
在select后加入关键字all表示不去重(默认) |
and |
在where中使用and表示将判断条件连接起来 |
or |
在where中使用or表示判断条件多选一 |
not |
在where中使用not表示判断条件取反 |
在下面的查询语句中,我们仍旧使用Student这张表来进行操作。先回顾一下这张表的字段。
create table Student(
ID varchar(20) not null,
name varchar(10) not null,
age int,
class varchar(50),
primary key (ID));
select name distinct
from Student
where age=18 and class="A";
在Student这张表中查询所有年龄是18岁,并且班级是A的学生的名字,并将结果去重。
多关系查询是指在多个表中通过一些操作查找出希望的信息。除去上面已有的关键字,我们还会使用到下面这些。
类型 |
含义 |
A,B |
在from后面通过逗号连接多张表,表示将这些表进行笛卡儿积运算 |
natural join |
将natural join关键字前后的两张表进行自然连接运算 |
A join B using(c) |
将A和B通过c属性自然连接 |
(补充:笛卡尔积
)
为了能够进行多关系查询,我们需要有除了Student的另外一张表。再建一张表,表示上数学课的所有学生的信息和成绩情况。(实际上这两张表建的都不好,不能满足基本的几个范式,但是为了方便起见用来举例)
create table Math(
ID varchar(20) not null,
name varchar(10) not null,
sex varchar(5),
score int,
primary key(ID));
select score
form Student natural join Math
where class<>"B" and sex="men"
将Student表和Math表自然连接,所得的结果查询出不是B班的男生的成绩。
我们已经总结了单关系和多关系运算的查询方法,但是只有这些
类型 |
含义 |
as |
将as前的关系起一个别名,在此语句中,可以用别名来代指这个表 |
* |
在select中通过: “表名.*” 来表示查找出这个表中所有的属性 |
order by |
让查询结果中的信息按照给定的属性排序(默认升序,上小下大) |
desc |
在order by之后的属性后使用,表示采用降序排序 |
asc |
在order by之后的属性后使用,表示采用升序排序(默认) |
between |
在where中使用between表示一个数在两个数值之间取值 |
not between |
between的反义词,在两个数之外取值 |
union/union all |
将两个SQL语句做并运算,并且自动去重,添加all表示不去重 |
intersect/intersect all |
将两个SQL语句做交运算,并且自动去重,添加all表示不去重 |
except/except all |
将两个SQL语句做差运算,并且自动去重,添加all表示不去重 |
is null |
在where中使用is null表示这个值是空值 |
is not null |
在where中使用is not null表示这个值不是空值 |
select S.*
from Student as S,Math as M
where S.ID = M.ID
将Student和Math两张表做笛卡儿积,结果中所有ID相同的信息,取出他们属于Student属性的部分作为结果。
select name
from Student natural join Math
where class="A" and sex="women"
order by score desc;
在Student和Math自然连接的结果中,找出A班的女生的姓名,并且按照成绩的降序把名字排列出来。
select name
from Math
where score between 60 and 90;
order by score asc;
在Math表中,找出成绩在60分到90分之间的学生姓名,并且将姓名按照成绩的升序排列出来。
(select name
from Student natural join Math
where class="A" and sex="women"
order by score desc)
union
(select name
from Math
where score between 60 and 90;
order by score);
将上面两个查出来的结果做并集,并且去重。
select name
from Student
where age is null;
在Student表中记录的年龄值未填写(为空)的所有人的姓名查出来。
已经总结了SQL语句的很多关键字,现在我们可任意的进行排序、查找。但是如果我们要获得一些与数据相关的统计信息,但是这些信息在数据库中没有,那么我们要使用SQL中的聚集函数来进行操作。
类型 |
含义 |
avg |
平均值 |
min |
最小值 |
max |
最大值 |
sum |
总和 |
count |
计数 |
distinct |
表示将distinct后的属性去重 |
group by |
将在group by上取值相同的信息分在一个组里 |
having |
对group by产生的分组进行筛选,可以使用聚集函数 |
select class,avg(score) as avg_score
from Student natural join Math
group by class
having avg(score) < 60;(这里应该是avg(score) >60吧)
在Student与Math表自然连接的结果中按照班级分组,并且去除那些班级的平均成绩没到60的班级,剩下的班级和该班成绩的平均数(该班成绩的平均数这个属性被重命名为avg_score)作为一张新表被输出出来
第二篇:
关于SQL中的having用法(这篇很清晰的介绍了通过having和不通过having用法的区别)
https://www.cnblogs.com/lao-tang/p/6398577.html
现在 Student表有如下数据
现需求如下:查找每个老师的学生的平均年龄且平均年龄大于12
不使用 HAVING
1SELECT*FROM (SELECT TeacherID, AVG(Age) AS AGE FROM Student
2 GROUPBY TeacherID) T WHERE T.AGE>12
使用HAVING
1 SELECT TeacherID, AVG(Age) AS AGE FROM Student
2 GROUPBY TeacherID
3 HAVING AVG(Age) >12
结果如下:
HAVING:给分组设置条件
SQL语句中设定集合函数的查询条件时使用Having从句而不是where从句。通常情况下,having从句是被放置在SQL命令的结尾处。
第三篇
Sql中的exists,not exists的用法
https://www.cnblogs.com/mytechblog/articles/2105785.html
sql中exists,notexists的用法
exists : 强调的是是否返回结果集,不要求知道返回什么,比如:
select name from student where sex = 'm' and mark exists(select1 from grade where ...) ,只要
exists引导的子句有结果集返回,那么exists这个条件就算成立了,大家注意返回的字段始终为1,如果改成“select 2from grade where ...”,那么返回的字段就是2,这个数字没有意义。所以exists子句不在乎返回什么,而是在乎是不是有结果集返回。
而 exists 与 in 最大的区别在于in引导的子句只能返回一个字段,比如:
select name from student where sex = 'm' and mark in (select1,2,3 from grade where ...)
,in子句返回了三个字段,这是不正确的,exists子句是允许的,但in只允许有一个字段返回,在1,2,3中随便去了两个字段即可。
而not exists 和not in 分别是exists 和 in 的对立面。
exists (sql 返回结果集为真)
not exists (sql 不返回结果集为真)
下面详细描述not exists的过程:
如下:
表A
ID NAME
1 A1
2 A2
3 A3
表B
ID AID NAME
1 1 B1
2 2 B2
3 2 B3
表A和表B是1对多的关系 A.ID => B.AID
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE A.ID=B.AID)
执行结果为
1 A1
2 A2
原因可以按照如下分析
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=1)
--->SELECT * FROM B WHERE B.AID=1有值返回真所以有数据
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=2)
--->SELECT * FROM B WHERE B.AID=2有值返回真所以有数据
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=3)
--->SELECT * FROM B WHERE B.AID=3无值返回真所以没有数据
NOT EXISTS 就是反过来
SELECT ID,NAME FROM A WHERENOT EXIST(SELECT * FROM B WHERE A.ID=B.AID)
执行结果为
3 A3
===========================================================================
EXISTS = IN,意思相同不过语法上有点点区别,好像使用IN效率要差点,应该是不会执行索引的原因
SELECT ID,NAME FROM A WHEREID IN (SELECT AID FROM B)
NOT EXISTS = NOT IN ,意思相同不过语法上有点点区别
SELECT ID,NAME FROM A WHEREIDNOT IN (SELECT AID FROM B)
有时候我们会遇到要选出某一列不重复,某一列作为选择条件,其他列正常输出的情况.
如下面的表table:
Id Name Class Count Date
1 苹果 水果 10 2011-7-1
1 桔子 水果 20 2011-7-2
1 香蕉 水果 15 2011-7-3
2 白菜 蔬菜 12 2011-7-1
2 青菜 蔬菜 19 2011-7-2
如果想要得到下面的结果:(Id唯一,Date选最近的一次)
1 香蕉 水果 15 2011-7-3
2 青菜 蔬菜 19 2011-7-2
正确的SQL语句是:
SELECT Id, Name, Class, Count, Date
FROM table t
WHERE (NOT EXISTS
(SELECT Id, Name,Class, Count, Date FROM table
WHERE Id = t.Id ANDDate > t.Date))
如果用distinct,得不到这个结果, 因为distinct是作用与所有列的
SELECT DISTINCT Id, Name, Class, Count, Date FROM table
结果是表table的所有不同列都显示出来,如下所示:
1 苹果 水果 10 2011-7-1
1 桔子 水果 20 2011-7-2
1 香蕉 水果 15 2011-7-3
2 白菜 蔬菜 12 2011-7-1
2 青菜 蔬菜 19 2011-7-2
如果用Group by也得不到需要的结果,因为Groupby 要和聚合函数共同使用,所以对于Name,Class和Count列要么使用Group by,要么使用聚合函数. 如果写成
SELECT Id, Name, Class, Count, MAX(Date)
FROM table
GROUP BY Id, Name, Class, Count
得到的结果是
1 苹果 水果 10 2011-7-1
1 桔子 水果 20 2011-7-2
1 香蕉 水果 15 2011-7-3
2 白菜 蔬菜 12 2011-7-1
2 青菜 蔬菜 19 2011-7-2
如果写成
SELECT Id, MAX(Name), MAX(Class), MAX(Count), MAX(Date)
FROM table
GROUP BY Id
得到的结果是:
1 香蕉 水果 20 2011-7-3
2 青菜 蔬菜 19 2011-7-2
如果用in有时候也得不到结果,(有的时候可以得到,如果Date都不相同(没有重复数据),或者是下面得到的Max(Date)只有一个值)
SELECT DISTINCT Id, Name, Class, Count, Date FROM table
WHERE (Date IN
(SELECT MAX(Date)
FROM table
GROUP BY Id))
得到的结果是:(因为MAX(Date)有两个值2011-7-2,2011-7-3)
1 桔子 水果 20 2011-7-2
1 香蕉 水果 15 2011-7-3
2 青菜 蔬菜 19 2011-7-2
注意in只允许有一个字段返回
有一种方法可以实现:
SELECT Id, Name, Class, COUNT, Date
FROM table1 t
WHERE (Date =
(SELECT MAX(Date)
FROM table1
WHERE Id = t .Id))
第四篇
SQL子查询Exists和Not Exists的区别(这篇讲的很精彩)
https://blog.csdn.net/qq_27571221/article/details/53090467
MySQL EXISTS 和 NOT EXISTS 子查询语法如下:
· SELECT … FROM table WHERE EXISTS (subquery)
该语法可以理解为:将主查询的数据,放到子查询中做条件验证,根据验证结果(TRUE 或 FALSE)来决定主查询的数据结果是否得以保留。
MySQL EXISTS 子查询实例
下面以实际的例子来理解 EXISTS 子查询。下面是原始的数据表:
article 文章表:
aid |
title |
content |
uid |
1 |
文章1 |
文章1正文内容… |
1 |
2 |
文章2 |
文章2正文内容… |
1 |
3 |
文章3 |
文章3正文内容… |
2 |
4 |
文章4 |
文章4正文内容… |
4 |
user 用户表:
aid |
title |
content |
1 |
admin |
|
2 |
小明 |
|
3 |
Jack |
我们要查出 article 表中的数据,但要求 uid 必须在 user 表中存在。SQL 语句如下:
· SELECT * FROM article WHERE EXISTS (SELECT * FROM user WHEREarticle.uid = user.uid)
返回查询结果如下:
aid |
title |
content |
uid |
1 |
文章1 |
文章1正文内容… |
1 |
2 |
文章2 |
文章2正文内容… |
1 |
3 |
文章3 |
文章3正文内容… |
2 |
从语句执行结果可以看出,article 表中第 4 条记录没有被保留,原因就是该条记录的数据在子查询中返回的结果是 FALSE 。
当上面的 SQL 使用 NOT EXISTS 时,查询的结果就是 article 表中 uid 不存在于 user 表中的数据记录。
我们先介绍下使用的3个数据表:
student数据表:
sno 学号 |
sname |
ssex |
sage |
20161181 |
Altair |
男 |
20 |
20161182 |
Desmond |
男 |
18 |
20161183 |
Ezio |
男 |
22 |
20161184 |
Christina |
女 |
19 |
course数据表:
cno 课程编号 |
cname 课程名 |
1 |
C语言 |
2 |
数据结构 |
3 |
信号与系统 |
4 |
模拟电子技术 |
5 |
高数 |
sc数据表:
sno 学号 |
cno 课程编号 |
grade 成绩 |
20161181 |
1 |
99 |
20161182 |
2 |
98 |
20161181 |
2 |
97 |
20161181 |
3 |
95 |
20161184 |
3 |
92 |
20161181 |
4 |
90 |
20161181 |
5 |
88 |
20161183 |
5 |
58 |
EXISTS代表存在量词∃。带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或者逻辑假值“false”。
一个例子1.1:
要求:查询选修了课程”信号与系统“的同学
SELECT s.Sname FROM student s
WHERE EXISTS
(SELECT * FROM sc, course c WHERE sc.sno = s.sno AND sc.cno = c.cno AND c.cname =
'信号与系统')
使用存在量词EXISTS后,若内层查询结果为非空,则外层的WHERE子句返回值为真,否则返回值为假。
在本例中,首先分析最内层的语句:
SELECT * FROM sc, course c WHERE sc.sno = s.sno AND sc.cno = c.cno AND c.cname =
'信号与系统'
本例中的子查询的查询条件依赖于外层父查询的某个属性值(本例中的是Student的Sno值),这个相关子查询的处理过程是:
首先取外层查询中(student)表的第一个元组,根据它与内层查询相关的属性值(Sno值)处理内层查询,若外层的WHERE返回为真,则取外层查询中该元组的Sname放入结果表;
然后再取(student)表的下一组,重复这一过程,直至外层(Student)表全部检查完毕。
查询结果表:
Sname |
Altair |
Christina |
与EXISTS谓词相对的是NOT EXISTS谓词。使用存在量词NOT EXISTS后,若对应查询结果为空,则外层的WHERE子语句返回值为真值,否则返回假值。
例子2.1:
要求:查询没有选修课程”信号与系统“的同学
SELECT s.Sname FROM student s
WHERE NOT EXISTS
(SELECT * FROM sc, course c WHERE sc.sno = s.sno AND sc.cno = c.cno AND c.cname =
'信号与系统')
使用NOT EXISTS之后,若内层查询结果为非空,则对应的NOT EXISTS不成立,所以对应的WHERE语句也不成立。
在例子1.1中李勇同学对应的记录符合内层的select语句的,所以返回该记录数据,但是对应的NOT EXISTS不成立,WHERE语句也不成立,表示这不是我们要查询的数据。
查询结果表:
Sname |
Desmond |
Ezio |
例子2.2(这是一个用NOT EXISTS表示全称量词的例子):
要求:查询选修了全部课程的学生姓名。
SQL语句:
SELECT Sname
FROM Student
WHERE NOT EXISTS
(SELECT * FROM Course WHERE NOT EXISTS
(SELECT * FROM SC WHERE Sno=Student.Sno AND Cno=Course.Cno)
);
这个算是一个比较复杂的sql语句了,两个EXISTS和三个WHERE。
这个sql语句可以分为3层,最外层语句,最内层语句,中间层语句。
我们很关心最外层语句,因为结果表中的数据都是最外层的查询的表中的数据,我们更关心最内层的数据,因为最内层的数据包含了全部的判断语句,决定了student表中的那一条记录是我们查询的记录。
我们由内而外进行分析:
最外层的student表中的第一条记录是Altair同学对应的记录,然后中间层的course表的第一条记录是数据库对应的记录,然后对该数据进行判断(最内层的WHERE语句),结果返回真,则内层的NOT EXISTS为假,
然后继续对course表中的下一条记录进行判断,返现NOT EXISTS的值也为假,直到遍历完course表中的所有的数据,内层的NOT EXISTS的值一直都是假,所以中间层的WHERE语句的值也一直都是假。
对应student的Altair记录,course表中的所有的记录对应的中间层的返回值为假,所以最外层的NOT EXISTS对应的值为真,最外层的WHERE的值也为真,则Altair对应的记录符合查询条件,装入结果表中。
然后继续对student表中的下一条记录进行判断,直达student表中的所有数据都遍历完毕。
先取一条student记录,进入中层,再取一条course的记录,进入内层,此时student的记录和course的记录,作为内层判断的条件,比如此时我取的第一条记录是Altair,那么我里面的Sql就可以写成
SELECT * FROM Course WHERE NOT EXISTS
(SELECT * FROM SC WHERE Sno =
'20161181'AND Cno=Course.Cno)
)
此处 sno 20161181即Altair的学号,这条sql的意思是选出没有被Altair选择的课程,如果不存在,则返回false,再跟最外层的NOT EXISTS关联,负负得正。每一条循环的意思就是指,筛选出的每一个学生都不存在没有被他选取的那门课,即选了所有课。
最终查询结果:
Sname |
Altair |
第五篇:
SQL中的Except,Intersect用法
https://www.cnblogs.com/dyufei/archive/2009/11/11/2573976.html
SQL中 EXCEPT、INTERSECT用法
EXCEPT 返回两个结果集的差(即从左查询中返回右查询没有找到的所有非重复值)。
INTERSECT 返回两个结果集的交集(即两个查询都返回的所有非重复值)。
UNION返回两个结果集的并集。
{ (<SQL-查询语句1>)}
{ EXCEPT | INTERSECT }
{ (<SQL-查询语句2> )}
· (1)所有查询中的列数和列的顺序必须相同。
· (2)比较的两个查询结果集中的列数据类型可以不同但必须兼容。
· (3)比较的两个查询结果集中不能包含不可比较的数据类型(xml、text、ntext、image 或非二进制CLR 用户定义类型)的列。
· (4)返回的结果集的列名与操作数左侧的查询返回的列名相同。ORDERBY 子句中的列名或别名必须引用左侧查询返回的列名。
· (5)不能与COMPUTE 和 COMPUTE BY子句一起使用。
· (6)通过比较行来确定非重复值时,两个NULL 值被视为相等。(EXCEPT 或 INTERSECT 返回的结果集中的任何列的为空性与操作数左侧的查询返回的对应列的为空性相同。)
如果 EXCEPT 或 INTERSECT 用于比较两个以上的查询集,则数据类型转换是通过一次比较两个查询来确定的,并遵循前面提到的表达式求值规则。
tableAtableB
NULL |
NULL |
NULL |
2 |
1 |
3 |
1 |
4 |
2 |
5 |
3 |
5 |
4 |
|
5 |
|
A:(SELECT * FROM TableA) EXCEPT (SELECT * FROM TableB)
结果: 1
(1 row(s) affected)
B: SELECT * FROM TableA INTERSECT SELECT * FROM TableB
结果:2
3
4
5
(4 row(s) affected)
部分转载于:https://blog.csdn.net/quinnnorris/article/details/71056445
SQL关键字的执行顺序:
1. FROM:对FROM子句中前两个表执行笛卡尔积生成虚拟表vt1
2. ON: 对vt1表应用ON筛选器只有满足 join_condition 为真的行才被插入vt2
3. OUTER(join):如果指定了 OUTER JOIN, 保留表(preserved table)中未找到的行,将行作为外部行添加到vt2,生成t3,如果from包含两个以上表,则对上一个联结生成的结果表和下一个表重复执行步骤和步骤直接结束。
4. WHERE:对vt3应用 WHERE 筛选器只有使 where_condition 为true的行才被插入vt4
5. GROUP BY:按GROUP BY子句中的列,对vt4中的行分组生成vt5
6. CUBE|ROLLUP:把超组(supergroups)插入vt6,生成vt6
7. HAVING:对vt6应用HAVING筛选器只有使 having_condition 为true的组才插入vt7
8. SELECT:处理select列表产生vt8
9. DISTINCT:将重复的行从vt8中去除产生vt9
10. ORDER BY:将vt9的行按order by子句中的列列表排序生成一个游标vc10
11. TOP:从vc10的开始处选择指定数量或比例的行生成vt11 并返回调用者