40 - 數據庫基礎

1 數據庫概述

        數據庫指的是按照數據結構來組織、存儲、管理數據的倉庫,經常使用的數據庫種類爲關係型數據庫和非關係型數據庫。關係型數據庫模型是把複雜的數據歸結爲簡單的二元關係(即二維表格形式——)。
        在關係數據庫中,對數據的操做幾乎所有創建在一個或多個關係表格上,經過對這些關聯的表格分類、合併、鏈接或選取等運算實現數據的管理。
常見的數據庫有MySQLpython

1.1 關係數據庫之ACID理論

        ACID,指數據庫事務正確執行的四個基本要素的縮寫。包含:原子性(Atomicity)一致性(Consistency)隔離性(Isolation)持久性(Durability)。一個支持事務(Transaction)的數據庫,必需要具備這四種特性,不然在事務過程(Transaction processing)當中沒法保證數據的正確性,交易過程很可能達不到交易方的要求。MySQL的Innode支持事務,因此它遵照ACID原則。mysql

特性 描述
原子性(atomicity) 一個事務是一個不可分割的工做單位,事務中包括的全部操做要麼所有作完,要麼什麼都不作
一致性(consistency) 事務必須是使數據庫從一個一致性狀態變到另外一個一致性狀態。一致性與原子性是密切相關的
隔離性(isolation) 一個事務的執行不能被其餘事務干擾。即一個事務內部的操做及使用的數據對併發的其餘事務是隔離的,併發執行的各個事務之間不能互相干擾
持久性(durability) 持久性也稱永久性(permanence),指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其餘操做或故障不該該對其有任何影響

1.2 關係數據庫之概念

在關係數據庫中,關係就是二維表,由行和列組成。sql

  • 行row,也稱爲記錄Record、元組。
  • 列Column,也稱爲字段Filed、屬性。
  • 域Domain,叫作字段的取值範圍 。例如gender字段的取值就是M或者F兩個值。

其餘概念性的東西:數據庫

  • 維數:關係的維數指關係中屬性的個數
  • 基數:元組的個數

注意在關係中,屬性的順序並不重要。理論上,元組順序也不重要,可是因爲元組順序與存儲相關,會影響查詢效率。centos

1.2.1 候選鍵

關係中,能惟一標識一條元組(記錄)的屬性或屬性集合,成爲候選鍵能夠是多個字段的組合。
houxuan安全

1.2.2 主鍵

表示一列或者多列組成惟一的key,也就是經過這一個或者多個列能惟一的標識一條記錄。即被選擇的候選鍵。bash

  • 主鍵的列不能包含空值null。主鍵每每設置爲整型、長整型,且自增AUTO_INCREMENT。
  • 表中能夠沒有主鍵,可是通常表設計中,每每都會有主鍵,以避免記錄重複
  • 功能主要在於查數據、定位數據

zhujian

1.2.3 外鍵

嚴格來講,當一個關係中的某個屬性或屬性的集合與另外一個關係(也能夠是自身)的候選鍵匹配時,就稱做這個屬性或屬性集合的外鍵。服務器

  • 簡單來講,就是A表的某個字段數據來源於B表的主鍵(候選鍵)。
  • 外鍵約束,和外鍵不約束。 約束時,字段數據必須來源於關聯表的主鍵(候選鍵)數據結構

    雖然能夠關聯本身,可是並不經常使用

waijian

員工表的FK_depet_no字段就是員工表的外鍵。

1.2.4 約束Constraint

爲了保證數據的完整正確,數據模型還必須有完整性約束。必須有值約束,某些列的值必須有值,不準爲空null。

  • 域約束Domain Constraint:限定了表中字段的取值範圍 -- (通常在代碼中判斷)
  • 實體完整性Entity Integrity:PRIMARY KEY約束定義了主鍵,就定義了主鍵約束。主鍵不重複且惟一,不能爲空。
  • 引用完整性Referential Integrity:外鍵定義中,能夠不是引用另外一張表的主鍵(能夠是任意字段),但每每實際只會關注引用主鍵。
    • 插入規則:若是在表B插入一條記錄,B的外鍵列的數據,必須是表A中存在的主鍵值。(自動生效,不須要指定)
    • 更新規則:定義外鍵約束時指定該規則。
    • 刪除規則:定義外鍵約束時指定該規則。

更新規則和刪除規則,可選項以下:

  • CASCADE:級聯刪除,刪除被關聯數據時,從表關聯的數據所有刪除。
  • SET NULL:從父表刪除或更新行,會設置子表中的外鍵列爲NULL,但必須保證子表沒有指定 NOT NULL,也就是說子表的字段能夠爲NULL才行。
  • RESTRICT:若是從父表刪除主鍵,若是子表引用了,則拒絕對父表的刪除或更新操做。(保護數據)
  • NO ACTION:表中SQL的關鍵字,在MySQL中與RESTRICT相同。拒絕對父表的刪除或更新操做。

外鍵約束,是爲了保證數據完整性、一致性、杜絕數據冗餘、數據錯誤。

建議先使用,等到鏈接的很是深刻時,再使用代碼邏輯來解決外鍵約束關係。

1.2.5 索引

能夠看做是一本字典的目錄,爲了快速檢索用的。空間換時間,顯著提升查詢效率。能夠對一列或者多列字段設定索引。(B+樹)

  • 主鍵索引(PRIMARY):主鍵會自動創建主鍵索引,主鍵自己就是爲了快速定位惟一記錄。
  • 惟一索引(UNIQUE):表中的索引列組成的索引必須惟一,但能夠爲空,非控制必須惟一。
  • 普通索引(KEY):沒有惟一性的要求,就是建了一個字典的目錄而已。

1.3 實體聯繫

首先來看一下實體和聯繫:

  • 實體Entity:現實世界中具備相同屬性的一組對象,能夠是物理存在的事物或抽象的事物。
  • 聯繫Relationship:實體之間的關聯集合。

總結一下:

  • 實體在數據庫中就是一個一個表
  • 聯繫在數據庫中就是記錄與記錄的對應關係

在關係型數據庫中實體主要有如下三種聯繫:

類型 描述 解決方法
一對多聯繫
1:n
一個員工屬於一個部門,一個部門有多個員工 員工外鍵
部門主鍵
多對多聯繫
m:n
一個員工屬於多個部門,一個部門有多個員工 創建第三表
一對一聯繫
1:1
假設有實體管理者,一個管理者管理一個部門,一個部門只有一個管理者 字段建在哪張表都行

一對一不多用。

1.4 視圖

視圖、也稱虛表、開起來很像表。它是由查詢語句生成的。能夠經過視圖進行CRUD操做。
做用:

  1. 簡化操做,將複雜查詢SQL語句定義爲視圖,能夠簡化查詢。
  2. 數據安全,視圖能夠只顯示真實表的部分列,或計算後的記過,從而隱藏真實表的數據

2 SQL

        Structured Query Language,是一種對關係數據庫中的數據進行定義和操做的語言方法,是大多數關係數據庫管理系統所支持的工業標準。

2.1 分類

  • 數據查詢語言(DQL):data query language,也成爲數據檢索語句,做用是從表格中獲取數據,肯定數據怎麼樣在應用程序給出。關鍵字select是SQL用的最多的動詞,其餘DQL經常使用的保留字段有where、order by、group by和having
  • 數據操做語言(DML):data manipulation language,其中包括動詞insert、update和delete,他們用於添加、修改、刪除表中的行,也稱動做查詢語句。
  • 數據處理語言(TPL):它的語句能確保被DML語句影響的表的全部行及時得以更新。TPL語句包括,begin、transaction、commit和rollback
  • 數據控制語言(DCL):data control languag,它的語句經過grant或revoke 得到許可,肯定 單個用戶和用戶組對數據庫對象的訪問。某些RDBMS可用GRANT或revoke控制對單個列的訪問。
  • 指針控制語言(CCL):它的語句,像 declare cursor、fetch into、update where current用於對一個或多個表單獨執行的操做
  • 數據定義語言(DDL):data definition language,其語句包括create和drop、alter。在數據庫中建立新表或刪除表(create table 或者 drop table),爲表加入索引等。是動做查詢的一部分

咱們平常開發會用到的SQL語言類型爲:DML、DQL以及DDL

RDBMS的數據庫、表的概念其實就至關於目錄,文件,及內容

2.2 規範

編寫SQL語句時,咱們要遵頊以下規範:

  1. SQL語句大小寫不敏感(通常建議,SQL的關鍵字、函數等大寫)
  2. SQL語句末尾應該使用分號結束
  3. 註釋
    • 多行註釋 /*註釋內容*/
    • 單行註釋 --註釋內容
    • MySQL 註釋可使用 #
  4. 使用空格或縮進來提升可讀性
  5. 命名規範
    • 必須以字母開頭
    • 可使用數字、#、$和_
    • 不可以使用關鍵字

3 MySQL

MySQL是Web世界中使用最普遍的數據庫服務器,訪問及管理mysql數據庫的最經常使用標準化語言爲SQL結構化查詢語句。早先的MySQL使用的是MyISAM引擎,它是一種利用索引順序存取數據的軟件。從MySQL 4.0版本開始支持InnoDB引擎。

  • MyISAM,不支持事物,插入、查詢速度快
  • InnoDB:支持事務,行級鎖,MySQL 5.5起的默認引擎

3.1 安裝MySQL

這裏僅列出在Linux下的安裝:

  • 經過yum進行安裝
一、安裝MySQL
yum install -y mysql-server (centos 7如下)
yum install -y mariadb-server (centos 7及以上)

二、啓動服務
/etc/init.d/mysqld start (centos 7如下)
systemctl start maridab (centos 7及以上)

三、關閉服務
/etc/init.d/mysqld stop (centos 7如下)
systemctl stop maridab (centos 7及以上)
  • 編譯安裝
1.安裝依賴包
yum install -y ncurses-devel libaio-devel
rpm -qa ncurses-devel libaio-devel

2.安裝cmake編譯工具
yum install -y cmake

3.上傳源碼包
rz -y mysql-5.5.49.tar.gz

4.解壓並安裝
tar xf mysql-5.5.49.tar.gz
cd mysql-5.5.49
 
cmake . -DCMAKE_INSTALL_PREFIX=/application/mysql-5.5.49 \
-DMYSQL_DATADIR=/application/mysql-5.5.49/data \
-DMYSQL_UNIX_ADDR=/application/mysql-5.5.49/tmp/mysql.sock \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DEXTRA_CHARSETS=gbk,gb2312,utf8,ascii \
-DENABLED_LOCAL_INFILE=ON \
-DWITH_INNOBASE_STORAGE_ENAINE=1 \
-DWITH_FEDERATED_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITHOUT_EXAMPLE_STORAGE_ENGINE=1 \
-DWITHOUT_PARTITION_STORAGE_ENGINE=1 \
-DWITH_FAST_MUTEXES=1 \
-DWITH_ZLIB=bundled \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_EMBEDDED_SERVER=1 \
-DWITH_DEBUG=0
 
make && make install && cd ..
5.建立連接文件
ln -s /application/mysql-5.5.49/ /application/mysql

6.建立數據庫用戶及配置文件
useradd -M -s /sbin/nologin mysql

7.初始化數據庫
/application/mysql/scripts/mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data

8.定義環境變量
cp /application/mysql/bin/* /usr/local/sbin
或者
PATH=/application/mysql/bin:$PATH

9.開啓數據庫
/application/mysql/bin/mysql start

10.登陸數據庫
mysql
若是設置了用戶密碼
mysql -uroot -p123456

11.關閉數據庫
/application/mysql/bin/mysql stop

12.設置密碼
mysqladmin password 123456 -S /data/3306/mysql.sock

3.2 數據類型

MySQL的數據類型:

類型 含義
tinyint 1字節,帶符號的範圍是-128到127。無符號的範圍是0到255。bool或boolean,就是tinyint,0表示假,非0表示真
smallint 2字節,帶符號的範圍是-32768到32767。無符號的範圍是0到65535
int 整型,4字節,同Integer,帶符號的範圍是-2147483648到2147483647。無符號的範圍是0到4294967295
bigint 長整型,8字節,帶符號的範圍是-9223372036854775808到9223372036854775807。無符號的範圍是0到18446744073709551615
float 單精度浮點數精確到大約7位小數位
double 雙精度浮點數精確到大約15位小數位
DATE 日期。支持的範圍爲'1000-01-01'到'9999-12-31'
DATETIME 支持的範圍是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'
TIMESTAMP 時間戳。範圍是'1970-01-01 00:00:00'到2037年
char(M) 固定長度,右邊填充空格以達到長度要求。M爲長度,範圍爲0~255。M指的是字符個數
varchar(M) 變長字符串。M 表示最大列長度。M的範圍是0到65,535。但不能突破行最大字節數65535
text 大文本。最大長度爲65535(2^16-1)個字符
BLOB 大字節。最大長度爲65535(2^16–1)字節的BLOB列

BLOG:字節類型,存圖片,存二進制文件,能不用則不用,只會用一個字符串來存圖片的位置

3.4 用戶及受權操做

受權用戶:grant語句,取消權限:revoke語句

grant all on *.* to 'dahl'@'10.0.0.13' identified by '123456';
revoke all on *.* from dahl;
  • all:表示全部權限
  • *.*:表示全部庫的全部表
  • 'dah'@'10.0.0.13':表示用戶名,和登錄的IP地址,%爲通配符,能夠表示任意地址

刪除用戶:

drop user dahl;

3.5 庫操做

數據庫在文件系統上就是用目錄體現的,因此對庫的操做,能夠理解爲對目錄的操做。建立數據庫,會在MySQL的data目錄下建立同名文件夾

3.5.1 建立數據庫

語法格式:create database 數據庫名稱

create database db_name;
create database db_name default charset utf8;
create database if not exists db_name character set utf8;
create database if not exists db_name character set utf8mb4 collater utf8mb4_general_ci;
  • character set:指定字符集。
  • utf8mb4:是utf8的擴展,支持4字節utf8mb4,須要mysql5.5.3+
  • collate:指定字符串的校隊規則,用來作字符串的比較的。例如a、A誰大

3.5.2 刪除數據庫

語法格式:drop database 數據庫名稱

drop database db_name;

刪除數據庫目錄,注意會刪除庫下的全部表文件

3.5.3 其餘操做

查看數據庫中存在的數據庫

show databases;

使用(切換)當前使用的數據庫(激活show tables語句)

use db_name;

查看建立庫的信息

show create database test;

3.6 表操做

表在文件系統上是用文件體現的,因此對錶的操做,能夠理解爲對文件的操做。

建立表,會在對應的庫目錄下建立表空間文件

3.6.1 建立單表

create table user_info(
    id int not null auto_increment primary key,
    name char(20),
    age int,
    gender char(1),
    deparment_id int,
    constraint 約束名稱 foreign key(deparment_id) references dep_info(id)
)engine = innodb default charset=utf8;
 
--> 語法格式:
--> create table 表名(
-->      列名  類型  [是否爲空] [是否默認值] [自增] [主鍵]  ,
-->      列名2  類型
-->      .... ....
-->      [ constraint 外鍵名稱 foreign key(本表的被約束字段) reference 目標表名(字段) ]      
--> ) engine = 存儲引擎名稱 default charset = utf8;

各字段含義:

  • 列名
  • 數據類型
  • 是否能夠爲空(null/not null)
  • 是否默認值(default value)
  • 是否自增(auto_icrement):一個表只能存在一個自增列而且必須有索引(普通索引或主鍵索引),類型必須是數值型。
  • 主鍵(primarr key):數據不能爲空、不能重複,能夠加速查找(數據庫的B樹結構)
  • 外鍵(constraint) :對錶內某字段的內容進行約束,必須是某個表的某個字段已有的值,含外鍵的表能夠理解爲1對多,注意外鍵關聯的兩個字段數據類型要一致 

3.6.2 建立多表外鍵關聯

  • 一對多:一個表的某個字段的數據來自於另外一個表已存在的數據。
  • 多對多:一個表的某幾個字段的數據來自於另外一個或幾個表已存在的數據。

一對多:

CREATE TABLE user_info (
    id INT NOT NULL auto_increment PRIMARY KEY,
    NAME CHAR (20),
    age INT,
    gender CHAR (1),
    deparment_id INT,
    CONSTRAINT 約束名稱 FOREIGN KEY (deparment_id) REFERENCES dep_info (id)
) ENGINE = INNODB DEFAULT charset = utf8;

CREATE TABLE dep_info (
    id INT NOT NULL auto_increment PRIMARY KEY,
    title CHAR (32),
) ENGINE = innode DEFAULT charset = utf8;

多對多:須要關係表來代表多對多關係

CREATE TABLE `boy` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` char(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
CREATE TABLE `girl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` char(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
CREATE TABLE `b2g` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `b_id` int(11) DEFAULT NULL,
  `g_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_b` (`b_id`),
  KEY `FK_G` (`g_id`),
  CONSTRAINT 約束名稱1 FOREIGN KEY (`b_id`) REFERENCES `boy` (`id`),
  CONSTRAINT 約束名稱2 FOREIGN KEY (`g_id`) REFERENCES `girl` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.6.3 刪除表

drop table tb_name;

3.6.4 查看錶結構

desc table_name [ col_name ]

若是添加列明,表示查看錶中某一列的結構。

3.6.4 其餘操做

查看建立表的語句

show create table table_name;

查看當前庫的全部表

show tables;

3.7 操做表數據(DML語句)

針對表的數據進行操做,主要涉及4類:

  • 增長 insert
  • 刪除 delete
  • 修改 update
  • 查找 select

插入內容就至關於在表文件中按照MySQL的格式寫數據

3.7.1 insert語句

語法格式1:insert into table_name(col_name1,col_name2) values(value1,value2)
含義:

  • field和value是一一對應的。
  • 當字段名省略時,表示插入字段全部數據,values後面的值須要列出全部字段

語法格式2:insert into table_name(col_name) select field from table_name
含義:

  • 把select查到的結果,看成數據來賦值給value
  • 查詢到的數據字段要和插入的字段數量一致

語法格式3:insert into table_name (col_name,...) values (value1,..) on duplicate key update col_name=value1,...;

  • 若是主鍵衝突、惟一鍵衝突,就執行update後的語句,這條語句的意思是:主鍵不存在則新增記錄,主鍵存在,則更新部分字段。

語法格式4:insert ignore into table_name (col_name1,..) values (values1,..);

  • 若是主鍵衝突、惟一鍵衝突,就忽略錯誤,返回一個警告
  • 通常用在大批量導入測試數據的場景下
INSERT INTO `test`.`employees_copy` (
    `id`,
    `emp_no`,
    `birth_date`,
    `first_name`,
    `last_name`,
    `gender`,
    `FK_depet_no`,
    `hire_date`
)
VALUES
    (
    '10',
    '10010',
    '1990-08-02',
    'Dahl',
    'Lee',
    'F',
    'd001',
    '1990-08-02'
);

INSERT INTO boy (id) SELECT
    id
FROM
    employees;

3.7.2 update 語句

語法格式:update [ignore] table_name set col_name = value1,... [ where xxx = xxx

  • 注意更新語句必定要帶where條件,除非你真的知道你要改什麼東西
UPDATE student
SET NAME = 'dahl'
WHERE
    id = 2;

3.7.3 delete 語句

語法格式:delete from table_name [ where xxx = xxx ]

  • 刪除必定要包含條件
DELETE
FROM
    student
WHERE
    id = 2;

生產中不會真的刪除數據,通常都會添加標緻位來區分是否刪除。除非你真的要刪除。

3.7.4 select 語句

select 語句是 SQL中最複雜的語句,由於它很是靈活。下面是select語句的完整格式

SELECT
    [ DISTINCT ] select_expr ,...
FROM
    table_references 
WHERE
    where_definition  
GROUP BY
    { col_name | expr | position } [ ASC | DESC ],...[ WITH ROLLUP ]
HAVING
    where_definition 
ORDER BY
    { col_name | expr | position } [ ASC | DESC ] ,...
LIMIT {[ OFFSET ,] row_count | row_count OFFSET OFFSET }
[ FOR UPDATE | LOCK IN SHARE MODE ]]

FOR UPDATE 會把行進行鎖定(排他鎖)

3.7.4.1 簡單查詢

使用select col_name,... from table_name;

select * from student;
select id,name from student;
select id as std_no,name from student;
select std.id ,std.name from student as std;
select id,CONCAT(first_name,last_name) as name  from student;
  • 當僅存在一個表時,select後面的字段能夠不用跟代表。
  • as 語句表示別名,是能夠省略的,可是建議不要省略別名。
  • * 表示全部字段。
  • concat:字符串處理函數,用於合併

3.7.4.2 limit子句

對結果集進行過濾,限制輸出的條目數

  • limit:限制輸出的條目數
  • offset:與limit連用,表示偏移量
select * from employees limit 3 -- 輸出3條信息
select * from employees limit 3 offset 10 -- 漂移10條之後再輸出3條
select * from employees limit 10,3 --漂移10條之後再輸出3條

注意:limt還支持: 偏移量,取幾條。其實就是簡寫而已。上面例子第二句和第三句的含義是相同的。

Limit 必須在排序以後,由於排序會改變limit顯示的記錄

3.7.4.3 where子句

where子句主要用於作條件判斷,它支持的操做符以下:

運算符 描述
= 等於
<> 不等於(!=也能夠。只不過不太符合SQL的規範)
>、<、>=、<= 大於、小於、大於等於、小於等於
BETWEEN 在某個範圍以內,between a and b等價於[a, b]
LIKE 字符串模式匹配,%表示任意多個字符,_表示一個字符
IN 指定針對某個列的多個可能值
AND
OR
select first_name from employees where emp_no > 10;
select * from salaries where salary > 50000;
select * from salaries where salary between 60000 and 80000;  -- 60000 < salary < 80000
select * from employees where last_name like 'P%';
SELECT emp.emp_no AS no,CONCAT(first_name,' ', last_name) AS name from employees AS emp where emp.emp_no in (10009,100010,10020); -- 相似集合類型

關於使用like進行模糊匹配:

  • 建議使用左前綴,由於效率高。('%a%',和'%a'效率很低,建議不要使用,除非真的須要)
  • 能不用like,就不用,效率很低,若是真的要搜索,那麼建議使用搜索引擎(solr、lucence、elasticsearch)

3.7.4.4 order by子句

對查詢結果進行排序,能夠升序ASC、降序DESC

select * from salaries order by salary limit 3
select * from salaries order by salary desc;
select * from salaries ORDER by emp_no desc,salary desc

默認爲升序,當指定多個列時,優先按照第一列排序、當第一列相同時,再使用第二列排序。

3.7.4.5 distinct 去重

distinct 用於對字段進行去重操做,相同的只取1個

select distinct emp_no from salaries;
select distinct emp_no,salary from salaries;
  • 當distinct包含連個字段時,那麼就是聯合去重了。即以(emp_np,salay)爲總體進行去重

3.7.4.6 聚合函數

經常使用的聚合函數以下表:
函數|描述
----|----|
COUNT(expr)|返回記錄中記錄的數目,若是指定列,則返回非NULL值的行數
COUNT(DISTINCT|expr,[expr...])|返回不重複的非NULL值的行數
AVG([DISTINCT]|expr)|返回平均值,返回不一樣值的平均值
MIN(expr),|MAX(expr)|最小值,最大值
SUM([DISTINCT]|expr)|求和,Distinct返回不一樣值求和

看需求,count通常會和分組進行連用,也經常使用在統計條數,count(id),在統計條數時,建議使用主鍵字段,能夠得到更快的統計速度。

3.7.4.7 group by和having

group by主要用於分組顯示,若是想要對分組後的數據進行再次過濾,可使用having子句。

select emp_no,sum(salary) as sum_sal from salaries group by emp_no having sum_sal > 1000000;
  • group by 跟多個字段時,能夠理解爲 將多個字段組合成元組來分組,當元組惟一時,進行聚合統計。
  • 除分組和聚合字段之外的其餘字段(非分組字段),是不可預知的。
  • 對分組以後的數據再次過濾,就須要使用Having了。能夠對聚合後的結果設置別名來在having中引用。

3.7.4.8 子查詢

查詢語句能夠嵌套,內部查詢就是子查詢。

  • 子查詢必須在一組小括號中。
  • 子查詢中不能使用Order by。
select f.salary from (select * from salaries where salaries.emp_no > 10003) as f
select first_name from employees where emp_no in (select emp_no from salaries);

3.7.4.9 inner join(內鏈接)

inner join,簡寫爲join ,用於鏈接兩個表的內容,須要注意的是,鏈接方式爲笛卡爾乘積,所有交叉。

  • A表有20條數據,B表有20條數據的話,那麼a join b 就是 400條數據。
  • 當B表存在於A表同名的數據時,會被重命名

有如下兩種方式:

  • 等值鏈接:只選某些field相等的元組(行),使用on限定關聯的結果
  • 天然鏈接(natural join):特殊的等值鏈接,會去掉重複的列。用的不多(通常僅僅會留下兩表中主鍵相同的記錄)
select * from employees natural join salaries;
select * from employees inner join salaries on employees.emp_no = salaries.emp_no

3.7.4.10 outer join(外鏈接)

outer join 外鏈接,主要分爲:

  • 左外鏈接(left join):從左表(table1)返回全部的行,即便右表(table2)中沒有匹配。若是右表中沒有匹配,則結果爲 NULL。
  • 右外鏈接(right join):從右表(table2)返回全部的行,即便左表(table1)中沒有匹配。若是左表中沒有匹配,則結果爲 NULL

在mariadb中,outer join 必需要配合on參數使用,不然會提示語法錯誤

select * from   employees left join salaries on employees.emp_no = salaries.emp_no where employees.emp_no > 10010;

在使用left jion時,on和where條件的區別以下:

  1. on條件是在生成臨時表時使用的條件,它無論on中的條件是否爲真,都會返回左邊表中的記錄。
  2. where條件是在臨時表生成好後,再對臨時表進行過濾的條件。

本身和本身鏈接

給定 Employee 表,編寫一個 SQL 查詢,該查詢能夠獲取收入超過他們經理的員工的姓名。在上面的表格中,Joe 是惟一一個收入超過他的經理的員工

表結構:

Create table If Not Exists Employee (Id int, Name varchar(255), Salary int, ManagerId int)
Truncate table Employee
insert into Employee (Id, Name, Salary, ManagerId) values ('1', 'Joe', '70000', '3')
insert into Employee (Id, Name, Salary, ManagerId) values ('2', 'Henry', '80000', '4')
insert into Employee (Id, Name, Salary, ManagerId) values ('3', 'Sam', '60000', 'None')
insert into Employee (Id, Name, Salary, ManagerId) values ('4', 'Max', '90000', 'None')

sql語句:

select emp.Name as Employee from Employee  as emp left join Employee as man_emp on emp.ManagerID = man_emp.Id where emp.Salary > man_emp.Salary;

4 儲過程、觸發器

  • 存儲過程(Stored Procedure):數據庫系統中,一段完成特定功能的SQL語句。編寫成相似函數的方式,能夠傳參並調用。支持流程控制語句。
  • 觸發器(Trigger):由事件觸發的特殊的存儲過程,例如insert數據時觸發。

這兩種技術,雖然是數據庫高級內容,性能不錯,但基本不多用了。它們移植性差,使用時佔用的服務器資源,排錯、維護不方便。

最大的緣由,不太建議把邏輯放在數據庫中。

5 事務Transaction

InnoDB引擎,支持事務。
事務,由若干條語句組成的,指的是要作的一系列操做。
關係型數據庫中支持事務,必須支持其四個屬性(ACID):

特性 描述
原子性(atomicity) 一個事務是一個不可分割的工做單位,事務中包括的全部操做要麼所有作完,要麼什麼都不作
一致性(consistency) 事務必須是使數據庫從一個一致性狀態變到另外一個一致性狀態。一致性與原子性是密切相關的
隔離性(isolation) 一個事務的執行不能被其餘事務干擾。即一個事務內部的操做及使用的數據對併發的其餘事務是隔離的,併發執行的各個事務之間不能互相干擾
持久性(durability) 持久性也稱永久性(permanence),指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其餘操做或故障不該該對其有任何影響

分析:

  • 原子性:要求事務中的全部操做,不可分割,不能作了一部分操做,還剩一部分操做;
  • 一致性:多個事務並行執行的結果,應該和事務排隊執行的結果一致。若是事務的並行執行和多線程讀寫共享資源同樣不可預期,就不能保證一致性。
  • 隔離性:就是指多個事務訪問共同的數據了,應該互不干擾。隔離性,指的是究竟在一個事務處理期間,其餘事務能不能訪問的問題
  • 持久性:比較好理解,就是事務提交後,數據不能丟失。

6 MySQL隔離級別

隔離性很差,事務的操做就會互相影響,帶來不一樣嚴重程度的後果。

6.1 隔離性很差,帶來的問題

  1. 更新丟失Lost Update:事務A和B,更新同一個數據,它們都讀取了初始值100,A要減10,B要加100,A減去10後更新爲90,B加100更新爲200,A的更新丟失了,就像歷來沒有減過10同樣。
  2. 髒讀:事務A和B,事務B讀取到了事務A未提交的數據(這個數據多是一箇中間值,也可能事務A後來回滾事務)。事務A是否最後提交併不關心。只要讀取到了這個被修改的數據就是髒讀。
  3. 不可重複讀Unrepeatable read:事務A在事務執行中相同查詢語句,獲得了不一樣的結果,不能保證同一條查詢語句重複讀相同的結果就是不可
    以重複讀。
    • 例如,事務A查詢了一次後,事務B修改了數據,事務A又查詢了一次,發現數據不一致了。
    • 注意,髒讀講的是能夠讀到相同的數據的,可是讀取的是一個未提交的數據,而不是提交的最終結果。
  4. 幻讀Phantom read:事務A中同一個查詢要進行屢次,事務B插入數據,致使A返回不一樣的結果集,如同幻覺,就是幻讀。數據集有記錄增長了,能夠看作是增長了記錄的不可重複讀。

6.2 隔離級別

隔離級別由低到高,以下表
隔離級別|描述
----|----|
READ UNCOMMITTED |讀取到未提交的數據
READ COMMITTED |讀已經提交的數據,ORACLE默認隔離級別
REPEATABLE READ |能夠重複讀,MySQL的 默認隔離級別。
SERIALIZABLE |可串行化。事務間徹底隔離,事務不能併發,只能串行執行

  • 隔離級別越高,串行化越高,數據庫執行效率低;隔離級別越低,並行度越高,性能越高。
  • 隔離級別越高,當前事務處理的中間結果對其它事務不可見程度越高。
-- 設置會話級或者全局隔離級別
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
-- 查詢隔離級別
SELECT @@global.tx_isolation;
SELECT @@tx_isolation;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 禁用自動提交
SET AUTOCOMMIT = 0

小結:

  • SERIALIZABLE,串行了,解決全部問題
  • REPEATABLE READ,事務A中同一條查詢語句返回一樣的結果,就是能夠重複讀數據了。例如語句爲(select *from user)。解決的辦法有:
    1. 對select的數據加鎖,不容許其它事務刪除、修改的操做
    2. 第一次select的時候,對最後一次確切提交的事務的結果作快照
    3. 解決了不能夠重複讀,可是有可能出現幻讀。由於另外一個事務能夠增刪數據。
  • READ COMMITTED,在事務中,每次select能夠讀取到別的事務剛提交成功的新的數據。由於讀到的是提交後的數據,解決了髒讀,可是不能解決 不可重複讀 和 幻讀 的問題。由於其餘事務先後修改了數據或增刪了數據。
  • READ UNCOMMITTED,能讀取到別的事務尚未提交的數據,徹底沒有隔離性可言,出現了髒讀,當前其餘問題均可能出現。

6.3 事務語法

START TRANSACTION或BEGIN開始一個事務,START TRANSACTION是標準SQL的語法。
使用COMMIT提交事務後,變動成爲永久變動。
ROLLBACK能夠在提交事務以前,回滾變動,事務中的操做就如同沒有發生過同樣(原子性)。
SET AUTOCOMMIT語句能夠禁用或啓用默認的autocommit模式,用於當前鏈接。SET AUTOCOMMIT = 0禁用自
動提交事務。若是開啓自動提交,若是有一個修改表的語句執行後,會當即把更新存儲到磁盤。

6.4 數據倉庫和數據庫的區別

本質上來講沒有區別,都是存放數據的地方。可是

  • 數據庫關注數據的持久化、數據的關係,爲業務系統提供支持,事務支持;
  • 數據倉庫存儲數據的是爲了分析或者發掘而設計的表結構,能夠存儲海量數據。

數據庫存儲在線交易數據OLTP(聯機事務處理OLTP,On-line Transaction Processing);數據倉庫存儲歷史數據用於分析OLAP(聯機分析處理OLAP,On-Line Analytical Processing)。數據庫支持在線業務,須要頻繁增刪改查;數據倉庫通常囤積歷史數據支持用於分析的SQL,通常不建議刪改。

相關文章
相關標籤/搜索