MySQL的sql語言多表查詢操作

數據完整性

作用: 保證用戶輸入到數據庫中的數據的一致性、正確性。

確保數據的完整性 = 在創建表時給表中添加約束

完整性的分類:

  • 實體完整性:
  • 域完整性:
  • 引用完整性: 學生表(學號 ,姓名) 成績表( 學號,科目,成績)
1.1 實體完整性約束

實體:即表中的一行(一條記錄)代表一個實體(entity)

實體完整性的作用:標識每一行數據不重複。

約束類型:

主鍵約束(primary key)

唯一約束(unique)

自動增長列(auto_increment)

1.1.1 主鍵約束(primary key)

​ 注:每個表中要有一個主鍵。

​ 特點:數據唯一,且不能爲null

示例:

第一種添加方式:

CREATE TABLE student(
	id int primary key,
	name varchar(50)
);

第二種添加方式:此種方式優勢在於,可以創建聯合主鍵

CREATE TABLE student(
	id int,
	name varchar(50),
	primary key(id)
);
CREATE TABLE student(
	classid int,
	stuid int,
	name varchar(50),
	primary key(classid,stuid)
);

第三種添加方式:(不推薦)

CREATE TABLE student(
	id int,
	name varchar(50)
);
ALTER TABLE student  ADD  PRIMARY KEY (id);
1.1.2 唯一約束(unique)

特點:數據不能重複。可以爲null

CREATE TABLE student(
	Id int primary key,
	Name varchar(50) unique
);
1.1.3 自動增長列(auto_increment)

sqlserver數據庫 (identity) oracle數據庫( sequence)

自動增長不能單獨使用,一般需要和主鍵配合。

給主鍵添加自動增長的數值,列只能是數值類型

CREATE TABLE student(
	Id int primary key auto_increment,
	Name varchar(50)
) auto_increment=100;
INSERT INTO student(name) values(‘tom’);
1.2 域完整性約束

域完整性約束的作用:限制此單元格的數據正確,不對其它單元格起作用,域代表當前單元格

域完整性約束:數據類型、非空約束(not null)、默認值約束(default)

check約束(mysql 5.5不支持)check(sex='男’or sex=‘女’)

1.2.1 數據類型

數值類型

類型 大小 範圍(有符號) 範圍(無符號) 用途
TINYINT 1 字節 (-128,127) (0,255) 小整數值
SMALLINT 2 字節 (-32 768,32 767) (0,65 535) 大整數值
MEDIUMINT 3 字節 (-8 388 608,8 388 607) (0,16 777 215) 大整數值
INT或INTEGER 4 字節 (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整數值
BIGINT 8 字節 (-9 233 372 036 854 775 808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 極大整數值
FLOAT 4 字節 查看幫助文檔 查看幫助文檔 單精度浮點數值
DOUBLE 8 字節 查看幫助文檔 查看幫助文檔 雙精度浮點數值
DOUBLE(M,D) 8個字節,M表示長度,D表示小數位數 同上,受M和D的約束 DUBLE(5,2) -999.99-999.99 同上,受M和D的約束 雙精度浮點數值
DECIMAL(M,D) 對DECIMAL(M,D) ,如果M>D,爲M+2否則爲D+2 依賴於M和D的值,M最大值爲65 依賴於M和D的值,M最大值爲65 小數值

日期類型:

表示時間值的日期和時間類型爲DATETIME、DATE、TIMESTAMP、TIME和YEAR。

每個時間類型有一個有效值範圍和一個"零"值,當指定不合法的MySQL不能表示的值時使用"零"值。

TIMESTAMP類型有專有的自動更新特性

類型 大小(字節) 範圍 格式 用途
DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
TIME 3 ‘-838:59:59’/‘838:59:59’ HH:MM:SS 時間值或持續時間
YEAR 1 1901/2155 YYYY 年份值
DATETIME 8 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和時間值
TIMESTAMP 4 1970-01-01 00:00:00/2038 結束時間是第 2147483647 秒,北京時間 2038-1-19 11:14:07,格林尼治時間 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和時間值,時間戳

字符串類型:

字符串類型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET

類型 大小 用途
CHAR 0-255字符 定長字符串 char(10) 10個字符
VARCHAR 0-65535字符 變長字符串 varchar(10) 10個字符
TINYBLOB 0-255字節 不超過 255 個字符的二進制字符串
TINYTEXT 0-255字節 短文本字符串
BLOB(binary large object) 0-65 535字節 二進制形式數據
TEXT 0-65 535字節 長文本數據
MEDIUMBLOB 0-16 777 215字節 二進制形式的中等長度數據
MEDIUMTEXT 0-16 777 215字節 中等長度文本數據
LONGBLOB 0-4 294 967 295字節 二進制形式的極大數據
LONGTEXT 0-4 294 967 295字節 極大文本數據

CHAR和VARCHAR類型類似,但它們保存和檢索的方式不同。它們的最大長度和是否尾部空格被保留等方面也不同。在存儲或檢索過程中不進行大小寫轉換。

BINARY和VARBINARY類類似於CHAR和VARCHAR,不同的是它們包含二進制字符串而不要非二進制字符串。也就是說,它們包含字節字符串而不是字符字符串。這說明它們沒有字符集,並且排序和比較基於列值字節的數值。

BLOB是一個二進制大對象,可以容納可變數量的數據。有4種BLOB類型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它們只是可容納值的最大長度不同。

有4種TEXT類型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。

1.2.2 非空約束

not null

CREATE TABLE student(
	Id int primary key,
	Name varchar(50) not null,
	Sex varchar(10)
);
INSERT INTO student values(1,’tom’,null);
1.2.3 默認值約束

default

CREATE TABLE student(
	Id int primary key,
	Name varchar(50) not null,
	Sex varchar(10) default '男'
);
insert intostudent1 values(1,'tom','女');
insert intostudent1 values(2,'jerry',default);
1.3 引用完整性約束

(參照完整性約束)

外鍵約束:FOREIGN KEY 

示例:

第一種添加外鍵方式。推薦

#學生表(主表)
CREATE TABLE student(
	sid int primary key,
	name varchar(50) not null,
	sex varchar(10) default '男'
);
#成績表(從表)
create table score(
        id int,
        score int,
        sid int , 
        CONSTRAINT fk_score_sid foreign key(sid) references student(sid)
);
-- 外鍵列的數據類型一定要與主鍵的類型一致

第二種添加外鍵方式。

ALTER TABLE score ADD CONSTRAINT fk_stu_score FOREIGN KEY(sid) REFERENCES student(sid);

第二節 多表查詢

多個表之間是有關係的,那麼關係靠誰來維護?

多表約束:外鍵約束。

2.1 多表的關係
2.1.1 一對多關係

客戶和訂單,分類和商品,部門和員工.

一對多建表原則:在多的一方創建一個字段,字段作爲外鍵指向一方的主鍵.

2.1.2 多對多關係

學生和課程:

多對多關係建表原則:需要創建第三張表,中間表中至少兩個字段,這兩個字段分別作爲外鍵指向各自一方的主鍵.

2.1.3 一對一關係

一個丈夫對應一個妻子

一個員工對應一個簡歷

在實際的開發中應用不多.因爲一對一可以創建成一張表.

兩種建表原則:

唯一外鍵對應:在多的一方創建一個外鍵指向一的一方的主鍵,將外鍵設置爲unique和非空.

主鍵對應:讓一對一的雙方的主鍵進行建立關係.

2.2 多表查詢

多表查詢有如下幾種:

1 合併結果集;UNION 、 UNION ALL

2 連接查詢

2.1內連接 [INNER] JOIN ON

2.2外連接 OUTER JOIN ON

  • 左外連接 LEFT [OUTER] JOIN
  • 右外連接 RIGHT [OUTER] JOIN

3 子查詢

2.2.1 合併結果集

作用:合併結果集就是把兩個select語句的查詢結果合併到一起!

合併結果集有兩種方式:

l UNION:去除重複記錄,例如:SELECT* FROM t1 UNION SELECT * FROM t2;

l UNION ALL:不去除重複記錄,例如:SELECT * FROM t1 UNION ALL SELECT * FROM t2。
在這裏插入圖片描述
在這裏插入圖片描述

注意:被合併的兩個結果:列數必須相同,列類型可以不同。

2.2.2 連接查詢

連接查詢就是求出多個表的乘積,例如t1連接t2,那麼查詢出的結果就是t1*t2。

在這裏插入圖片描述
連接查詢會產生笛卡爾積,假設集合A={a,b},集合B={0,1,2},則兩個集合的笛卡爾積爲{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以擴展到多個集合的情況。

那麼多表查詢產生這樣的結果並不是我們想要的,那麼怎麼去除重複的,不想要的記錄呢,當然是通過條件過濾。通常要查詢的多個表之間都存在關聯關係,那麼就通過關聯關係去除笛卡爾積。

示例 1:現有兩張表

emp表

CREATE TABLE emp(
	empno	int,
	ename	varchar(50),
	job		varchar(50),
	mgr		int,
	hiredate	date,
	sal		decimal(7,2),
	comm	decimal(7,2),
	deptno	int
);
#添加數據SQL語句省略

dept表

CREATE TABLE dept(
	deptno		int,
	dname		varchar(14),
	loc		varchar(13)
);
#添加數據SQL語句省略

執行如下SQL語句

select * from emp,dept;

在這裏插入圖片描述

使用主外鍵關係做爲條件來去除無用信息

SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;

在這裏插入圖片描述
上面查詢結果會把兩張表的所有列都查詢出來,也許你不需要那麼多列,這時就可以指定要查詢的列了。

SELECT emp.ename,emp.sal,emp.comm,dept.dname 
FROM emp,dept 
WHERE emp.deptno=dept.deptno;

在這裏插入圖片描述

一:內連接

上面的連接語句就是內連接,但它不是SQL標準中的查詢方式,可以理解爲方言!

SQL標準的內連接爲:

SELECT * 
FROM emp e 
INNER JOIN dept d 
ON e.deptno=d.deptno;
注意:on後面 主外鍵關係

內連接的特點:查詢結果必須滿足條件。

二:外連接

包括左外連接和右外連接,外連接的特點:查詢出的結果存在不滿足條件的可能。

a.左外連接:以左表爲主表,右表是從表

SELECT * FROM emp e 
LEFT OUTER JOIN dept d 
ON e.deptno=d.deptno;

左連接是先查詢出左表(即以左表爲主),然後查詢右表,左表中滿足條件和不滿足條件都顯示出來,右邊不滿足條件的顯示NULL。

我們還是用上面的例子來說明。其中emp表中“張三”這條記錄中,部門編號爲50,而dept表中不存在部門編號爲50的記錄,所以“張三”這條記錄,不能滿足e.deptno=d.deptno這條件。但在左連接中,因爲emp表是左表,所以左表中的記錄都會查詢出來,即“張三”這條記錄也會查出,但相應的右表部分顯示NULL。

在這裏插入圖片描述

b.右外連接

右連接就是先把右表中所有記錄都查詢出來,然後左表滿足條件的顯示,不滿足顯示NULL。例如在dept表中的40部門並不存在員工,但在右連接中,如果dept表爲右表,那麼還是會查出40部門,但相應的員工信息爲NULL。

SELECT * FROM emp e 
RIGHT OUTER JOIN dept d 
ON e.deptno=d.deptno;

在這裏插入圖片描述

連接查詢總結:

​ 連接不限於兩張表,連接查詢也可以是三張、四張,甚至N張表的連接查詢。通常連接查詢不可能需要整個笛卡爾積,而只是需要其中一部分,那麼這時就需要使用條件來去除不需要的記錄。這個條件大多數情況下都是使用主外鍵關係去除。

2.2.3 子查詢

一個select語句中包含另一個完整的select語句。

子查詢就是嵌套查詢,即SELECT中包含SELECT,如果一條語句中存在兩個,或兩個以上SELECT,那麼就是子查詢語句了。裏面的查詢叫做子查詢,外層的查詢叫父查詢,一般情況都是先執行子查詢,再執行父查詢。

l 子查詢出現的位置:

​ a. where後,作爲被查詢的條件的一部分;

​ b. from後,作臨時表;

l 當子查詢出現在where後作爲條件時,還可以使用如下關鍵字:

​ a. any

​ b. all

l 子查詢結果集的常見形式:

​ a. 單行單列(用於條件)

​ b. 多行單列(用於條件)

​ c. 多行多列(用於臨時表)

示例:

1. 工資高於JONES的員工。

分析:

查詢條件:工資>JONES工資,其中JONES工資需要一條子查詢。

第一步:查詢JONES的工資

SELECT sal FROM emp WHERE ename='JONES';

第二步:查詢高於JONES工資的員工

SELECT * FROM emp WHERE sal > (第一步結果);

結果:

SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='JONES');

2. 查詢與SCOTT同一個部門的員工。

l 子查詢作爲條件

l 子查詢形式爲單行單列

分析:

查詢條件:部門=SCOTT的部門編號,其中SCOTT 的部門編號需要一條子查詢。

第一步:查詢SCOTT的部門編號

SELECT deptno FROM emp WHERE ename='SCOTT';

第二步:查詢部門編號等於SCOTT的部門編號的員工

SELECT * FROM emp WHERE deptno = (SELECT deptno FROM emp WHERE ename='SCOTT');

3. 工資高於30號部門所有人的員工信息

分析:

SELECT * FROM emp WHERE sal>(SELECT MAX(sal)FROM emp WHERE deptno=30);

查詢條件:工資高於30部門所有人工資,其中30部門所有人工資是子查詢。高於所有需要使用all關鍵字。

第一步:查詢30部門所有人工資

SELECT sal FROM emp WHERE deptno=30;

第二步:查詢高於30部門所有人工資的員工信息

SELECT * FROM emp WHERE sal > ALL (第一步)

結果:

SELECT * FROM emp WHERE sal > ALL (SELECT sal FROM emp WHERE deptno=30)

l 子查詢作爲條件

l 子查詢形式爲多行單列(當子查詢結果集形式爲多行單列時可以使用ALL或ANY關鍵字)

4.from後面子查詢

SELECT ename,job,hiredate FROM (SELECT ename,job,hiredate FROM emp WHERE hiredate>'1987-1-1') AS temp;
2.2.4 導出導入數據庫

1 使用命令方式

導出數據庫表

mysqldump -uroot -p 數據庫名 > school.sql

導入數據庫表

mysql -u root -p
mysql>use 數據庫
然後使用source命令,後面參數爲腳本文件(如這裏用到的.sql)
mysql>source d:/dbname.sql

2 使用SQLyog工具完成導出導入(演示操作)

1 先備份,右擊數據庫選擇備份---》備份數據庫,轉儲到sql
2 導入,右擊選擇 "執行SQL腳本"
2.2.5 創建用戶和授權

要使用命令行登錄。

創建用戶

CREATE USER `zhangsan` IDENTIFIED BY '123';
CREATE USER `zhangsan`@`localhost` IDENTIFIED BY '123';
CREATE USER `zhangsan`@`%` IDENTIFIED BY '123';

授權

GRANT ALL PRIVILEGES ON *.* TO 'kunkun'@'localhost'; 

撤銷權限

REVOKE ALL ON school.* FROM `zhangsan`;

刪除用戶

DROP USER `zhangsan`; 

綜合練習

某網上商城數據庫表結構如下:

# 創建用戶表
create table user(
	 userId int primary key auto_increment,
  	 username varchar(20) not null,
  	 password varchar(18) not null,
     address varchar(100),
     phone varchar(11)
);

#一對多的實現
#創建分類表
create table category(
  cid varchar(32) PRIMARY KEY ,
  cname varchar(100) not null		#分類名稱
);

# 商品表
CREATE TABLE `products` (
  `pid` varchar(32) PRIMARY KEY,
  `name` VARCHAR(40) ,
  `price` DOUBLE(7,2),
   category_id varchar(32),
   constraint foreign key(category_id) references category(cid)
);

#多對多的實現
#訂單表
create table `orders`(
  `oid` varchar(32) PRIMARY KEY ,
  `totalprice` double(12,2), #總計
  `userId` int,
   constraint foreign key(userId) references user(userId) #外鍵
);

# 訂單項表
create table orderitem(
  oid varchar(32),	#訂單id
  pid varchar(32),	#商品id
  num int ,         #購買商品數量
  primary key(oid,pid), #主鍵
  foreign key(oid) references orders(oid),
  foreign key(pid) references products(pid)
);

////////////////////////////////////////////////////////////////////////////////
#初始化數據

#用戶表添加數據
INSERT INTO USER(username,PASSWORD,address,phone) VALUES('張三','123','北京昌平沙河','13812345678');
INSERT INTO USER(username,PASSWORD,address,phone) VALUES('王五','5678','北京海淀','13812345141');
INSERT INTO USER(username,PASSWORD,address,phone) VALUES('趙六','123','北京朝陽','13812340987');
INSERT INTO USER(username,PASSWORD,address,phone) VALUES('田七','123','北京大興','13812345687');

#給商品表初始化數據
insert into products(pid,name,price,category_id) values('p001','聯想',5000,'c001');
insert into products(pid,name,price,category_id) values('p002','海爾',3000,'c001');
insert into products(pid,name,price,category_id) values('p003','雷神',5000,'c001');
insert into products(pid,name,price,category_id) values('p004','JACK JONES',800,'c002');
insert into products(pid,name,price,category_id) values('p005','真維斯',200,'c002');
insert into products(pid,name,price,category_id) values('p006','花花公子',440,'c002');
insert into products(pid,name,price,category_id) values('p007','勁霸',2000,'c002');
insert into products(pid,name,price,category_id) values('p008','香奈兒',800,'c003');
insert into products(pid,name,price,category_id) values('p009','相宜本草',200,'c003');
insert into products(pid,name,price,category_id) values('p010','梅明子',200,null);


#給分類表初始化數據
insert into category values('c001','電器');
insert into category values('c002','服飾');
insert into category values('c003','化妝品');
insert into category values('c004','書籍');

#添加訂單
insert into orders values('o6100',18000.50,1);
insert into orders values('o6101',7200.35,1);
insert into orders values('o6102',600.00,2);
insert into orders values('o6103',1300.26,4);

#訂單詳情表
insert into orderitem values('o6100','p001',1),('o6100','p002',1),('o6101','p003',1)
3.1 綜合練習1-【多表查詢】

1>查詢所有用戶的訂單

SELECT o.oid,o.totalprice, u.userId,u.username,u.phone 
FROM orders as o INNER JOIN USER as u ON o.userId=u.userId; 

2>查詢用戶id爲 1 的所有訂單詳情

SELECT o.oid,o.totalprice, u.userId,u.username,u.phone ,oi.pid
FROM  orders o INNER JOIN USER u ON o.userId=u.userId
INNER JOIN orderitem oi ON o.oid=oi.oid
where u.userid=1;
3.2 綜合練習2-【子查詢】

1>查看用戶爲張三的訂單

SELECT * FROM orders WHERE userId=(SELECT userid FROM USER WHERE username='張三');

2>查詢出訂單的價格大於800的所有用戶信息。

SELECT * FROM USER WHERE userId IN (SELECT DISTINCT userId FROM orders WHERE totalprice>800)
3.3 綜合練習3-【分頁查詢】

1>查詢所有訂單信息,每頁顯示5條數據

#查詢第一頁
SELECT * FROM orders LIMIT 0,5

總結

1 數據完整性 :數據的正確性。

​ 實體完整性:

​ 主鍵約束:不能重複,不能爲爲null

​ 唯一約束: 不能重複 ,可以爲null

​ 自動增長: auto_increment, 默認從1 開始每次增長1

​ 域完整性:

​ 數據類型:

​ int

​ double

​ double(5,2)

​ decimal(5,2);

​ char 0-255

​ varchar 長度不固定

​ text

​ blob

​ date

​ datetime

​ timestamp

​ 非空約束 not null

​ 默認約束 default

​ 引用完整性

​ 外鍵約束

2 多表查詢

2.1 表關係

​ 一對多

​ 多對多(兩個一對多)

​ 一對一

2.2 多表查詢

​ 合併結果集

​ union 去掉重複

​ union all 包含重複

​ 連接查詢

​ 交叉連接(笛卡爾積)

​ 內連接

​ 傳統寫法

​ select *from emp ,dept where emp.deptno=dept.deptno;

​ 標準寫法

​ select *from emp inner join dept on emp.deptno=dept.deptno;

​ 外連接

​ 左外連接

​ select *from emp left outer join dept on emp.deptno=dept.deptno;

​ 右外連接

​ select *from emp right outer join dept on emp.deptno=dept.deptno;

​ 子查詢:

​ where 子查詢

​ from 子查詢

​ 子查詢結果:

​ 1 單行單列

​ 2 多行單列

​ 3 多行多列

2.3 導出導入

​ mysqldump

​ source

2.4 創建用戶

​ create user zhangsan identified by ‘123’;

​ 授權

​ grant all on school.* to zhangsan

​ 撤銷權限

​ revoke all on scholl.* from zhangsan

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章