曾經的Mysql學習筆記

文件保存數據缺點:

​ 文件的安全性問題

​ 文件不利於數據查詢和管理

​ 文件不利於存儲海量數據

​ 文件在程序中控制不方便

連接服務器

mysql -h 127.0.0.1(默認本地連接) -P 3306(端口號) -u root(用戶名)-p xxx(密碼,明文,不推薦)

注意:連接前需要打開mysql服務 (運行窗口:services.msc 打開服務)或者

​ 命令行 net start/stop MySQL57(你的服務名)開啓/關閉服務

MYSQL架構

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jlkxt8TN-1585360158449)(F:\courseware_note\MySQL課件\mysql_framework.png)]

(1)MySQL向外提供的交互接口(Connectors)

​ Connectors組件,是MySQL向外提供的交互組件,如java,.net,php等語言可以通過該組件來操作SQL語 句,實現與SQL的交互。

(2)管理服務組件和工具組件(Management Service & Utilities)

​ 提供對MySQL的集成管理,如備份(Backup),恢復(Recovery),安全管理(Security)等

(3)連接池組件(Connection Pool)

​ 負責監聽對客戶端向MySQL Server端的各種請求,接收請求,轉發請求到目標模塊。每個成功連接MySQL Server的客戶請求都會被創建或分配一個線程,該線程負責客戶端與MySQL Server端的通信,接收客戶端發送的命令,傳遞服務端的結果信息等。

(4)SQL接口組件(SQL Interface)

​ 接收用戶SQL命令,如DML,DDL和存儲過程等,並將最終結果返回給用戶。

(5)查詢分析器組件(Parser)

​ 首先分析SQL命令語法的合法性,並嘗試將SQL命令分解成數據結構,若分解失敗,則提示SQL語句不合理。

(6)優化器組件(Optimizer)

對SQL命令按照標準流程進行優化分析。

(7)緩存主件(Caches & Buffers)

緩存和緩衝組件

(8)插件式存儲引擎(Pluggable Storage Engines)

​ MySQL存儲引擎在MySQL中扮演重要角色,其作比較重要作用,大致歸結爲如下兩方面:

​ 作用一:管理表創建,數據檢索,索引創建等

​ 作用二:滿足自定義存儲引擎開發。

(9)物理文件(File System)

實際存儲MySQL 數據庫文件和一些日誌文件等的系統,如Linux,Unix,Windows等。

存儲引擎的查看及對比

查看存儲引擎

show engines;

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rpFcgYse-1585360158451)(F:\courseware_note\MySQL課件\showengines.png)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BJ07tGVq-1585360158452)(F:\courseware_note\MySQL課件\enginnes.png)]

不同的存儲引擎,創建表的文件不一樣。

MyISAM 在數據目中有三個不同的文件,分別是

.frm:表結構

.MYD:表數據

.MYI:表索引

innodb 在數據目錄中有兩個不同的文件,分別是

.frm:表結構

.ibd:表數據,表索引

總結:

常用的三種引擎對比(innodb,MyISAM,memory)

//TODO

SQL分類

DDL數據定義語言

用來維護存儲數據的結構

代表指令: create, drop, alter

DML數據操縱語言

用來對數據進行操作

代表指令: insert,delete,update

DML中又單獨分了一個DQL數據查詢語言

代表指令: select

DCL數據控制語言

主要負責權限管理和事務

代表指令: grant,revoke,commit

庫的操作

創建庫
CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [, create_specification] ...]
 
create_specification:   
[DEFAULT] CHARACTER SET charset_name    //指定數據庫採用的字符集
[DEFAULT] COLLATE collation_name        //指定數據庫字符集的校驗規則
查看系統默認字符集以及校驗規則

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SxuVU3kZ-1585360158452)(F:\courseware_note\MySQL課件\charset_collation.png)]

查看數據庫支持的字符集/校驗規則
show charset;
show collation;

注意:

​ utf8_ general_ ci [不區分大小寫]

​ utf8_ bin [區分大小寫]

操作庫
顯示創建語句
mysql> show create database mytest;
+----------+----------------------------------------------------------------+ 
| Database | Create Database                                                | 
+----------+----------------------------------------------------------------+ 
| mysql    | CREATE DATABASE `mytest` /*!40100 DEFAULT CHARACTER SET utf8 */ | 
+----------+----------------------------------------------------------------+

說明:
MySQL 建議我們關鍵字使用大寫,但是不是必須的。

​ 數據庫名字的反引號``, 是爲了防止使用的數據庫名剛好是關鍵字

​ /*!40100 default… */ 這個不是註釋,表示當前mysql版本大於4.01版本,就執行這句話

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-l2SDD0bx-1585360158454)(F:\courseware_note\MySQL課件\without_keyword.png)]

修改數據庫

對數據庫的修改主要指的是修改數據庫的字符集,校驗規則

create—>alter 語法相同

刪除數據庫
DROP DATABASE [IF EXISTS] db_ name;

執行刪除之後的結果:

數據庫內部看不到對應的數據庫

對應的數據庫文件夾被刪除,級聯刪除,裏面的數據表全部被刪

不要隨意刪除數據庫!!!!

備份和恢復

備份操作(退出連接) 不用連接數據庫也可執行

備份庫

mysqldump -P3306 -u root -p 密碼 -B 數據庫名1 數據庫名2 ... > 數據庫備份存儲的文件路徑.sql

備份表

mysqldump -P3306 -u root -p 密碼 -B 數據庫名 表1 表2 ... > 數據庫備份存儲的文件路徑.sql

恢復

source 備份的路徑.sql;

注意:

​ 如果備份一個數據庫時,沒有帶上-B參數, 在恢復數據庫時,需要先創建空數據庫,然後使用數據庫,再使

用source來還原。

查看連接情況
show processlist

​ 告訴我們當前有哪些用戶連接到我們的MySQL,如果查出某個用戶不是你正常登陸的,很有可能你的數據庫被 人入侵了。如果發現自己數據庫比較慢時,可以用這個指令來查看數據庫連接情況。

表的操作

創建表
CREATE TABLE table_name (    
    field1 datatype [commit],    
    field2 datatype [commit],    
    field3 datatype ) character set 字符集 collate 校驗規則 engine 存儲引擎;
    //commit 註釋 對字段的描述
查看錶結構
desc 表名;

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VSTR6bi6-1585360158454)(F:\courseware_note\MySQL課件\tablestructure.png)]

修改表

修改表的結構,比如字段名字,字段大小,字段類型,表的字符集類型,表的存儲引擎等等。

添加(add)/修改(modify)/刪除(drop)字段等等。這時我們就需要修改表。

ALTER TABLE  tablename ADD (column datatype [DEFAULT expression][,column datatype]...);
 
ALTER TABLE  tablename MODIfy (column datatype [DEFAULT expression][,column datatype]...);
 
ALTER TABLE  tablename DROP (column);

定位添加一個字段(對原表數據沒有影響) add

 alter table 表名 add field datatype [comment 'xxx' after field(已存在字段)];

修改一個字段類型或字段類型長度 modify

alter table 表名 modify field datatype 約束條件;

刪除一個字段 drop(刪除字段會將對應列的數據都刪除)

alter table 表名 drop field;

修改表名 rename (to) to可以省略

 alter table 表名 rename (to) 新名稱;

修改字段名(列名) change eg. 將name 改爲 xingming。

alter table 表名 change name xingming varchar(60); --新字段需要完整定義
刪除表
DROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name] ...

數據類型

數據類型分類

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-bi2y0FW3-1585360158455)(F:\courseware_note\MySQL課件\datatype.png)]

數值類型

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-bU0KCuCO-1585360158456)(F:\courseware_note\MySQL課件\int.png)]

默認有符號

儘量不使用unsigned,對於int類型可能存放不下的數據,int unsigned同樣可能存放不下,直接將int類型提升爲bigint類型。

bit類型
bit[(M)] : 位字段類型。M表示每個值的位數,1到64。如果M被忽略,默認爲1。

bit字段在顯示時,是按照ASCII碼對應的值顯示。(若插入65,則顯示A)

值只存放0或1,這時可以定義bit(1)。這樣可以節省空間。

float類型
float[(m, d)] [unsigned] : M指定顯示長度,d指定小數位數,佔用空間4個字節

float(4,2)表示的範圍是-99.99 ~ 99.99,MySQL在保存值時會進行四捨五入。

decimal
decimal(m, d) [unsigned] : 定點數m指定長度,d表示小數點的位數 m省略默認爲10 d省略默認爲0

和float的區別:

​ decimal的精度更準確,比float精度更高(float表示的精度大約是七位)

​ decimal最大整數位m爲65,支持小數最大尾數d是30

如果需要更高的精度,使用decimal

字符串類型
char
char(L): 固定長度字符串,L是可以存儲的長度,單位爲字符,最大長度值可以爲255
varchar
varchar(L): 可變長度字符串,L表示字符長度,最大長度65535個字節

char(2)/varchar(2) 可存儲 ab 或者 工大 按個數算。

關於varchar(len),len到底是多大,這個len值,和表的編碼密切相關:
varchar長度可以指定爲0到65535之間的值,但是有1 - 3 個字節用於記錄數據大小,所以說有效字節數是 65532。

​ 當我們的表的編碼是utf8時,varchar(n)的參數n最大值是65532/3=21844[因爲utf中,一個字符佔用3個字 節]

​ 如果編碼是gbk,varchar(n)的參數n最大是65532/2=32766(因爲gbk中,一個字符佔用2字節)。

char和varchar的比較

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-GQcbEfTI-1585360158456)(F:\courseware_note\MySQL課件\char_varchar.png)]

如何選擇?

總結: (char)定長的磁盤空間比較浪費,但是效率高 。如果數據確定長度一樣,使用char

​ 例如:身份證號,手機號

​ (varchar)變長的磁盤空間比較節省,但是效率低。如果數據長度有變化,使用varchar

​ 例如:姓名,地址。 但是要保證最長的數據可以存儲。

日期和時間類型

常用的日期有如下三個:

​ datetime 時間日期格式 ‘yyyy-mm-dd HH:ii:ss’ 表示範圍從1000到9999,佔用八字節

​ timestamp:時間戳,從1970年開始的 yyyy-mm-dd HH:ii:ss格式和datetime完全一致,佔用四字節

​ date:日期 ‘yyyy-mm-dd’,佔用三字節

timestamp(時間戳)不需要賦值,顯示當前時間

enum和set
enum

枚舉,單選類型

enum('選項1','選項2','選項3',...);       		最多 65535個選項
set

集合,多選類型

set('選項值1','選項值2','選項值3', ...);		  最多 64個選項

該設定只是提供了若干個選項的值,最終一個單元格中,實際只存儲了其中一個值;

而且出於效率考慮,這些值實 際存儲的是“數字”

枚舉enum所對應的數字是1,2,3,4…65535,添加枚舉值的時候,也可以添加對應的編號 (但不建議,不利於閱讀)

集合set所對應的的數字是1,2,4,8,16,32…最多64個選項

表的約束

約束字段的是字段的數據類型,但單數據類型約束很單一。

爲了更好地保證數據的合法性,從業務邏輯角度保證數據的正確性,需要表的約束

空屬性

兩個值:null(默認值)/ not null

因爲空數據沒辦法參與運算,實際開發中儘可能保證字段不爲空

not null 約束的字段 插入數據時不給該字段插值則插入失敗

默認值
mysql> create table tt10 (    
    -> name varchar(20) not null,    
    -> age tinyint unsigned default 0,    
    -> sex char(2) default '男'    
    -> ); 

數據在插入的時候不給該字段賦值,就使用默認值

列描述

comment,專門用來表述字段,根據創建語句保存,方便程序員或DBA(數據庫管理員)進行了解

注意:

​ comment 註釋信息通過 show create 命令查看 , desc 命令查看不到

zerofill(補零)
int(5) unsigned zerofill;

如果寬度小於設定的寬度(int(5),這裏設置的是 5),自動填充0。

若插入1,則顯示00001,zerofill 隻影響顯示結果,實際儲存的還是1 (可用hex()函數證明)

設置zerofill屬性,相當於一種格式化輸出而已

主鍵

primary key

不能重複,不能爲空,主鍵所在列通常是整數類型

一個表只能有一個主鍵,若多個字段作爲主鍵,可以使用複合主鍵

mysql> create table tt14( 
    -> id int unsigned, 
    -> course char(10) comment '課程代碼', 
    -> score tinyint unsigned default 60 comment '成績', 
    -> primary key(id, course) -- id和course爲複合主鍵
    -> ); 

追加和刪除主鍵

alter table 表名 add primary key(字段列表);           //	 追加主鍵
alter table 表名 drop primary key;                   //	刪除主鍵
自增長

​ auto_increment:當對應的字段,不給值,會自動的被系統觸發,系統會從當前字段中已經有的最大值+1操

作, 得到一個新的不同的值。

​ 自增長的特點:

​ 任何一個字段要做自增長,前提是本身是一個索引(key一欄有值)

​ 自增長字段必須是整數

​ 一張表最多只能有一個自增長

通常和主鍵搭配使用,作爲邏輯主鍵。

唯一鍵

​ unique:

​ 表中往往有很多字段都需要唯一性,但表中只能有一個主鍵,唯一鍵就解決了多個字段需要唯一性約束的問題。

​ 唯一鍵與主鍵的區別 :

​ 主鍵不允許爲空

​ 唯一鍵允許爲空,而且允許多個值爲空(空字段不做唯一性比較)

外鍵

​ 定義於主表和從表之間的關係

foreign key (字段名) references 主表(列) ;

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ze7ou0n4-1585360158457)(F:\courseware_note\MySQL課件\foreign.png)]

外鍵約束主要定義在從表上,主表必須有主鍵約束或者唯一鍵約束

主鍵表

create table myclass (        
    id int primary key,        
    name varchar(30) not null comment'班級名'    
);

從表

create table stu (        
    id int primary key,        
    name varchar(30) not null comment '學生名',        
    class_id int,        
    foreign key (class_id) references myclass(id)    
); 

插入

 insert into myclass values(10, 'C++大牛班'),(20, 'java大神班'); 
 insert into stu values(100, '張三', 10),(101, '李四',20); 

外鍵的列數據必須在主表存在或者爲null

 insert into stu values(102, 'wangwu',30);   //沒有30班級,所以插入失敗
 insert into stu values(102, 'wangwu', null); //表示來了一個學生,還沒有分配班級

基本查詢(增刪改查)

CRUD : Create, Retrieve,Update,Delete

create

INSERT [INTO] table_name [(column [, column] ...)]     
VALUES (value_list) [, (value_list)] ...   
value_list: value, [, value] ...
單行+全列插入

全列插入table_name後的列名可省

INSERT INTO students VALUES (101, 10001, '孫悟空', '11111'); 
多行+指定列插入

value_list 數量必須和指定列數量及順序一致

INSERT INTO students (id, sn, name) VALUES 
(102, 20001, '曹孟德'), 
(103, 20002, '孫仲謀'); 
插入否則更新

on duplicate

因爲主鍵或唯一鍵的唯一性約束導致的重複插入失敗

INSERT INTO students (id, sn, name) VALUES (100, 10010, '唐大師')    
ON DUPLICATE KEY UPDATE sn = 10010, name = '唐大師'; 
Query OK, 2 rows affected (0.47 sec)
 
-- 0 row affected:      表中有衝突數據,但衝突數據的值和 update 的值相等 
-- 1 row affected:      表中沒有衝突數據,數據被插入 
-- 2 row affected:      表中有衝突數據,並且數據已經被更新
替換

replace(推薦使用)

-- 主鍵 或者 唯一鍵 沒有衝突,則直接插入; 
-- 主鍵 或者 唯一鍵 如果衝突,則刪除後再插入
 
REPLACE INTO students (sn, name) VALUES (20001, '曹阿瞞'); Query OK, 2 rows affected (0.00 sec)
 
-- 1 row affected:      表中沒有衝突數據,數據被插入 
-- 2 row affected:      表中有衝突數據,刪除後重新插入

Retrieve

select列
全列查詢
select *from table_name;
-- 通常情況下不建議使用 * 進行全列查詢 
-- 1. 查詢的列越多,意味着需要傳輸的數據量越大;
-- 2. 可能會影響到索引的使用。(索引待後面課程講解)
指定列查詢

指定列的順序不需要按定義表的順序來

查詢字段爲表達式
SELECT id, name, yingyu + 10 FROM exam_result; 
SELECT id, name, yuwen + shuxue + yingyu FROM exam_result; 
-- 數據庫數據不發生改變,只是查詢顯示改變
查詢結果指定別名
SELECT id, name, yuwen + shuxue + yingyu (as) total FROM exam_result;  -- as 不建議省略
結果去重

distinct

SELECT DISTINCT shuxue FROM exam_result;    -- 重複結果不顯示
where條件
比較運算符

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EPqAhNPZ-1585360158458)(F:\courseware_note\MySQL課件\operator.png)]

where條件使用表達式
-- WHERE 條件中使用表達式 
-- 別名不能用在 WHERE 條件中
 
SELECT name, yuwen + shuxue + yingyu 總分 FROM exam_result     
WHERE yuwen + shuxue + yingyu < 200;
Null的查詢

 SELECT name, qq FROM students WHERE qq IS NOT NULL; 
 +-----------+-------+ 
 | name      | qq    | 
 +-----------+-------+ 
 | 孫悟空     | 11111 | 
 +-----------+-------+ 
 1 row in set (0.00 sec)
 
-- NULL 和 NULL 的比較,= 和 <=> 的區別
 
SELECT NULL = NULL, NULL = 1, NULL = 0; 
+-------------+----------+----------+ 
| NULL = NULL | NULL = 1 | NULL = 0 | 
+-------------+----------+----------+ 
|        NULL |     NULL |     NULL | 
+-------------+----------+----------+ 
1 row in set (0.00 sec)
 
SELECT NULL <=> NULL, NULL <=> 1, NULL <=> 0; 
+---------------+------------+------------+ 
| NULL <=> NULL | NULL <=> 1 | NULL <=> 0 | 
+---------------+------------+------------+ 
|             1 |          0 |          0 | 
+---------------+------------+------------+ 
1 row in set (0.00 sec)

結果排序

order by

– ASC 爲升序(從小到大)

– DESC 爲降序(從大到小)

– 默認爲 ASC

排序時,NULL 視爲比任何值都小,升序出現在最上面

單字段排序
SELECT name, qq FROM students ORDER BY qq DESC;
多字段排序
SELECT name, shuxue, yingyu, yuwen FROM exam_result ORDER BY shuxue DESC, yingyu, yuwen; 

多字段排序具有優先級,對orderby後的第一個字段進行設定的排序,若第一個字段值相等

則利用第二個字段設定的順序進行比較

然後對第一個字段的排列,如果第二個字段的值也相等,則進行第三個字段的比較,再進行第一個字段的排列

總的來說,實際上排列的只是orderby後的第一個字段,後面的比較都是爲了第一個字段值相等時的情況服務的

使用表達式,別名
SELECT name, yuwen + yingyu + shuxue FROM exam_result  ORDER BY yuwen + yingyu + shuxue DESC; 

SELECT name, yuwen + yingyu + shuxue 總分 FROM exam_result   ORDER BY 總分 DESC; 
篩選分頁結果
-- 起始下標爲 0
 
-- 從 0 開始,篩選 n 條結果 
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;
 
-- 從 s 開始,篩選 n 條結果 
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s, n;
 
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
-- 從 s 開始,篩選 n 條結果,相對其他語法清晰
-- 偏移量算法: pageSize * (PageNumber-1)pageSize:一頁多少條 PageNumber:多少頁

建議:對未知表進行查詢時,好加一條 LIMIT 1,避免因爲表中數據過大,查詢全表數據導致數據庫卡死

LIMIT m,n : 表示從第m+1條開始,取n條數據;

LIMIT n : 表示從第0條開始,取n條數據,是limit(0,n)的縮寫。

Update

對查詢到的結果進行列值更新

UPDATE table_name SET column = expr [, column = expr ...]    
[WHERE ...] [ORDER BY ...] [LIMIT ...]
更新值爲具體值
一次更新一個列
UPDATE table_name SET column = expr WHERE name = 'value'; 
一次更新多個列
UPDATE table_name SET column = expr, column = expr ...  WHERE name = 'value'; 
更新值在原值基礎上變更

例如:給數學成績加30分

-- 查看原數據 
SELECT name, shuxue, yuwen + shuxue + yingyu 總分 FROM exam_result    ORDER BY 總分 LIMIT 3; 
+-----------+--------+--------+ 
| name      | shuxue | 總分   | 
+-----------+--------+--------+ 
| 宋公明     |     65 |    170 | 
| 劉玄德     |     85 |    185 | 
| 曹孟德     |     60 |    197 | 
+-----------+--------+--------+

 -- 數據更新,不支持 shuxue += 30 這種語法 *********
 UPDATE exam_result SET shuxue = shuxue + 30    ORDER BY yuwen + shuxue + yingyu LIMIT 3;    -- 查看更新後數據 
 -- 思考:這裏還可以按總分升序排序取前 3 個麼?  不可以 因爲更新後總分已經發生改變
 SELECT name, shuxue, yuwen + shuxue + yingyu 總分 FROM exam_result    WHERE name IN ('宋公明', '劉玄德', '曹孟德'); 
 +-----------+--------+--------+ 
 | name      | shuxue | 總分   |
 +-----------+--------+--------+ 
 | 曹孟德     |     90 |    227 | 
 | 劉玄德     |    115 |    215 | 
 | 宋公明     |     95 |    200 | 
 +-----------+--------+--------+ 
 3 rows in set (0.00 sec)
 
-- 按總成績排序後查詢結果 
SELECT name, shuxue, yuwen + shuxue + yingyu 總分 FROM exam_result    ORDER BY 總分 LIMIT 3; 
+-----------+--------+--------+ 
| name      | shuxue | 總分   | 
+-----------+--------+--------+ 
| 宋公明     |     95 |    200 | 
| 劉玄德     |    115 |    215 | 
| 唐三藏     |     98 |    221 | 
+-----------+--------+--------+ 
3 rows in set (0.00 sec)

注意: 沒有 WHERE 子句,則更新全表 慎用!!!!

Delete

DELETE FROM  table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]

注意:delete刪除之後,自增id也會在原值上增長

刪除整表操作要慎用!delete刪除整表數據並不會刪除表結構

截斷表
TRUNCATE [TABLE] table_name

注意:此操作慎用

Delete和Truncate的區別:

delete:

​ 1.可以根據條件刪除部分數據

​ 2.可以刪除整個表的數據,返回刪除的記錄數

​ 3.相對truncate速度慢

​ 4.不會重置auto_increment的值

truncate:

​ 1.只能對整表操作,不能像 DELETE 一樣針對部分數據操作;

​ 2.實際上 MySQL 不對數據操作,所以比 DELETE 更快

​ 3.會重置 AUTO_INCREMENT 項

插入查詢結果

INSERT INTO table_name [(column [, column ...])] SELECT ...

案例:刪除表中的重複記錄,重複的數據只能有一份

實現步驟:

​ 1.創建一個跟原表一模一樣的結構的表

第一種方式:

show create table table_name;
 -- 查詢表結構,重新創建一個一樣的表

第二種方式:

create table 新表名 like 原表名;

​ 2.查詢原表的數據,並且去重

select distinct id,name from 原表;

​ 3.查詢原表去重的數據插入到新表

insert into 新表名(id,name)select distinct id,name from 原表;

​ 4.刪除原表

drop table 原表名;

​ 5.講新表名字改爲原表名

alter table 新表名 rename to 原表名;

聚合函數

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EGdaWPF0-1585360158459)(F:\courseware_note\MySQL課件\function.PNG)]

注意:使用*做統計,不受NULL影響。

​ 用列做統計,受NULL影響。

group by子句(分組查詢)

select column1, column2, .. from table group by column;

案例:

準備工作,創建一個僱員信息表(來自oracle 9i的經典測試表)

​ EMP員工表

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-NqQtFL2V-1585360158459)(F:\courseware_note\MySQL課件\emp.png)]

​ DEPT部門表

​ SALGRADE工資等級表

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-oSBGXkJT-1585360158460)(F:\courseware_note\MySQL課件\dept.png)]

顯示每個部門的平均工資和最高工資

select deptno,avg(sal),max(sal) from EMP group by deptno;

每個部門的每種崗位的平均工資和最低工資

 select avg(sal),min(sal),job, deptno from EMP group by deptno, job;

顯示平均工資低於2000的部門和它的平均工資 having和group by配合使用,對group by結果進行過濾

select avg(sal) as myavg from EMP group by deptno having myavg<2000;

內置函數

日期函數

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-D2FEwFbO-1585360158461)(F:\courseware_note\MySQL課件\date.PNG)]

案例:創建一個留言表

mysql> create table msg (
    ->  id int primary key auto_increment,    
    ->  content varchar(30) not null,    
    ->  sendtime datetime    
    -> );

顯示所有留言信息,發佈日期只顯示日期,不用顯示時間

select content,date(sendtime) from msg;

查詢在2分鐘內發佈的帖子

select * from msg where date_add(sendtime, interval 2 minute) > now();

字符串函數

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Jlf2i8NC-1585360158461)(F:\courseware_note\MySQL課件\String.PNG)]

顯示student表中的信息,顯示格式:“XXX的語文是XXX分,數學XXX分,英語XXX分”

select concat(name, '的語文是',chinese,'分,數學是',math,'分') as '分數' from student;

注意:length函數返回字符串長度,以字節爲單位。如果是多字節字符則計算多個字節數;如果是單字 節字符則算作一個字節。比如:字母,數組算作一個字節,中文表示多個字節數(與字符集編碼有關)

以首字母小寫的方式顯示所有員工的姓名

-- 分析SMITH -> sMITH

-- SMITH -> S ->s
-- s MITH ->sMITH
-- 要用到 subString concat lcase
select concat(lcase(substring(ename, 1, 1)),substring(ename,2)) from EMP;

數學函數

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DdSei15i-1585360158462)(F:\courseware_note\MySQL課件\Math.PNG)]

其他函數

user() 查詢當前用戶

md5(str)對一個字符串進行md5摘要,摘要後得到一個32位字符串

database()顯示當前正在使用的數據庫

password()函數,MySQL數據庫使用該函數對用戶加密

ifnull(val1, val2) 如果val1爲null,返回val2,否則返回val1的值

ifnull(null,null)結果也爲null,是第二個null

-- 計算出員工的年薪(包含獎金),但是部分員工獎金爲null
select ename,sal*12+comm from emp;
-- 無獎金的員工得到的年薪結果都爲null null參與運算都爲null
select ename,sal*12+ifnull(comm,0) from emp;
練習

​ 查找字符串’10,A,B’ 中逗號’,'出現的次數cnt

select length('10,A,B')-length((replace('10,A,B',',',''))) as cnt;

複合查詢(重點)

多表查詢

僱員名、僱員工資以及所在部門的名字

-- 因爲上面的數據來自EMP和DEPT表,因此要聯合查詢
select * from EMP,DEPT
-- 其實我們只要emp表中的deptno = dept表中的deptno字段的記錄
select EMP.ename, EMP.sal, DEPT.dname from EMP, DEPT where EMP.deptno = DEPT.deptno;

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pzLNaV37-1585360158463)(F:\courseware_note\MySQL課件\tables.png)]

顯示各個員工的姓名,工資,及工資級別

select ename, sal, grade from EMP, SALGRADE where EMP.sal between losal and hisal;

自連接

指在同一張表連接查詢

顯示員工FORD的上級領導的編號和姓名(mgr是員工領導的編號–empno)

方式一:子查詢

select empno,ename from emp where emp.empno=(select mgr from emp where ename='FORD');

方式二:多表查詢(自查詢)

-- 使用到表的別名 
select leader.empno,leader.ename from emp leader, emp worker where leader.empno = worker.mgr and worker.ename='FORD';
-- 利用別名將一個表當兩個表進行多表查詢,也叫自連接

子查詢(嵌套查詢)

子查詢是指嵌入在其他sql語句中的select語句,也叫嵌套查詢

單行子查詢

指子查詢只返回單列,單行數據;

顯示SMITH同一部門的員工

select * from EMP WHERE deptno = (select deptno from EMP where ename='smith');
多行子查詢

返回單列多行數據

in關鍵字

查詢和10號部門的工作相同的僱員的名字,崗位,工資,部門號,但是不包含10自己的

select ename,job,sal,empno from emp where job in (select distinct job from emp where deptno=10) and deptno<>10;
all關鍵字

顯示工資比部門30的所有員工的工資高的員工的姓名、工資和部門號

select ename, sal, deptno from EMP where sal > all(select sal from EMP where deptno=30);
select ename, sal, deptno from EMP where sal > (select max(sal) from EMP where deptno=30);
any關鍵字

顯示工資比部門30的任意員工的工資高的員工的姓名、工資和部門號

select ename, sal, deptno from EMP where sal > any(select sal from EMP where deptno=30);
多列子查詢

指查詢返回多個列數據的子查詢語句

案例:查詢和SMITH的部門和崗位完全相同的所有僱員,不含SMITH本人

select ename from EMP where (deptno, job)=(select deptno, job from EMP where ename='SMITH') and ename <> 'SMITH'; 
在from子句中使用子查詢

子查詢語句出現在from子句中。這裏要用到數據查詢的技巧,把一個子查詢當做一個臨時表使用。

顯示高於自己部門平均工資的員工的姓名、部門、工資、平均工資

select ename, deptno, sal, format(asal,2) from EMP,(select avg(sal) asal, deptno dt from EMP group by deptno) tmp where EMP.sal > tmp.asal and EMP.deptno=tmp.dt;

查找每個部門工資最高的人的姓名、工資、部門、最高工資

select EMP.ename, EMP.sal, EMP.deptno, ms from EMP, (select max(sal) ms, deptno from EMP group by deptno) tmp  where EMP.deptno=tmp.deptno and EMP.sal=tmp.ms;

顯示每個部門的信息(部門名,編號,地址)和人員數量

方法1:使用多表(缺點:求出多表的笛卡爾積再過濾)

select DEPT.dname, DEPT.deptno, DEPT.loc,count(*) '部門人數' from EMP, DEPT where EMP.deptno=DEPT.deptno group by DEPT.deptno,DEPT.dname,DEPT.loc;

方法2:使用子查詢

-- 1. 對EMP表進行人員統計
select count(*), deptno from  EMP group by deptno; 
-- 2. 將上面的表看作臨時表 
select DEPT.deptno, dname, mycnt, loc from DEPT, (select count(*) mycnt, deptno from  EMP group by deptno) tmp where DEPT.deptno=tmp.deptno;
合併查詢

爲了合併多個select的執行結果,可以使用集合操作符 union,union all。(相同子集纔可以合併)

union

用於取得兩個結果集的並集。當使用該操作符時,會自動去掉結果集中的重複行。

案例:將工資大於2500或職位是MANAGER的人找出來

 select ename, sal, job from EMP where sal>2500 union     
 select ename, sal, job from EMP where job='MANAGER';
union all

於取得兩個結果集的並集。當使用該操作符時,不會去掉結果集中的重複行。

 select ename, sal, job from EMP where sal>2500 union all    
 select ename, sal, job from EMP where job='MANAGER'; 

應用場景:

​ 複雜的查詢拆分

​ 查的結果來自不同表

表的內連和外連(重點)

內連接

接實際上就是利用where子句對兩種表形成的笛卡兒積進行篩選,之前用的都是內連接的簡寫形式

-- 標準寫法
select 字段 from 表1 inner join 表2 on 連接條件 and 其他條件;

顯示SMITH的名字和部門名稱

-- 用前面的寫法 
select ename, dname from EMP, DEPT where EMP.deptno=DEPT.deptno and ename='SMITH';
 
-- 用標準的內連接寫法 
select ename, dname from EMP inner join DEPT on EMP.deptno=DEPT.deptno and ename='SMITH';

外連接

左外連接

以左表爲基準,左表完全顯示

select 字段名  from 表名1 left join 表名2 on 連接條件
右外連接

以右表爲基準,右表完全顯示

select 字段 from 表名1 right join 表名2  on  連接條件;

案例

-- 建兩張表 
-- 學生表
create table stu (id int, name varchar(30)); 
insert into stu values(1,'jack'),(2,'tom'),(3,'kity'),(4,'nono'); 
-- 成績表 
create table exam (id int, grade int); 
insert into exam values(1, 56),(2,76),(11, 8);

查詢所有學生的成績,如果這個學生沒有成績,也要將學生的個人信息顯示出來

-- 當左邊表和右邊表沒有匹配時,也會顯示左邊表的數據 右表數據爲null
select * from stu left join exam on stu.id=exam.id; 

對stu表和exam表聯合查詢,把所有的成績都顯示出來,即使這個成績沒有學生與它對應,也要顯示出來

select * from stu right join exam on stu.id=exam.id;

左外連接和右外連接可以相互轉換

列出部門名稱和這些部門的員工信息,同時列出沒有員工的部門

-- 左外連接 
select d.dname, e.* from dept d left join emp e on d.deptno=e.deptno; 
-- 右外連接
select d.dname, e.* from emp e right join dept d on d.deptno=e.deptno;

索引特性(重點)

InnoDB 不支持 全文索引

Memory 不支持 全文索引、聚合索引

MyISAM 不支持 哈希索引、聚合索引

索引:提高數據庫的性能 以插入、更新、刪除的速度爲代價(因爲還需要往二叉樹裏寫入數據) 提高數據的檢索速度

三個不用:不用加內存,不用改程序,不用調SQL

只要執行正確的create index 查詢速度就能提高成百上千倍

常見索引

主鍵索引(primary key)

唯一索引(unique)

普通索引(index)

全文索引(fulltext)–解決中子文索引問題。

基本原理

沒有索引的表進行整表掃描

表中添加索引之後,索引會形成一個二叉樹,索引利用二分查找

添加索引之後時間複雜度由O(n)變爲O(log n)

索引說明

索引佔用磁盤空間,以空間換時間

當添加一條記錄,除了添加到表中,還要維護二叉樹,速度有影響,但不大

當我們添加一個索引,不能夠解決所有查詢問題,需要分別給字段建立索引;(只會對加了索引的字段提高檢索效率)

alter table EMP add index(empno);

創建索引

創建主鍵索引

第一種方式

-- 在創建表的時候,直接在字段名後指定 primary key 
create table  user1(id int primary key, name varchar(30));

第二種方式

-- 在創建表的最後,指定某列或某幾列爲主鍵索引 
create table  user2(id int, name varchar(30), primary key(id)); 

第三種方式

create table  user3(id int, name varchar(30)); 
-- 創建表以後再添加主鍵 alter table user3 add primary key(id);
主鍵索引的特點

一個表中,最多有一個主鍵索引,當然可以使符合主鍵

主鍵索引的效率高(主鍵不可重複)

創建主鍵索引的列,它的值不能爲null,且不能重複

主鍵索引的列基本上是int (約定)

創建唯一索引

三種方式同主鍵索引

唯一索引的特點

一個表中,可以有多個唯一索引

查詢效率高

如果在某一列建立唯一索引,必須保證這列不能有重複數據

如果一個唯一索引上指定not null,等價於主鍵索引

普通索引的創建

第一種方式

create table user8(id int primary key,
                   name varchar(20),
                   email varchar(30),
                   index(name)
                   -- 在表的定義最後,指定某列爲索引 
                  );

第二種方式

create table user9(id int primary key,  name varchar(20),  email varchar(30)); 
alter table user9 add index(name); 
-- 創建完表以後指定某列爲普通索引

第三種方式

create table user10(id int primary key,  name varchar(20),  email varchar(30)); 
-- 創建一個索引名爲 idx_name 的索引    
create index idx_name on user10(name);
普通索引的特點

一個表中可以有多個普通索引,普通索引在實際開發中用的比較多

如果某列需要創建索引,但是該列有重複的值,那麼我們就應該使用普通索引

全文索引的創建

MYSQL提供全文索引機制,但是存儲引擎必須是MyISAM,默認只支持英文,

如果想對中文進行全文檢索,使用sphinx的中文版(coreseek)

java領域中中使用搜索引擎一般用Solr(底層是Lucene(一個搜索庫))

大數據領域中使用搜索引擎一般用Elasticsearch(底層也是Lucene)

CREATE TABLE articles (
    id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
    title VARCHAR(200),
    body TEXT,
    FULLTEXT (title,body)
)engine=MyISAM;
INSERT INTO articles (title,body) VALUES('MySQL Tutorial','DBMS stands for DataBase ...'),    ('How To Use MySQL Well','After you went through a ...'),
('Optimizing MySQL','In this tutorial we will show ...'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...');

explain工具(查看數據庫的執行過程,經常用到的數據庫優化工具)

explain select * from articles where body like '%database%'\G   
-- \G 將查詢結果進行按列打印,可以使每個字段打印到單獨的行。
*************************** 1. row ***************************
					id: 1
					select_type: SIMPLE
					table: articles
					type: ALL possible_keys: NULL
					key: NULL  <== key爲null表示沒有用到索引      
					key_len: NULL          
					ref: NULL         
					rows: 6        
					Extra: Using where 1 row in set (0.00 sec)
全文索引的使用
 -- MATCH AGAINST
 -> SELECT * FROM articles    
 -> WHERE MATCH (title,body) AGAINST ('database');
 *************************** 1. row ***************************
 					id: 1  
 					select_type: SIMPLE
 					table: articles
					type: fulltext 
 					possible_keys: title
 					key: title <= key用到了title      
 					key_len: 0          
 					ref:          
 					rows: 1        
 					Extra: Using where

查詢索引

第一種方法

show keys from 表名;

第二種方法

show index from 表名; 

第三種方法(信息比較簡略)

 desc 表名;

刪除索引(類比索引的創建)

第一種方法(刪除主鍵索引)

alter table 表名 drop primary key; 

第二種方法

 alter table 表名 drop index 索引名; 

第三種方法

 drop index 索引名 on 表名 ;

索引創建原則

比較頻繁作爲查詢條件的字段應該創建索引

唯一性太差的字段不適合單獨創建索引,即使頻繁作爲查詢條件(例如:性別)

更新非常頻繁的字段不適合作創建索引 (更新頻繁需要頻繁維護索引,頻繁更新效率會更低)

不會出現在where子句中的字段不該創建索引(不會用來檢索的字段加索引沒有意義)

事務管理

事務就是一組DML語句組成

這些語句在邏輯上存在相關性,這一組DML語句要麼全部成功,要麼全部失敗,是一個整體。

(例如轉賬給他人50,你的賬戶扣款50的同時他人賬戶收款50纔算成功)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2NVpN9qj-1585360158464)(F:\courseware_note\MySQL課件\transaction.jpg)]

事務的基本操作

開啓事務

start transaction; 

創建保存點

savepoint 保存點名;

回到保存點(根據具體情況)

rollback to 保存點名;
注意事項

如果沒有設置保存點,也可以回滾,只能回滾到事務的開始。直接使用 rollback(前提是事務還沒有提交)

如果一個事務被提交了(commit),則不可以回退(rollback) (建議cheak後再commit)

同理,rollback之後也不能commit,因爲rollback 和 commit後 事務都結束了

rollback to 可以選擇回退到哪個保存點 rollback to之後可以commit,rollback to 只是回到了某一保存點

InnoDB支持事務,MyISAM不支持事務

開始事務可以使 start transaction

事物的隔離級別

場景:多個客戶端同時操作某張表,如何進行隔離操作(保證數據的一致性)

無隔離性的問題
髒讀

是指當一個事務正在訪問數據,並且對數據進行了修改,而這種修改還沒有提交到數據庫中,這時,另外一個事務

也訪問這個數據,然後使用了這個數據。

即一個事務讀到了另一個事務沒有提交的數據。

不可重複讀

是指在一個事務內,多次讀同一數據。在這個事務還沒有結束時,另外一個事務也訪問該同一數據。

在第一 個事務中的兩次讀數據之間,由於第二個事務的修改,那麼第一個事務兩次讀到的的數據可能是不

一樣的。這樣就 發生了在一個事務內兩次讀到的數據是不一樣的

即不能讀到相同的數據內容

解決辦法:如果只有在修改事務完全提交之後纔可以讀取數據,則可以避免該問題

幻讀

是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中

的全部數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼,以後就會發

生操作第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺一樣。

解決辦法:如果在操作事務完成數據處理之前,任何其他事務都不可以添加新數據,則可避免該問題

不可重複讀的重點是修改:同樣的條件, 你讀取過的數據,再次讀取出來發現值不一樣了

幻讀的重點在 於新增或者刪除:同樣的條件, 第1次和第2次讀出來的記錄數不一樣

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-TjGWHskN-1585360158464)(F:\courseware_note\MySQL課件\tran.png)]

設置事務的隔離級別
set session transaction isolation level read uncommitted; -- 設置事務隔離級別爲讀未提交
查看事務的隔離級別
select @@tx_isolation; -- 默認事務隔離級別爲可重複讀(repeatable read)

可串行化案例:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hcINWbp8-1585360158465)(F:\courseware_note\MySQL課件\serializable.png)]

DBMS:數據庫管理系統

事務的ACID特性

原子性

事務是應用中最小的執行單位,就如原子是自然界的最小顆粒,具有不可再分的特徵一樣,事務是應用中不可再分

的最小邏輯執行體。

一致性

事務執行的結果,必須使數據庫從一個一致性狀態,變到另一個一致性狀態。當數據庫只包含事務成功提交的結果

時,數據庫處於一致性狀態。如果系統運行發生中斷,某個事務尚未完成而被迫中斷,而改未完成的事務對數據庫

所做的修改已被寫入數據庫,此時數據庫就處於一種不正確(不一致)的狀態。因此一致性是通過原子性來保證

的。

隔離性

各個事務的執行互不干擾,任意一個事務的內部操作對其他併發事務都是隔離的。也就是說,併發執行的事務之間

不能看到對方的中間狀態,併發執行的事務之間不能互相影響。

持久性

持久性是指一個事務一旦被提交,它對數據庫所做的改變都要記錄到永久存儲其中(如:磁盤)。

視圖

視圖是一個虛擬表,其內容由查詢定義。

視圖包含一系列帶有名稱的列和行數據。視圖的數據變 化會影響到基表,基表的數據變化也會影響到視圖。

基本使用

創建視圖
create view 視圖名 as select語句;
刪除視圖
drop view 視圖名;
視圖的意義

可以簡化查詢,提高了重用性

對數據庫重構,卻不影響程序的運行

提高了安全性能。可以對不同的用戶,設定不同的視圖。

讓數據更加清晰,想要什麼樣的數據,就創建什麼樣的視圖

視圖的規則和限制

與表一樣,必須唯一命名(不能出現同名視圖或表名)

創建視圖數目無限制,但要考慮複雜查詢創建爲視圖之後的性能影響 視圖不能添加索引,也不能有關聯的觸發器

或者默認值

視圖可以提高安全性,必須具有足夠的訪問權限

order by 可以用在視圖中,但是如果從該視圖檢索數據 select 中也含有 order by ,那麼該視圖中的 order by 將被

覆蓋

視圖可以和表一起使用

用戶管理

用戶

用戶信息

MySQL中的用戶,都存儲在系統數據庫mysql的user表中

mysql> select host,user,authentication_string from user;
+-----------+---------------+-------------------------------------------+
| host      | user          | authentication_string                     | 
+-----------+---------------+-------------------------------------------+
| localhost | root          | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| localhost | mysql.session | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| localhost | mysql.sys     | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | 
+-----------+---------------+-------------------------------------------+

字段解釋:

host:表示這個用戶可以從哪個主機登陸,如果是localhost,表示只能從本機登陸

user:用戶名 authentication_string:用戶密碼通過password函數加密後的

*_priv:用戶擁有的權限

創建用戶
create user '用戶名'@'登陸主機/ip' identified by '密碼';
刪除用戶
drop user '用戶名'@'主機名'

只寫用戶名,不寫主機名,不能刪除,它默認是%,%表示所有地方可以登錄的用戶

修改用戶密碼
自己改自己密碼
set password=password('新的密碼');
root用戶修改指定用戶密碼
set password for '用戶名'@'主機名'=password('新的密碼');

數據庫的權限

MySQL數據庫提供的權限列表:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MJBQb0gv-1585360158466)(F:\courseware_note\MySQL課件\list.png)]

給用戶授權 grant

剛創建的用戶沒有任何權限。需要給用戶授權。

grant 權限列表 on 庫.對象名 to '用戶名'@'登陸位置' [identified by '密碼']

權限列表:

grant select on ...
 
grant select, delete, create on ....
 
grant all [privileges] on ... -- 表示賦予該用戶在該對象上的所有權限

*. * 代表本系統中的所有數據庫的所有對象(表,視圖,存儲過程等)

庫.* : 表示某個數據庫中的所有數據對象(表,視圖,存儲過程等) identified by可選。

如果用戶存在,賦予權限的同時修改密碼,如果該用戶不存在,就是創建用戶

-- root 給 litao 賦予賬戶查詢mytest庫的DEPT表的權限 
mysql> grant select on mytest.DEPT to 'litao'@'localhost'; 

如果發現賦權限後,沒有生效,執行如下指令:(數據庫的權限在內存中放着,可能沒有及時刷新)

flush privileges;
-- flush不成功可以退出用戶重新登陸
回收權限 revoke
revoke 權限列表 on 庫.對象名 from '用戶名'@'登陸位置';

-- 回收litao對數據庫的所有權限 
revoke all on mytest.DEPT from 'litao'@'localhost';
面試題

SQL查詢中各個關鍵字的執行先後順序 from > on> join > where > group by > with > having > select > distinct > order by > limit

在MySQL中有例外:having後可以使用別名。

Java的JDBC編程

簡介

​ JDBC(Java DataBase Connectivity,Java數據庫連接)技術的簡稱,是一種用於執行SQL語句的Java

API(由 java.sql.,javax.sql. 包中的一些類和接口組成)。使數據庫開發人員能夠用純Java API 來編寫數據庫應

用程序。

工作原理

JDBC 爲多種關係數據庫提供了統一訪問方式

真正的數據庫訪問操作實現是由各自數據庫廠商提供的。通常把廠商提供的特定於數據庫的訪問API稱爲數據庫

JDBC驅動程序。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-INsgpDTZ-1585360158467)(F:\courseware_note\MySQL課件\JDBC.png)]

使用步驟

命令行中使用MYSQL的步驟

鏈接數據庫(地址,端口,用戶名,密碼)

使用數據庫

創建SQL命令(語句)

執行

返回結果

顯示到控制檯(結果處理)

斷開連接

JDBC使用流程

java:方法通過對象來調用,對象通過類實例化

數據庫操作的步驟進行面向對象的抽象(JDBC API)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-yz3aY1zJ-1585360158468)(F:\courseware_note\MySQL課件\JDBC_lc.png)]

  1. 加載驅動(pom文件中配置MySQL驅動程序,通過Class加載驅動類)

    Class.forName("com.mysql.jdbc.Driver");
    
  2. 創建連接

    Connection connection = DriverManager.getConnection(url)
    

    JDBC規範中對url的定義:

    ​ <databasePrdductName>:Mysql ->mysql H2->h2 Oracle->oracle

    jdbc:<databasePrdductName>://host:port/<databaseName>?param1=value1&param2=value2

    String url = "jdbc:mysql://127.0.0.1:3306/memo?user=root&password=123456&useSSL=false";
    -- 用戶名密碼也可在DriverManager.getConnection(url,user,password);中指定
    

    3.準備SQL語句

    String sql = "select id,name,create_time,modify_time from memo_group";
    -- 寫清楚列名,不要用*
    

    4.創建命令

    Statement statement = connection.createStatement();
    

    5.執行命令

    ResultSet resultSet = Statement.executeQuery(sql);
    

    6.處理結果

    While(resultSet.next()){
    // 每次執行next如果返回true,定位到數據庫記錄的下一條
    // getXxx(int)通過查詢結果記錄的列的下標取值(從1開始),不建議採用這種方式
    // 用getXxx(String)用列名
    	 int id = resultSet.getInt("id");
         String name = resultSet.getString("name");
         LocalDateTime createdTime = resultSet.getTimestamp("created_time").toLocalDateTime();
    //Timestamp ->(toLocalDateTime()) LocalDateTime
    //LocalDateTime ->(Timestamp.valueOf()) Timestamp
         LocalDateTime modifyTime = resultSet.getTimestamp("modify_time").toLocalDateTime();
         System.out.println(id + " " + name + " " + createdTime + " " + modifyTime);
     }
    

    7.關閉結果集

    resultSet.close();
    

    8.關閉操作命令

    statement.close();
    

    9.關閉連接

    connection.close();
    

    類似於模板設計模式 通過變化SQL語句,執行命令和結果處理,來完成插入,更新,刪除操作

    在finally塊中關閉結果集,操作命令,連接或者使用try-with-resources方式自動關閉資源

    try (
                        Connection connection = DriverManager.getConnection(url);
                        Statement statement = connection.createStatement();
                        ResultSet resultSet = statement.executeQuery(sql);
                ) {...}
    

    resultSet,statement,connection都實現了AutoCloseable接口,可以自動關閉

    模板設計模式實現JDBC開發

    模板設計模式+函數接口實現JDBC開發

    JDBC常用接口和類

    JDBC API

    掌握Java JDBC API (位於 java.sql 包下) 即可掌握Java數據庫編程。

    數據庫連接

    獲取Connection對象通常有兩種方式:

    ​ 一種是通過DriverManager的靜態方法獲取

    ​ 一種是通過DataSource(數據源)對象獲取。

    實際應用中會使用DataSource對象。

    數據源:可以複用連接的數據庫連接池

    statement對象

    Statement對象主要是將SQL語句發送到數據庫中。JDBC API中主要提供了三種Statement對象。

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BSSG1XFL-1585360158468)(F:\courseware_note\MySQL課件\statement.png)]

    預編譯命令

    將Statement變爲PrepareStatement,傳入sql,執行命令的時候不傳入sql

    PrepareStatement statement = connection.prepareStatement(sql);
    ResultSet resultSet = Statement.executeQuery();
    

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9bIMtSRz-1585360158469)(F:\courseware_note\MySQL課件\goodstate.png)]

hile(resultSet.next()){
// 每次執行next如果返回true,定位到數據庫記錄的下一條
// getXxx(int)通過查詢結果記錄的列的下標取值(從1開始),不建議採用這種方式
// 用getXxx(String)用列名
int id = resultSet.getInt(“id”);
String name = resultSet.getString(“name”);
LocalDateTime createdTime = resultSet.getTimestamp(“created_time”).toLocalDateTime();
//Timestamp ->(toLocalDateTime()) LocalDateTime
//LocalDateTime ->(Timestamp.valueOf()) Timestamp
LocalDateTime modifyTime = resultSet.getTimestamp(“modify_time”).toLocalDateTime();
System.out.println(id + " " + name + " " + createdTime + " " + modifyTime);
}


7.關閉結果集

```java
resultSet.close();

8.關閉操作命令

statement.close();

9.關閉連接

connection.close();

類似於模板設計模式 通過變化SQL語句,執行命令和結果處理,來完成插入,更新,刪除操作

在finally塊中關閉結果集,操作命令,連接或者使用try-with-resources方式自動關閉資源

try (
                    Connection connection = DriverManager.getConnection(url);
                    Statement statement = connection.createStatement();
                    ResultSet resultSet = statement.executeQuery(sql);
            ) {...}

resultSet,statement,connection都實現了AutoCloseable接口,可以自動關閉

模板設計模式實現JDBC開發

模板設計模式+函數接口實現JDBC開發

JDBC常用接口和類

JDBC API

掌握Java JDBC API (位於 java.sql 包下) 即可掌握Java數據庫編程。

數據庫連接

獲取Connection對象通常有兩種方式:

​ 一種是通過DriverManager的靜態方法獲取

​ 一種是通過DataSource(數據源)對象獲取。

實際應用中會使用DataSource對象。

數據源:可以複用連接的數據庫連接池

statement對象

Statement對象主要是將SQL語句發送到數據庫中。JDBC API中主要提供了三種Statement對象。

[外鏈圖片轉存中…(img-BSSG1XFL-1585360158468)]

預編譯命令

將Statement變爲PrepareStatement,傳入sql,執行命令的時候不傳入sql

PrepareStatement statement = connection.prepareStatement(sql);
ResultSet resultSet = Statement.executeQuery();

[外鏈圖片轉存中…(img-9bIMtSRz-1585360158469)]

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