MySql
1 概念
- database:數據庫,存儲數據的集合。
- 數據庫管理系統:DataBase Management System,DBMS。用于建立,使用和維護數據庫,對數據庫
進行統一管理和控制的大型軟件,保證了數據庫的完整性和安全性。
一般我們說的數據庫指的是存儲數據的集合和數據庫管理系統。即存儲,維護和管理數據。
常見的數據庫:MYSQL,Oracle,DB2等等
2 SQL語句
2.1 SQL分類
- DDL:Data Definition language,數據定義語言,用于定義數據庫對象:數據庫,表,列。關鍵字:create,show,drop,alter等。(結構)
- DML:Data Manipulation language,用于對數據庫中的記錄進行更新。關鍵字:insert,delete,update等(數據)。
- DQL:Data Query language,用于查詢數據庫中表的記錄。關鍵字:select,from,where等。【重點】
- DCL:Data Control language,用于定義數據庫的訪問權限和安全級別及創建用戶。關鍵字:grant等。(了解即可)
2.2 對數據庫的操作(create,drop,alter,show)
增:
create database 庫名 [character set gbk collate gbk_chinese_ci];
刪:
drop database 庫名;
改:
alter database 庫名 character set utf8; 修改某數據庫的字符集
查:
show databases; 顯示所有的數據庫
show create database 庫名; 顯示某個數據庫
其它:
use 庫名; 使用某個數據庫
select database(); 顯示當前所用的數據庫
2.3 對表單的操作:(create,drop,alter,show)
以下表名均用stu代替:
增:
create table stu(
字段名1 類型1(長度)[約束],
字段名2 類型2(長度)[約束]...
);
約束:
唯一約束:unique,唯一
非空約束:not null,非空
主鍵約束:primary key ,唯一和非空的組合。
刪:
alter table stu drop 字段名; 刪除列
drop table stu; 刪除表單
改:
*alter table stu add 字段名 類型1(長度)[約束]; 增加一列
*alter table stu modify 字段名 類型1(長度)[約束]; 修改列的長度和約束
*alter table stu change 舊列名 新列名 類型1(長度)[約束]; 修改列名
*alter table stu drop 字段名; 刪除列
*alter table stu character set utf8; 修改表的字符集
*rename table 舊表名 to 新表名; 修改表名
查:
show tables; 查看所有表單
desc 表名; 查看表單結構
2.4 對表單中數據的操作(insert into,update,delete)
增:
方式1:插入部分/所有列的值
insert into 表名(字段名1,字段名2...字段名n) values(與前面對應的值);
方式2:插入所有列的值
insert into 表名 values(所有列的對應的值);
1.列名和后面values里面的列名數以及順序必須一致。
2.列名的類型和插入的值必須一致,插入的值不能超過最大長度。
3.值如果是字符串或者日期必須加上''單引號。
刪:
delete from 表名 [where]...; 不加判斷條件即為刪除整個表格
truncate table 表名; 刪除整個表格
delete和truncate的區別:
1:delete是一行一行的刪除數據,不清空auto_increment記錄數,刪除的數據可以一個事務中恢復
2:truncate是直接把表格刪除,再創建一個新的表格,清空auto_increment,所以效率較delete高。
這是徹底刪除,無法恢復
改:
*update 表名 set 字段名=值,字段名=值...;
*update 表名 set 字段名=值,字段名=值...where條件;
查:
select */列名1,列名2.. from 表名; 查詢全部/部分列的信息
3 SQL查詢
3.1 簡單查詢
語法:select [distinct] */列名,列名 from 表名 [where條件];
distinct表示去重。
例子:
1.查詢所有商品: select * from 表名;
2.查詢商品名和商品價格: select name,price from 表名;
3.別名查詢,使用關鍵字as。as可省略
select name as '商品名' from 表名;/select name '商品名' from 表名;
4.去重查詢: select distinct name from 表名;
5.將所有商品價格加上10進行顯示。
select price+10 from 表名;
2.2 條件查詢
> < <= >= = <> : 大于,小于,小于等于,大于等于,等于,不等于
where 等同于java中的 if,但是在where語句后進行判斷操作時使用'=',而不是用'=='。
* between...and... 在...和...之間
* in(數據1,數據2...數據n); 在幾個數據中
* and: 和,并且
* or: 或
* like: 模糊查詢,占位符%和_,%表示占0或多個字符,_表示占一個字符
* is null:判斷是否為空。(了解)
2.3 排序
order by 字段名 asc/desc : 默認asc升序,desc為降序。ascending,descending
例子:
1:查詢所有的商品,按價格進行降序排序
select * from product order by price desc;
2:查詢所有名稱含有"士"的商品,并按價格降序排序
select * from product where name like '%士%' order by price desc;
order by 的排序在篩選完成后進行,因此order by語句放在sql語句最后面。
2.4 聚合函數
聚合函數不統計null值。
* count(*|字段名); 對全部/某列的數據計數
* sum():求和
* max:求最大值
* min:求最小值
* avg:求平均值
例子:
1:獲得所有商品的價格的總和:
select sum(price) from product;
2:獲得所有商品的平均價格:
select avg(price) from product;
3:獲得所有商品的個數
select count(*) from product; 統計所有商品一般用*
2.5 分組
group by 字段名 :
group_concat():組合在一起
案例:group by結合聚合函數使用(聚合函數前寫得字段名必須是用于分組的字段名)
-- 創建數據庫mydb1
CREATE DATABASE mydb1;
-- 使用數據庫mydb1
USE mydb1;
-- 創建表單product
CREATE TABLE product(
id INT,NAME VARCHAR(50),price INT
);
-- 往表格中添加數據
INSERT INTO product VALUES(1,'蘋果',20);
INSERT INTO product VALUES(2,'李子',2);
INSERT INTO product VALUES(3,'葡萄',55);
INSERT INTO product VALUES(4,'桃子',40);
INSERT INTO product VALUES(5,'西瓜',22);
INSERT INTO product VALUES(88,'冬瓜',10);
-- 將所有商品的id值變為1
UPDATE product SET id=1;
-- 將部分商品的id值變為2
UPDATE product SET id=2 WHERE price BETWEEN 10 AND 30;
-- 1:根據id字段分組,分組后統計商品的個數
SELECT id,COUNT(*) AS '商品數量' FROM product GROUP BY id;
-- 2:根據id字段分組,分組統計每組商品的平均價格,并且平均價格大于20
SELECT id,AVG(price) AS 平均價格 FROM product GROUP BY id HAVING AVG(price)>20;
-- 3:根據id字段分組,顯示每組里面的成員,這個時候如果只用group by就只能顯示每組的第一個成員,因此要加上group_concat():括號內不能用*
SELECT id,GROUP_CONCAT(NAME) FROM product group by id;
1:


2.6 分組后篩選(having)
- having是分組后篩選
where和having的區別
- 1.having是在分組后對數據進行過濾.where是在分組前對數據進行過濾
- 2.having后面可以使用聚合函數(統計函數)where后面不可以使用聚合函數。理解:沒有篩選出某一列數據之前當然不能用聚合函數進行統計。
- 3.having后面加的條件一定要與分組有關,因為他是分組后進行篩選的關鍵字。
- 4.WHERE是分組前記錄的條件,如果某行記錄沒有滿足WHERE子句的條件,那么這行記錄不會參加分組;而HAVING是對分組后數據的約束。
2.7 分頁查找(limit)
sql查詢語句完整格式:
select [distinct] */列名,列名... from 表名 where 條件 group by 按照?列名分組
order by[asc/desc] having 分組后篩選條件 limit m,n;
distinct去重,where是在分組前的篩選條件,group by一般和聚合函數或者group_concat一起使用,
單獨使用沒意義。order by默認排序asc,having后接分組后的篩選條件。limit中m代表從第m行開始,
顯示n行。
分頁顯示:limit (current-1)*n,n; current為當前頁面,下一頁的limit格式就是這樣寫
3 數據完整性
為了確保用戶輸入的數據保存到數據庫中是正確的,在創建表的時候要給表中的列添加約束。
完整性的分類:
- 實體完整性
- 域完整性
- 引用完整性
3.1 實體完整性
實體中的每一行就代表一個實體。實體完整性的作用:標識的每一行記錄都不重復
約束類型:主鍵約束(primary key),唯一約束(unique),自動增長列(auto_increment)
3.1.1 主鍵約束(primary key)
注意:每個表中都必須要有一個主鍵
特點:數據唯一,且不能為null,相當于unique和not null的結合
三種添加主鍵的方式:
方式一:直接在建表字段定義時添加
create table user(
id int primary key
);
方式二:建表時在最后添加,好處時可以創建聯合主鍵
create table user(
id int,username varchar(50),
primary key(id)
);
create table user(
id int,
name varchar(50),
primary key(id,name)
);
方式三:通過sql語句添加:
create table user(id int,name varchar(50));
alter table user add constraint user_pk primary key(id);
3.1.2 唯一約束(unique)
特點:數據不能重復
create table user(id int,username varchar(50) unique);
3.1.3 自動增長列(auto_increment)
特點:給主鍵添加自動增加的數值,列只能是整數類型
create table user(
id int primary key auto_increment,username varchar(50)
);
3.2 域完整性
域完整性的作用:限制此單元格的數據正確
域完整性約束:
- 非空約束:not null
- 默認值約束:default
3.2.1 非空約束(not null)
create table user(
id int,name varchar(50) not null
);
name被限制不能為空
3.2.2 默認約束(default)
create table user(
id int,name varchar(50),sex varchar(20) default '男'
);
insert into user values(1,'小芳','女');
insert into user values(1,'小芳',default);
3.3 引用完整性(foreign key:外鍵約束)
外鍵約束的兩種添加方式:
create table student(
sid int primary key auto_increment,
username varchar(50) not null,
sex varchar(10) default '男'
);
create table score(
id int primary key auto_increment,
score int,
sid int
);
方式一:直接在建表時表中添加
create table score(
id int primary key auto_increment,name varchar(50) not null,
sid int,
constraint fk_score_sid foreign key(sid) references student(sid)
);
方式二:sql語句添加外鍵
alter table score add constraint fk_score foreign key(sid) references student(sid);
3.4 表與表之間的關系
外鍵指向主鍵
3.4.1 一對一
對其中任意一個表添加一個外鍵列,并且要給外鍵列添加唯一約束,否則就不是一對一而是一對多了
3.4.2 一對多(多對一):相對而言
在多的一方添加外鍵列,創建外鍵約束指向一的表的主鍵。
3.4.3 多對多
需要創建一個第三方表格,至少要有兩個外鍵列,分別指向兩個表的主鍵
4 多表查詢
多表查詢有以下幾種:
- 連接查詢【重要】
- 內連接查詢 --- 隱式連接、顯式連接
- 外連接查詢 --- 左外連接、右外連接
- 子查詢【非常重要】
- 聯合查詢
4.1 連接查詢【重要】
連接查詢就是求出多個表的乘積,例如t1連接t2,那么查詢出的結果就是t1*t2。
連接查詢會產生笛卡兒積,這樣的查詢結果會有大量的無用數據,所以就需要使用篩選得到可用數據
4.1.1 內連接查詢
語法:
隱式內連接:
select [*][列名,列名...] from t1,t2 [where條件];
顯式內連接:
select [*][類名,列名...] from t1 [inner] join t2 on [篩選條件] [where條件];
4.1.2 外連接查詢
語法:
左外連接查詢:
select [*][列名,列名...] from t1 left [outer] join t2 on[篩選條件][where條件];
右外連接查詢:
select [*][列名,列名...] from t1 right [outer] join t2 on[篩選條件][where條件]
外連接和內連接的區別:
內連接放在前面的顯示作為主表,右邊的作為從表。外連接則跟左右連接有關。
-
內連接查詢特點:查詢結果必須滿足條件,不滿足條件不顯示。
例:張三的部門deptno為50,而在dept表中只有10、20、30、40部門, 那么內連接查詢結果中就不會出現“張三”這條記錄, 因為它不能滿足e.deptno=d.deptno這個條件。
-
外連接查詢特點:查詢出的結果存在不滿足條件的可能。滿足條件的顯示出來,不滿足條件的顯示NULL。
emp表中“張三”這條記錄中,部門編號為50, 而dept表中不存在部門編號為50的記錄, 所以“張三”這條記錄不能滿足e.deptno=d.deptno這條件。 但在左連接中,因為emp表是左表,所以左表中的記錄都會查詢出來, 即“張三”這條記錄也會查出,但相應的右表部分顯示NULL。
4.2 子查詢【非常重要】
子查詢就是嵌套查詢,即select包含select
子查詢出現的位置:
1:where后面,作為被查詢條件的一部分
2:from后面,作表
具體使用見例子
當子查詢結果集形式為多行單列時可以使用ALL或ANY關鍵字
例如:
1:查詢工資高于30號部門所有人的員工信息
select * from emp where sal>(select max(sal) from emp where deptno=30);
等價于:
select * from emp where sal>ALL(select sal from emp where deptno=30);
2:查詢工作和工資與MARTIN完全相同的員工信息
select * from emp where (job,sal) in (select job,sal from emp where name='martin');
3:有2個以上直接下屬的員工信息
select * from emp where mgr in(select mgr from emp group by mgr having count(*)>=2);
4:求各個部門薪水最高的員工所有信息
select * from emp e,(select max(sal) as maxsal,deptno from emp group by deptno) as a
where e.sal=a.maxsal and a.deptno=e.deptno;
4.3 聯合查詢
聯合查詢就是把兩個select語句的查詢結果合并到一起
被合并的兩個結果:列數、列類型必須相同。
合并查詢的兩種方式:
union:去除重復記錄
select * from t1 union select * from t2;
union all:不去除重復記錄
select * from t1 union select * from t2;
5 多表查詢的練習
-- mysql
-- 新建一個day09_exercise的數據庫
CREATE DATABASE day09_exercise;
USE day09_exercise;
SELECT DATABASE();
-- 創建用戶user表
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50)
);
DESC USER;
-- 創建訂單表
CREATE TABLE orders(
id INT PRIMARY KEY AUTO_INCREMENT,
price DOUBLE,
user_id INT
);
DESC orders;
-- 給訂單表添加外鍵約束\ 一對多,向多的表格添加外鍵
ALTER TABLE orders ADD CONSTRAINT user_fk FOREIGN KEY(user_id) REFERENCES USER(id);
-- 向user表中添加數據
INSERT INTO USER VALUES(3,'張三'),(4,'李四'),(5,'王五'),(6,'趙六');
SELECT * FROM USER;
-- 向orders表中插入數據
INSERT INTO orders VALUES(1,1314,3),(2,1314,3),(3,15,4),(4,315,5),(5,1014,NULL);
SELECT * FROM orders;
-- mysql練習三:
-- --查看用戶為張三的訂單詳情
-- 思路:多表查詢
-- 內連接查詢---隱式查詢:
SELECT * FROM USER u,orders o WHERE u.id=o.user_id AND u.username='李四';
-- 內連接查詢---顯式查詢:
SELECT * FROM USER u INNER JOIN orders AS o ON u.id=o.user_id WHERE u.username='李四';
SELECT * FROM orders AS o INNER JOIN USER u ON u.id=o.user_id AND u.username='李四';
-- 上面查詢時,on后面接and表示并且查詢也可以,但不建議,推薦除了主從表的條件用on,其他條件用where
-- 在前面的作為主表,顯示時出現在前面
-- 外連接查詢---左連接查詢
SELECT * FROM USER u LEFT OUTER JOIN orders o ON u.id=o.user_id WHERE u.username='李四';
--- 外連接查詢---右連接查詢
SELECT * FROM USER u RIGHT OUTER JOIN orders o ON u.id=o.user_id WHERE u.username='李四';
-- 外連接和內連接的區別:
--
-- 查詢出訂單的價格大于300的所有用戶信息。
SELECT * FROM USER WHERE id=(SELECT user_id FROM orders WHERE price>300); -- 錯誤
-- 上面式子錯誤,子查詢得到的結果是多個的,用id=只能等于一個數,因此用in
SELECT * FROM USER WHERE id IN (SELECT user_id FROM orders WHERE price>300);
-- 查詢訂單價格大于300的訂單信息及相關用戶的信息。
SELECT * FROM USER,orders WHERE user.id=orders.user_id AND price>300;
-- 上面兩個式子,前者user中沒有price列,所以要到orders里面找到price來進行篩選,
-- 而后者則是拼接后進行篩選,這個時候的表格中已經有price列了,因此直接篩選即可