1. 程式人生 > 實用技巧 >記錄的增刪改查

記錄的增刪改查

學習目錄

  • 使用INSERT實現資料的插入
  • UPDATE實現資料的更新
  • 使用DELETE實現資料的刪除
  • 使用SELECT查詢資料以及
  • 單表查詢
  • 多表查詢

1 插入資料--insert

1.插入完整資料
語法一
insert into 表名(欄位1,欄位2,欄位3) values(值1,值2,值3)
例項:
insert into t1(id,name,age) values (1,'alex',23)
語法二
insert into 表名values(值1,值2,值3)
例項:
insert into t1 values (1,'alex',23)

2.指定欄位插入資料
語法
insert into 表名(欄位2,欄位3) values(值2,值3)
例項:
insert into t1(name,age) values('alex',23)

3.插入多條資料
語法
insert into 表名 values(值1,值2,值3),
					   (值4,值5,值6),
					   (值7,值8,值9);
例項
insert into t1 values(1,'alex',73),
						(2,'ailsa',23),
						(3,'wusir',84);

4.插入查詢結果
語法
insert into 表名(欄位1,欄位2,欄位3)
				select 欄位1,欄位2,欄位3 from 表2 where 條件;
例項			
insert into emp(id,name) select id,name from emp_bak 
where id = 1;

2 更新資料--update

單獨更新一個欄位
語法:
	update 表名 set 欄位1 = 新值1,
			where 條件;
例項:
	update s1 set name = 'ailsa',
		       where id = 1;

更新多個欄位
語法:
	update 表名 set 欄位1 = 新值1,
			欄位2 = 新值2
			where 條件;
例項:
	update s1 set name = 'ailsa',
		      gender = 'female',
		       where id = 1;

3 刪除資料--delete

語法:
	delete from 表名 where 條件;
	delete from s1 where id = 2;
注:
	不加where條件就是清空表,一定要慎重使用delete

清空表:
       delete from t1; # 如果有自增id,新增的資料,仍然是以刪除前的最後一樣作為起始。
       truncate table t1;# 資料量大,刪除速度比上一條快,且直接從零開始,

drop table 表名 是把整個表刪除,在資料庫中找不到該表,而delete只是把表中的資料清除,表結構還在。

4 查詢資料--select

4.1 單表查詢

4.1.1 單表查詢的完整語法及優先順序

語法:
select distinct 欄位1,欄位2 [,...] from 表名
				where 條件
				group by field
				having 篩選條件
				order by filed
				limit 條數
注:
   group by field 根據什麼進行分組,一般是某個欄位或多個欄位
   order by filed 根據什麼進行排序,一般是某個欄位或多個欄位
   having主要配合group by使用,對分組後的資料進行過濾,裡面可以使用聚合函式
   where是針對select查詢的過濾,各有區別和用處
   
優先順序:
	from
	where
	group by
	select
	distinct
	having
	order by
	limit
解釋說明:
	1.先找到表:from
	2.拿著where指定的約束條件,去表中取出符合條件的一條條資料
	3.將取出的資料進行分組group by,如果沒有group by,則每行為一組
	4.執行select 查詢所指定的欄位
	5.若有distinct 則去重
	6.將結果按照條件排序 order by
	7.限制結果的顯示條數 limit

4.1.2 準備資料

create table emp(
	id int primary key auto_increment,
	emp_name char(20) not null,
	sex enum("male","female") not null default "male",
	age int(3) unsigned not null default 28,
	hire_date date not null,
	post char(50),
	post_comment char(100),
	salary double(15,2),
	office int,
	depart_id int);
	
插入資料
insert into emp(emp_name,sex,age,hire_date,post,salary,office,depart_id) values
('huahua','male',18,'20170301','teacher',7300.33,401,1), #以下是教學部
('weiwei','male',78,'20150302','teacher',1000000.31,401,1),
('lala','male',81,'20130305','teacher',8300,401,1),
('zhangsan','male',73,'20140701','teacher',3500,401,1),
('liulaogen','male',28,'20121101','teacher',2100,401,1),
('aal','female',18,'20110211','teacher',9000,401,1),
('zhugelang','male',18,'19000301','teacher',30000,401,1),
('成龍','male',48,'20101111','teacher',10000,401,1),

('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是銷售部門
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),

('張野','male',28,'20160311','operation',10000.13,403,3), #以下是運營部門
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬銀','female',18,'20130311','operation',19000,403,3),
('程咬銅','male',18,'20150411','operation',18000,403,3),
('程咬鐵','female',18,'20140512','operation',17000,403,3)

4.1.3 簡單查詢

# 查詢所有的欄位資訊
select * from emp;

# 查詢指定欄位資訊
select id,emp_name from emp;

#避免重複distinct
select distinct post from emp;

# 通過四則運算查詢[+ - * /]
select emp_name,salary*12 from emp;
為欄位重新命名
select emp_name,salary*12 as annual_salary from emp;
注: as 可以省略
	
# 定義顯示格式
1. concat()用於連線字串
select concat("姓名: ",emp_name," 年薪: ",salary*12) as annual_salary from emp;
2.concat_ws() 第一個引數為分隔符
select concat_ws(":",emp_name,salary*12) as annual_salary from emp;

# 結合case語句
select (case 
	when emp_name = "jingliyang" then emp_name
	when emp_name = "alex" then concat(emp_name,"_sb")
	else
	concat(emp_name,"_NB")
	end	
) as new_name
from emp;

4.1.4 where

where 字句中可以使用:
1.比較運算子:> <  >= <=  <>  !=

2.between...and ,between 80 and 100,在80到100之間,閉區間

3.in("a","b","c") 是否屬於括號內的元素,滿足其中一個就可以

4.like "%好" 

​	萬用字元:

​	% 表示任意字元(0個到n個)

​	_ 表示一個字元

5.邏輯運算子:多條件可以使用邏輯運算子 and or not

例項

# 單條件查詢
select emp_name,post from emp where post="sale";

# 多條件查詢
select emp_name,salary from emp where post = "teacher" and salary > 10000;

# between...and
select emp_name,salary from emp where salary between 1000 and 5000;

# is null判斷是否為空,不能用=,而是用is
select emp_name,post_comment from emp where post_comment is  null;

select emp_name,post_comment from emp where post_comment ="";
ps:
	查詢都沒有結果,我們手動修改一下資料
	update emp set post_comment="" where id = 1;
	
注:空字串與null是不一樣的,有興趣可以自己查一查

# in
select emp_name,salary from emp where salary=3000 or salary=3500 or salary=4000 or salary=9000;

select emp_name,salary from emp where salary in (3000,3500,4000,9000);

select emp_name,salary from emp where salary not in (3000,3500,4000,9000);

# like

萬用字元 %
select * from emp where emp_name like "a%";
萬用字元 _
select * from emp where emp_name like "zhang___";

4.1.5 group by

# 單獨使用group by關鍵字分組
select post from emp group by post;
注:
	使用group by,查詢欄位必須是分組欄位,想要獲取其他資訊,可以藉助聚合函式,
        一般情況下,group by是和聚合函式配合使用的.
	錯誤例項:
	select id,post,emp_namefrom emp group by post;
        # 分組的欄位跟查詢欄位要保持一致,不然資料對應不上
# 與group_concat()函式搭配使用
select post,group_concat(emp_name) from emp group by post;
# 與聚合函式一起使用
select post,count(id) count_num from emp group by post;

聚合函式
count 計數
sum 求和
avg 求平均
max 最大值
min 最小值

4.1.6 having

where 與 having的區別
where 是針對分組之前的欄位內容進行過濾,而having是針對分組後的
例項:
select emp_name,post from emp where salary>5000;
錯誤例項:
select post,group_concat(emp_name) 人員 from emp group by  post having salary>1000;# 會報錯,因為分組之後就沒有salary這個欄位了,所以查不到;
# 正確例項
select post,group_concat(emp_name) 人員 from emp group by  post having post="teacher";

4.1.7 order by

升序 order by 欄位 asc(預設升序,可以不寫)
降序 order by 欄位 desc

# 單列排序
select id,emp_name,post,salary from emp order by salary desc;

# 多列排序,越前面的優先順序越高
select id,emp_name,age,post,salary from emp order by age,salary desc;
# 先按照年紀排序,年紀相同的話按照salary從高到低排序

4.1.8

# 顯示前三條,預設從0開始
select id,emp_name,post from emp limit 3;
# 從0開始,先查出第一條,然後包含這條再往後查5條
select id,emp_name,post from emp limit 0,5;
# 從第3開始,即先查出第4條,然後包含這條再往後查7條
select id,emp_name,post from emp limit 3,7;

4.1.9 使用正則

# ^ 以什麼開頭
select id,emp_name,post from emp where emp_name regexp "^a";
# $ 以什麼結尾
select id,emp_name,post from emp where emp_name regexp "zhang$";
# 匹配指定字元內容
select id,emp_name,post from emp where emp_name regexp "i{1}";

4.2 多表查詢

資料準備

create database day04;
create table dep(
	id int primary key,
	name char(20)
);
create table emp(
	id int primary key auto_increment,
	name char(20),
	sex enum("male","female") not null default "male",
	age int,
	dep_id int
);

# 插入資料
insert into dep values
(200,'技術'),
(201,'人力資源'),
(202,'銷售'),
(203,'運營');

insert into emp(name,sex,age,dep_id) values
('ailsa','male',18,200),
('lala','female',48,201),
('huahua','male',38,201),
('zhangsan','female',28,202),
('zhaosi','male',18,200),
('shenteng','female',18,204)
;

4.2.1 多表聯查

1.交叉連線:笛卡爾積 把表合併,沒有任何條件

A表中的每一條記錄都與B表相連,沒有任何指定條件
select * from emp,dep;

2.內連線:join

兩張表公共的部分,必須同時有,沒有就不顯示
select emp.id,emp.name,emp.age,dep.name from emp join dep on emp.dep_id = dep.id;

3.外連線之左連線

以左表為主表,根據左表資料匹配右表,左表的資料是全的,而右表若匹配不上則顯示null
select emp.id,emp.name,emp.age,dep.name from emp left join dep on emp.dep_id = dep.id;

4.外連線之右連線

以右表為主表,根據右表資料匹配左表,右表資料是全的,而左表若匹配不上則為null
select emp.id,emp.name,emp.age,dep.name from emp right join dep on emp.dep_id = dep.id;

5.全外連線

把左右兩邊的資料都顯示完整,匹配不上的則顯示為null,在mysql中沒有真正的全外連線,可以使用union來實現
select emp.id,emp.name,emp.age,dep.name from emp left join dep on emp.dep_id = dep.id
union
select emp.id,emp.name,emp.age,dep.name from emp right join dep on emp.dep_id = dep.id;

#注 union與union all的區別:union會去掉相同的紀錄

4.2.2 符合條件的多表連查

 #示例1:以內連線的方式查詢emp和dep表,並且emp表中的age欄位值必須大於25,
即找出年齡大於25歲的員工以及員工所在的部門
select emp.name,dep.name from emp inner join dep on emp.dep_id = dep.id
    where age > 25;

#示例2:以內連線的方式查詢emp和dep表,並且以age欄位的升序方式顯示
select emp.id,emp.name,emp.age,dep.name from emp join dep on emp.dep_id = dep.id
    where age > 25
    order by age;

4.2.3 子查詢

1.子查詢是將一個查詢語句巢狀在另一個查詢語句中
2.內層查詢語句的查詢結果,可以為外層查詢語句提供查詢條件
3.子查詢中可以包含: in   not in  any   all  exists  not exists 等關鍵字
4.還可以包含比較運算子: = != > <等

1.帶in關鍵字的子查詢

# 1.查詢平均年齡在25歲以上的部門名
select id,name from dep where id in (select dep_id from emp group by dep_id having avg(age) > 25);

#2.檢視技術部員工姓名
子查詢方式
select id,name from emp where dep_id = (select id from dep where name="技術");
連表方式
select emp.id,emp.name,dep.name from emp left join dep on emp.dep_id=dep.id
where dep.name="技術";

# 3.檢視不足1人的部門名(子查詢得到的是有人的部門id)-->換句話說就是查詢沒有人的部門
select id,name from dep where id not in(select dep_id from emp group by dep_id having count(id)>=1 );

2.帶比較運算子的子查詢

比較運算子: =、!=、>、>=、<、<=、<>

# 1.查詢大於所有人平均年齡的員工與年齡
select name,age from emp where age>(select avg(age) from emp);
# 2.查詢大於部門內平均年齡的員工姓名,年齡
select name,age from emp t1 join (select dep_id,avg(age) avg_age from emp group by dep_id) t2 on t1.dep_id = t2.dep_id where t1.age > t2.avg_age;

3.帶exists關鍵字的子查詢

exists關鍵字表示存在,在使用exists關鍵字時,內層查詢不返回查詢的記錄,而是返回一個真假值,True或False

當返回True時,外層查詢語句將進行查詢;當返回值為False時,外層查詢語句不進行查詢

# dep表中是否存在dep_id=203
select * from emp where exists (select id from dep where id=203);

# dep表中是否存在dep_id=205
select * from emp where exists (select id from dep where id=205);

5 SQL多表查詢練習題

1 準備資料

CREATE TABLE class (
  cid int(11) NOT NULL AUTO_INCREMENT,
  caption varchar(32) NOT NULL,
  PRIMARY KEY (cid)
) ENGINE=InnoDB CHARSET=utf8;

INSERT INTO class VALUES
(1, '三年二班'), 
(2, '三年三班'), 
(3, '一年二班'), 
(4, '二年九班');

CREATE TABLE teacher(
  tid int(11) NOT NULL AUTO_INCREMENT,
  tname varchar(32) NOT NULL,
  PRIMARY KEY (tid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO teacher VALUES
(1, '張磊老師'), 
(2, '李平老師'), 
(3, '劉海燕老師'), 
(4, '朱雲海老師'), 
(5, '李傑老師');

CREATE TABLE course(
  cid int(11) NOT NULL AUTO_INCREMENT,
  cname varchar(32) NOT NULL,
  teacher_id int(11) NOT NULL,
  PRIMARY KEY (cid),
  KEY fk_course_teacher (teacher_id),
  CONSTRAINT fk_course_teacher FOREIGN KEY (teacher_id) REFERENCES teacher (tid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO course VALUES
(1, '生物', 1), 
(2, '物理', 2), 
(3, '體育', 3), 
(4, '美術', 2);

CREATE TABLE student(
  sid int(11) NOT NULL AUTO_INCREMENT,
  gender char(1) NOT NULL,
  class_id int(11) NOT NULL,
  sname varchar(32) NOT NULL,
  PRIMARY KEY (sid),
  KEY fk_class (class_id),
  CONSTRAINT fk_class FOREIGN KEY (class_id) REFERENCES class (cid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO student VALUES
(1, '男', 1, '理解'), 
(2, '女', 1, '鋼蛋'), 
(3, '男', 1, '張三'), 
(4, '男', 1, '張一'), 
(5, '女', 1, '張二'), 
(6, '男', 1, '張四'), 
(7, '女', 2, '鐵錘'), 
(8, '男', 2, '李三'), 
(9, '男', 2, '李一'), 
(10, '女', 2, '李二'), 
(11, '男', 2, '李四'), 
(12, '女', 3, '如花'), 
(13, '男', 3, '劉三'), 
(14, '男', 3, '劉一'), 
(15, '女', 3, '劉二'), 
(16, '男', 3, '劉四');

CREATE TABLE score (
  sid int(11) NOT NULL AUTO_INCREMENT,
  student_id int(11) NOT NULL,
  course_id int(11) NOT NULL,
  num int(11) NOT NULL,
  PRIMARY KEY (sid),
  KEY fk_score_student (student_id),
  KEY fk_score_course (course_id),
  CONSTRAINT fk_score_course FOREIGN KEY (course_id) REFERENCES course (cid),
  CONSTRAINT fk_score_student FOREIGN KEY (student_id) REFERENCES student(sid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO score VALUES
(1, 1, 1, 10),
(2, 1, 2, 9),
(5, 1, 4, 66),
(6, 2, 1, 8),
(8, 2, 3, 68),
(9, 2, 4, 99),
(10, 3, 1, 77),
(11, 3, 2, 66),
(12, 3, 3, 87),
(13, 3, 4, 99),
(14, 4, 1, 79),
(15, 4, 2, 11),
(16, 4, 3, 67),
(17, 4, 4, 100),
(18, 5, 1, 79),
(19, 5, 2, 11),
(20, 5, 3, 67),
(21, 5, 4, 100),
(22, 6, 1, 9),
(23, 6, 2, 100),
(24, 6, 3, 67),
(25, 6, 4, 100),
(26, 7, 1, 9),
(27, 7, 2, 100),
(28, 7, 3, 67),
(29, 7, 4, 88),
(30, 8, 1, 9),
(31, 8, 2, 100),
(32, 8, 3, 67),
(33, 8, 4, 88),
(34, 9, 1, 91),
(35, 9, 2, 88),
(36, 9, 3, 67),
(37, 9, 4, 22),
(38, 10, 1, 90),
(39, 10, 2, 77),
(40, 10, 3, 43),
(41, 10, 4, 87),
(42, 11, 1, 90),
(43, 11, 2, 77),
(44, 11, 3, 43),
(45, 11, 4, 87),
(46, 12, 1, 90),
(47, 12, 2, 77),
(48, 12, 3, 43),
(49, 12, 4, 87),
(52, 13, 3, 87);

2 練習題

1、查詢所有的課程的名稱以及對應的任課老師姓名

2、查詢學生表中男女生各有多少人

3、查詢物理成績等於100的學生的姓名

4、查詢平均成績大於八十分的同學的姓名和平均成績

5、查詢所有學生的學號,姓名,選課數,總成績

6、 查詢姓李老師的個數

7、 查詢沒有報李平老師課的學生姓名

8、 查詢物理課程比生物課程高的學生的學號

9、 查詢沒有同時選修物理課程和體育課程的學生姓名

10、查詢掛科超過兩門(包括兩門)的學生姓名和班級

11、查詢選修了所有課程的學生姓名

12、查詢李平老師教的課程的所有成績記錄

13、查詢全部學生都選修了的課程號和課程名

14、查詢每門課程被選修的次數

15、查詢只選修了一門課程的學生姓名和學號

16、查詢所有學生考出的成績並按從高到低排序(成績去重)

17、查詢平均成績大於85的學生姓名和平均成績

18、查詢生物成績不及格的學生姓名和對應生物分數

19、查詢在所有選修了李平老師課程的學生中,這些課程(李平老師的課程,不是所有課程)平均成績最高的學生姓名

20、查詢每門課程成績最好的前兩名學生姓名

答案

建議先自己做,然後再對照答案哦,特殊說明一下,SQL寫法有很多種,所以只要結果一致,不必糾結是否一模一樣。

1、查詢所有的課程的名稱以及對應的任課老師姓名
select c.cid,c.cname,t.tname from course  c left join teacher t on c.teacher_id = t.tid ;

2、查詢學生表中男女生各有多少人
select gender,count(1) 人數 from student group by gender;

3、查詢物理成績等於100的學生的姓名
select sname,num from student  s left join score s1 on s.sid = s1.student_id
left join course c on s1.course_id = c.cid
where c.cname = "物理" and s1.num = 100;

4、查詢平均成績大於八十分的同學的姓名和平均成績
select sname,avg(num) 平均成績 from student s left join score s1 on s.sid = s1.student_id group by sname having avg(num)>=80;

5、查詢所有學生的學號,姓名,選課數,總成績
select s.sid,s.sname,count(1) 課程數,sum(num) 總成績 from student s left join score s1 on s.sid = s1.student_id
where num > 0
group by s.sid,s.sname ;

6、 查詢姓李老師的個數
select count(1) 個數 from teacher where tname like "李%";

7、 查詢沒有報李平老師課的學生姓名
select sname from student where sname not in
(select distinct sname from student s 
left join score s1 on s.sid = s1.student_id
left join course c on s1.course_id = c.cid
left join teacher t on t.tid = c.teacher_id
where t.tname = "李平老師");

8、 查詢物理課程比生物課程高的學生的學號
select t1.student_id from 
(select student_id,num from score s1
left join course c on s1.course_id = c.cid
where cname = "物理") t1
join 
(select student_id,num from score s1
left join course c on s1.course_id = c.cid
where cname = "生物") t2
on t1.student_id = t2.student_id
where t1.num > t2.num;

9、 查詢沒有同時選修物理課程和體育課程的學生姓名
# 第一種寫法
select * from student where sid in(
select student_id from score where course_id in (select cid from course where cname = "物理" or cname = "體育")
group by student_id having count(student_id) = 1
);
# 第二種寫法
select * from student where sid in(
select student_id from score s left join course c on s.course_id = c.cid
where cname = "物理" or cname = "體育"
group by student_id having count(student_id) = 1
);

10、查詢掛科超過兩門(包括兩門)的學生姓名和班級
select s.sname,count(1) 個數 from student s
join score s1 on s.sid = s1.student_id
where num < 60 group by sname having count(1)>=2;
11 、查詢選修了所有課程的學生姓名
select distinct sname,s1.student_id from student  s join score s1 on s.sid=s1.student_id
group by sname,s1.student_id having count(1) >= (select count(cid) from course);
11、查詢選修了所有課程的學生姓名
select sname from student s
join score s1 on s.sid = s1.student_id
group by sname having count(student_id) =
(select count(1) from course);

12、查詢李平老師教的課程的所有成績記錄
select s.student_id,c.cname,s.num from score s
left join course c on s.course_id = c.cid
left join teacher t on t.tid = c.teacher_id
where t.tname = "李平老師";
 
13、查詢全部學生都選修了的課程號和課程名
select course_id,cname from score s
left join course c on s.course_id = c.cid
group by course_id
HAVING count(1) = (select count(1) from student);

14、查詢每門課程被選修的次數(每門課有多少學生選擇)
select cname,count(1) 次數 from score s
left join course c on s.course_id = c.cid
group by cname;
	
15、查詢只選修了一門課程的學生姓名和學號
select student_id,sname from score s
join student s1 on s.student_id = s1.sid
group by student_id,sname
having count(1) = 1;

16、查詢所有學生考出的成績並按從高到低排序(成績去重)
select distinct num from score order by num desc;

17、查詢平均成績大於85的學生姓名和平均成績
select sname,avg(num) 平均成績 from score s
join student s1 on s.student_id = s1.sid
group by sname
having avg(num)>85;

18、查詢生物成績不及格的學生姓名和對應生物分數
select sname,num from score s
left join student s1 on s.student_id = s1.sid
left join course c on s.course_id = c.cid
where cname = "生物" and num < 60;

19、查詢在所有選修了李平老師課程的學生中,這些課程(李平老師的課程,不是所有課程)平均成績最高的學生姓名
select sname,avg(num) 平均成績 from score s
left join student s1 on s.student_id = s1.sid
left join course c on s.course_id = c.cid
left join teacher t on c.teacher_id = t.tid
where tname = "李平老師"
group by sname 
order by avg(num) desc 
limit 1;

# 第二種方法
select sname,avg(num) 平均成績 from score s
left join student s1 on s.student_id = s1.sid
left join course c on s.course_id = c.cid
left join teacher t on c.teacher_id = t.tid
where tname = "李平老師"
group by sname
having avg(num)=
(select max(平均成績) from (select sname,avg(num) 平均成績 from score s
left join student s1 on s.student_id = s1.sid
left join course c on s.course_id = c.cid
left join teacher t on c.teacher_id = t.tid
where tname = "李平老師"
group by sname) t);

20、查詢每門課程成績最好的前兩名學生姓名
# 拿到第一名 union 第二名
select student_id,s.course_id,num from score s
join 
(select max(num) max_num,course_id from score group by course_id) t
on s.course_id = t.course_id
where num=max_num
union
select student_id,s.course_id,max(num) second_num from score s
join 
(select max(num) max_num,course_id from score group by course_id) t
on s.course_id = t.course_id
where num<max_num
group by s.course_id;