Java學習筆記二十(數據庫基礎)

第一章 數據庫概述

1.1 數據庫概述

DBMS:數據庫管理系統(Database Management System)是一種操縱和管理數據庫的大型軟件,例如建立、使用和維護數據庫。

DB:數據庫(Database)

SQL:結構化查詢語言,(Structure Query Language),專門用來操作/訪問數據庫的通用語言。
MySQL:其中的一款關係型數據庫管理系統

以下是2019年DB-Engines Ranking 對各數據庫受歡迎程度進行調查後的統計結果:(查看數據庫最新排名:https://db-engines.com/en/ranking)
1

關係型數據庫,採用關係模型來組織數據,簡單來說,關係模型指的就是二維表格模型。類似於Excel工作表。非關係型數據庫,可看成傳統關係型數據庫的功能閹割版本,基於鍵值對存儲數據,通過減少很少用的功能,來提高性能。

關係型數據庫設計規則

  • 遵循ER模型和三範式

    • E entity 代表實體的意思 對應到數據庫當中的一張表
    • R relationship 代表關係的意思
  • 三範式:1、列不能拆分 2、唯一標識 3、關係引用主鍵

  • 具體體現

    • 將數據放到表中,表再放到庫中。
    • 一個數據庫中可以有多個表,每個表都有一個名字,用來標識自己。表名具有唯一性。
    • 表具有一些特性,這些特性定義了數據在表中如何存儲,類似java和python中 “類”的設計。
    • 表由列組成,我們也稱爲字段。每個字段描述了它所含有的數據的意義,數據表的設計實際上就是對字段的設計。創建數據表時,爲每個字段分配一個數據類型,定義它們的數據長度和字段名。每個字段類似java 或者python中的“實例屬性”。
    • 表中的數據是按行存儲的,一行即爲一條記錄。每一行類似於java或python中的“對象”。
      在這裏插入圖片描述

1.2 MySQL概述

MySQL是一種開放源代碼的關係型數據庫管理系統,開發者爲瑞典MySQL AB公司。在2008年1月16號被Sun公司收購。而2009年,SUN又被Oracle收購。目前 MySQL被廣泛地應用在Internet上的中小型網站中。由於其體積小、速度快、總體擁有成本低,尤其是開放源碼這一特點,使得很多互聯網公司選擇了MySQL作爲網站數據庫(Facebook, Twitter, YouTube,阿里的螞蟻金服,去哪兒,魅族,百度外賣,騰訊)。
在這裏插入圖片描述

第二章 MySQL的使用

2.1 MySQL服務的啓動

“我的電腦/計算機”–>右鍵–>“管理”–>“服務”–>啓動和關閉MySQL服務

“開始菜單”–>“控制面板”–>“管理工具”–>“服務”–>啓動和關閉MySQL

“任務管理器”–>“服務”–>啓動和關閉MySQL

或者

命令行

net  start  MySQL服務名
net  stop  MySQL服務名

2.2 客戶端連接MySQL

1、命令行客戶端:

mysql -h 主機IP地址 -P 端口號	-u 用戶名	-p回車
Enter Password:密碼

如果訪問本機,-h localhost可以省略

如果端口號沒有修改,-P 3306可以省略

除了-p與密碼之間不要空格外,其他的-h,-P,-u與後面的參數值之間可以有空格

想要連接成功,必須保證服務開啓的

2、其他客戶端,例如:可視化工具Navicat或SQLyog等
在這裏插入圖片描述

2.3 導入和導出數據

2.3.1 單個數據庫備份

C:\Windows\System32> mysqldump -h主機地址 -P端口號 -u用戶名 -p密碼 --database 數據名 > 文件路徑/文件名.sql

例如:

C:\Windows\System32>mysqldump -hlocalhost -P3306 -uroot -p123456 --database test > d:/test.sql

在這裏插入圖片描述

2.3.2 導入執行備份的sql腳本

先登錄mysql,然後執行如下命令:

mysql> source  sql腳本路徑名.sql

例如:

mysql>source d:/test.sql;

在這裏插入圖片描述

第三章 MySQL數據類型和運算符

3.1 MySQL數據類型

整型系列:xxxInt

int(M),必須和unsigned zerofill一起使用纔有意義

在這裏插入圖片描述
浮點型系列:float,double

double(M,D):表示最長爲M位,其中小數點後D位

例如:double(5,2)表示的數據範圍[-999.99,999.99],如果超過這個範圍會報錯。

定點型系列:decimal

decimal(M,D):表示最長爲M位,其中小數點後D位

字符串類型:char,varchar(M),text

char如果沒有指定寬度,默認爲1個字符

varchar(M),必須指定寬度

日期時間類型:year, date, datetime, timestamp

注意一下每一種日期時間的表示範圍
在這裏插入圖片描述
其他類型:bit, xxBlob, 枚舉,集合等

+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| eid            | int(11)      | NO   | PRI | NULL    | auto_increment |
| ename          | varchar(20)  | NO   |     | NULL    |                |
| tel            | char(11)     | NO   |     | NULL    |                |
| gender         | char(1)      | YES  |     | 男        |                |
| salary         | double       | YES  |     | NULL    |                |
| commission_pct | double(3,2)  | YES  |     | NULL    |                |
| birthday       | date         | YES  |     | NULL    |                |
| hiredate       | date         | YES  |     | NULL    |                |
| job_id         | int(11)      | YES  |     | NULL    |                |
| email          | varchar(32)  | YES  |     | NULL    |                |
| mid            | int(11)      | YES  |     | NULL    |                |
| address        | varchar(150) | YES  |     | NULL    |                |
| native_place   | varchar(10)  | YES  |     | NULL    |                |
| did            | int(11)      | YES  |     | NULL    |                |
+----------------+--------------+------+-----+---------+----------------+

3.2 MySQL運算符

1、算術運算符

加:+
減:-
乘:*
除:/   div(只保留整數部分)
模:%   mod

2、比較運算符

大於:>
小於:<
大於等於:>=
小於等於:>=
等於:=   不能用於null判斷
不等於:!=  或 <>
安全等於:<=>  可以用於null值判斷

3、邏輯運算符(建議用單詞,可讀性來說)

邏輯與:&& 或 and
邏輯或:|| 或 or
邏輯非:! 或 not
邏輯異或:^ 或 xor

4、範圍

區間範圍:between x  and  y
	    not between x  and  y
集合範圍:in (xxx)
	    not  in(xxx)

5、模糊查詢(只針對字符串類型,日期類型)

like 'xxx'
如果想要表示0~n個字符,用%
如果想要表示確定的1個字符,用_

6、位運算符(很少使用)

左移:<<
右移:>>
按位與:&
按位或:|
按位異或:^

7、特殊的null值處理

#(1)判斷時
xx is null
xx is not null
xx <=> null

#(2)計算時
ifnull(xx,代替值)  當xx是null時,用代替值計算
/*一、運算符
1、算術運算符
+:加
-:減
*:乘
/:除   可以保留小數部分
div:除  如果整數與整數相除只保留整數部分
%:求餘數
mod:求餘數
*/
select 1+1;
select 1/2; #0.5
select 1 div 2; #0

/*
2、比較運算符
>:大於
<:小於
=:等於  注意區別,Java中是==,mysql中是=
>=:大於等於
<=:小於等於
!=:不等於
<>:不等於
<=>:安全等於  用於判斷null值的比較運算符
		null值的判斷,習慣上我們用is null 和is not null
*/
#查詢薪資大於20000元的員工
select * from t_employee where salary > 20000;

#查詢所有男員工
select * from t_employee where gender = '男';
select * from t_employee where gender != '女';
select * from t_employee where gender <> '女';

#查詢獎金比例commision_pct是null的員工
select  * from t_employee where commission_pct <=> null;
select  * from t_employee where commission_pct is null;

/*
3、邏輯運算符
&&和and:邏輯與
	兩個條件同時滿足
||和or:邏輯或
	兩個條件滿足任意一個
^和xor:邏輯異或
	兩個條件只能滿足其中一個
!和not:
	不滿足xx條件
	*/
#查詢薪資大於20000元的女員工	
select * from t_employee where salary > 20000 && gender = '女';
select * from t_employee where salary > 20000 and gender = '女';

#查詢男員工
select * from t_employee where not gender = '女';
select * from t_employee where !(gender = '女');

#查詢薪資大於10000  異或 性別是男的,即它倆只能滿足一個
#即查詢薪資大於10000的女的或薪資低於10000的男的
select * from t_employee where salary>10000 ^ gender ='男';
select * from t_employee where salary>10000 xor gender ='男';
/*
4、範圍
(1)區間範圍:
	在[a,b]之間,between a and b
	不在[a,b]之間,not between a and b
(2)集合範圍
	in(...)
	not in(...)
*/
#查詢薪資在[15000,20000]之間的員工
select * from t_employee where salary between 15000 and 20000;
select * from t_employee where salary >= 15000 and salary <=20000;

#查詢薪資在9000,10000,12000
select * from t_employee where salary in(9000,10000,12000);
select * from t_employee where salary =9000 || salary =10000 || salary =12000;
 /*
5、模糊查詢
like '%x%' x代表確定的字符 %表示不確定的0~n個字符
     '_x%'  x代表確定的字符 _表示確定的1個字符
*/
#查詢,名字ename中包含“冰”這個字的員工
select * from t_employee where ename like '%冰%';

#查詢,名字ename是張xx,三個字
select * from t_employee where ename like '張__';

#查詢,名字ename是第二個字是'冰'
select * from t_employee where ename like '_冰%';

第四章 SQL

4.1 MySQL的語法規範和要求

(1)mysql的sql語法不區分大小寫

MySQL的關鍵字和函數名等不區分大小寫,但是對於數據值是否區分大小寫,和字符集與校對規則有關。

ci(大小寫不敏感),cs(大小寫敏感),_bin(二元,即比較是基於字符編碼的值而與language無關,區分大小寫)

(2)命名時:儘量使用26個英文字母大小寫,數字0-9,下劃線,不要使用其他符號

(3)建議不要使用mysql的關鍵字等來作爲表名、字段名等,如果不小心使用,請在SQL語句中使用`(飄號)引起來

(4)數據庫和表名、字段名等對象名中間不要包含空格

(5)同一個mysql軟件中,數據庫不能同名,同一個庫中,表不能重名,同一個表中,字段不能重名

(6)標點符號:

必須成對

必須英文狀態下半角輸入方式

字符串和日期類型可以使用單引號’’

列的別名可以使用雙引號"",給表名取別名不要使用雙引號。取別名時as可以省略

如果列的別名沒有包含空格,可以省略雙引號,如果有空格雙引號不能省略。

(7)SQL腳本中如何加註釋

單行註釋:#註釋內容

單行註釋:–空格註釋內容 其中–後面的空格必須有

多行註釋:/* 註釋內容 */

#以下兩句是一樣的,不區分大小寫
show databases;
SHOW DATABASES;

#創建表格
#create table student info(...); #表名錯誤,因爲表名有空格
create table student_info(...); 

#其中name使用``飄號,因爲name和系統關鍵字或系統函數名等預定義標識符重名了。
CREATE TABLE t_stu(
    id INT,
    `name` VARCHAR(20)
);

select id as "編號", `name` as "姓名" from t_stu; #起別名時,as都可以省略
select id as 編號, `name` as 姓名 from t_stu; #如果字段別名中沒有空格,那麼可以省略""
select id as 編 號, `name` as 姓 名 from t_stu; #錯誤,如果字段別名中有空格,那麼不能省略""

4.2 SQL分類

DDL:數據定義語言,定義庫,表結構等,包括create,drop,alter等
(create、drop可以操作數據庫和表,一般操作表時需要加上數據庫.來表示是哪個數據庫中的表;alter用來操作表)

DML:數據操作語言,增刪改查數據,包括insert,delete,update,select等

DCL:數據控制語言,權限,事務等管理。

4.3 DDL(v1.0)

1、查看所有數據庫

show databases;

2、指定使用某個數據庫

use 數據庫名;

3、創建數據庫

create database 數據庫名;

create database 數據庫名 charset 'utf8'; #在mysql中字符集名稱不要使用utf-8

create database 數據庫名 charset 'gbk';

4、刪除數據庫

drop database 數據庫名;

5、查看某個庫下的所有表格

show tables ;  #前提是前面有use 數據庫名;的語句
show tables from 數據庫名;

6、創建表格

create table 【數據名.】表名(
	字段名1 數據類型,
	字段名2 數據類型,
	....
);

7、刪除表格

drop table 【數據庫名.]表名稱;

8、查看某個表結構

describe 【數據庫名.]表名稱;
desc 【數據庫名.]表名稱;

9、增加一列

alter table 【數據庫名.]表名稱 add 【column】 字段名 數據類型;
alter table 【數據庫名.]表名稱 add 【column】 字段名 數據類型 first;
alter table 【數據庫名.]表名稱 add 【column】 字段名 數據類型 after 另一個字段;

10、刪除一列

alter table 【數據庫名.]表名稱 drop 【column】 字段名;

11、修改列數據類型

alter table 【數據庫名.]表名稱 modify 【column】 字段名 新數據類型;

12、修改列名

alter table 【數據庫名.]表名稱 change【column】 舊字段名 新字段名 新數據類型;

13、修改列的位置

alter table 【數據庫名.]表名稱 modify 【column】字段名 數據類型 first;
alter table 【數據庫名.]表名稱 modify 【column】字段名 數據類型 after 另一個字段;

14、修改表名稱

alter table 舊錶名 rename 新表名;
rename table 舊錶名 to 新表名;

alter操作數據庫中的表結構,可以使用的關鍵字有add、drop、modify、change(用來改列名)、rename。

4.4 DML(v1.0)

1、添加數據

insert into 【數據庫名.]表名稱 values(值列表); 
#要求值列表的順序、個數、類型,要與表格中的字段的順序、個數、類型一一匹配

insert into 【數據庫名.]表名稱(部分字段列表) values(值列表);
#要求列表的順序、個數、類型,要與前面的(部分字段列表)的順序、個數、類型一一匹配

insert into 【數據庫名.]表名稱 values(值列表1),(值列表2)。。。;

insert into 【數據庫名.]表名稱(部分字段列表) values(值列表1),(值列表2)。。。;

2、修改數據

update 【數據庫名.]表名稱 set 字段名1 = 值1, 字段名2 = 值2 。。。 【where 條件】;

如果沒有加where條件,表示修改所有行,這個字段的值

3、刪除數據

delete from 【數據庫名.]表名稱 【where 條件】;

如果沒有where條件,表示刪除整張表的數據;

truncate 【數據庫名.]表名稱;#刪除整張表的數據,還可以使用這個語句,效率更高,但是它不能回滾

用delete刪除整張表和用truncate刪除整張表的數據的區別?

(1)truncate速度快

(2)truncate無法回滾

truncate因爲底層是把表drop掉,然後新建了一張空表。

delete因爲底層是一行一行刪數據。

4、簡單查詢數據

select * from 【數據庫名.]表名稱; #查詢整張表的所有數據

select 字段列表  from 【數據庫名.]表名稱;  #查詢部分列表

select * from 【數據庫名.]表名稱 【where 條件】;

select 字段列表  from 【數據庫名.]表名稱 【where 條件】;

使用distinct可以對查詢結果進行去重

第五章 約束與索引

5.1 關係型數據庫設計規則

  • 遵循ER模型和三範式

    • E entity 代表實體的意思 對應到數據庫當中的一張表
    • R relationship 代表關係的意思
  • 三範式:1、列不能拆分 2、唯一標識 3、關係引用主鍵

  • 具體體現

    • 將數據放到表中,表再放到庫中。
    • 一個數據庫中可以有多個表,每個表都有一個名字,用來標識自己。表名具有唯一性。
    • 表具有一些特性,這些特性定義了數據在表中如何存儲,類似java和python中 “類”的設計。
    • 表由列組成,我們也稱爲字段。每個字段描述了它所含有的數據的意義,數據表的設計實際上就是對字段的設計。創建數據表時,爲每個字段分配一個數據類型,定義它們的數據長度和字段名。每個字段類似java 或者python中的“實例屬性”。
    • 表中的數據是按行存儲的,一行即爲一條記錄。每一行類似於java或python中的“對象”。

在這裏插入圖片描述

5.2 約束與索引的概念

1、數據完整性(Data Integrity)是指數據的精確性(Accuracy)和可靠性(Reliability)。它是應防止數據庫中存在不符合語義規定的數據和防止因錯誤信息的輸入輸出造成無效操作或錯誤信息而提出的。

數據的完整性要從以下四個方面考慮:

  • 實體完整性(Entity Integrity):例如,同一個表中,不能存在兩條完全相同無法區分的記錄
  • 域完整性(Domain Integrity):例如:年齡範圍0-120,性別範圍“男/女”
  • 引用完整性(Referential Integrity):例如:員工所在部門,在部門表中要能找到這個部門
  • 用戶自定義完整性(User-defined Integrity):例如:用戶名唯一、密碼不能爲空等,本部門經理的工資不得高於本部門職工的平均工資的5倍。

2、根據約束的特點,分爲幾種:

  • 鍵約束:主鍵約束、外鍵約束、唯一鍵約束
  • Not NULL約束:非空約束
  • Check約束:檢查約束
  • Default約束:默認值約束
  • 自增約束

3、約束(CONSTRAINTS)與索引(INDEX)

約束是用來對數據業務規則和數據完整性進行實施、維護。約束的作用範圍僅限在當前數據庫,約束可以被當做數據庫對象來處理,它們具有名稱和關聯模式。是邏輯約束,不會因爲設置約束而額外佔用空間。

索引是一個單獨、物理的存儲在數據頁上的數據庫結構,它是表中一列或若干列值的集合和相應的指向表中數據值的物理標識數據頁的邏輯指針清單(類似於新華字典的目錄索引頁)。索引的存在會增加數據庫的存儲空間,也會使插入、修改數據的時間開銷變多(因爲插入和修改數據時,索引也要隨之變動),但是可以大大提高查詢速度。因此應該在鍵列、或其他經常要查詢、排序、按範圍查找的列上建立索引,而對於在查詢中很少使用和參考的列、修改非常頻繁的列,值很少的列(例如性別只有男和女)等列上不應該創建索引。

Mysql會在主鍵、唯一鍵、外鍵列上自動創建索引,其他列需要建立索引的話,需要手動創建。

其中主鍵刪除,對應的索引也會刪除

刪除唯一鍵的方式是通過刪除對應的索引來實現的

刪除外鍵,外鍵列上的索引還在,如果需要刪除,需要單獨刪除索引

5.3 DDL(v2.0)

1、查看某個表的約束

SELECT * FROM information_schema.table_constraints WHERE table_name = '表名稱';
或
SHOW CREATE TABLE 表名;

2、查看某個表的索引

SHOW INDEX FROM 表名稱;

3、主鍵約束:primary key

主鍵分爲單列主鍵和複合主鍵:
在這裏插入圖片描述
主鍵的特點:(1)唯一併且非空(2)一個表只能有一個主鍵約束(3)主鍵約束名就叫做PRIMARY(4)創建主鍵會自動創建對應的索引,同樣刪除主鍵對應的索引也會刪除。

(1)如何在建表時指定主鍵約束

create table 【數據名.】表名(
	字段名1 數據類型  primary key ,
	....
);
或
create table 【數據名.】表名(
	字段名1 數據類型,
	....,
    primary key(字段名1)
);
或
create table 【數據名.】表名(
    字段名1 數據類型,
    字段名2 數據類型,
	....,
    primary key(複合主鍵字段列表)#如果是複合主鍵,那麼就需要在所有字段列表後面使用這種形式指定,不能在字段後面直接加primary key
);

(2)如何在建表後指定主鍵約束

alter table 表名稱 add primary key (主鍵字段列表);

(3)如何刪除主鍵約束

alter table 表名稱 drop primary key;

4、唯一鍵約束:unique key

(1)唯一鍵約束特點

同一個表可以有多個唯一約束。

唯一約束可以是某一個列的值唯一,也可以多個列組合值的唯一。

MySQL會給唯一約束的列上默認創建一個唯一索引。

刪除唯一鍵只能通過刪除對應索引的方式刪除,刪除時需要指定唯一鍵索引名

(2)如何在建表時指定唯一鍵約束

create table 【數據名.】表名(
	字段名1 數據類型  primary key ,
	字段名2 數據類型 unique key,
	....
);

create table 【數據名.】表名(
    字段名1 數據類型  primary key ,
    字段名2 數據類型,
    字段名3 數據類型,
	....,
    unique key(複合唯一字段列表)#如果是複合唯一鍵,那麼就需要在所有字段列表後面使用這種形式指定,不能在字段後面直接加unique key
);

(3)如何在建表後增加唯一鍵約束

alter table 表名稱 add 【constraint 約束名】 unique 【key】 (字段名列表);
#如果沒有指定約束名,(字段名列表)中只有一個字段的,默認是該字段名,如果是多個字段的默認是字段名列表的第1個字段名。也可以通過show index from 表名;來查看

(4)如何刪除唯一鍵約束

ALTER TABLE 表名稱 DROP INDEX 唯一性約束名;
#注意:如果忘記名稱,可以通過“show index from 表名稱;”查看

5、外鍵約束:foreign key

(1)外鍵特點

  • 外鍵約束是保證一個或兩個表之間的參照完整性,外鍵是構建於一個表的兩個字段或是兩個表的兩個字段之間的參照關係。

  • 在創建外鍵約束時,如果不給外鍵約束名稱,默認名不是列名,而是自動產生一個外鍵名(例如 student_ibfk_1;),也可以指定外鍵約束名。

  • 當創建外鍵約束時,系統默認會在所在的列上建立對應的普通索引。但是索引名是列名,不是外鍵的約束名。

  • 刪除外鍵時,關於外鍵列上的普通索引需要單獨刪除。

(2)要求

  • 在從表上建立外鍵,而且主表要先存在。

  • 一個表可以建立多個外鍵約束

  • 從表的外鍵列,在主表中引用的只能是鍵列(主鍵,唯一鍵,外鍵),推薦引用主表的主鍵。

  • 從表的外鍵列與主表被參照的列名字可以不相同,但是數據類型必須一樣

(3)約束關係:約束是針對雙方的

添加了外鍵約束後,主表的修改和刪除受約束

添加了外鍵約束後,從表的添加和修改受約束

(4)5個約束等級

  • Cascade方式:在父表上update/delete記錄時,同步update/delete掉子表的匹配記錄

  • Set null方式:在父表上update/delete記錄時,將子表上匹配記錄的列設爲null,但是要注意子表的外鍵列不能爲not null

  • No action方式:如果子表中有匹配的記錄,則不允許對父表對應候選鍵進行update/delete操作

  • Restrict方式:同no action, 都是立即檢查外鍵約束

  • Set default方式(在可視化工具SQLyog中可能顯示空白):父表有變更時,子表將外鍵列設置成一個默認的值,但Innodb不能識別

如果沒有指定等級,就相當於Restrict方式

(5)如何在建表時指定外鍵約束

create table 【數據名.】從表名(
	字段名1 數據類型  primary key ,
	字段名2 數據類型 【unique key】,
	....,
    【constraint 外鍵約束名】 foreign key (從表字段) references 主表名(主表字段) 【on update 外鍵約束等級】【on delete 外鍵約束等級【
    #外鍵只能在所有字段列表後面單獨指定
    #如果要自己命名外鍵約束名,建議 主表名_從表名_關聯字段名_fk
);

create table 【數據名.】表名(
    字段名1 數據類型,
    字段名2 數據類型,
	....,
    primary key(複合主鍵字段列表),#如果是複合主鍵,那麼就需要在所有字段列表後面使用這種形式指定,不能在字段後面直接加primary key
    unique key(複合唯一字段列表),#如果是複合唯一鍵,那麼就需要在所有字段列表後面使用這種形式指定,不能在字段後面直接加unique key
    foreign key (從表字段) references 主表名(主表字段) 【on update 外鍵約束等級】【on delete 外鍵約束等級【
    #外鍵只能在所有字段列表後面單獨指定
);

(6)如何在建表後指定外鍵約束

alter table表名稱 add 【constraint 外鍵約束名】 foreign key (從表字段名) references 主表名(主表被參照字段名) 【on update xx】[on delete xx];

(7)如何刪除外鍵約束

ALTER TABLE 表名稱 DROP FOREIGN KEY 外鍵約束名;
#查看約束名 SELECT * FROM information_schema.table_constraints WHERE table_name = '表名稱';
#刪除外鍵約束不會刪除對應的索引,如果需要刪除索引,需要用ALTER TABLE 表名稱 DROP INDEX 索引名;
#查看索引名 show index from 表名稱;

6、非空約束:not null

NOT NULL 非空約束,規定某個字段不能爲空

(1)如何在建表時給某個字段指定非空約束

create table 【數據名.】表名(
	字段名1 數據類型  primary key ,
	字段名2 數據類型 【unique key】 【not null】,
	....,
    foreign key (從表字段) references 主表名(主表字段) 【on update 外鍵約束等級】【on delete 外鍵約束等級【
    #外鍵只能在所有字段列表後面單獨指定
);

create table 【數據名.】表名(
    字段名1 數據類型 【not null】,
    字段名2 數據類型 【not null】,
	....,
    primary key(複合主鍵字段列表),#如果是複合主鍵,那麼就需要在所有字段列表後面使用這種形式指定,不能在字段後面直接加primary key
    unique key(複合唯一字段列表),#如果是複合唯一鍵,那麼就需要在所有字段列表後面使用這種形式指定,不能在字段後面直接加unique key
    foreign key (從表字段) references 主表名(主表字段) 【on update 外鍵約束等級】【on delete 外鍵約束等級【
    #外鍵只能在所有字段列表後面單獨指定
);

(2)如何在建表後指定某個字段非空

ALTER TABLE 表名稱 MODIFY 字段名 數據類型 NOT NULL 【default 默認值】;
#如果該字段原來設置了默認值約束,要跟着一起再寫一遍,否則默認值約束會丟失

(3)如何在建表後取消某個字段非空

ALTER TABLE 表名稱 MODIFY 字段名 數據類型 【default 默認值】;
#如果該字段原來設置了默認值約束,要跟着一起再寫一遍,否則默認值約束會丟失

7、默認值約束:default

(1)如何在建表時給某個字段指定默認約束

create table 【數據名.】表名(
	字段名1 數據類型  primary key ,
	字段名2 數據類型 【unique key】 【not null】 【default 默認值】,
	....,
    foreign key (從表字段) references 主表名(主表字段) 【on update 外鍵約束等級】【on delete 外鍵約束等級【
    #外鍵只能在所有字段列表後面單獨指定
);

create table 【數據名.】表名(
    字段名1 數據類型 【not null】 【default 默認值】,
    字段名2 數據類型 【not null】 【default 默認值】,
	....,
    primary key(複合主鍵字段列表),#如果是複合主鍵,那麼就需要在所有字段列表後面使用這種形式指定,不能在字段後面直接加primary key
    unique key(複合唯一字段列表),#如果是複合唯一鍵,那麼就需要在所有字段列表後面使用這種形式指定,不能在字段後面直接加unique key
    foreign key (從表字段) references 主表名(主表字段) 【on update 外鍵約束等級】【on delete 外鍵約束等級【
    #外鍵只能在所有字段列表後面單獨指定
);

(2)如何在建表後指定某個字段的默認值約束

ALTER TABLE 表名稱 MODIFY 字段名 數據類型  【default 默認值】 【NOT NULL】;
#如果該字段原來設置了非空約束,要跟着一起再寫一遍,否則非空約束會丟失

(3)如何在建表後取消某個字段的默認值約束

ALTER TABLE 表名稱 MODIFY 字段名 數據類型 【NOT NULL】;
#如果該字段原來設置了非空約束,要跟着一起再寫一遍,否則非空約束會丟失

8、檢查約束:check

檢查約束,mysql暫不支持

9、自增約束:auto_increment

(1)關於自增長auto_increment:

  • 一個表最多隻能有一個自增長列
  • 自增長列必須是鍵列(主鍵列,唯一鍵列,外鍵列),並且要求非空。
  • 自增列必須是整數類型
  • InnoDB表的自動增長列可以手動插入,但是插入的值如果是空或者0,則實際插入的將是自動增長後的值。

(2)如何在建表時指定自增長列

create table 【數據名.】表名(
	字段名1 數據類型  primary key auto_increment,
	字段名2 數據類型 【unique key】 【not null】 【default 默認值】,
	....
);

或
create table 【數據名.】表名(
	字段名1 數據類型  primary key ,
	字段名2 數據類型 【unique key  not null】 auto_increment,
	....
);

(3)如何在建表後指定自增長列

alter table 【數據名.】表名 modify 自增字段名 數據類型 auto_increment;

(4)如何刪除自增約束

alter table 【數據名.】表名 modify 自增字段名 數據類型;

5.4 DML(v2.0)

1、如果某列有自增約束,怎麼添加該字段的值

添加數據時,對於自增列

insert into 【數據庫名.]表名稱 values(值列表);#在值列表中,對應自增列可以賦值爲null和0

insert into 【數據庫名.]表名稱(部分字段列表) values(值列表);#自增列在(部分字段列表)中不寫就可以

2、如果某列有默認值約束,怎麼添加、修改該字段的值

添加數據時,對於有默認值列

insert into 【數據庫名.]表名稱 values(值列表);#在值列表中,對應默認值列,如果想用默認值,用default

insert into 【數據庫名.]表名稱(部分字段列表) values(值列表);#對應默認值列,如果想用默認值,在(部分字段列表)中不寫就可以

修改數據

update 【數據庫名.]表名稱 set 字段名1 = 值1, 字段名2 = 值2 。。。 【where 條件】; #對應默認值列,如果想用默認值,寫字段名 = default就可以

第六章 函數

兩種SQL函數
在這裏插入圖片描述

6.1單行函數

  • 只對一行進行變換,每行返回一個結果
  • 可以嵌套
  • 參數可以是一字段或一個表達式或一個值

6.1.1 字符串函數

函數 用法
CONCAT(S1,S2,…,Sn) 連接S1,S2,…,Sn爲一個字符串
CONCAT_WS(s, S1,S2,…,Sn) 同CONCAT(s1,s2,…)函數,但是每個字符串之間要加上s
CHAR_LENGTH(s) 返回字符串s的字符數
LENGTH(s) 返回字符串s的字節數,和字符集有關
INSERT(str, index , len, instr) 將字符串str從第index位置開始,len個字符長的子串替換爲字符串instr
UPPER(s) 或 UCASE(s) 將字符串s的所有字母轉成大寫字母
LOWER(s) 或LCASE(s) 將字符串s的所有字母轉成小寫字母
LEFT(s,n) 返回字符串s最左邊的n個字符
RIGHT(s,n) 返回字符串s最右邊的n個字符
LPAD(str, len, pad) 用字符串pad對str最左邊進行填充,直到str的長度爲len個字符
RPAD(str ,len, pad) 用字符串pad對str最右邊進行填充,直到str的長度爲len個字符
LTRIM(s) 去掉字符串s左側的空格
RTRIM(s) 去掉字符串s右側的空格
TRIM(s) 去掉字符串s開始與結尾的空格
TRIM(【BOTH 】s1 FROM s) 去掉字符串s開始與結尾的s1
TRIM(【LEADING】s1 FROM s) 去掉字符串s開始處的s1
TRIM(【TRAILING】s1 FROM s) 去掉字符串s結尾處的s1
REPEAT(str, n) 返回str重複n次的結果
REPLACE(str, a, b) 用字符串b替換字符串str中所有出現的字符串a
STRCMP(s1,s2) 比較字符串s1,s2
SUBSTRING(s,index,len) 返回從字符串s的index位置其len個字符
  • 舉例1:大小寫控制函數
函數 結果
LOWER(‘SQL Course’) sql course
UPPER(‘SQL Course’) SQL COURSE

這類函數改變字符的大小寫。

  • 舉例2:字符控制函數
函數 結果
CONCAT(‘Hello’,‘World’) HelloWorld
SUBSTR(‘HelloWorld’,1,5) Hello
LENGTH(‘HelloWorld’) 10
INSTR(‘HelloWorld’,‘W’) 6
LPAD(salary,10,’*’) *****24000
RPAD(salary,10, ‘*’) 24000*****
TRIM(‘H’ FROM ‘HelloWorld’) elloWorld
REPLACE(‘abcd’,‘b’,‘m’) amcd

6.1.2 數值函數/數學函數

函數 用法
ABS(x) 返回x的絕對值
CEIL(x) 返回大於x的最小整數值
FLOOR(x) 返回小於x的最大整數值
MOD(x,y) 返回x/y的模
RAND() 返回0~1的隨機值
ROUND(x,y) 返回參數x的四捨五入的有y位的小數的值
TRUNCATE(x,y) 返回數字x截斷爲y位小數的結果
SQRT(x) 返回x的平方根
POW(x,y) 返回x的y次方
  • 舉例1:ROUND:四捨五入
ROUND(45.926, 2)     -->  45.93
  • 舉例2:TRUNCATE:截斷
TRUNCATE(45.926)      --> 45
  • 舉例3:MOD:求餘
MOD(1600, 300)	 --> 100

6.1.3 日期函數

函數 用法
CURDATE() 或 CURRENT_DATE() 返回當前日期
CURTIME() 或 CURRENT_TIME() 返回當前時間
NOW() / SYSDATE() / CURRENT_TIMESTAMP() / LOCALTIME() / LOCALTIMESTAMP() 返回當前系統日期時間
YEAR(date) / MONTH(date) / DAY(date) / HOUR(time) / MINUTE(time) / SECOND(time) 返回具體的時間值
WEEK(date) / WEEKOFYEAR(date) 返回一年中的第幾周
DAYOFWEEK() 返回周幾,注意:週日是1,週一是2,。。。週六是7
WEEKDAY(date) 返回周幾,注意,周1是0,周2是1,。。。週日是6
DAYNAME(date) 返回星期:MONDAY,TUESDAY…SUNDAY
MONTHNAME(date) 返回月份:January,。。。。。
DATEDIFF(date1,date2) / TIMEDIFF(time1, time2) 返回date1 - date2的日期間隔 / 返回time1 - time2的時間間隔
DATE_ADD(datetime, INTERVAL expr type) 返回與給定日期時間相差INTERVAL時間段的日期時間
DATE_FORMAT(datetime ,fmt) 按照字符串fmt格式化日期datetime值
STR_TO_DATE(str, fmt) 按照字符串fmt對str進行解析,解析爲一個日期

其中:

(1)DATE_ADD(datetime,INTERVAL expr type)

表達式類型:

參數類型 參數類型
YEAR YEAR_MONTH
MONTH DAY_HOUR
DAY DAY_MINUTE
HOUR DAY_SECOND
MINUTE HOUR_MINUTE
SECOND HOUR_SECOND
MINUTE_SECOND

舉例:

SELECT DATE_ADD(NOW(), INTERVAL 1 YEAR);
SELECT DATE_ADD(NOW(), INTERVAL -1 YEAR);   #可以是負數
SELECT DATE_ADD(NOW(), INTERVAL '1_1' YEAR_MONTH);   #需要單引號

(2)DATE_FORMAT(datetime,fmt) 和 STR_TO_DATE(str, fmt)

格式符 說明 格式符 說明
%Y 4位數字表示年份 %y 表示兩位數字表示年份
%M 月名錶示月份(January,…) %m 兩位數字表示月份(01,02,03。。。)
%b 縮寫的月名(Jan.,Feb.,…) %c 數字表示月份(1,2,3,…)
%D 英文後綴表示月中的天數(1st,2nd,3rd,…) %d 兩位數字表示月中的天數(01,02…)
%e 數字形式表示月中的天數(1,2,3,4,5…)
%H 兩位數字表示小數,24小時制(01,02…) %h和%I 兩位數字表示小時,12小時制(01,02…)
%k 數字形式的小時,24小時制(1,2,3) %l 數字形式表示小時,12小時制(1,2,3,4…)
%i 兩位數字表示分鐘(00,01,02) %S和%s 兩位數字表示秒(00,01,02…)
%W 一週中的星期名稱(Sunday…) %a 一週中的星期縮寫(Sun.,Mon.,Tues.,…)
%w 以數字表示週中的天數(0=Sunday,1=Monday…)
%j 以3位數字表示年中的天數(001,002…) %U 以數字表示年中的第幾周,(1,2,3。。)其中Sunday爲週中第一天
%u 以數字表示年中的第幾周,(1,2,3。。)其中Monday爲週中第一天
%T 24小時制 %r 12小時制
%p AM或PM %% 表示%

6.1.4 流程函數

函數 用法
IF(value,t ,f) 如果value是真,返回t,否則返回f
IFNULL(value1, value2) 如果value1不爲空,返回value1,否則返回value2
CASE WHEN 條件1 THEN result1 WHEN 條件2 THEN result2 … [ELSE resultn] END 相當於Java的if…else if…else…
CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值1 THEN 值1 … [ELSE 值n] END 相當於Java的switch…case…
  • 舉例1:
SELECT employee_id,12 * salary * (1 + IFNULL(commission_pct,0)) as "年薪"
FROM employees;
  • 舉例2:
SELECT last_name, job_id, salary,
       CASE job_id WHEN 'IT_PROG'  THEN  1.10*salary
                   WHEN 'ST_CLERK' THEN  1.15*salary
                   WHEN 'SA_REP'   THEN  1.20*salary
       ELSE      salary END     "實發工資"
FROM   employees;
  • 舉例3:
SELECT employee_id,salary, CASE WHEN salary>=15000 THEN '高薪' 
				  WHEN salary>=10000 THEN '潛力股'  
				  WHEN salary>=8000 THEN '屌絲' 
				  ELSE '草根' END  "描述"
FROM employees; 

6.1.5 其他函數

函數 用法
database() 返回當前數據庫名
version() 返回當前數據庫版本
user() 返回當前登錄用戶名
password(str) 返回字符串str的加密版本,41位長的字符串
md5(str) 返回字符串str的md5值,也是一種加密方式

6.2 分組函數

  • 什麼是分組函數

分組函數作用於一組數據,並對一組數據返回一個值。
在這裏插入圖片描述

  • 組函數類型
    • AVG()
    • SUM()
    • MAX()
    • MIN()
    • **COUNT() **

可以對數值型數據使用AVG 和 SUM 函數。

SELECT AVG(salary), MAX(salary),MIN(salary), SUM(salary)
FROM   employees
WHERE  job_id LIKE '%REP%';

可以對任意數據類型的數據使用 MIN 和 MAX 函數。

SELECT MIN(hire_date), MAX(hire_date)
FROM	  employees;

COUNT(*)count(1返回表中記錄總數,適用於任意數據類型

SELECT COUNT(*)
FROM	  employees
WHERE  department_id = 50;

•COUNT(expr) 返回expr不爲空的記錄總數。

SELECT COUNT(commission_pct)
FROM   employees
WHERE  department_id = 50;
  • 問題:用count(*),count(1)誰好呢?

    其實,對於myisam引擎的表是沒有區別的。這種引擎內部有一計數器在維護着行數。

    Innodb引擎的表用count(*)直接讀行數,效率很低,因爲innodb真的要去數一遍。

在這裏插入圖片描述
(1)A∩B

(2)A

(3)A - A∩B

(4)B

(5)B - A∩B

(6)A ∪ B

(7)A ∪B- A∩B 或者 (A - A∩B) ∪ (B - A∩B)

如何實現?

(1)內連接

(2)外連接:左外連接、右外連接、全外連接(mysql使用union代替全外連接)

1、內連接:實現A∩B

select 字段列表
from A表 inner join B表
on 關聯條件
where 等其他子句;

或

select 字段列表
from A表 , B表
where 關聯條件 and 等其他子句;

代碼示例:

#查詢員工的姓名和他所在的部門的名稱
#員工的姓名在t_employee
#部門的名稱在t_department
SELECT ename "員工的姓名",dname "部門名稱"
FROM t_employee INNER JOIN t_department
ON t_employee.did = t_department.did

SELECT ename "員工的姓名",dname "部門名稱"
FROM t_employee , t_department
WHERE t_employee.did = t_department.did


#查詢薪資高於20000的男員工的姓名和他所在的部門的名稱
SELECT ename "員工的姓名",dname "部門名稱"
FROM t_employee INNER JOIN t_department
ON t_employee.did = t_department.did
WHERE salary>20000 AND gender = '男'

2、左外連接

#實現查詢結果是A
select 字段列表
from A表 left join B表
on 關聯條件
where 等其他子句;

#實現A -  A∩B
select 字段列表
from A表 left join B表
on 關聯條件
where 從表關聯字段 is null and 等其他子句;

代碼示例:

#查詢所有員工的姓名和他所在的部門的名稱
SELECT ename "員工的姓名",dname "部門名稱"
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did


#查詢所有沒有部門的員工
SELECT ename "員工的姓名",dname "部門名稱"
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL

3、右外連接

#實現查詢結果是B
select 字段列表
from A表 right join B表
on 關聯條件
where 等其他子句;

#實現B -  A∩B
select 字段列表
from A表 right join B表
on 關聯條件
where 從表關聯字段 is null and 等其他子句;

代碼示例:

#查詢所有部門,以及所有部門下的員工信息
SELECT * 
FROM t_employee RIGHT JOIN t_department
ON t_employee.did = t_department.did

#查詢那些沒有員工屬於它的部門
SELECT * 
FROM t_employee RIGHT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL

4、用union代替全外連接

#實現查詢結果是A∪B
#用左外的A,union 右外的B
select 字段列表
from A表 left join B表
on 關聯條件
where 等其他子句

union 

select 字段列表
from A表 right join B表
on 關聯條件
where 等其他子句;



#實現A∪B -  A∩B  或   (A -  A∩B) ∪ (B - A∩B)
#使用左外的 (A -  A∩B)  union 右外的(B - A∩B)
select 字段列表
from A表 left join B表
on 關聯條件
where 從表關聯字段 is null and 等其他子句

union

select 字段列表
from A表 right join B表
on 關聯條件
where 從表關聯字段 is null and 等其他子句

代碼示例:

#查詢所有員工,所有部門,包括沒有員工的部門,和沒有部門的員工
SELECT *
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did

UNION

SELECT *
FROM t_employee RIGHT JOIN t_department
ON t_employee.did = t_department.did


#查詢那些沒有部門的員工和所有沒有員工的部門

#沒有部門的員工
SELECT *
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL

UNION 

#所有沒有員工的部門
SELECT *
FROM t_employee RIGHT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL

5、自連接

兩個關聯查詢的表是同一張表,通過取別名的方式來虛擬成兩張表

select 字段列表
from 表名 別名1 inner/left/right join 表名 別名2
on 別名1.關聯字段 = 別名2的關聯字段
where 其他條件

代碼示例:

#查詢員工的編號,姓名,薪資和他領導的編號,姓名,薪資
#這些數據全部在員工表中
#把t_employee表,即當做員工表,又當做領導表
#領導表是虛擬的概念,我們可以通過取別名的方式虛擬
SELECT emp.eid "員工的編號",emp.ename "員工的姓名" ,emp.salary "員工的薪資",
	mgr.eid "領導的編號" ,mgr.ename "領導的姓名",mgr.salary "領導的薪資"
FROM t_employee emp INNER JOIN t_employee mgr
#t_employee emp:如果用emp.,表示的是員工表的
#t_employee mgr:如果用mgr.,表示的是領導表的
ON emp.mid = mgr.eid

#表的別名不要加"",給列取別名,可以用"",列的別名不使用""也可以,但是要避免包含空格等特殊符號。

第八章 select語句的6大子句

8.1 6大子句順序

(1)from:從哪些表中篩選

(2)where:從表中篩選的條件

(3)group by:分組依據

(4)having:在統計結果中再次篩選

(5)order by:排序

(6)limit:分頁

order by:

降序:desc

升序:用麼默認,要麼加asc

limit:

limit m,n

m = (第幾頁 - 1)*每頁的數量

n = 每頁的數量

代碼示例:

#查詢每個部門的男生的人數,並且顯示人數超過5人的,按照人數降序排列,
#每頁只能顯示10條,我要第2頁
SELECT did,COUNT(*) "人數"
FROM t_employee
WHERE gender = '男'
GROUP BY did
HAVING COUNT(*)>5
ORDER BY 人數 DESC
LIMIT 10,10

8.2 group by與分組函數

在這裏插入圖片描述
可以使用GROUP BY子句將表中的數據分成若干組

SELECT column, group_function(column)
FROM table
[WHERE	condition]
[GROUP BY	group_by_expression];

明確:WHERE一定放在FROM後面GROUP BY 前面

在SELECT列表中所有未包含在分組函數中的列都應該包含在 GROUP BY子句中

SELECT   department_id, AVG(salary)
FROM     employees
GROUP BY department_id ;

包含在 GROUP BY 子句中的列不必包含在SELECT 列表中

SELECT   AVG(salary)
FROM     employees
GROUP BY department_id ;

使用多個列分組
在這裏插入圖片描述

SELECT   department_id dept_id, job_id, SUM(salary)
FROM     employees
GROUP BY department_id, job_id ;

8.3 having與分組函數

在這裏插入圖片描述

SELECT   department_id, MAX(salary)
FROM     employees
GROUP BY department_id
HAVING   MAX(salary)>8000 ;

having與where的區別?

(1)where是從表中篩選的條件,而having是統計結果中再次篩選

(2)where後面不能加“分組/聚合函數”,而having後面可以跟分組函數

#統計部門平均工資高於8000的部門和平均工資
SELECT   department_id, AVG(salary)
FROM     employees
WHERE    AVG(salary) > 8000 #錯誤
GROUP BY department_id;

在這裏插入圖片描述

#統計部門平均工資高於8000的部門和平均工資
SELECT   department_id, AVG(salary)
FROM     employees
GROUP BY department_id
HAVING   AVG(salary)>8000 ;

order by:

降序:desc

升序:用麼默認,要麼加asc

limit:

limit m,n

m = (第幾頁 - 1)*每頁的數量

n = 每頁的數量

代碼示例:

#查詢每個部門的男生的人數,並且顯示人數超過5人的,按照人數降序排列,
#每頁只能顯示10條,我要第2頁
SELECT did,COUNT(*) "人數"
FROM t_employee
WHERE gender = '男'
GROUP BY did
HAVING COUNT(*)>5
ORDER BY 人數 DESC
LIMIT 10,10

第九章 子查詢

嵌套在另一個查詢中的查詢,根據位置不同,分爲:

(1)where型

①子查詢是單值結果,那麼可以對其使用(=,>等比較運算符)

②子查詢是多值結果,那麼可對其使用(【not】in(子查詢結果),或 >all(子查詢結果),或>=all(子查詢結果),<all(子查詢結果),<=all(子查詢結果),或 >any(子查詢結果),或>=any(子查詢結果),<any(子查詢結果),<=any(子查詢結果))

(2)from型

必須給子查詢取別名

(3)exists型

注意:不管子查詢在哪裏,子查詢必須使用()括起來

示例代碼:

查詢全公司最高工資的員工信息
select * from 員工表 where 薪資 = (select max(薪資) from 員工表);

select * from 員工表 where 薪資 > all(select salary from 員工表  where 員工姓名 in(...));

查詢每個部門的編號,名稱,平均工資
select 部門編號, 部門名稱, 平均工資
from 部門表 inner join (select 部門編號,avg(薪資) from 員工表  group by 部門編號) temp
on 部門表.部門編號 = temp.部門編號

查詢那些有員工的部門
select 部門編號, 部門名稱 from 部門表
where exists (select * from 員工表  where 部門表.部門編號 = 員工表.部門編號);

第十章 事務

1、事務處理(事務操作):保證所有事務都作爲一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。當在一個事務中執行多個操作時,要麼所有的事務都被提交(commit),那麼這些修改就永久地保存下來;要麼數據庫管理系統將放棄所作的所有修改,整個事務回滾(rollback)到最初狀態。

2、事務的ACID屬性:

(1)原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。

(2)一致性(Consistency)
事務必須使數據庫從一個一致性狀態變換到另外一個一致性狀態。

(3)隔離性(Isolation)
事務的隔離性是指一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的數據對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。

(4)持久性(Durability)
持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來的其他操作和數據庫故障不應該對其有任何影響

3、mysql開始事務和結束事務

mysql默認是自動提交,執行一句就提交一句。

我想要手動提交事務:

(1)set autocommit=false;

接下來所有語句都必須手動提交,否則就不會永久生效

(2)start transaction;

commit; 或 rollback; 或發生異常;

4、數據庫的隔離級別

  • 對於同時運行的多個事務, 當這些事務訪問數據庫中相同的數據時, 如果沒有采取必要的隔離機制, 就會導致各種併發問題:
    • 髒讀: 對於兩個事務 T1, T2, T1 讀取了已經被 T2 更新但還沒有被提交的字段。 之後, 若 T2 回滾, T1讀取的內容就是臨時且無效的。
    • 不可重複讀: 對於兩個事務T1, T2, T1 讀取了一個字段, 然後 T2 更新了該字段。 之後, T1再次讀取同一個字段, 值就不同了。
    • 幻讀: 對於兩個事務T1, T2, T1 從一個表中讀取了一個字段, 然後 T2 在該表中插入了一些新的行。 之後, 如果 T1 再次讀取同一個表, 就會多出幾行。
  • 數據庫事務的隔離性:數據庫系統必須具有隔離併發運行各個事務的能力, 使它們不會相互影響, 避免各種併發問題。
  • **一個事務與其他事務隔離的程度稱爲隔離級別。**數據庫規定了多種事務隔離級別, 不同隔離級別對應不同的干擾程度, 隔離級別越高, 數據一致性就越好, 但併發性越弱。
  • 數據庫提供的 4 種事務隔離級別:

在這裏插入圖片描述

  • Oracle 支持的 2 種事務隔離級別:READ COMMITED, SERIALIZABLE。 Oracle 默認的事務隔離級別爲: READ COMMITED 。

  • Mysql 支持 4 種事務隔離級別。 Mysql 默認的事務隔離級別爲: REPEATABLE READ。在mysql中REPEATABLE READ的隔離級別也可以避免幻讀了。

  • 在MySql中設置隔離級別

    • 每啓動一個 mysql 程序, 就會獲得一個單獨的數據庫連接。每個數據庫連接都有一個全局變量 @@tx_isolation, 表示當前的事務隔離級別.
    • 查看當前的隔離級別: SELECT @@tx_isolation;
    • 查看全局的隔離級別: SELECT @@global.tx_isolation;
    • 設置當前 mySQL 連接的隔離級別:
    set tx_isolation ='repeatable-read';
    
    • 設置數據庫系統的全局的隔離級別:
    set global tx_isolation ='read-committed';
    

    注意:這裏的隔離級別中間是減號,不是下劃線。

第十一章 用戶與權限

1、身份認證:

(1)IP+用戶名作爲身份驗證

​ 例如:root@localhost:只允許在本機使用root用戶登錄

​ root@%:運行在任意機器上使用root用戶登錄

[email protected]:只運行在192.168.11.56主機上使用root用戶登錄

​ chailinyan@%:運行在任意機器上使用chailinyan用戶登錄

建立用戶時,用於身份驗證的IP地址,是連接你的服務的客戶端的IP地址

例如:[email protected],表示客戶端在192.168.11.56的機器上可以訪問你的mysql服務

而這個客戶端,要連接你的服務時,-h後面的主機的IP地址是,服務器所在的機器的IP地址。

例如:mysql服務在192.168.11.11機器上, 客戶端在192.168.11.56上,那麼客戶端可以用[email protected]或root@%,連接時填寫-h192.168.11.11 -u root

(2)密碼

2、給每個用戶權限,4個權限級別:

(1)全局

(2)數據庫

(3)表

(4)字段

依次校驗權限,如果前面通過了,後面就不校驗了:

全局 > 數據庫 > 表 > 字段

注意:root@localhost,這個用戶始終保留所有的全局權限。

3、查看賬戶權限:

show grants for user@host;

4、SQLyog新建用戶
在這裏插入圖片描述
在這裏插入圖片描述
5、設置權限
在這裏插入圖片描述

第十二章 經典問題

1、命令行操作sql亂碼問題

mysql> INSERT INTO t_stu VALUES(1,'張三','男');
ERROR 1366 (HY000): Incorrect string value: '\xD5\xC5\xC8\xFD' for column 'sname' at row 1

原因:安裝數據庫時選擇utf8,服務器端認爲你的客戶端的字符集是utf-8,而實際上你的客戶端的字符集是GBK。
在這裏插入圖片描述
查看所有字符集:SHOW VARIABLES LIKE ‘character_set_%’;
在這裏插入圖片描述
解決方案,設置當前連接的客戶端字符集 “SET NAMES GBK;”

set names gbk;是爲了告訴服務器,客戶端用的GBK編碼,防止亂碼。
在這裏插入圖片描述
有的時候,這樣還不能解決,例如,某些win10操作系統環境下,那麼修改命令行的屬性-》選項-》勾選使用舊版控制檯,然後重啓電腦
在這裏插入圖片描述

2、忘記root用戶密碼問題

1:通過任務管理器或者服務管理,關掉mysqld(服務進程)

2:通過命令行+特殊參數開啓mysqld

mysqld --skip-grant-tables

3:此時,mysqld服務進程已經打開,並且,不需要權限檢查.

4:mysql -uroot 無密碼登陸服務器.

5: 修改權限表

(1) use mysql;

(2) update user set Password = password(‘123456’) where User = ‘root’;

(3)flush privileges;

6:通過任務管理器,關掉mysqld服務進程.

7:再次通過服務管理,打mysql服務。

8:即可用修改後的新密碼登陸.

3、查看字符集和校對規則

關於SQL的關鍵字和函數名等不區分大小寫,但是對於數據值是否區分大小寫,和字符集與校對規則有關。

_ci(大小寫不敏感),_cs(大小寫敏感),_bin(二元,即比較是基於字符編碼的值而與language無關)

(1)查看所有字符集和校對規則
在這裏插入圖片描述
(2)查看GBK和UTF-8字符集的校對規則

show collation like ‘gbk%’;
在這裏插入圖片描述
show collation like ‘utf8%’;
在這裏插入圖片描述
utf8_unicode_ci和utf8_general_ci對中、英文來說沒有實質的差別。
utf8_general_ci 校對速度快,但準確度稍差。
utf8_unicode_ci 準確度高,但校對速度稍慢。

如果你的應用有德語、法語或者俄語,請一定使用utf8_unicode_ci。一般用utf8_general_ci就夠了。

(3)查看服務器的字符集和校對規則
在這裏插入圖片描述
(4)查看和修改某個數據庫的字符集和校對規則
在這裏插入圖片描述

在這裏插入圖片描述
修改數據庫的字符集和校對規則:

ALTER DATABASE 數據庫名稱 DEFAULT CHARACTER SET 字符集名稱 【COLLATE 校對規則名稱】;

例如:

ALTER DATABASE ceshi_db DEFAULT CHARACTER SET utf8 collate utf8_general_ci;
在這裏插入圖片描述
注意:修改了數據庫的默認字符集和校對規則後,原來已經創建的表格的字符集和校對規則並不會改變,如果需要,那麼需要單獨修改。

(5)查看某個表格的字符集和校對規則

查看字符集:show create table users;
在這裏插入圖片描述
如果要查看校對規則:show table status from bookstore like ‘%users%’ ;
在這裏插入圖片描述
修改某個表格的字符集和校對規則:

修改表的默認字符集:

ALTER TABLE 表名稱 DEFAULT CHARACTER SET 字符集名稱 【COLLATE 校對規則名稱】;

把表默認的字符集和所有字符列(CHAR,VARCHAR,TEXT)改爲新的字符集:

ALTER TABLE 表名稱 CONVERT TO CHARACTER SET 字符集名稱 【COLLATE 校對規則名稱】;

例如:ALTER TABLE ceshi_table DEFAULT CHARACTER SET gbk collate gbk_chinese_ci;

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