【数据库】SQL语法

写在前面:
本篇文章是根据 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的原理是(先where再select)先筛选再select,筛选的是数据库表里面本来就有的字段;
    而,having的原理是(先select再having)先select,然后从select出来的内容进行筛选。having筛选的字段是从前筛选的字段筛选的。
  • 聚合函数:原本不存在于原始语句里的内容,通过SQL语句而临时生成的函数;
    有where和having都可以使用(但不并存)的场景;
    有只可以使用where,不可以使用having的情况;
    有只可以使用having,不可以使用where的情况;

INSERT

一段 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','fred@123.com','1'),
      (null,'Harry','0','harry@123.com','1');

注意事项:
id为自增,所以values里写NULL;
value里若需要批量插入,只需要写:(),(),();(最外围不需要再加一个括号)
————————————————————————————————————

需要注意

  • 基本语句(select/from/where…)、table name、column name不区分大小写
    但参数区分大小写;
  • 文字参数需要加上双引号,数字参数直接写。
  • 操作数据库时,需要先进入此数据库(use 数据库名)才能操作下一步;
    操作数据库中的表时,无需进入表,进入了所在数据库即可指定表来操作。
  • 内含子运行式时:因为运行式整体只能出现一个";“在最尾;所以不论子运行式有多少个,其括号结尾都不需要加”;"。
    ————————————————————————————————————

x,yx 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
要选取34
——————————————
应该写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
...

数字 Where

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+名字+年份

  • 方法(1):使用 between and
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
  • 方法(2):使用 and
select id,title,year 
from movies 
where year >= 1995 and year <= 2000;
注:and后不能直接写 <= 2000,必须写 year <= 2000;
  • 方法(3):使用 in(…)
select id,title,year 
from movies 
where year in(1995,1996,1997,1998,1999,2000);
注:in(...)只会选择集合中提到的数字,而不是范围!误写in(1995,2000)只会显示这两年的数据!!

文本 Where

需要注意:写文本参数需要加上双引号

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)

EXISTSNOT EXISTS 是个非常重要的查询关键词;总是拿来和 INNOT 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则父查询中的这个元组允许放入结果表,否则进行父查询下一个元组的判定。

  • 关于EXISTS和IN的效率高低之分讲解:
    https://blog.csdn.net/baidu_37107022/article/details/77278381

——————————————————
列出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

排序 Rows

需要注意: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

重要笔记:

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

—————————————————————————————————————————

SQL Review: Simple SELECT Queries

以这张表作范本:

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

INSERT INTO 表名 
VALUES(col1值 , col2值 , col3值 , col4值 );


SQL Lesson 6: Multi-table queries with JOINs

JOIN 连表 (table)

当查找的数据在多张关联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

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

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 ...就好

——————————————————————

Creating tables

数据类型 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

——————————————————————

Altering tables(列的增加、修改、删除)

改变表格:比如列的增加、修改、删除

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)的值。关键词 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只可以写在参数最前面。

——————————————————————

Dropping tables (注!实际工作中谨慎操作)

FORMAT :

DROP TABLE 表名;

——————————————————————
1.NOT IN和NOT EXISTS的区别

无论哪个表,用not exists都比not in 要快;
且如果数据中有null,not in是查不到的,用not exists就可以;
——————————————————————

踩坑记录

  • 1.建立成绩表( SC):参数为SNO,CNO,SCGRADE (代表:学号,课号,成绩);
    一名学生需要填写至少2门课号(后续需要“分别匹配课号和成绩”进行操作),建表和填数据的格式是什么?

一开始我理解的重点是:需要结合课号和成绩,于是产生了两种思维:

一个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 --删除 命令

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值