1. 程式人生 > 實用技巧 >python之什麼是函式

python之什麼是函式

MySQL

前言:

Java後端 第一步 認識SQL

1.認識SQL

1.1mysql 啟動方法

mysql 環境變數配置正確後,要使用管理員身份啟動 cmd

cmd1 :

net start mysql
service mysql restart

cmd2 :

mysql -u root -p
mysql -u root -p****** --或者直接輸入密碼

cmd3 : pwd = mysql_native_password

更改環境變數後配置MySQL,或者發現MySQL服務關閉了(不能從資料庫中查詢到東西)

  1. 把當前MySQL目錄\bin新增到系統變數,非使用者變數

  2. 進入mysql基礎目錄,修改 my.ini 檔案,base,data目錄均修改,可以不跳過密碼檢查

  3. 管理員模式進入cmd,\bin目錄下 mysqld -install

  4. \bin目錄下 net start mysql

5.mysql -uroot -p**

可能需要重複配置比較費力,不建議改變原始路徑

1.2 sql 基本語句


1.2.1基本操作
sc delete mysql    --刪除所有配置 慎用

create database xxx ; --建立一個數據庫

drop database xxxxx ; --刪除資料庫的所有內容,包括原資料庫

show databases; --檢視所有的資料庫

use xxxxxx; --切換xxxxxx資料庫

show tables; --檢視資料庫中所有的表

describe xxx ; --檢視xxxxxx資料庫中xxx表單的資訊

sqlyog operations : 選中ctrl+a---執行語句 左上角按鈕執行

飄號引用 sqlName.tableName

1.2.2建立表單 主鍵必須非空
CREATE TABLE `school`.`techer` ( `id` INT(10) NOT NULL COMMENT '教職工號', `name` VARCHAR(10) COMMENT '姓名', `age` INT(3) COMMENT '年齡', PRIMARY KEY (`id`) ) ENGINE=INNODB CHARSET=utf8 COLLATE=utf8_general_ci; 

----初始化一個數據庫的表形狀

學習sql語法妙招:先用GUI 然後看GUI操作後的sql語句

1.3 sql基本資料型別

sql數值型別

tinyint   1 bit
smallint  2 bit 
mediumint 3 bit
int       4 bit   
bigint    8 bit
float     8 bit
decimal	  字元型串浮點數 精確,精確,商用

sql字串型別

char 				0~255
varchar 可變字元 	0~65535 
tinytext 			2^8-1
text 				2^16-1

sql時間日期

date YYYY-MM-DD 
time HH:mm:ss
datetime YYYY-MMM-DD HH:mm:ss 
timestamp 1970.1.1-now 
year

sql null

無值 null 運算 null

1.4 sql欄位屬性

Unsigned :

  • 無符號整數
  • 宣告非負

zerofill :

  • 不足的位數用0補全到 限定位數 eg.INT(10) 1->0000000001

自增

  • 自動在上一條記錄上+1
  • 唯一的主鍵 index 要子增 整數型別

非空 :

NULL

NOT NULL :如果不賦值 報錯

1.5 sql表單語句

show create database school  --檢視建立資料庫語句
show create table student --檢視 student 資料表的定義語句
desc student --顯示錶的結構

1.6 sql 中ENGINE INNODB和MYISAM 的區別

MYISAMINNODB
事務支援不支援支援
資料行鎖定不支援 (表鎖)支援 (行鎖)
外來鍵約束不支援支援
全文索引支援不支援
表空間的大小較小較大 ,約為2倍
常規使用操作節約空間 ,速度較快安全性高,事務處理,多表多使用者操作
物理檔案上*.frm --表結構的定義檔案 ; *.MYD資料檔案(data) ; *.MYI 索引檔案 (index)在資料庫表中只有一個*.frm檔案,以及上級目錄下的ibdata1 檔案

物理空間的儲存位置 :

所有的資料庫檔案都存在data目錄下

設定資料庫表中的字符集編碼

CHARSET=utf8

不設定的情況,會是mysql預設的字符集編碼 (不支援中文)

MySQL 的預設編碼是 Latin1

在my.ini 中配置 預設的編碼

character-set-server=utf8

1.7 sql的表單修改 (修改正規化)

1.7.1表單內操作

改名規則 :

ALTER TABLE 舊錶名 RENAME AS 新表名

新增規則 :

ALTER TABLE 表名 ADD 欄位名 列屬性 [屬性]

修改規則 :

ALTER TABLE 表名 MODIFY 欄位名 列屬性[屬性]
ALTER TABLE 表名 CHANGE 舊欄位名 新欄位名 列屬性[屬性]

刪除規則(刪除列) :

ALTER TABLE 表名 DROP 欄位名

修改主鍵

ALTER TABLE Skills DELETE PRIMARY KEY
ALTER TABLE Skills ADD PRIMARY KEY ( SkillID, SkillName );

新增外來鍵

alter table user add key `outside_KEY` (`id`);

1.7.2 表單整體操作

整體刪除

DROP TABLE IF EXISTS `XXX`

其他語法規則

( ` )單反號 (飄號) 用來 標識 庫名;表名;欄位名;索引;別名

一個DATABASE 有一個 db.opt 來儲存當前的options 選項表

註釋 # ;/* */ ;--;

SQL大小寫不敏感

2.MySQL資料管理

2.1 外來鍵

2.1.1 建立表時候直接新增外來鍵

建表 grade

CREATE TABLE `grade`(
 `gradeID` INT(10) NOT NULL  AUTO_INCREMENT COMMENT '年級號',
 `gradeName` VARCHAR(20) NOT NULL DEFAULT 'name' COMMENT '年級名',
  PRIMARY KEY (`gradeID`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

建表 student 並新增外來鍵

CREATE TABLE IF NOT EXISTS `student` (
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '學生學號' ,
`otherInformation` VARCHAR(50) NOT NULL DEFAULT 'info' COMMENT '其他資訊' ,
`gradeID` INT(10) NOT NULL COMMENT '學生的年級',
PRIMARY KEY (`id`) ,--主鍵
KEY `FK_gradeID` (`gradeID`), --新增外來鍵
CONSTRAINT  `FK_gradeID` FOREIGN KEY (`gradeID`)  REFERENCES `grade`(`gradeID`)  --新增約束
)ENGINE =INNODB CHARSET=utf8

邏輯關係 :

grade 不可被直接刪除 由於student 定義了對於grade 的外部鍵

刪除有外來鍵的表 ,不可直接刪除依賴的表

2.1.2 建立表後新增外來鍵

ALTER TABLE `student`  --修改表名
ADD CONSTRAINT `FK_gradeID` FOREIGN KEY (`gradeID`)  REFERENCES `grade` (`gradeID`) --新增約束 增加外來鍵欄位的位置

不用外來鍵 :

阿里內部(業界)強制規範 :不得使用外來鍵與內部相關聯 ,一切外來鍵概念必須再應用層解決

2.2 DML語言 (修改資料)

資料庫的意義 :大規模資料儲存 建議全文背誦

2.2.1 新增

插入單個欄位

INSERT INTO `grade` VALUES(content) -- 內容和列資料 一一匹配

插入多個欄位

INSERT INTO `grade` (`gradeName`) --形容 表.列
VALUES('大四') ,('研一'); --值
INSERT INTO `student` VALUES(1,'info1',1),(2,'info2',2); --外來鍵值 必須對應於索引中的匹配

2.2.2修改

uodate 修改 (狀態)

修改一個屬性

UPDATE `student` set `name`='狂神' WHERE id=1;

修改多個屬性 , 逗號隔開

UPDATE `student` SET `name`='老八',`age`= 35 ,`otherInformation`='老八蜜汁小憨包' WHERE id=2;

WHERE 附加運算子

操作符含義範圍
=等於絕對滿足條件
<> 或者 !=不等於絕對不滿足
>大於絕對大於
<小於絕對小於
<=小於等於。。
>=大於等於。。
BETWEEN ...and...範圍範圍與
AND條件與
OR條件或

2.2.3 刪除

刪除單條資料

DELETE FROM `student` WHERE id=9;

清空表單 (不建議使用)

DELETE FROM `student`

建議使用的清空資料庫操作

TRUNCATE `student`

二者的相同點:都能刪資料 都不會刪除表單結構

區別:

  • TRUNCATE 重新設定 ,自增列 計數器會歸零
  • TRUNCATE 不會影響事務,索引從一開始
  • DELETE 影響事務 ,新索引設定為上次刪除的最後一位加一

而且DELETE刪除後 重啟資料庫 的現象

引擎問題
INNODB自增列從一開始 (儲存在記憶體中,斷電即失)
MYISAM自增從上一個自增開始(存在檔案中 斷電不失)

2.2.4重新整理資料庫

flush privileges

2.2.5 DML小結

INSERT INTO `student` VALUES(5,'網銀',3,'老鐵',30,CURRENT_TIME); --嚴格按列 否則失敗
UPDATE `student` SET `name`='王銀' ,age=18 WHERE id=5; 
DELETE FROM `student` WHERE id=5;

SELECT

3.DQL查詢資料

3.1 認識DQL

3.1.1重要性

  • Data QUERY LANGUAGE : 資料查詢語言

  • 支援所有型別的查詢

  • SQL最核心的語言規範

  • SQL使用頻率最高的語言規範

    3.1.2 SELECT完整語法

    SELECT [ALL | DISTINCT]
    {* | TABLE.* | [TABLE.field1][AS alias1],[TABLE.field2][AS alias2] ,...}
    FROM `tableName` as [TABLE_alias]
    [LEFT | RIGHT | INNER JOIN table_name] -- 聯表查詢
    [WHERE ... ] -- 指定結果滿足條件
    [GROUP BY ... ] -- 指定結果按照欄位分組
    [HAVING] -- 過濾分組的記錄必須滿足的次要條件
    [ORDER BY ... ] -- 指定查詢記錄按一個或者多個排序
    [LIMIT {[OFFSET]ROW_COUNT | ROW_COUNTOFFSET OFFSET}];
    -- 指定查詢的記錄從那條至哪條
    

3.2 查詢

3.2.1 基本查詢操作

1.查詢表的所有資料

SELECT * FROM student; --不帶飄號 
SELECT * FROM `grade`; --帶飄號  

2.查詢指定欄位

SELECT `gradeName` FROM grade ; 
SELECT `name` ,`age` FROM student; 

3.查詢指定欄位,指定別名

SELECT `name` AS 學生姓名,`age` AS 學生年齡 FROM student;

3.2.2 DQL函式

1.連線函式

SELECT CONCAT ('姓名 : ',`name`) AS 標準名 FROM `student`;

3.2.3 普通的查詢操作

1.去重操作

SELECT DISTINCT `name` FROM `student` ;

2.所有資料 +1

SELECT `totalScore`+1 FROM `student`; 

注意:只是顯示出來的資料+1 不會改變原表的內容

3.2.4 DQL (SELECT)的其他功能

1.查詢SQL版本號

SELECT VERSION()

2.計算表示式的結果

SELECT 100*3-1 AS

3.查詢自增步長

SELECT @@auto_insrement_increment 

3.3 進階查詢

3.3.1where條件子句

作用 : 檢索資料中的符合條件的值

運算子語法描述
AND &&a AND b a&&b邏輯與
OR ||a OR b a||b邏輯或
Not !NOT a ! a邏輯非

對於區間查詢的三種寫法

  1. &&
SELECT studentNo ,studentRes FROM result WHERE studentRes >=80 && studentRes <=95;
  1. BETWEEN AND
SELECT studentNo ,studentRes FROM result WHERE studentRes BETWEEN 80 AND 95;
  1. AND
SELECT studentNo ,studentRes FROM result WHERE studentRes >=80 AND studentRes <=95;

或 ,非 操作類似 不多冗述

3.3.2模糊查詢

本質 : 比較運算子

運算子語法描述
IS NULLa is nullNULL為真
IS NOT NULLa is not null不是NULL 為真
BETWEENa between b and ca 在 b c間 為真
Likea like bSQL匹配 a 匹配b 為真
ina in (a1,a2,a3....)a在給定陣列欄位中為真

查詢萬用字元 :

% 匹配任何數量的任意字元

SELECT studentRes FROM result where studentName Like '劉%'
-- 可以匹配如劉洋 劉建偉 劉行趙麗 劉大蘇打大大啊sdadasa 
-- 匹配名字中有 嘉的 Like '%嘉%'

_ 匹配一個任意字元

SELECT studentRes FROM result where studentName Like '劉_'
-- 可以匹配如 劉洋 劉備 劉兵 劉申 
-- '劉__'匹配兩個任意字元
-- '劉___'匹配三個任意字元 以此類推....

3.4 JOINON聯表查詢

3.4.1七種理論

3.4.2三個例子

3examples :

1.INNER JOIN 相交查詢

SELECT s.gradeID ,s.`name` -- 查詢內容
FROM `student` AS s        -- 起別名
INNER JOIN `grade` AS g    -- 內聯查詢
WHERE s.gradeID=g.gradeID; -- 條件

2.Right JOIN 即使左表沒有匹配也會從右表返回所有的值 以右表為基準

SELECT s.gradeID,s.name
FROM `student` AS s -- 左表
RIGHT JOIN `grade` AS g -- 右表  
ON s.gradeID=g.gradeID; 

3.Left JOIN 即使右表沒有匹配也會返回左表的所有值 以左表為基準

SELECT s.gradeID,s.name
FROM `student` AS s   -- 左表
LEFT JOIN `grade` AS g -- 右表
ON s.gradeID=g.gradeID; 

語句思路:

1.分析需求 ,分析查詢的欄位來自哪些表 student result subject (連線查詢)

2.確定使用哪種的連線查詢

3.判斷交叉點 :相同的資料

4.判斷交叉條件:WHERE 子句

注意:

ON 連線查詢

WHERE 條件查詢

3.4.3多表查詢

SELECT s.gradeID,s.name ,sc.totalScore  -- student的年級 學生姓名 總分
FROM student AS s -- 
LEFT JOIN grade AS g 
ON s.gradeID=g.gradeID
RIGHT JOIN score AS sc
ON sc.id=s.gradeID;

3.5 自查詢,自連線

自己和自己連線

把一張表拆成兩張表

複習:

1.建表

CREATE TABLE IF NOT EXISTS`school`.`學習清單`(
`pid` INT(10) NOT NULL DEFAULT 1 COMMENT '父親id',
`selfid` INT(10) NOT NULL DEFAULT 2 COMMENT '自己id',
`content` VARCHAR(20) COMMENT '內容',
PRIMARY KEY (`selfid`)
)ENGINE=INNODB CHARSET=utf8 COLLATE=utf8_general_ci;

2.插值

INSERT INTO `學習清單`
VALUES(1,1,'軟體開發'),(2,2,'人工智慧'),
(1,3,'Java程式設計思想'),(1,4,'編譯原理'),
(2,5,'機器學習'),(2,6,'資料探勘');

3.自連線,自分割槽

SELECT a.`content` AS `父類`,b.`content` AS `子類`
FROM `學習清單` AS a,`學習清單` AS b
WHERE a.`selfid`=b.`pid`;

結果:

定義自己的父親是自己 ,講一個父類分為幾個子類的過程

修改後

UPDATE `學習清單` SET `pid`=0 WHERE content='軟體開發' OR content='人工智慧';

3.6 分頁和排序

起始頁下標 [i ,pagesize] 容納量 (i-1)*pagesize

SELECT a.`content` AS `父類` ,b.`content` AS `子類`
FROM `學習清單` AS a ,`學習清單` AS b
WHERE b.pid=a.selfid
ORDER BY `父類` ASC 
LIMIT 0,6;

limit 語法:

limit 查詢起始下標 pageSize

排序 語法 :

ORDER BY `key` ASC  -- 升序
ORDER BY `KEY` DESC -- 降序

3.7.子查詢 (巢狀查詢)

where 語句中再巢狀一個 select 語句

1.原始方法 : 聯表查詢方法

SELECT s.otherInformation AS `愛好`,s.id AS `身份號碼`,sc.totalScore AS `總分`
FROM `student` AS s
INNER JOIN `score` AS sc
ON s.id=sc.id
ORDER BY sc.totalScore DESC

2.新方法 : 子查詢(巢狀where方法) 子查詢不能多於一行

SELECT DISTINCT s.otherInformation AS `愛好`,s.id AS `身份號碼`,s.`name` -- DISTINCT 去重 
FROM `student` AS s 
WHERE s.id IN (
	SELECT id FROM `score` WHERE `totalScore` BETWEEN 600 AND 700  -- where in 查詢範圍
)
ORDER BY s.id ASC ;

3.8 SELECT小結

某寶,某東,某夕夕千人千面

不僅是 mysql 還有Redis ,cloud ,SequoialDB 等非關係/快取儲型,比較複雜

4.MySQL函式

具體請參考官網文件 : https://dev.mysql.com/doc/refman/5.7/en/introduction.html 用的話直接查詢即可

4.1常用函式

SELECT 為先 永遠SELECT

ABS()|CEILING()|FLOOR()|RAND()|SIGN() .....都是見名知意的

4.2聚合函式

函式名描述
COUNT()計數
SUM()求和
AVG()平均值
MAX()最大值
MIN()最小值
......

忽略所有的NULL值

select count(name) from `student`

select * 1 null的辨析 請上網參考各路博文和官方DOC 只有納百家之長 才能清晰理解,這裡不粘連結

4.3DQL查詢分組

eg. 查詢一個科目的 平均,最大,最小分,並分類統計

SELECT  s.name AS `姓名`,s.age AS `年齡`,AVG(`高等數學`) AS `平均分` ,MAX(`高等數學`) AS `最高分`, MIN(`高等數學`) `最低分`
FROM `score` AS sc
INNER JOIN student AS s
ON s.id=sc.id 
GROUP BY s.id

4.4資料庫級別的MD5查詢加密

4.4.1定義

來自baidu :

MD5資訊摘要演算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼雜湊函式,可以產生出一個128位(16位元組)的雜湊值(hash value),用於確保資訊傳輸完整一致。MD5由美國密碼學家羅納德·李維斯特(Ronald Linn Rivest)設計,於1992年公開,用以取代MD4演算法。這套演算法的程式在 RFC 1321 標準中被加以規範。1996年後該演算法被證實存在弱點,可以被加以破解,對於需要高度安全性的資料,專家一般建議改用其他演算法,如SHA-2。2004年,證實MD5演算法無法防止碰撞(collision),因此不適用於安全性認證,如SSL公開金鑰認證或是數字簽名等用途。

4.4.2加密程式碼(mysql實現)

1.建表

CREATE TABLE `testmd5`(
`id` INT(4) NOT NULL ,
`name` VARCHAR(20) NOT NULL ,
`pwd` VARCHAR (50) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE =INNODB DEFAULT CHARSET=utf8;

2.插值

INSERT INTO `testmd5` VALUES (1,'zhangsan','123456'),(2,'wangwei','123456'),(3,'lisi','1233456');

3.MD5方式加密

UPDATE testmd5 SET pwd=MD5(pwd)

或者在插入時就加密

INSERT INTO `testmd5` VALUES (4,'sange',MD5('pop3'));

4.檢驗使用者傳過來的密碼正確性

select * from testmd5 where `name`='sange' and pwd=md5('pop3')

5.事務和業務

5.1什麼是事務

要麼都成功,要麼都失敗

eg1.定義某個事務為 : A給B轉賬 x元,保證A 擁有大於等於x元.

事務成功為 : A的賬戶記錄減少x元 ,並且B的賬戶記錄增加x元 ,兩者必須都成功 才事務成功,否則事務失敗


SQL執行事務抽象邏輯A賬戶狀態B賬戶狀態總和
*初始狀態100010002000
A記錄 - 200A給B轉賬20080010002000
B記錄 + 200B收到A的20080012002000
*結束狀態80012002000

絕對滿足表格,事務成功 Transaction success

5.2ACID原則


事務原則 : ACID 原則 原子性,一致性,隔離性,永續性

1.原子性 Atomicity

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

2.一致性 Consistency

事務前後資料的完整性必須保持一致

3 隔離性 Isolation

事物的隔離是多個使用者併發訪問資料庫時,資料庫為每一個使用者開啟的事務,不能被其他的事務的操作資料干擾,多個併發事務之間要相互隔離

4.永續性 Durability

永續性是一個事務一旦被提交,他對資料庫中的資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響

隔離產生的一些問題

髒讀:

指一個事務讀取了另外一個事務未提交的資料

不可重複讀

在一個事務內讀取表中的某一行資料 多次讀取結果不同 (非錯誤,是場合不對)

虛讀幻讀):

是指在一個事務內讀取到了別的事務插入的資料 導致前後讀取不一致

5.3測試事務

5.3.1 內容

  1. 設定事務自動提交到資料庫的狀態
SET autocommit=0; -- 設定事務 關閉 
SET autocommit=1; -- 設定事務 開啟(預設)

2.手動處理事務

標記一個事務的開始,從此時起sql都在同一個事務內

set autocommit=0;

start transaction

增加事務記錄

insert xxx

提交

commit 

事務失敗 ,回滾

ROLLBACK

事務結束 回覆到預設狀態

set autocommit=1;

注 :

儲存點 :設定一個事務的儲存點

SAVEPOINT 

回滾到儲存點

rollback to savepoint

撤銷儲存點

release savepoint

事務邏輯圖 :原創

5.3.2事務實現

只有程式碼

轉賬事務實現

一次執行一條,這很重要

CREATE DATABASE  IF NOT EXISTS `shop` ;

USE shop;

CREATE TABLE IF NOT EXISTS account(
id INT(10) NOT NULL AUTO_INCREMENT COMMENT '賬戶名',
name VARCHAR(10) NOT NULL COMMENT '姓名',
money DECIMAL(9,4) NOT NULL COMMENT '賬戶金額',
PRIMARY KEY (id)
)ENGINE=INNODB CHARSET=utf8 COLLATE=utf8_general_ci

INSERT INTO account VALUES(1,'Roky',1000.00),(2,'Jane',5000.00),(3,'Pony',10000.00);

SET autocommit=0;

START TRANSACTION

UPDATE account SET money=money-200 WHERE name='Jane'
UPDATE account SET money=money+200 WHERE name='Roky'

COMMIT
ROLLBACK

SET autocommit=1;

6.索引原理

推薦部落格:https://blog.codinglabs.org/articles/theory-of-mysql-index.html

從作業系統,計算機底層架構和資料結構,演算法講解的索引原理。是一篇質量極其高的博文,博主寫了半個月,成文時間2011年,年代較遠,但沒有影響它的價值,個人看了3天。順便說兩句,從計算機底層總結的東西,都值得我們仔細鑽研;程式不僅僅是事務邏輯和框架,從來都是資料結構演算法,不懂底層原理,只能成為附庸

6.1 閱讀博文和官方Doc 心得筆記

1.索引本質

我們想更加快速的找到資料,我們都知道mysql是根據索引查詢資料,但是普通的查詢可能不會高效,依靠資料結構才能更加高效,所以所謂索引是一種資料結構

2.為什麼選擇資料結構

解決海量使用者對於海量資料的高併發問題

3.MySQL選擇的資料結構

我們已經知道 BST 在查詢方面的效能非常優越,但會造成退化,AVL和 R-B這兩個變種對於退化做了一些優化,R-B相對於AVL來說Rotate沒那麼多,增加了結點的parent和color,已經非常優越了,於是,Java的HashMap選擇了這種結構,但是MySQL並沒有選擇這兩種,而是更為複雜的 B-Tree 和 B+Tree ,MySQL和HashMap都是以Key-Value方式查詢Value。而HashMap是程式執行時有效的,非持久化,就是在RAM中斷電即失,而MySQL是永續性的,儲存在磁碟的分割槽,說白了,HashMap效能再高,儲存的資料也要依靠記憶體大小,而MySQL是廉價的硬碟,資料量大到幾百億還可以執行。在Sahni博士所著作的資料結構與演算法 樹的末尾章節有詳細講述B-樹的原理,但是沒有程式碼描述,總體來說,這種結構相對複雜.

2.1 B- /B+樹 概括結構

一切樹的本質 : 對於用連結串列描述的結構來講永遠是遞迴的.

一些定義

根節點 :根

內部節點 : 非空非根的結點

外部結點:葉子節點的兒子節點 ,就是NULL

抽象結構:一個B-樹 是一個m叉搜尋樹,可以理解為有序陣列和樹形的結合。

結點概況:一個節點數為m的B樹可以有[m/2,m]個,這個結點是一個長度為m的陣列,這個陣列是有絕對不降序的,(絕對不降序是指對於陣列的整體元素來講,可以有相同的元素,但是MySQL不允許這種情況)對於內部的結點來講,根節點陣列長度至少為2,所有的外部節點都在同一個層,保證了樹高h可以絕對一致化

排列順序:一個結點的陣列最頭部結點的孩子結點的Key都小於該節點,一個結點陣列尾部結點Key都大於該節點,一個結點陣列中第i個元素Key 大於他的第i子Key,小於他的第i+1子的Key。

查詢方式:所以我們在查詢一個元素時候,先在根節點中間比較,找到適合的區間,這個過程是二分,對於合適區間進行跳躍,這個過程是樹形.

B+樹的優化:B+樹對於 原結點的陣列做了優化,每個結點增加了 一個指向下一個元素的指標,這個可以優化WHERE語句的區間查閱行為。

3.底層原理

對於計算機底層原理不敢多說,筆者是大一小白一枚,計算機導論有講述,不過涉及過少,因為競賽和做專案原因提前學習MySQL.

6.2 索引分類

在一個表中主鍵索引只有一個 ,唯一索引可以有多個

  • 主鍵索引 PRIMARY KEY

    • 唯一標識,主鍵不可重複,只能有一個列作為主鍵索引
  • 唯一索引 UNIQUE KEY

    • 避免重複的列出現,唯一索引可以重複 ,多個都可以標識位 唯一索引
  • 常規索引 KEY/INDEX

    • 預設的
  • 全文索引 FULLTEXT

    • 在特定的資料庫引擎下才有 (MyISAM)

索引的新增方式

  • 建立表初期,給索引增加欄位 ,在欄位後面新增 xxx KEY (xxx欄位)
  • 建立完畢,增加索引 ALTER TABLE xxx ADD xxx KEY xxx (xxx)

顯示索引資訊

SHOW INDEX FROM `account`

增加全文索引

ALTER TABLE `shop`.`account` ADD FULLTEXT INDEX `fullindex` (`name`) 

分析 sql 的執行情況

EXPLAIN SELECT * FROM `account`
SELECT * FROM `account` WHERE MATCH(`name`) AGAINST('Pony');

mysql之explain相關博文 :

https://blog.csdn.net/jiadajing267/article/details/81269067

6.3 測試百萬級資料量

MySQL 不僅儲存資料,增刪改查 而且是可以程式設計的

6.3.1插入隨機的百萬資料

定義函式

DELIMITER $$

CREATE FUNCTION analog()
RETURNS INT
BEGIN
DECLARE num INT DEFAULT 1000000;
DECLARE i INT DEFAULT 0;
WHILE i<num DO
INSERT INTO app_user (name,email,phone,gender,password,age)VALUES(CONCAT('使用者',i),CONCAT(FLOOR(RAND()(9999999-1000000)+1000000),'@qq.com'),CONCAT('18',FLOOR(RAND()((999999999-10000000)+10000000))),FLOOR(RAND()2),UUID(),FLOOR(RAND()100));
SET i=i+1;
END WHILE;
RETURN i;
END;

執行函式

SELECT analog()

6.3.2測試查詢

測試

SELECT * FROM `app_user` WHERE `name`='使用者9999'

解釋

explain SELECT * FROM `app_user` WHERE `name`='使用者9999'

我們給名字新增普通索引試一下

CREATE INDEX id_app_user_name ON app_user(`name`)

新增索引耗費時間10~15s左右

可以看到時間和效率大大提升了

查詢時間由2.718 sec ->0.001 sec

查詢列數由 992787 row -> 1 row

這在解決高併發問題上很有效的

6.4新增索引的原則

  • 索引不是越多越好,多則繁瑣,你也記不住
  • 不要對程序變動資料加索引,一致性
  • 小資料量的表不需要索引,畫蛇添足,多此一舉
  • 索引一般加在經常常用來查詢的欄位上

7.許可權管理與資料庫備份

許可權管理的目的:

在公司中,一個業務或服務有一個數據庫,這個資料庫管理員享有最高的許可權,而普通員工只有一般許可權,不可能所有人都最高許可權,不然你刪庫跑路怎麼辦

7.1 SQLYog視覺化管理

無腦點選左上角即可

7.2 SQL命令管理

1.建立使用者

create user juminiy identified by '123456' -- pwd

2.修改密碼

當前使用者

set password =password('123456')

其他使用者

set password for juminiy =password('123456')

重新命名使用者

rename user juminiy to kkk03

授權 對於某個使用者的全部許可權

grant all privileges on *.* to juminiy

但是不能給別人授權, root可以,唯一的和ROOT不同處就是GRANT

檢視許可權

show grant for juminiy

檢視root許可權

show grant for root@localhost

撤銷許可權

revoke all privileges on *.* from juminiy  

刪除使用者

drop user juminiy

7.3 SQL備份

1.為什麼備份 :

  • 保證重要的資料不丟失
  • 資料的轉移

2.MySQL資料庫備份的方式

  • 直接拷貝

  • 視覺化工具手動匯出

  • 命令列匯出 mysqldump 命令列使用

    資料庫匯出

先 net start mysql

直接在 cmd 或者 bash上操作即可

# mysqldump -h 主機 -u 使用者名稱 -p 密碼 資料庫 表1,表2,表3 > 物理磁碟的位置 /檔名
mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sql

資料庫匯入

-- 先登入資料庫
mysql -uroot -p123456
-- 執行匯入
source d:/a.sql
-- 不登入資料庫
mysql -uroot -pxxxxxx 庫<備份檔案

保證這個資料庫名存在,資料庫存在,才能匯入成功

8.資料庫的規約,三大正規化

8.1 為什麼需要資料規範化?

  • 資訊重複

  • 更新異常

  • 刪除異常

    • 無法正常刪除資訊
  • 插入異常

    • 無法正常顯示資訊

8.2 三大正規化 :

8.2.1 第一正規化 1NF:

原子性:保證每一列不可分

8.2.2 第二正規化 2NF:

前提:滿足1NF

每張表只描述一件事務

8.2.3 第三正規化 3NF:

前提:滿足 2NF

第三正規化需要確保資料表中的每一列資料都PRIMARY KEY直接相關,不能間接相關

那麼在實際的應用中呢,正規化雖然是正規化,但是是有問題的,有時候為了效能,可以不滿足1NF 2NF 3NF

8.4 規範性和效能的問題

阿里規約:關聯查詢的表不可超過三張

  • 考慮商業化的需求和目標 (成本,使用者體驗)資料庫的效能更重要
  • 在規範效能的問題的時候,需要適當放的考慮一下規範性
  • 故意給某些表增加一些冗餘的欄位 (從多表聯查變為單表查詢)
  • 故意增加一些計算列 (從大資料量降低為小資料量的查詢)

9.JDBC

Java操作資料庫

9.1 資料庫驅動

驅動:音效卡,顯示卡,資料庫

eg.資料庫需要驅動程式才能執行

9.2JDBC

SUN公司為了簡化開發人員的(對資料庫統一的)操作,提供了一個(Java)操作,按照具體的規範去做

匯入依賴的包

java.sql

javax.sql

需要的jar包,不然載入不了

9.3 java操作資料庫

1.載入驅動
Class.forName("com.mysql.jdbc.Driver");
2.使用者資訊和URL

mysql版本

String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=false";
String name="root";
String password="123456";

oracle版本

String url="jdbc:oracle:thin@localhost1521:sid";
3.連線
Connection c=DriverManager.getConnection(url,name,password);
4.SQL的物件:操作SQL

和mySQL操作相同,見名知意

c.rollback();
c.commit();
c.setAutoCommit(false);
5.執行SQL的物件:執行SQL

和SQL操作相同,也是見名知意的

Statement s=c.createStatement();
s.executeQuery();
s.execute();
s.executeUpdate();
6.獲得結果集

不知道什麼型別就用Object就可了

ResultSet rs=s.executeQuery(s1);
rs.getObject();
7.釋放連線
rs.close();
s.close();
c.close();

9.4 SQL注入

使用statement物件(不安全的)用java操作資料庫

jdbc中的statement物件用於向資料庫傳送SQL語句,想完成對於資料庫的增刪改查,只需要通過這個物件向資料庫傳送增刪改查的訊號即可。

Statement物件的executeUpdate 方法,用於向資料庫傳送增,刪,改,查的SQL語句,executeUpdate執行完成後,將會返回一個整數(告知我們幾行發生變化,提示資訊和SQL相同)

1.預備工作:封裝一個工具類

public class sqlIn {
 private Connection c;
 private Statement s;
 private ResultSet rs;
 public void drive() throws ClassNotFoundException, SQLException {
     Class.forName("com.mysql.jdbc.Driver");
     String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=false";
     String name="root";
     String password="123456";
     c= DriverManager.getConnection(url,name,password);
     s=c.createStatement();
 }
 public void login(String name,String pwd) throws SQLException {
     String opr="select * from `login` where `name`='"+name+"' and password='"+pwd+"'";
     rs=s.executeQuery(opr);
     while(rs.next()){
         System.out.println(rs.getObject("name"));
         System.out.println(rs.getObject("password"));
     }
 }
}

2.正常查詢

public static void main(String[] args) throws SQLException, ClassNotFoundException {
     sqlIn p=new sqlIn();
     p.drive();
     p.login("Tom","123456");
 }

3.SQL注入

欺騙伺服器的規範

sql存在漏洞 ,違法的字串拼接

select * from `tableName` where `rowName1`=' 'or 1=1' `rowName2`=' 'or 1=1'

程式碼實現

public static void main(String[] args) throws SQLException, ClassNotFoundException {
     sqlIn p=new sqlIn();
     p.drive();
     p.login(  " 'or '1=1"  ,   " 'or '1=1"  );
 }

9.5 安全的物件

java一個專門防止SQL注入的類: PreparedStatement

接上邊的9.4的類

java操作資料庫

1.新增資料

public void insert(int id,String name,String pwd) throws SQLException {
   String opr="insert into login(`id`,`name`,`password`) values(?,?,?)";
   ps=c.prepareStatement(opr);//c->connection 物件
   ps.setInt(1,id);
   ps.setString(2,name);
   ps.setString(3,pwd);
   ps.executeUpdate();//執行更新 否則無效
}
public static void main(){
p.insert(13,"ppd1234","91881qq");插入
}

2.刪除資料

public void delete(int id) throws SQLException {
   String opr="delete from `login` where id="+Integer.valueOf(id);
   ps=c.prepareStatement(opr);
   ps.executeUpdate();
}
public static void main(String args[]){
p.delete(1);
}

3.更新資料和查詢資料不多解釋,opr字串就是SQL中的操作,Java執行excuteUpdate()就能成功

9.6使用IDEA連線資料庫

Community版本:右邊欄

Education版本:https://blog.csdn.net/cnds123321/article/details/102854508

踩了好多坑才連線上 嗚嗚嗚///

9.7 Java執行事務

java操作事務和SQL操作事務是一樣的同樣遵循ACID原則

如果不瞭解什麼是事務 請回到 5事務和業務章節學習

eg.使用者轉賬

public void accountPay(String fromAccount,String toAccount,int Money) throws SQLException {
   try{
       c.setAutoCommit(false);
       StringBuilder sb1=new StringBuilder();
       sb1.append("update account set money=money-").append(Integer.valueOf(Money).toString()).append(" where `name`= '").append(fromAccount).append("'");
       ps=c.prepareStatement(sb1.toString());
       ps.executeUpdate();
       StringBuilder sb2=new StringBuilder();
       sb2.append("update account set money=money+").append(Integer.valueOf(Money).toString()).append(" where `name` = '").append(toAccount).append("'");
       ps=c.prepareStatement(sb2.toString());
       ps.executeUpdate();
   }catch (SQLException e1){
       try{
           c.rollback();//失敗了 先回滾 錢不能沒 ...
       }catch(SQLException e2){
           e1.printStackTrace();
           e2.printStackTrace();
       }
   }finally{
       c.setAutoCommit(true);
       System.out.println("Successful!");
   }
public static void main(String args[]){
p.accountPay("Weiwei","Liping",500);
}

9.8 資料庫連線

資料庫連線--執行完畢--釋放

連線--釋放 十分的浪費資源

通俗解釋:就是你去銀行,只有一個服務員,你進去,為你服務,你出去了,銀行關閉,下一個人再進來,在連線,服務完,再關閉。而連線池的作用就是設定多個服務員,每個服務員都在等待,銀行不會關閉。

可以用別人寫好的,例如:DBCP,C3P0,Tomcat ,Druld:Alibaba

也可以自己用java手動實現一個(DataSource)介面

匯入依賴:

DBCP :

commons-dbcp2-2.7.0.jar

commons-pool2-2.8.0.jar

使用封裝的工具類,測試程式碼和原來的沒有任何的區別

10.基礎完結散花,撒花,撒歡,撒歡兒