写在前面:
本篇文章是根据 https://sqlbolt.com/ 课程内容编写的
此site有习题可练习,亦可根据给定的table在线写SQL语句,实时查看返回结果,推荐使用。
每道Exercise Task 下方有 Read this task’s SOLUTION,即查看正确答案。
Table ↘
Table ——→ Database(数据库)
Table ↗ ↘
Table(表) ——→ Server(伺服器/服务器)
Table ↘ ↗
Table ——→ Database(数据库)
Table ↗
SQL类型与JAVA类型的对应:
SQL JAVA
Decimal BigDecimal
Long Integer
TEXT String
tinyint Boolean
datetime java.util.date
bigint java.math.BigInteger
自增长的id Java要用Long
快速引索:
查看版本或打开
xxxx$ mysql -u root -p
Enter password: 8位密码
退出当前这步操作
mysql>control键+C
退出MySQL
mysql>exit
查看当前MySQL版本
1.登录时会返回版本信息;
2.登录后:
mysql>select version();
+-----------+
| version() |
+-----------+
| 8.0.15 |
+-----------+
查看所有数据库
mysql>show databases;
//此刻可面对Tables了
使用某个数据库
mysql>use 库名;
综合以上两项,查看有哪些数据库,选定一个数据库,查看此数据库中所有表
mysql>show databases;
mysql>use 库名;
mysql>show tables;
查看表中:列的信息
mysql>desc 表名;
查看表中:列与参数的信息(与上条语句的区别是:若此条语句中没有保存参数,会返回Empty set (0.00 sec)
)
mysql>select * from 表名;
表改名
mysql>rename table 旧名 to 新名;
删除一个表
mysql>drop table 表名;
// 一定要声明drop的是table,不然系统不知是库还是表
查看一个表中有几行数据
mysql> select count(*) from 表名;
+----------+
| count(*) |
+----------+
| 6 |
+----------+
创建一个数据库
mysql>create database 数据库名 charset utf8;
如忘了声明charset,如下操作:
mysql>set names gbk;
删除一个数据库(谨慎操作)
mysql>drop database 数据库名;
// 一定要声明drop的是database,不然系统不知是库还是表
库改名?
Database不能改名,只有Tables和Query可改。
TRUNCATE和DELETE的区别?
TRUNCATE :是一个数据定义语言,会被隐式提交,执行后不能回滚;而DELETE是从表中删除一行数据,同时把删除的操作以日志的形式保存,以便将来回滚;
TRUNCATE删除数据后,会立即释放占用的数据空间,数据不能被恢复;DELETE删除的数据占用空间还在,还可以恢复;
TRUNCATE执行速度比DELETE快;
清空表数据
mysql> truncate 表名;
// 一定要声明drop的是database,不然系统不知是库还是表
一句简单的SQL语法:
select(column) from (table)where(限制条件);
如:
select * from table_name where 1;
意思为选择所有column,来自xx表,条件无。
一段包含大多数格式的SQL语句:
SELECT 列名 , COUNT (列名) AS xxx //SELECT 默认参数:*
FROM 表名 //此处可再添加:表A LEFT ON 表B ON 表A.col1 = 表B.col1
WHERE 限制数字/文字条件 ( 或添加exists(...) ) //WHERE 默认参数:1
GROUP BY 列名
ORDER BY 列名 ASC/DESC LIMIT xxx; //ORDER BY 要在最后一行
或者:有HAVING(HAVING与WHERE的关系要注意):
SELECT 列名 , COUNT (列名) AS xxx //SELECT 默认参数:*
FROM 表名 //此处可再添加:表A LEFT ON 表B ON 表A.col1 = 表B.col1
GROUP BY 列名
HAVING 条件
ORDER BY 列名 ASC/DESC LIMIT xxx; //ORDER BY 要在最后一行
HAVING与WHERE的区别!
先where再select
)先筛选再select,筛选的是数据库表里面本来就有的字段;先select再having
)先select,然后从select出来的内容进行筛选。having筛选的字段是从前筛选的字段筛选的。一段 INSERT 语句:
INSERT INTO
VALUES
INSERT INTO 表名 (col1 , col2 , col3)
VALUES(col1值 , col2值 , col3值 , col4值 );
批量INSERT:
insert into 表名(col1 , col2 , col3)
values(col1值 , col2值 , col3值 , col4值),
(col1值 , col2值 , col3值 , col4值);
一段 UPDATE 语句:
UPDATE
SET
WHERE
UPDATE 表名
SET 列名 = "更新后的参数"
WHERE ID = "需更新参数的行ID" ;
一段 DELETE 语句:
DELETE FROM
WHERE
delete from 表名
where 列的限制条件;
一段 CREATING TABLE 语句:
CREATE TABLE 表名 (
列名 数据类型 约束 , //每一行后都以一个逗号结尾
列名 数据类型 约束 ,
列名 数据类型 约束 //最后一行不要加逗号
);
一段 DROPPING TABLE 语句 (注!实际工作中谨慎操作!):
DROP TABLE 表名;
增加一条列
ALTER TABLE
ADD COLUMN
ALTER TABLE 表名
ADD COLUMN 列名 数据类型 ;
修改列类型
ALTER TABLE
MODIFY
ALTER TABLE 表名
MODIFY 列名 数据类型 ;
修改列名
ALTER TABLE
CHANGE
ALTER TABLE 表名
CHANGE 列名 新列名 数据类型 ;
删除一条列(不能同时删除多条)
ALTER TABLE
DROP
ALTER TABLE 表名
DROP 列名 ;
————————————————————————————————————
如何批量插入?
例子
insert into 表名
(id,last_name,gender,email,d_id)
values(null,'Fred','0','[email protected]','1'),
(null,'Harry','0','[email protected]','1');
注意事项:
id为自增,所以values里写NULL;
value里若需要批量插入,只需要写:(),(),();
(最外围不需要再加一个括号)
————————————————————————————————————
需要注意:
;
“在最尾;所以不论子运行式有多少个,其括号结尾都不需要加”;
"。x,y
和x offset y
意思是相反的;
①limit x, y
表示: 跳过 x 条数据,读取 y 条数据;
②limit x offset y
表示: 跳过 y 条数据,读取 x 条数据;
比如:从第0个开始,获取20条数据**(不包括第0个)**
selete * from testtable limit 0, 20;
selete * from testtable limit 20 offset 0;
比如:从第40个开始,获取20条数据**(不包括第40个)**
selete * from testtable limit 40, 20;
selete * from testtable limit 20 offset 40;
易错点:千万注意!
比如有组合为1,2,3,4
要选取3
和4
——————————————
应该写limit 2,2
还是 limit 3,2
??
答案为:limit 2,2
————————————————————————————————————
附习题目录:
All Lessons
Introduction to SQL
SQL Lesson 1: SELECT queries 101 选择查询
SQL Lesson 2: Queries with constraints (Pt. 1) 带约束的查询
SQL Lesson 3: Queries with constraints (Pt. 2)
SQL Lesson 4: Filtering and sorting Query results 过滤和排序查询结果
SQL Review: Simple SELECT Queries
SQL Lesson 6: Multi-table queries with JOINs 带JOINs的多表查询
SQL Lesson 7: OUTER JOINs
SQL Lesson 8: A short note on NULLs 关于空值的简短说明
SQL Lesson 9: Queries with expressions 带表达式的查询
SQL Lesson 10: Queries with aggregates (Pt. 1) 使用聚合的查询
SQL Lesson 11: Queries with aggregates (Pt. 2)
SQL Lesson 12: Order of execution of a Query 查询的执行顺序
SQL Lesson 13: Inserting rows 增行
SQL Lesson 14: Updating rows 改行
SQL Lesson 15: Deleting rows 删行
SQL Lesson 16: Creating tables 创表
SQL Lesson 17: Altering tables 改表
SQL Lesson 18: Dropping tables 删表
SQL Lesson X: To infinity and beyond!
以这张表作范本:
Table: Movies
Id Title Director Year Length_minutes
1 Toy Story John Lasseter 1995 81
2 A Bug's Life John Lasseter 1998 95
3 Toy Story 2 John Lasseter 1999 93
4 Monsters, Inc. Pete Docter 2001 92
5 Finding Nemo Andrew Stanton 2003 107
6 The Incredibles Brad Bird 2004 116
7 Cars John Lasseter 2006 117
8 Ratatouille Brad Bird 2007 115
9 WALL-E Andrew Stanton 2008 104
10 Up Pete Docter 2009 101
显示3行
SELECT * FROM movies limit 3;
——————————————————————
Id Title Director Year Length_minutes
1 Toy Story John Lasseter 1995 81
2 A Bug's Life John Lasseter 1998 95
3 Toy Story 2 John Lasseter 1999 93
限定column与行数
select id,title,year from movies limit 3;
//注:limit与3间必须有空格
——————————————————————
Id Title Year
1 Toy Story 1995
2 A Bug's Life 1998
3 Toy Story 2 1999
列出电影清单
select title from movies where 1;
//注:where 1 表示没有条件
——————————————————————
Title
Toy Story
A Bug's Life
Toy Story 2
Monsters, Inc.
Finding Nemo
The Incredibles
Cars
...
列出电影+年份的清单
select title,year from movies where 1;
——————————————————————
Id Title Year
1 Toy Story 1995
2 A Bug's Life 1998
3 Toy Story 2 1999
...
select * from table where 条件 = 1;
Operator Condition SQL Example
「!=」「<」「<=」「>」「>=」 不等于 小于 大于 col !=4
between...and... 在...和...之间 col between 1.4 and 2.5 //包括1.4和2.5
not between...and... 不在...和...之间 col not between 1 and 10
in(...) 在(...)集合内 col in (2,4,6) //这是特指,而不是指范围!!
not in(...) 不在(...)集合内 col not in (1,3,5)
exists(...)
not exists(...) 详情参考 文本 Where中的介绍。。。
若现在有条件1=aabb;条件2=bbcc;
and 求交集 1 and 2 = bb
or 求并集 1 or 2 = aabbbbcc
列出1995-2000年的电影ID+名字+年份
select id,title,year
from movies
where year between 1995 and 2000;
——————————————————————
Id Title Year
1 Toy Story 1995
2 A Bug's Life 1998
3 Toy Story 2 1999
select id,title,year
from movies
where year >= 1995 and year <= 2000;
注:and后不能直接写 <= 2000,必须写 year <= 2000;
select id,title,year
from movies
where year in(1995,1996,1997,1998,1999,2000);
注:in(...)只会选择集合中提到的数字,而不是范围!误写in(1995,2000)只会显示这两年的数据!!
需要注意:写文本参数需要加上双引号
Operator Condition SQL Example
= 等于 col = "abc"
「!=」「<>」 不等于 col != "abc"
LIKE 等于 col LIKE "abc"
NOT LIKE 不等于 col NOT LIKE "abc"
% 模糊匹配 col LIKE "%AT%" 匹配结果: matches "BATS" , "ATTIC" or even "AT"
col LIKE "AT%" 匹配结果: matches "ATS", but not "BAT"
_ 模糊匹配(单字符) col LIKE "AN_" 匹配结果: matches "AND" , but not "AN"
IN(...) 在集合内 col IN("A","B","C")
NOT IN(...) 不在集合内 col NOT IN("D","E","F")
EXISTS(...)
NOT EXISTS(...)
EXISTS / NOT EXISTS (where)
EXISTS
和 NOT EXISTS
是个非常重要的查询关键词;总是拿来和 IN
和 NOT IN
做比较;
他强调的是是否返回结果集,不要求数据返回,个人理解他像Boolean类型的if语句,只产生逻辑真值“true
”或逻辑假值“false
”。
他们的区别还在于in
引导的子句只能返回一个字段,比如:
select name from student where sex = 'm' and mark in (select 1,2,3 from grade where ...)
,in子句只允许返回一个字段,而exists子句是允许的(类似循环)。
例子:
SELECT sname
FROM student
WHERE exists
(
SELECT *
FROM sc
WHERE sc.sno=student.sno AND cno=1;
)
我们可以这样理解上面的SQL语句做的事情:
本查询涉及student表
和sc表
;外部查询先进行一次,再看到内部查询:若内部条件运行一次后结果符合EXISTS或NOT EXISTS
的预期(即SC表中SNO = Student表中SNO,且CNO=1,是存在的,与EXISTS期望一致),得到true
值,则会将此条结果(即 *
)传递给外部查询。EXISTS或NOT EXISTS
只关心Boolean值,不关心内部是如何运行的,若完成了判断,他的任务就结束了。
由exists引出的子查询,其目标列表达式通常都用*
(例子中为SELECT * FROM sc
);因为EXISTS的子查询只返回真值或者假值,不返回选择出来的结果,因此,你给什么样的列名最后返回的都是true或者false,所以给出实际列名无意义。
对于适用于EXISTS查询的环境理解:
1.首先子查询中必须要有依赖父查询的条件,即我们单独把子查询的select语句提出来不能正常运行。
2.每次查询时,父查询表中的一个元组对子查询所有的元组进行判定,如果为true则父查询中的这个元组允许放入结果表,否则进行父查询下一个元组的判定。
——————————————————
列出ToyStory系列的电影ID+名字+年份
select id,title,year
from movies
where title like "toy story%" ;
——————————————————————
Id Title Year
1 Toy Story 1995
3 Toy Story 2 1999
11 Toy Story 3 2010
需要注意:ORDER必须写在最后一行!!!
需要注意:ORDER必须写在最后一行!!!再次重复
写文本参数需要加上双引号
Operator Condition SQL Example
ORDER BY 按col排序 ORDER BY col ASC/DESC
ASC 升序 Ascending ORDER BY col ASC
DESC 降序 Descending ORDER BY col DESC
LIMIT OFFSET 从offset取limit LIMIT num_limit OFFSET num_offset
ORDER BY 多列排序 ORDER BY col1 ASC,col2 DESC
列出John Lasseter导演的电影,要ID+名字+年份+导演,按年份降序排列最后三部。
select id,title,year,director
from movies
where director = "John Lasseter"
order by year desc limit 3;
注:年份降序 与 最后三部 = 年份最新的三部
order要写在最后行;where col="参数" 其中的参数区分大小写
——————————————————————
Id Title Year Director
12 Cars 2 2011 John Lasseter
7 Cars 2006 John Lasseter
3 Toy Story 2 1999 John Lasseter
重要笔记:
select
from 表名
where
select distinct xxx // 比如:select导演,表中column有重复的导演行,但要求结果不能有重复的导演行时
from 表名
order by xxx asc/desc;
select xxx
from 表名
order by xxx
limit 数字
select xxx
from 表名
order by xxx
limit 2,4; // 指:跳过2个参数,选取4个参数;(若参数为1、2、3、4、5、6、7,意思选取3、4、5、6)
或 limit 4 offset 2; // 指:跳过2个参数,选取4个参数
select xxx
from 表1
join 表2
on id.表1 = id.表2
// join...on... 指和另一个表关联起来
/ /join后写另一个表名
// on写两个表中对应的column,比如:id.table1 = id.table2
select xxx
from 表名
where xxx is null; //选取某column为空的值
或者 where xxx is not null;
select xxx, (xxx + xxx) / xxx as 新column名
from xxx
// select行可以进行加减乘除,as表示新建一个column名
// + - * /
select max(xxx) 或 avg(xxx) 或 sum(xxx) 或
from xxx;
select max(xxx) 或 min(xxx) 或 avg(xxx) 或 sum(xxx) //选出最大/最小/计算平均数/计算总和
from xxx;
select xxx,count(1) //统计行数,也可以写成count(*)
from xxx;
select xxx
from xxx
group by xxx
having xxx;
// 比如group by了Role列,在这个基础上,再选择只显示Role中的"Engineer"这行,就用having
需要注意:
因为“统计”实为对column的操作,所以需要写在首行(select行),加逗号与column操作区分;
但GROUP BY和HAVING写在单独的GROUP BY行;
Operator Condition SQL Example
以下操作写在Select行(与column操作在同一行,加逗号区分)
COUNT(*), 计数 count(col)
COUNT(col)
MIN(col) 最小 min(col)
MAX(col) 最大 max(col)
AVG(col) 平均 avg(col)
SUM(col) 求和 sum(col)
以下操作写在单独一行:GROUP BY行
GROUP BY 分组 group by col1,col2
HAVING 分组后条件 HAVING col>100
详细解释:
COUNT(col):COUNT必须经过GROUP BY归类后再使用;意思是统计col列的数量,生成一条新列;
GROUP BY:若以GROUP BY Directer来分组,则相同导演名会排在一起;比如John在一堆,Pete在一堆;
COUNT (AS) (必须经过GROUP BY归类后再使用!!!)
HAVING COUNT(*) (必须经过GROUP BY归类后再使用)
模版:
筛选后每组的行数等于10才输出
...
group by ...
having count(*) = 10
比如:从tb表中找到classId出现超过5次的纪录
select classId
from tb
group by classId
having count(*) > 5;
SPECIAL EXAMPLE :
列出:每单个导演以及他的电影数量(不允许有重复导演名的行数出现)
select *,count(director)
from movies
where 1
group by director; //此句代表把所有相同导演名归类到一行,不会出现重复姓名的行
——————————————————————
Id Title Director Year Length_minutes Count(Director)
9 WALL-E Andrew Stanton 2008 104 2
8 Ratatouille Brad Bird 2007 115 2
13 Brave Brenda Chapman 2012 102 1
14 Monsters University Dan Scanlon 2013 110 1
12 Cars 2 John Lasseter 2011 120 5
11 Toy Story 3 Lee Unkrich 2010 103 1
10 Up Pete Docter 2009 101 2
特别提醒:
如表所示,count(director)操作 得到的新column名为:count(director)
可以自定义改名
方式为:select *,count(director) AS 新名,由此得到新column名即为:新名
列出电影数量最多的三位导演
select director ,count(director) as count
from movies
where 1
group by director
order by count desc limit 3;
——————————————————————
Director Count
John Lasseter 5
Andrew Stanton 2
Brad Bird 2
—————————————————————————————————————————
以这张表作范本:
Table: North_american_cities
City Country Population Latitude Longitude
Guadalajara Mexico 1500800 20.659699 -103.349609
Toronto Canada 2795060 43.653226 -79.383184
Houston United States 2195914 29.760427 -95.369803
New York United States 8405837 40.712784 -74.005941
Philadelphia United States 1553165 39.952584 -75.165222
Havana Cuba 2106146 23.05407 -82.345189
Mexico City Mexico 8555500 19.432608 -99.133208
Phoenix United States 1513367 33.448377 -112.074037
Los Angeles United States 3884307 34.052234 -118.243685
Ecatepec de Morelos Mexico 1742000 19.601841 -99.050674
Montreal Canada 1717767 45.501689 -73.567256
Chicago United States 2718782 41.878114 -87.629798
List all the Canadian cities and their populations
列出所有加拿大的城市和人口
select city,country,population
from north_american_cities
where country = "Canada";
——————————————————————
City Country Population
Toronto Canada 2795060
Montreal Canada 1717767
Order all the cities in the United States by their latitude from north to south
列出所有美国城市,根据latitude,从北到南
select city,country,latitude
from north_american_cities
where country = "United States"
order by latitude desc;
——————————————————————
省略
INSERT INTO 表名
VALUES(col1值 , col2值 , col3值 , col4值 );
当查找的数据在多张关联table里
通俗地说:把多张表合并成一张表
select *
from table1 left join table2 on table.id = table2.id
where 1 ;
需要注意:。。。
Operator Condition SQL Example
JOIN .. ON .. 依据ID组成1个表 t1 JOIN t2 ON t1.id = t2.id
INNER JOIN 只保留2个表相同ID的ROW t1 INNER JOIN t2 后面可接 ON t1.id = t2.id
LEFT JOIN 保留t1所有的ROW t1 LEFT JOIN t2 后面可接 ON t1.id = t2.id // 让t1表和t2表的id相等作为依据
RIGHT JOIN 保留t2所有的ROW t1 RIGHT JOIN t2 后面可接 ON t1.id = t2.id // 让t1表和t2表的id相等作为依据
IS/IS NOT NULL col是否为NULL col IS / IS NOT NULL
详细解释:
A LEFT JOIN B:以左边这张表为标准;即上方的select col是以左边的A表为标准。
ON后写两个表的column相等,两个column前记得要添加表名+"."!!
以这2张表作范本:
Table: Movies (Read-Only)
Id Title Director Year Length_minutes
1 Toy Story John Lasseter 1995 81
2 A Bug's Life John Lasseter 1998 95
3 Toy Story 2 John Lasseter 1999 93
4 Monsters, Inc. Pete Docter 2001 92
...
Table: Boxoffice (Read-Only)
Movie_id Rating Domestic_sales International_sales
5 8.2 380843261 555900000
14 7.4 268492764 475066843
8 8 206445654 417277164
12 6.4 191452396 368400000
3 7.9 245852179 239163000
6 8 261441092 370001000
...
Find the domestic and international sales for each movie
找到每一部电影的国内和国际销售额
SELECT title,Domestic_sales,International_sales
FROM movies left join Boxoffice on movies.id = Boxoffice.movie_id
where 1;
——————————————————————
Title Domestic_sales International_sales
Toy Story 191796233 170162503
A Bug's Life 162798565 200600000
Toy Story 2 245852179 239163000
。。。
——————————————————————
UPDATE 表名
SET 列名 = "更改后的参数" , 列名2 = "更改后的参数" // 这里不能用AND
WHERE ID = 需更改参数的行ID ;
注意!
update多个参数时,set语句中:每个参数要写完整的一句,不能求方便而统一写,比如:
update 表名
set title = "A",dir = "B"
where id = X;
// 不能写 set title,dir = "A","B"
// update的set中只能用逗号分割,不能用and分割!!
以这张表作范本:
Id Title Director Year Length_minutes
1 Toy Story John Lasseter 1995 81
2 A Bug's Life El Directore 1998 95
3 Toy Story 2 John Lasseter 1899 93
4 Monsters, Inc. Pete Docter 2001 92
5 Finding Nemo Andrew Stanton 2003 107
6 The Incredibles Brad Bird 2004 116
7 Cars John Lasseter 2006 117
8 Ratatouille Brad Bird 2007 115
9 WALL-E Andrew Stanton 2008 104
10 Up Pete Docter 2009 101
The director for A Bug’s Life is incorrect, it was actually directed by John Lasseter
把A Bug’s Life的导演名改成John Lasseter
UPDATE movies
SET director = "John Lasseter"
WHERE id = 2;
——————————————————————
Id Title Director Year Length_minutes
1 Toy Story John Lasseter 1995 81
2 A Bug's Life John Lasseter 1998 95
3 Toy Story 2 John Lasseter 1999 93
4 Toy Story 4 El Directore 2015 90
Both the title and directory for Toy Story 8 is incorrect! The title should be “Toy Story 3” and it was directed by Lee Unkrich
把Toy Story 3的导演名改成Lee Unkrich
UPDATE movies
SET title = "Toy Story 3", director = "Lee Unkrich"
WHERE id = 11;
——————————————————————
省略
注意!!大坑!!
在一条UPDATE语句中,如果要更新多个字段,字段间不能使用AND
,而应该用逗号
分隔!!!!!!!!!!!!!!!
在一条UPDATE语句中,如果要更新多个字段,字段间不能使用AND
,而应该用逗号
分隔!!!!!!!!!!!!!!!
在一条UPDATE语句中,如果要更新多个字段,字段间不能使用AND
,而应该用逗号
分隔!!!!!!!!!!!!!!!
在一条UPDATE语句中,如果要更新多个字段,字段间不能使用AND
,而应该用逗号
分隔!!!!!!!!!!!!!!!
在一条UPDATE语句中,如果要更新多个字段,字段间不能使用AND
,而应该用逗号
分隔!!!!!!!!!!!!!!!
在一条UPDATE语句中,如果要更新多个字段,字段间不能使用AND
,而应该用逗号
分隔!!!!!!!!!!!!!!!
——————————————————————
DELETE FROM 表名
where 列的限制条件;
以movies表作范本:
This database is getting too big, lets remove all movies that were released before 2005.
把2005年前发行的所有电影都删除
delete from movies
where year < 2005;
——————————————————————
省略
注意!!大坑!!
删除方法无需再写delete * from ...
,直接写delete from ...
就好
删除方法无需再写delete * from ...
,直接写delete from ...
就好
删除方法无需再写delete * from ...
,直接写delete from ...
就好
删除方法无需再写delete * from ...
,直接写delete from ...
就好
删除方法无需再写delete * from ...
,直接写delete from ...
就好
——————————————————————
数据类型 Data type :
INTEGER, BOOLEAN
The integer datatypes can store whole integer values like the count of a number or an age. In some implementations, the boolean value is just represented as an integer value of just 0 or 1.
FLOAT, DOUBLE, REAL
The floating point datatypes can store more precise numerical data like measurements or fractional values. Different types can be used depending on the floating point precision required for that value.
CHARACTER(num_chars), VARCHAR(num_chars), TEXT
The text based datatypes can store strings and text in all sorts of locales. The distinction between the various types generally amount to underlaying efficiency of the database when working with these columns.
Both the CHARACTER and VARCHAR (variable character) types are specified with the max number of characters that they can store (longer values may be truncated), so can be more efficient to store and query with big tables.
DATE, DATETIME
SQL can also store date and time stamps to keep track of time series and event data. They can be tricky to work with especially when manipulating data across timezones.
BLOB
Finally, SQL can store binary data in blobs right in the database. These values are often opaque to the database, so you usually have to store them with the right metadata to requery them.
约束:保证数据的完整性
Table Constraints (Constraint & Description)
PRIMARY KEY
This means that the values in this column are unique, and each value can be used to identify a single row in this table.
表示参数只能唯一存在,可以用来确定单个行(常用于定义ID列),PRIMARY KEY的组不可为NULL,一张表只能有一个PRIMARY KEY;
AUTOINCREMENT
For integer values, this means that the value is automatically filled in and incremented with each row insertion. Not supported in all databases.
对于INTEGER来说,他代表参数可以自增长(不适用于所有数据库,如PGsql);
UNIQUE
This means that the values in this column have to be unique, so you can't insert another row with the same value in this column as another row in the table. Differs from the `PRIMARY KEY` in that it doesn't have to be a key for a row in the table.(可定义电话号码)
表示唯一参数,与PRIMARY KEY不同之处:
PRIMARY = UNIQUE + NOT NULL
一张表只能有一个PRIMARY KEY;而UNIQUE可有多个,可为NULL值。
NOT NULL
This means that the inserted value can not be `NULL`.
CHECK (expression)
This is allows you to run a more complex expression to test whether the values inserted are value. For example, you can check that values are positive, or greater than a specific size, or start with a certain prefix, etc.
FOREIGN KEY
This is a consistency check which ensures that each value in this column corresponds to another value in a column in another table.
For example, if there are two tables, one listing all Employees by ID, and another listing their payroll information, the `FOREIGN KEY` can ensure that every row in the payroll table corresponds to a valid employee in the master Employee list.
FORMAT:
CREATE TABLE 表名 (
列名 数据类型 约束 , //每一行后都以一个逗号结尾
列名 数据类型 约束 ,
列名 数据类型 约束 //最后一行不要加逗号
);
EXAMPLE:
Movies table schema
CREATE TABLE movies (
id INTEGER PRIMARY KEY,
title TEXT,
director TEXT,
year INTEGER,
length_minutes INTEGER
);
Create a new table named Database with the following columns:
– Name A string (text) describing the name of the database
– Version A number (floating point) of the latest version of this database
– Download_count An integer count of the number of times this database was downloaded
This table has no constraints.
CREATE TABLE Database (
Name TEXT,
Version FLOAT,
Download_count INTEGER
);
——————————————————————
Name Version Download_count
SQLite 3.9 92000000
MySQL 5.5 512000000
Postgres 9.4 384000000
——————————————————————
改变表格:比如列的增加、修改、删除
FORMAT:
ALTER TABLE 表名
ADD COLUMN 列名 数据类型 DEFAULT 2.39;
增加一条列
ALTER TABLE 表名
ADD COLUMN 列名 数据类型 ;
修改列类型
ALTER TABLE 表名
MODIFY 列名 数据类型 ;
修改列名
ALTER TABLE 表名
CHANGE 列名 新列名 数据类型 ;
删除一条列(不能同时删除多条)
ALTER TABLE 表名
DROP 列名 ;
以movies表作范本:
Table: Movies
Id Title Director Year Length_minutes
1 Toy Story John Lasseter 1995 81
2 A Bug's Life John Lasseter 1998 95
3 Toy Story 2 John Lasseter 1999 93
Add a column named Aspect_ratio with a FLOAT data type to store the aspect-ratio each movie was released in.
ALTER TABLE Movies
ADD COLUMN Aspect_ratio FLOAT DEFAULT 2.39;
——————————————————————
Id Title Director Year Length_minutes Aspect_ratio
1 Toy Story John Lasseter 1995 81 2.39
2 A Bug's Life John Lasseter 1998 95 2.39
3 Toy Story 2 John Lasseter 1999 93 2.39
Add another column named Language with a TEXT data type to store the language that the movie was released in. Ensure that the default for this language is English.
ALTER TABLE Movies
ADD COLUMN Language TEXT DEFAULT "English";
——————————————————————
省略
——————————————————————
在表中,可能会包含重复值,这并不成问题。
不过,有时您也许希望仅仅列出不同(distinct)的值。关键词 distinct用于返回唯一不同的值。
select distinct name from A;
——————————————————————
name
a
b
c
如果select distinct id,name from A;?出现的是唯一的id还是唯一的name?
都不是,是唯一的id+name组合:
select distinct id,name from A;
——————————————————————
name id
a 1
b 2
b 5
c 3
c 4
注!不可以写select id,distinct name
distinct只可以写在参数最前面。
——————————————————————
FORMAT :
DROP TABLE 表名;
——————————————————————
1.NOT IN和NOT EXISTS的区别
无论哪个表,用not exists都比not in 要快;
且如果数据中有null,not in是查不到的,用not exists就可以;
——————————————————————
一开始我理解的重点是:需要结合课号和成绩,于是产生了两种思维:
一个CNO空格内并排放入两个参数;SCGRADE也一样,互相对应。
——————————————————
SNO CNO SCGRADE
1 A/B 90/95
2 A/C 87/96
但从没见过一个空格内可以存在多个参数这种说法,这样也可能导致与成绩匹配时的逻辑混乱;
第二种格式:
建立两个CNO和两个SCGRADE,互相对应。
——————————————————
SNO CNO1 CNO2 SCGRADE1 SCGRADE2
1 A B 90 95
2 A C 87 96
但这样就需要把CNO1和SCGRADE1对应起来分析,但也没见过这种说法。
想了很久也没有头绪,后来经过朋友的分析才知道,这两种方法都不对。
应该为:
SNO CNO SCGRADE
1 A 90
1 B 95
2 A 87
2 C 96
——————————————————————
C 课程;
+------+------------+----------+
| cno | cname | cteacher |
+------+------------+----------+
| 105 | Language | Liu |
| 106 | Literature | Liu |
| 107 | Art | Cheung |
| 108 | IT | Lee |
| 109 | Sport | Ho |
+------+------------+----------+
S 学生;
+------+------+------+
| sno | sname| sage |
+------+------+------+
| 1 | wang | 20 |
| 2 | kwok | 19 |
| 3 | chan | 18 |
| 5 | lam | 22 |
| 4 | pang | 22 |
+------+------+------+
SC 学生成绩;
+------+------+------+---------+
| id | sno | cno | scgrade |
+------+------+------+---------+
| 1 | 1 | 106 | 55 |
| 2 | 2 | 107 | 80 |
| 3 | 3 | 108 | 55 |
| 4 | 4 | 109 | 66 |
| 5 | 5 | 105 | 90 |
| 6 | 1 | 105 | 55 |
| 7 | 2 | 105 | 59 |
| 8 | 3 | 105 | 80 |
| 9 | 4 | 105 | 90 |
| 10 | 5 | 106 | 83 |
| 11 | 1 | 107 | 66 |
| 12 | 1 | 108 | 85 |
| 13 | 1 | 109 | 40 |
+------+------+------+---------+
问题与答案:
1)找出没选过“cheung”老师的所有学生姓名。
select sname
from S
where sno not in(
select sno
from SC
left join C
on SC.cno = C.cno
where C.cteacher = ’cheung‘
);
或者
select sname
from S
where S.sno not in(
select sno
from SC
where cno not in(
select cno
from C
where cteacher not like 'Cheung'
)
);
2) 列出既学过105号课程又学过106号课所有学生的姓名。
正确答案:
select S.sno,S.sname
from SC,S
where SC.cno=105 and SC.sno in(
select sno
from SC
where cno=106) and S.sno=SC.sno;
或(个人更推荐)
select S.sno,S.sname
from S
left join SC
on S.sno = SC.sno
where SC.cno=105 and SC.sno in(
select sno
from SC
where cno=106
);
要点在于:
cno要满足=105和106时,只能直接写一个条件,另一个条件要写在in()中;
且in()条件的指定属性要根据括号内的条件来写,比如括号内写cno=106,那么指定属性就不能写cno,可以写sno;
我写的:
select S.name
from S left join SC on S.sno=SC.sno
where SC.cno in(105,106);
区别:
我写的:直接把105和106当作合集,限定课号在这里面;
正确答案:限定课号为105,“and”课号限定在(一组新的完整select from where语句:限定课号为106)。
3) 列出2门(含2)以上不及格课程的学生姓名;及其平均成绩(要求有两门(含)以上不及格的人)。
select sname,avg(SC.scgrade) as 新列名
from S
left join SC
on S.sno = SC.sno
where SC.scgrade<60
group by S.sname
having count(1)>=2;
易错点:
容易忘掉:
新列的命名/改名方式:avg(SC.scgrade) as 新名字
left join
on XX = XX(这里写成了where)
where…
以下这两个搭配易搞错:
group by
having count(*)
group by
order by desc/asc limit ?
4).所有课程都选修的学生学号和姓名
select sno,sname
from S
where not exists(
select *
from C
where not exists(
select *
from SC
where SC.sno = S.sno and SC.cno = C.cno)
);
易错点:
not exists 后面没有 in!!!
答案:
1 wang
5)检索选修课程包含LIU老师所授课程的学生学号。
select distinct SC.sno
from SC,C
where SC.cno = C.cno and C.cteacher="LIU";
不写distinct的话会有多名重复学生;
自己写的:
select distinct sname
from S
where sno in(
select sno
from SC
left join C
on SC.cno = C.cno
where C.cteacher = "Liu"
);
select S.sno
from S
left join SC
on S.sno = SC.sno
where SC.cno in(
select cno
from C
where cteacher like 'Liu'
);
6)检索学号比WANG同学大,而年龄比他小的学生姓名。
select sname
from S
where sno > (
select sno
from S
where sname like'wang'
)and sage < (
select sage
from S
where sname like 'wang'
);
7)找到sno为1的学生没有选修的课程
我写的:
select distinct cname
from C
left join SC
on C.cno = SC.cno
where sno not like '1';
——————————————————————
1.select count(1) from user where id=2
count(1)括号中填1或2或3都不影响结果,这几话的意思是select出符合标准的多行数据;
——————————————————————
——————————————————————
——————————————————————
——————————————————————
——————————————————————
——————————————————————
——————————————————————
——————————————————————
——————————————————————
——————————————————————
——————————————————————
——————————————————————
——————————————————————
——————————————————————
一些附录:
## 数据库
创建库之前,先查看数据库中是否已存在,若有便删除。
if exists(select * from sysobjects where name =‘ConstructionDB’) --查找命令
drop DATABASE ConstructionDB --删除 命令