日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

数据库MYSQL学习系列二

發布時間:2025/7/14 数据库 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库MYSQL学习系列二 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2.1-MySQL數據類型

Number不止一種

×××
浮點型
×××

INT
SMALLINT
MEDIUMINT
BIGINT
type Storage Minumun Value Maximum Value
(Bytes) (Signed/Unsigned) (Signed/Unsigned)
TINYINT 1 -128 127
0 255
SMALLINT 2 -32768 32767
0 65535
MEDIUMINT 3 -8388608 8388607
0 16777215
INT 4 -2147483648 2147483647
0 4294967295
BIGINT 8 -9223372036854775808 9223372036854775807
0 18446744073709551615
老生常談的問題

int(11) VS int(21) 存儲空間,還是存儲范圍有區別?

答案是:兩者完全一樣,只是在顯示的時候補全0的位數不一樣。

可以通過下面的例子來驗證:

create table t(a int(11) zerofill, b int(21) zerofill);
insert into t values (1, 1);
select * from t;
MySQL默認是不帶0補全的。

只是在一些特殊情況下兩者顯示有區別,其本質完全一樣。

浮點型

FLOAT(M, D)
DOUBLE(M, D)
屬性 存儲空間 精度 精確性
Float 4 bytes 單精度 非精確
Double 8 bytes 雙精度 比Float精度高
精度丟失問題

精度丟失
一個例子:

create table t(a int(11), b float(7, 4));
insert into t values (2, 123.12345);
select * from t;
定點數-更精確的數字類型

DECIMAL
高精度的數據類型,常用來存儲交易相關的數據
DECIMAL(M,N).M代表總精度,N代表小數點右側的位數(標度)
1 < M < 254, 0 < N < 60;
存儲空間變長
性別、省份信息

一般使用tinyint、char(1)、enum類型。

經驗之談

存儲性別、省份、類型等分類信息時選擇TINYINT或者ENUM
BIGINT存儲空間更大,INT和BIGINT之間通常選擇BIGINT
交易等高精度數據選擇使用DECIMAL
存儲用戶名的屬性

CHAR
VARCHAR
TEXT
CAHR與VARCHAR

CHAR和VARCHAR存儲的單位都是字符
CHAR存儲定長,容易造成空間的浪費
VARCHAR存儲變長,節省存儲空間
字符與字節的區別

編碼\輸入字符串 網易 netease
gbk(雙字節) varchar(2)/4 bytes varchar(7)/7 bytes
utf8(三字節) varchar(2)/6 bytes varchar(7)/7 bytes
utf8mb4(四字節) varchar(2) ? varchar(7)/7 bytes
對于utf8mb4號稱占用四字節但是并不絕對。如果在utf8可以覆蓋到的范圍則仍然占用3字節。

utf8mb4最有優勢的應用場景是用于存儲emoji表情

emoji表情

MySQL版本 > 5.5.3
JDBC驅動版本 > 5.1.13
庫和表的編碼設為utf8mb4
TEXT與CHAR和VARCHAR的區別

CHAR和VARCHAR存儲單位為字符
TEXT存儲單位為字節,總大小為65535字節,約為64KB
CHAR數據類型最大為255字符
VARCHAR數據類型為變長存儲,可以超過255個字符
TEXT在MySQL內部大多存儲格式為溢出頁,效率不如CHAR
一個例子:

create table t (a char(256));
create table t (a varchar(256));
存儲頭像

BLOB
BINARY
性能太差,不推薦

經驗之談

CHAR與VARCHAR定義的長度是字符長度不是字節長度
存儲字符串推薦使用VARCHAR(N),N盡量小
雖然數據庫可以存儲二進制數據,但是性能低下,不要使用數據庫存儲文件音頻等二進制數據
存儲生日信息

DATE
TIME
DATETIME
TIMESTAMP
BIGINT
時間類型的區別在哪里

存儲空間上的區別

DATE三字節,如:2015-05-01
TIME三字節,如:11:12:00
TIMESTAMP,如:2015-05-01 11::12:00
DATETIME八字節,如:2015-05-01 11::12:00
存儲精度的區別

DATE精確到年月日
TIME精確到小時分鐘和秒
TIMESTAMP、DATETIME都包含上述兩者
TIMESTAMP VS DATETIME

存儲范圍的區別
TIMESTAMP存儲范圍:1970-01-01 00::00:01 to 2038-01-19 03:14:07
DATETIME的存儲范圍:1000-01-01 00:00:00 to 9999-12-31 23:59:59
MySQL在5.6.4版本之后,TimeStamp和DateTime支持到微妙

字段類型與市區的關聯關系
TIMESTAMP會根據系統時區進行轉換,DATETIME則不會
字段類型和時區的關系

國際化的系統
一個例子:

create table test (a datetime, b timestamp);
select now();
insert into test values (now(), now());
select from test;
set time_zone = '+00:00';
select from test;
BIGINT如何存儲時間類型

應用程序將時間轉換為數字類型
2.2-MySQL數據對象

MySQL常見的數據對象有哪些

DataBase/Schema
Table
Index
View/Trigger/Function/Procedure
庫、表、行層級關系

一個DataBase對應一個Schema
一個Schema包含一個或多個表
一個表里面包含一個或多個字段
一個表里包含一條或多條記錄
一個表包含一個或多個索引
多DataBase用途

業務隔離
資源隔離
表上有哪些常用的數據對象

索引
約束
視圖、觸發器、函數、存儲過程
什么是數據庫索引

讀書的時候如何快速定位某一章節
查找書籍目錄
在自己喜歡的章節加書簽,直接定位
索引就是數據庫中的數據的目錄(索引和數據是分開存儲的)
索引和數據是兩個對象
索引主要是用來提高數據庫的查詢效率
數據庫中數據變更同樣需要同步索引數據的變更
如何創建索引(一)

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
[index_type]
ON tbl_name (index_col_name,...)
[index_option]
[algorithm_option | lock_option] ...

index_col_name:
col_name [(length)] [ASC | DESC]

index_type:
USING {BTREE | HASH}
如何創建索引(二)

ALTER [IGNORE] TABLE tbl_name
[alter_specification [, alter_specification] ...]
[partition_options]

alter_specification:
table_options
| ADD [COLUMN] col_name column_definition
[FIRST | AFTER col_name]
ADD [COLUMN] (col_name column_definition,...)
ADD {INDEX|KEY} [index_name]
[index_type] (index_col_name,...) [index_option] ...
| ADD [CONSTRAINT [symbol]] PRIMARY KEY
[index_type] (index_col_name,...) [index_option] ...
| ADD [CONSTRAINT [symbol]]
UNIQUE [INDEX|KEY] [index_name]
約束

生活中的約束有哪些
每個人的指紋信息必須唯一
每個人的×××要求唯一
網上購物需要先登錄才能下單
唯一約束
對一張表的某個字段或者某幾個字段設置唯一鍵約束,保證在這個表里對應的數據必須唯一,如:用戶ID、手機號、×××等。
創建唯一約束

唯一約束是一種特殊的索引
唯一約束可以是一個或者多個字段
唯一約束可以在創建表的時候建好,也可以后面再補上
主鍵也是一種唯一約束
唯一約束

以如下這張表為例

CREATE TABLE order (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
orderid int(10) unsigned NOT NULL,
bookid int(10) unsigned NOT NULL DEFAULT '0',
userid int(10) unsigned NOT NULL DEFAULT '0',
number tinyint(3) unsigned NOT NULL DEFAULT '0',
address varchar(128) NOT NULL DEFAULT '',
postcode varchar(128) NOT NULL DEFAULT '',
orderdate datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
status tinyint(3) unsigned zerofill DEFAULT '000',
PRIMARY KEY (id),
UNIQUE KEY idx_orderid (orderid),
UNIQUE KEY idx_uid_orderid (userid, orderid),
KEY bookid (bookid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
索引有哪些
主鍵索引 ID
單鍵索引 orderid
單鍵索引 bookid
組合索引 (userid + orderid)
唯一約束有哪些
主鍵約束 (ID)
單鍵唯一索引 (orderid)
組合唯一索引 (userid + orderid)
添加唯一約束

添加主鍵
alter table order add primary key (id);
添加唯一索引
alter table order add unique key idx_uk_orderid (orderid);
外鍵約束

外鍵指兩張表的數據通過某種條件關聯起來
創建外鍵約束

將用戶表和訂單表通過外鍵關聯起來
alter table order add CONSTRAINT constraint_uid FOREIGN KEY (userid) REFERENCES user(userid);
使用外鍵的注意事項
必須是INNODB表,Myisam和其他引擎不支持外鍵
相互約束的字段類型必須要求一樣
主表的約束字段要求有索引
約束名稱必須要唯一,即使不在一張表上
View

產品需求
假如有其他部門的同事想查詢我們數據庫里的數據,但是我們并不想暴露表結構,并且只提供給他們部分數據
View的作用

視圖將一組查詢語句構成的結果集,是一種虛擬結構,并不是實際數據
視圖能簡化數據庫的訪問,能夠將多個查詢語句結構化為一個虛擬結構
視圖可以隱藏數據庫后端表結構,提高數據庫安全性
視圖也是一種權限管理,只對用戶提供部分數據
創建View

創建已完成訂單的視圖
create view order_view as select * from order where status=1;
Trigger

產品需求
隨著客戶個人等級的提升, 系統需要自動更新用戶的積分,其中一共有兩張表,分別為:用戶信息表和積分表
Trigger俗稱觸發器,指可以在數據寫入表A之前或者之后可以做一些其他動作
使用Trigger在每次更新用戶表的時候出發更新積分表
除此之外還有哪些

Function
Procedure
2.3-MySQL權限管理

連接MySQL的必要條件

網絡要通暢
用戶名和密碼要正確
數據庫需要加IP白名單
更細粒度的驗證(庫、表、列權限類型等等)
數據有哪些權限

show privileges命令可以查看全部權限

權限粒度

Data Privileges
DATA: SELECT, INSERT, UPDATE, DELETE
Definition Privileges
DataBase: CREATE, ALTER, DROP
Table: CREATE, ALTER, DROP
VIEW/FUNCTION/TRIGGER/PROCEDURE: CREATE, ALTER, DROP
Administrator Privileges
Shutdown DataBase
Replication Slave
Replication Client
File Privilege
MySQL賦權操作

GRANT
priv_type [(column_list)]
[, priv_type [column_list]] ...
ON [object_type] priv_level
TO user_specification [, user_specification] ...
[REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}]
[WITH with_option ...]
GRANT PROXY ON user_specification
TO user_specification [, user_specification] ...
[WITH GRANT OPTION]
如何新建一個用戶并賦權

使用MySQL自帶的命令
CREATE USER 'netease'@'localhost' IDENTIFIED BY 'netease163';
GRANT SELECT ON . TO 'netease'@'localhost' WITH GRANT OPTION;
其他方法

更改數據庫記錄
首先向User表里面插入一條記錄,根據自己的需要選擇是否向db和table_pirv表插入記錄
執行flush privileges命令,讓權限信息生效
更簡單的辦法

GRANT語句會判斷是否存在該用戶,如果不存在則新建
GRANT SELECT ON . TO 'NETEASE'@'localhost' IDENTIFIED BY 'netease163' WITH GRANT OPTION;
查看用戶的權限信息

查看當前用戶的權限
show grants;
查看其它用戶的權限
show grants for netease@'localhost';
如何更改用戶的權限

回收不需要的權限
revoke select on . from netease@'localhost';
重新賦權
grant insert on . to netease@'localhost';
如何更改用戶密碼

用新密碼,grant語句重新授權
更改數據庫記錄,Update User表的Password字段
注意:用這種辦法,更改完需要flush privileges刷新權限信息,不推薦
刪除用戶

DROP USER user [, user] ...
With Grant Option

允許被授予權利的人把這個權利授予其他的人
MySQL權限信息存儲結構

MySQL權限信息是存在數據庫表中
MySQL賬號對應的密碼也加密存儲在數據庫表中
每一種權限類型在元數據里都是枚舉類型,表明是否有該權限
有哪些權限相關的表

user
db
table_pirv
columns_pirv
host
權限驗證流程

查詢時從user->db->table_pirv->columns_pirv依次驗證,如果通過則執行查詢。

小結

MySQL權限信息都是以數據記錄的形式存儲在數據庫的表中。
MySQL的權限驗證相比網站登錄多了白名單環節,并且粒度更細,可以精確到表和字段。
MySQL權限上有哪些問題

使用Binary二進制安裝管理用戶沒有設置密碼
MySQL默認的test庫不受權限控制,存在安全風險
mysql_secure_installation

You can set a Password for root accounts.
You can remove root accounts that are accessible from outside the localhost.
You can remove anonymous-user accounts.
You can remove the test database.
小結

權限相關的操作不要直接操作表,統一使用MySQL命令。
使用二進制安裝MySQL安裝后,需要重置管理用戶(root)的密碼。
線上數據庫不要留test庫
實踐課:數據庫對象

何為表結構設計

表結構設計需要在正式進行開發之前完成
根據產品需求將復雜的業務模型抽象出來
設計表的時候需要注意哪些

理解各個表的依賴關系
理解各個表的功能特點
字段之間的約束、索引
字段類型、字段長度
收集表屬性

昵稱
生日
性別
手機號碼
住宅號碼
郵編
住宅地址
注冊地址
登錄IP
上一次登錄時間
郵件地址
理解表的功能特點——數據用途

create table tb_account(
account_id int not null auto_increment primary key,
nick_name varchar(20),
true_name varchar(20),
sex char(1),
mail_address varchar(50),
phone1 varchar(20) not null,
phone2 varchar(20),
password varchar(30) not null,
create_time datetime,
account_state tinyint,
last_login_time datetime,
last_login_ip varchar(20)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

create table tb_goods(
good_id bigint not null auto_increment primary key,
goods_name varchar(100) not null,
pic_url varchar(500) not null,
store_quantity int not null,
goods_note varchar(4096),
producer varchar(500),
category_id int not null
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

create table tb_goods_category(
category_id int not null auto_increment primary key,
category_level smallint not null,
category_name varchar(500),
upper_category_id int not null
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

create table tb_order(
order_id bigint not null auto_increment primary key,
account_id int not null,
create_time datetime,
order_amount decimal(12,2),
order_state tinyint,
update_time datetime,
order_ip varchar(20),
pay_method varchar(20),
user_notes varchar(500)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

create table tb_order_item(
order_item_id bigint not null auto_increment primary key,
order_id bigint not null,
goods_id bigint not null,
goods_quantity int not null,
goods_amount decimal(12,2),
uique key uk_order_goods(order_id, goods_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
數據類型——命名規范

所有表名,字段名全部使用小寫字母
不同業務,表名使用不同前綴區分。
生成環境表名字段名要有實際意義
單個字段盡量使用字段全名;多個字段之間用下劃線分隔
字段設計規范

字段類型選擇,盡量選擇能滿足應用要求的最小數據類型
盡量使用×××代替字符型。×××在字段長度、索引大小等方面開銷小效率更高,如郵編字段,手機號碼等
注釋,每個字段必須以comment語句給出字段的作用
經常訪問的大字段需要單獨放到一張表中,避免降低sql效率,圖片、電影等大文件數據禁止存數據庫
新業務統一建議使用utf8mb4字符集
用戶賦權

理解用戶到底需要什么權限
普通用戶只有數據讀寫權限
系統管理員具有super權限
權限粒度要做到盡可能的細
普通用戶不要設置with grant option屬性
權限粒度:系統層面>庫層面>表層面>字段層面
禁止簡單密碼
線上密碼要求隨機
2.4-SQL語言進階

本課程涉及建表SQL


-- Table structure for play_fav


DROP TABLE IF EXISTS play_fav;
CREATE TABLE play_fav (
userid bigint(20) NOT NULL COMMENT '收藏用戶id',
play_id bigint(20) NOT NULL COMMENT '歌單id',
createtime bigint(20) NOT NULL COMMENT '收藏時間',
status int(11) DEFAULT '0' COMMENT '狀態,是否刪除',
PRIMARY KEY (play_id,userid),
KEY IDX_USERID (userid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='歌單收藏表';


-- Records of play_fav


INSERT INTO play_fav VALUES ('2', '0', '0', '0');
INSERT INTO play_fav VALUES ('116', '1', '1430223383', '0');
INSERT INTO play_fav VALUES ('143', '1', '0', '0');
INSERT INTO play_fav VALUES ('165', '2', '0', '0');
INSERT INTO play_fav VALUES ('170', '3', '0', '0');
INSERT INTO play_fav VALUES ('185', '3', '0', '0');
INSERT INTO play_fav VALUES ('170', '4', '0', '0');
INSERT INTO play_fav VALUES ('170', '5', '0', '0');


-- Table structure for play_list


DROP TABLE IF EXISTS play_list;
CREATE TABLE play_list (
id bigint(20) NOT NULL COMMENT '主鍵',
play_name varchar(255) DEFAULT NULL COMMENT '歌單名字',
userid bigint(20) NOT NULL COMMENT '歌單作者賬號id',
createtime bigint(20) DEFAULT '0' COMMENT '歌單創建時間',
updatetime bigint(20) DEFAULT '0' COMMENT '歌單更新時間',
bookedcount bigint(20) DEFAULT '0' COMMENT '歌單訂閱人數',
trackcount int(11) DEFAULT '0' COMMENT '歌曲的數量',
status int(11) DEFAULT '0' COMMENT '狀態,是否刪除',
PRIMARY KEY (id),
KEY IDX_CreateTime (createtime),
KEY IDX_UID_CTIME (userid,createtime)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='歌單';


-- Records of play_list


INSERT INTO play_list VALUES ('1', '老男孩', '1', '1430223383', '1430223383', '5', '6', '0');
INSERT INTO play_list VALUES ('2', '情歌王子', '3', '1430223384', '1430223384', '7', '3', '0');
INSERT INTO play_list VALUES ('3', '每日歌曲推薦', '5', '1430223385', '1430223385', '2', '4', '0');
INSERT INTO play_list VALUES ('4', '山河水', '2', '1430223386', '1430223386', '5', null, '0');
INSERT INTO play_list VALUES ('5', '李榮浩', '1', '1430223387', '1430223387', '1', '10', '0');
INSERT INTO play_list VALUES ('6', '情深深', '5', '1430223388', '1430223389', '0', '0', '1');


-- Table structure for song_list


DROP TABLE IF EXISTS song_list;
CREATE TABLE song_list (
id bigint(20) NOT NULL COMMENT '主鍵',
song_name varchar(255) NOT NULL COMMENT '歌曲名',
artist varchar(255) NOT NULL COMMENT '藝術節',
createtime bigint(20) DEFAULT '0' COMMENT '歌曲創建時間',
updatetime bigint(20) DEFAULT '0' COMMENT '歌曲更新時間',
album varchar(255) DEFAULT NULL COMMENT '專輯',
playcount int(11) DEFAULT '0' COMMENT '點播次數',
status int(11) DEFAULT '0' COMMENT '狀態,是否刪除',
PRIMARY KEY (id),
KEY IDX_artist (artist),
KEY IDX_album (album)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='歌曲列表';


-- Records of song_list


INSERT INTO song_list VALUES ('1', 'Good Lovin\' Gone Bad', 'Bad Company', '0', '0', 'Straight Shooter', '453', '0');
INSERT INTO song_list VALUES ('2', 'Weep No More', 'Bad Company', '0', '0', 'Straight Shooter', '280', '0');
INSERT INTO song_list VALUES ('3', 'Shooting Star', 'Bad Company', '0', '0', 'Straight Shooter', '530', '0');
INSERT INTO song_list VALUES ('4', '大象', '李志', '0', '0', '1701', '560', '0');
INSERT INTO song_list VALUES ('5', '定西', '李志', '0', '0', '1701', '1023', '0');
INSERT INTO song_list VALUES ('6', '紅雪蓮', '洪啟', '0', '0', '紅雪蓮', '220', '0');
INSERT INTO song_list VALUES ('7', '風柜來的人', '李宗盛', '0', '0', '作品李宗盛', '566', '0');


-- Table structure for stu


DROP TABLE IF EXISTS stu;
CREATE TABLE stu (
id int(10) NOT NULL DEFAULT '0',
name varchar(20) DEFAULT NULL,
age int(10) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


-- Records of stu



-- Table structure for tbl_proc_test


DROP TABLE IF EXISTS tbl_proc_test;
CREATE TABLE tbl_proc_test (
id int(11) NOT NULL AUTO_INCREMENT,
num int(11) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;


-- Records of tbl_proc_test


INSERT INTO tbl_proc_test VALUES ('11', '1');
INSERT INTO tbl_proc_test VALUES ('12', '2');
INSERT INTO tbl_proc_test VALUES ('13', '6');
INSERT INTO tbl_proc_test VALUES ('14', '24');
INSERT INTO tbl_proc_test VALUES ('15', '120');
INSERT INTO tbl_proc_test VALUES ('16', '720');
INSERT INTO tbl_proc_test VALUES ('17', '5040');
INSERT INTO tbl_proc_test VALUES ('18', '40320');
INSERT INTO tbl_proc_test VALUES ('19', '362880');
INSERT INTO tbl_proc_test VALUES ('20', '3628800');
INSERT INTO tbl_proc_test VALUES ('21', '1');
INSERT INTO tbl_proc_test VALUES ('22', '2');
INSERT INTO tbl_proc_test VALUES ('23', '6');
INSERT INTO tbl_proc_test VALUES ('24', '24');
INSERT INTO tbl_proc_test VALUES ('25', '1');
INSERT INTO tbl_proc_test VALUES ('26', '2');
INSERT INTO tbl_proc_test VALUES ('27', '6');
INSERT INTO tbl_proc_test VALUES ('28', '24');
INSERT INTO tbl_proc_test VALUES ('29', '120');


-- Table structure for tbl_test1


DROP TABLE IF EXISTS tbl_test1;
CREATE TABLE tbl_test1 (
user varchar(255) NOT NULL COMMENT '主鍵',
key varchar(255) NOT NULL,
value varchar(255) NOT NULL,
PRIMARY KEY (user,key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='行列轉換測試';


-- Records of tbl_test1


INSERT INTO tbl_test1 VALUES ('li', 'age', '18');
INSERT INTO tbl_test1 VALUES ('li', 'dep', '2');
INSERT INTO tbl_test1 VALUES ('li', 'sex', 'male');
INSERT INTO tbl_test1 VALUES ('sun', 'age', '44');
INSERT INTO tbl_test1 VALUES ('sun', 'dep', '3');
INSERT INTO tbl_test1 VALUES ('sun', 'sex', 'female');
INSERT INTO tbl_test1 VALUES ('wang', 'age', '20');
INSERT INTO tbl_test1 VALUES ('wang', 'dep', '3');
INSERT INTO tbl_test1 VALUES ('wang', 'sex', 'male');


-- Procedure structure for proc_test1


DROP PROCEDURE IF EXISTS proc_test1;
DELIMITER ;;
CREATE DEFINER=root PROCEDURE proc_test1(IN total INT,OUT res INT)
BEGIN
DECLARE i INT;
SET i = 1;
SET res = 1;
IF total <= 0 THEN
SET total = 1;
END IF;
WHILE i <= total DO
SET res = res * i;
INSERT INTO tbl_proc_test(num) VALUES (res);
SET i = i + 1;
END WHILE;
END
;;
DELIMITER ;
說明

本課程介紹以MySQL SQL語法為基礎,不同數據庫SQL語法存在差異,并未完全遵照ANSI標準。
本課程結合一個實際項目(云音樂),介紹各種SQL語言在實際應用中如何實現業務功能。
SQL進階語法——order by

場景1:歌單按時間排序

-- 查看全部歌單
select * from play_list;

-- 按創建時間排序
select from play_list order by createtime;
-- MySQL默認升序,如果按降序排列,則使用如下語句。
select from play_list order by createtime desc;
-- 也可以按照多個字段來排序
select * from play_list order by bookedcount, trackcount;
SQL進階語法——distinct

場景2:統計云音樂創建歌單的用戶

-- 有重復
select userid from play_list;

-- 去重
select distinct userid from play_list;

-- 多個字段
select distinct userid, play_name from play_list;
distinct用于返回唯一不同的值
可以返回多列的唯一組合
底層實現使用排序,如果數據量大會消耗較多的IO和CPU
SQL進階語法——group by

場景3-1:統計云音樂創建歌單的用戶列表和每人創建歌單的數量。

-- 每個用戶歌單的最大訂閱數
select userid, max(bookedcount) from play_list group by userid;

-- 每個用戶歌單的數量
select userid, count() from play_list group by userid;
group by 根據單列或多列對數據進行分組,通常結合聚合函數使用,如count().
SQL進階語法——group by having

場景3-2:統計云音樂創建歌單的用戶列表和每人創建歌單的數量,并且只顯示歌單數量排序大于等于2的用戶

select userid, count() from play_list group by userid having count() >= 2;
having 是對結果進行過濾
SQL進階語法-like

select * from play_list where playname like '%男孩%';
通配符 描述
% 代替一個或多個字符
代替單個字符
[charlist] 中括號中的任何一個字符
[^charlist] 或者 [!charlist] 不在中括號中的任何單一字符
除了百分號在最右面的情況以外,他會對這個表中所有的記錄進行一次查詢匹配,而沒辦法使用索引,效率較低。大表中需要慎用like。可以使用全文檢索的手段。
SQL進階語法-limit, offset

場景4:查詢一個月內創建歌單(從第6行開始顯示10條記錄)

select * from play_list where (createtime between 1427791323 and 1430383307) limit 10 offset 6;
offset后的值不建議太大,需要消耗的IO較大
case when

case when 實現類似編程語言的if else功能,可以對SQL的輸出結果進行選擇判斷。
場景5:對于未錄入歌曲的歌單(trackcount = null),輸出結果時歌曲數返回0.

select case when play_name, trackcount is null then 0 else trackcount end from play_list;
select相關進階語法

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

連接的作用是用一個SQL語句把多個表中相互關聯的數據查出來

場景6:查詢收藏“老男孩”歌單的用戶列表

select * from play_list, play_fav where play_list.id=play_fav.play_id;
select play_fav.userid from play_list, play_fav where play_list.id=play_fav.play_id and play_list.play_name='老男孩';
-- 另一種寫法
select f.userid from play_list lst join play_fav f on lst.id=f.play_id where lst.play_name = '老男孩';
子查詢

MySQL還有另一種寫法,可以實現同樣的功能。
select userid from play_fav where play_id=(select id from play_list where play_name = '老男孩');
子查詢:內層查詢的結果作為外層的比較條件。一般子查詢都可以轉換成連接,推薦使用連接。

不利于MySQL的查詢優化器進行優化,可能存在性能問題
連接的實現是嵌套循環,選擇一個驅動表,遍歷驅動表,查詢內層表,依次循環。驅動表會至少查詢一邊,如果有索引等,內層表可以非常快,查詢優化器會選擇數據小的表作為驅動表。
子查詢由人為規定驅動表和內層表
連接- left Join

select lst.play_name from play_list lst left join play_fav f on lst.id = f.play_id where f.play_id is null;
LEFT JOIN從左表(play_list)返回所有的行,即使在右表中(play_fav)中沒有匹配的行。
與LEFT JOIN相對應的有RIGHT JOIN關鍵字,會從右表那里返回所有的行,即使在左表中沒有匹配的行。
場景7:查詢出沒有用戶收藏的歌單

SQL進階語法-union

場景8:老板想看創建和收藏歌單的所有用戶,查詢play_list和play_fav兩表中所有的userid

select userid from play_list union select userid from play_fav;
-- 默認會去重, 不想去重的話使用union all代替union。
DML進階語法

多值插入: insert into table values(....),(....)
可以一次插入多行數據,減少與數據庫的交互提高效率
eg: insert into A values(4, 33), (5, 33);
覆蓋插入: replace into table values (....)
可以簡化業務邏輯的判斷
忽略插入: insert ignore into table value (....)
可以簡化業務邏輯的判斷
查詢插入: insert into table_a select * from table_b
常用于導表操作
insert主鍵重復則update
INSERT INTO TABLE tbl VALUES (id, col1, col2) ON DUPLICATE KEY UPDATE col2=....;
eg: insert into A values(2, 40) on duplicate key update age=40;
可以簡化前端業務邏輯的判斷
連表update
A表:id, age
B表:id, name, age
A表id與B表id關聯,根據B表的age值更新A表的age。
eg: update A,B set A.age=B.age where A.id=B.id;
連表刪除
A表:id, age
B表:id, name, age
A表id與B表id關聯,根據B表的age值刪除A表的數據。
eg: delete A from A,B where A.id=B.id and B.name='pw';
總結

select查詢進階語法
order by/distinct/group by having (聚合函數) /like (%前綴后綴)
連接語法
內連接、左連接、右連接、 Union [ALL]
DML進階語法
insert/連表update/連表delete
2.5-內置函數

聚合函數

聚合函數面向一組數據,對數據進行聚合運算后返回單一的值。
MySQL聚合函數的基本語法:SELECT function(列) from 表
常用聚合函數:
函數 描述
AVG() 返回列的平均值
COUNT(DISTINCT) 返回列去重后的行數
COUNT() 返回列的行數
MAX() 返回列的最大值
MIN() 返回列的最小值
SUM() 返回列的總和
GROUP_CONCAT() 返回一組值的連接字符串(MySQL獨有)
實例還是上節中的那些表

場景1:查詢每張專輯總的點播次數和每首歌的平均點播次數。

select album, sum(playcount), avg(playcount) from song_list group by album;
場景2:查詢全部歌曲中的最大的播放次數和最小的播放次數。

select max(playcount), min(playcount) from song_list;
場景2續:查詢播放次數最多的歌曲

-- 錯誤查法
select song_name, max(playcount) from song_list;
-- 正確查法
select song_name, playcount from song_list order by playcount desc limit 1;
select count() from song_list;
select count(1) from song_list;
select count(song_name) from song_list;
count()和count(1)基本一樣,沒有明顯的性能差異。 count(*)和count(song_name)差別在于count(song_name)會除去song_name is null的情況

場景3:顯示每張專輯的歌曲列表

select album, GROUP_CONCAT(song_name) from song_list group by album;
-- 默認最大只能連接1024個字符,但是可以通過改數據庫參數來改變。
使用聚合函數做數據庫行列轉換

select user,
max(case when 'key'='age' then value end) age,
max(case when 'key'='sex' then value end) sex,
max(case when 'key'='dep' then value end) dep,
from tbl_test1
group by user;
預定義函數

預定義函數面向單值數據,返回一對一的處理結果(聚合函數可以理解成多對一)。
預定義函數基本語法:
select function(列) from 表;
select * from 表 where 列 = function(value) ...
預定義函數-字符串函數

函數 描述
LENGTH() 返回列的字節數
CHAR_LENGTH() 返回列的字符數
TRIM()/RTRIM()/LTRIM() 去除兩邊空格/去除右邊空格/去除左邊空格
SUBSTRING(str, pos, [len]) 從pos位置截取字符串str,截取len長度
LOCATE(substr, str, [pos]) 返回substr在str字符串中的位置
REPLACE(str, from_str, to_str) 將str字符串中的from_str替換成to_str
LOWER(), UPPER() 字符串轉換為小寫/大寫
字符串函數 - 實例
SELECT SUBSTRING('abcdef', 3);
-- 'cdef'
SELECT SUBSTRING('abcdef', -3);
-- 'def'
SELECT SUBSTRING('abcdef', 3, 2);
-- 'cd'
SELECT LOCATE('bar', 'foobarbar');
-- 4
SELECT LOCATE('xbar', 'foobar');
-- 0
SELECT LOCATE('bar', 'foobarbar', 5);
-- 7
預定義函數-時間處理函數

函數 描述
CURDATE() 當前日期
CURTIME() 當前時間
NOW() 顯示當前時間日期(常用)
UNIX_TIMESTAMP() 當前時間戳
DATE_FORMAT(date, format) 按指定格式顯示時間
DATE_ADD(date, INTERVAL unit) 計算指定日期向后加一段時間的日期
DATE_SUB(date, INTERVAL unit) 計算指定日期向前減一段時間的日期
實例:
SELECT NOW() + INTERVAL 1 MONTH;
SELECT NOW() - INTERVAL 1 WEEK;
預定義函數-數字處理函數

函數 描述
ABS() 返回數值的絕對值
CEIL() 對小數向上取整 CEIL(1.2)=2
ROUND() 四舍五入
POW(num, n) num的n次冪 POW(2, 2)=4
FLOOR() 對小數向下取整 CELL(1.2)=1
MOD(N, M) 取模(返回n除以m的余數)=N % M
RAND() 取0~1之間的一個隨機數
算數、邏輯運算

比較運算
函數 描述
IS, IS NOT 判定布爾值 IS True, IS NOT False, IS NULL

, >= 大于,大于等于
<, <= 小于,小于等于
= 等于
!=, <> 不等于
BETWEEN M AND N 取M和N之間的值
IN, NOT IN 檢查是否在或不在一組值之中
實例:查詢一個月內userid為1,3,5的用戶創建的歌單

select from play_list where (createtime between 1427791323 and 1430383307) and userid in (1,3,5);
,/,DIV,%,MOD,-,+
NOT, AND, &&, XOR, OR, ||
2.6-觸發器與存儲過程

觸發器

是什么
觸發器是加在表上的一個特殊程序,當表上出現特定的事件(INSERT/UPDATE/DELETE)時觸發該程序執行。
做什么
數據訂正;遷移表;實現特定的業務邏輯。
觸發器-基本語法

CREATE
[DEFINER = { user | CURRENT_USER }]
TRIGGER trigger_name trigger_time
trigger_event ON tbl_name
FOR EACH ROW
trigger_body t

trigger_time: { BEFORE | AFTER }
trigger_event: { INSERT | UPDATE | DELETE }
觸發器-實例

學生表:

CREATE TABLE stu (
name varchar(50),
course varchar(50),
score int(11),
PRIMARY KEY (name)
) ENGINE=InnoDB;
用于更正成績的觸發器:

DELIMITER //
CREATE TRIGGER trg_upd_score
BEFORE UPDATE ON stu
FOR EACH ROW
BEGIN
IF NEW.score < 0 THEN
SET NEW.score = 0;
ELSEIF NEW.score > 100 THEN
SET NEW.score = 100;
END IF;
END; //
DELIMITER ;
注意事項

觸發器對性能有損耗,應慎重使用。
同一類事件在一個表中只能創建一次。
對于事務表,觸發器執行失敗則整個語句回滾。
Row格式的主從復制,觸發器不會在從庫上執行。
使用觸發器時應防止遞歸執行。
存儲過程

定義:存儲過程是存儲在數據庫的一組SQL語句集,用戶可以通過存儲過程名和傳參多次調用的程序模塊。
特點:
使用靈活,可以使用流控制語句,自定義變量等完成復雜的業務邏輯。
提高數據安全性,屏蔽應用程序直接對表的操作,易于進行審計。
減少網絡傳輸。
提高代碼維護的復雜度,實際使用中要評估場景是否適合。
存儲過程-基本語法

CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body

proc_parameter:
[ IN | OUT | INOUT ] param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| [NOT] DETERMINISTIC
routine_body:
Valid SQL routine statement
存儲過程-實例

CREATE PROCEDURE proc_test1
(IN total INT, OUT res INT)
BEGIN
DECLARE i INT;
SET i = 1;
SET res = 1;
IF total <= 0 THEN
SET total = 1;
END IF;
WHILE i <= total DO
SET res = res * i;
INSERT INTO tbl_proc_test(num) VALUES (res);
SET i = i + 1;
END WHILE;
END;
存儲過程-流控制語句

流控制 描述
IF IF search_condition THEN statement_list [ELSEIF search_condition THEN statement_list][ELSE statement_list] END IF
CASE CASE case_value WHEN when_value THEN statement_list [ELSE statement_list] END CASE
WHILE WHILE search_condition DO statement_list END WHILE
REPEAT REPEAT statement_list UNTIL search_condition END REPEAT
存儲過程-調用

set @total=10;
set @res=1;
call proc_test1(@total, @res);
select @res;
自定義函數

自定義函數與存儲過程類似,但是必須帶有返回值(RETURN)。
自定義函數與sum(), max()等MySQL原生函數使用方法類似:
SELECT func(val);
SELECT * from tbl where col=func(val);
由于自定義函數可能在遍歷數據中使用,要注意性能損耗
自定義函數-基本語法

CREATE
[DEFINER = { user | CURRENT_USER}]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| [NOT] DETERMINISTIC
routine_body:
Valid SQL routine statement
自定義函數-實例

CREATE FUNCTION func_test1 (total INT)
RETURNS INT
BEGIN
DECLARE i INT;
DECLARE res INT;
SET i = 1;
SET res = 1;
IF total <= 0 THEN
SET total = 1;
END IF;
WHILE i < total DO
SET res = res * i;
SET i = i + 1;
END WHILE;
RETURN res;
END;
自定義函數-調用

select func_test1(4);
小結

知識點:觸發器、存儲過程、自定義函數
互聯網場景:觸發器和存儲過程不利于水平擴展,多用于統計和運維操作中。
2.7-MySQL字符集

字符集基礎

字符集:數據庫中的字符集包含兩層含義
各種文字和符號的集合,包括各國家文字、標點符號、圖形符號、數字等。
字符的編碼方式,即二進制數據與字符的映射規則。
字符集-分類

ASCII:美國信息互換標準編碼;英語和其他西歐語言;單字節編碼,7位表示一個字符,共128字符。
GBK:漢字內碼擴展規范;中日韓漢字、英文、數字;雙字節編碼;共收錄了21003個漢字,GB2312的擴展。
UTF-8:Unicode標準的可變長度字符編碼;Unicode標準(統一碼),業界統一標準,包括世界上數十種文字的系統;UTF-8使用一至四個字節為每個字符編碼。
其他常見字符集:UTF-32,UTF-16,Big5,latin1
MySQL字符集

查看字符集
SHOW CHARACTER SET;
新增字符集

編譯時加入: --with-charset=

./configure --prefix=/usr/local/mysql3 --with-plugins=innobase --with-charset=gbk
字符集與字符序

charset和collation
collation:字符序,字符的排序與比較規則,每個字符集都有對應的多套字符序。
不同的字符序決定了字符串在比較排序中的精度和性能不同。
查看字符序

show collation;
mysql的字符序遵從命名慣例:以_ci(表示大小寫不敏感),以_CS(表示大小寫敏感),以_bin(表示用編碼值進行比較)。

字符集設置級別

charset和collation的設置級別:
服務器級 >> 數據庫級 >> 表級 >> 列級
服務器級
系統變量(可動態設置):
character_set_server:默認的內部操作字符集
character_set_system:系統元數據(各字段名等)字符集
字符集設置級別

服務器級
配置文件

[mysqld]
character_set_server=utf8
collation_server=utf8_general_ci
數據庫級
CREATE DATABASE db_name CHARACTER SET latin1 COLLATE latin1_swedish_ci;
character_set_database:當前選中數據庫的默認字符集
主要影響load data等語句的默認字符集,CREATE DATABASE的字符集如果不設置,默認使用character_set_server的字符集。

表級
CREATE TABLE tbl1 (....) DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_bin;
列級
CREATE TABLE tbl1 (col1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci);
字符集設置級別

數據存儲字符集使用規則:
使用列集的CHARACTER SET設定值;
若列級字符集不存在,則使用對應表級的DEFAULT CHARACTER SET設定值;
若表級字符集不存在,則使用數據庫級的DEFAULT CHARACTER SET設定值;
若數據庫級字符集不存在,則使用服務器級character_set_server設定值。
-- 查看字符集
show [global] variables like 'character%';
show [global] variables like 'collation%';

-- 修改字符集
set global character_set_server=utf8; -- 全局
alter table xxx convert to character set xxx; -- 表
客戶端連接與字符集

連接與字符集
character_set_client:客戶端來源數據使用的字符集。
character_set_connection:連接層字符集。
character_set_results:查詢結果字符集。
mysql > set names utf8;

配置文件設置:
[mysql]
default-character-set=utf8
字符轉換過程
client > character_set_client > character_set_connection > Storage > character_set_results >client

推薦使用統一的字符集

常見亂碼原因:

數據存儲字符集不能正確編碼(不支持)client發來的數據:client(utf8)->Storage(latin1)
程序連接使用的字符集與通知mysql的character_set_client等不一致或不兼容。
使用建議

創建數據庫/表時顯式的指定字符集,不使用默認。
連接字符集與存儲字符集設置一致,推薦使用utf8。
驅動程序連接時顯式指定字符集(set names XXX).
mysql CAPI:初始化數據庫句柄后馬上用mysql_options設定MYSQL_CHARSET_NAME屬性為utf8.

mysql php API:連接到數據庫以后顯式用SET NAMES語句設置一次連接字符集。

mysql JDBC: url="jdbc:mysql://localhost:3306/blog_dbo?user=xx&password=xx&userUnicode=true&characterEncoding=utf8"

小結

字符集:表示的字符集和/字符編碼方式
字符的設置級別:服務器/數據庫/表/列
客戶端字符集:亂碼產生的原因與解決方式
2.8程序連接MySQL

程序連接MySQL基本原理

JDBC客戶端應用 -> java.sql.或javax.sql. -> 驅動程序 -> SQLserver/Oracle/MySQL

Java代碼示例

結構:

DriverManager -> Driver(是驅動程序對象的接口,指向具體數據庫驅動程序對象)=DriverManager.getDriver(String URL) -> Connectinon(是連接對象接口,指向具體數據庫連接對象)=DriverManager.getConnection(String URL) -> Statement(執行靜態SQL語句接口)=Connection.CreateStatement() -> ResultSet(是指向結果集對象的接口)=Statement.excuteXXX()

import java.sql.*;

/**

  • 使用JDBC連接MySQL
    */
    public class DBTest {

    public static Connection getConnection() throws SQLException,
    java.lang.ClassNotFoundException
    {
    //第一步:加載MySQL的JDBC的驅動
    Class.forName("com.mysql.jdbc.Driver");

    //設置MySQL連接字符串,要訪問的MySQL數據庫 ip,端口,用戶名,密碼 String url = "jdbc:mysql://localhost:3306/blog"; String username = "blog_user"; String password = "blog_pwd";//第二步:創建與MySQL數據庫的連接類的實例 Connection con = DriverManager.getConnection(url, username, password); return con;

    }

    public static void main(String args[]) {
    Connection con = null;
    try
    {
    //第三步:獲取連接類實例con,用con創建Statement對象類實例 sql_statement
    con = getConnection();
    Statement sql_statement = con.createStatement();

    /************ 對數據庫進行相關操作 ************/ //如果同名數據庫存在,刪除sql_statement.executeUpdate("drop table if exists user;"); //執行了一個sql語句生成了一個名為user的表sql_statement.executeUpdate("create table user (id int not null auto_increment," +" name varchar(20) not null default 'name', age int not null default 0, primary key (id) ); ");//向表中插入數據System.out.println("JDBC 插入操作:");String sql = "insert into user(name,age) values('liming', 18)";int num = sql_statement.executeUpdate("insert into user(name,age) values('liming', 18)");System.out.println("execute sql : " + sql);System.out.println(num + " rows has changed!");System.out.println("");//第四步:執行查詢,用ResultSet類的對象,返回查詢的結果String query = "select * from user"; ResultSet result = sql_statement.executeQuery(query);/************ 對數據庫進行相關操作 ************/System.out.println("JDBC 查詢操作:");System.out.println("------------------------");System.out.println("userid" + " " + "name" + " " + "age ");System.out.println("------------------------");//對獲得的查詢結果進行處理,對Result類的對象進行操作while (result.next()){int userid = result.getInt("id");String name = result.getString("name");int age = result.getInt("age");//取得數據庫中的數據System.out.println(" " + userid + " " + name + " " + age); }//關閉 result,sql_statementresult.close();sql_statement.close();//使用PreparedStatement更新記錄sql = "update user set age=? where name=?;";PreparedStatement pstmt = con.prepareStatement(sql);//設置綁定變量的值pstmt.setInt(1, 15);pstmt.setString(2, "liming");//執行操作num = pstmt.executeUpdate();System.out.println("");System.out.println("JDBC 更新操作:");System.out.println("execute sql : " + sql);System.out.println(num + " rows has changed!");//關閉PreparedStatementpstmt.close();//流式讀取result,row-by-rowquery = "select * from user"; PreparedStatement ps = (PreparedStatement) con.prepareStatement(query,ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); ps.setFetchSize(Integer.MIN_VALUE); result = ps.executeQuery(); /************ 對數據庫進行相關操作 ************/System.out.println("JDBC 查詢操作:");System.out.println("------------------------");System.out.println("userid" + " " + "name" + " " + "age ");System.out.println("------------------------");//對獲得的查詢結果進行處理,對Result類的對象進行操作while (result.next()){int userid = result.getInt("id");String name = result.getString("name");int age = result.getInt("age");//取得數據庫中的數據System.out.println(" " + userid + " " + name + " " + age); }//關閉 result,psresult.close();ps.close();con.close();} catch(java.lang.ClassNotFoundException e) {//加載JDBC錯誤,所要用的驅動沒有找到System.err.print("ClassNotFoundException");//其他錯誤System.err.println(e.getMessage()); } catch (SQLException ex) {//顯示數據庫連接錯誤或查詢錯誤System.err.println("SQLException: " + ex.getMessage()); }

    }

}
JDBC使用技巧

Statement與PreparedStatement的區別
connection, Statement與ResultSet關閉的意義
jdbc連接參數的使用
ResultSet游標的使用(setFetchSize)
Statement與PreparedStatement的區別

PreparedStatement在數據庫端預編譯,效率高,可以防止SQL注入。
對數據庫執行一次性存取的時候,用Statement對象進行處理。
線上業務推薦使用PreparedStatement.
PreparedStatement背后的故事

PREPARE -> EXECUTE -> DEALLOCATE PREPARE

PREPARE stmt1 FROM 'SELECT productCode, productName
From products
WHERE productCode = ?';
SET @pc = 'S10_1678';
EXECUTE stmt1 USING @pc;

DEALLOCATE PREPARE stmt1;
connection, Statement與ResultSet關閉的意義

MySQL數據庫端為connection與ResultSet維護內存狀態,一直不關閉會占用服務端資源。
MySQL最大連接數受max_connections限制,不能無限創建連接,所以用完要及時關閉。
JDBC connection關閉后ResultSet, Statement會自動關閉。但是如果使用連接池將不會關閉,因此推薦主動關閉。
jdbc連接參數的使用

字符集設置:
url="jdbc:mysql://localhost:3306/blog_dbo?userUnicode=true&characterEncoding=utf8";

超時設置:
url="jdbc:mysql://localhost:3306/blog_dbo?connectionTimeout=1000&socketTimeout=30000";

ResultSet游標的使用

默認的ResultSet對象不可更新,僅有一個向前移動的指針。因此,只能迭代它一次,并且只能按從第一行到最后一行的順序進行。可以生成可滾動和/或可更新的ResultSet對象。
setFetchSize()是設置ResultSet每次向數據庫取的行數,防止數據返回量過大將內存爆掉。
Python連接MySQL

Python:腳本語言,無需編譯、易開發
DBA使用Python的一般場景是編寫自動化運維工具、報表、數據遷移
Python MySQL驅動:python-mysqldb
import MySQLdb

建立和mysql數據庫的連接

conn = MySQLdb.connect(host='localhost', port=3306,user='bloguser',passwd='xxxx')

獲取游標

curs = conn.cursor()

選擇數據庫

conn.select_db('blog')

執行SQL,創建一個表

curs.execute("create table blog (id int, name varchar(200))")

插入一條記錄

value = [1, 'user1']
curs.execute("insert into blog values(%s, %s)", value)

插入多條記錄

values = [(2, "user2"), (3, "user3")]
curs.executemany("insert into blog values(%s, %s)", values)

提交

conn.commit()

關閉游標

curs.close()

關閉連接

conn.close()
2.9-DAO框架的使用

DAO框架

在應用程序中使用數據訪問對象(DAO),使我們可以將底層數據訪問邏輯與業務邏輯分離開來。DAO框架構建了為每一個數據源提供CRUD(創建、讀取、更新、刪除)操作的類。
DAO模式是標準J2EE設計模式之一。開發人員用這種模式將底層數據訪問操作與高層業務邏輯分離開。一個典型的DAO框架實現有以下組操作:
一個DAO工廠類
一個DAO接口(select/insert/delete/update)
一個實現了DAO接口的具體類
數據傳輸對象
DAO框架的特點

屏蔽底層數據訪問細節,實現業務邏輯和數據訪問邏輯的分離。
簡化代碼開發,提高代碼復用率。
相較于原生的SQL可能會帶來額外的 性能損耗(利用反射機制封裝對象,SQL轉換等)
MyBatis簡介

MyBatis是一個主流的DAO框架,是apache的一個開源項目iBatis的升級版。
MyBatis支持普通SQL查詢,存儲過程和高級映射,消除就幾乎所有JDBC代碼和參數的手工設置以及結果集的檢索。
接口豐富、使用簡單
相較于hibernate更加輕量級,支持原生的sql語句。
支持查詢緩存
MyBatis代碼示例

環境搭建,數據源于映射配置文件的編寫
單值、多值查詢
增刪改數據
連表查詢
示例代碼在sorence/DAO框架代碼示例.rar

MyBatis工作流程

加載配置并初始化,內部生成MappedStatement對象。
調用MyBatis提供的API(SqlSession.select/insert....),將SQL ID與數據對象傳遞給處理層。
處理層解析MappedStatement對象,獲取MySQL的連接,執行相應的SQL語句,接收返回結果。
MyBatis將接收到的返回結果封裝成對應的數據對象返回。
MyBatis使用技巧

區分#{}和${}的不同應用場景: #{}會生成預編譯SQL,會正確的處理數據的類型,而${}僅僅是文本替換。
注意MyBatis封裝數據時的性能損耗: 只返回需要的行數和字段。
使用MyBatis自帶的連接池功能: <dataSource type="POOLED">

轉載于:https://blog.51cto.com/8999a/2044499

總結

以上是生活随笔為你收集整理的数据库MYSQL学习系列二的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产午夜精品一区二区三区嫩草 | 久久久久网站 | 国产欧美日韩专区 | 免费国产在线观看 | 国产精品1000部啪视频 | 成人免费视频免费观看 | 九九视频免费在线观看 | 精品国产乱码久久久久久郑州公司 | 亚洲综合成人在线 | 成人久久免费视频 | 999www| 精品人妻无码一区二区三区换脸 | 操你啦免费视频 | 久久国产区| 久久免费国产视频 | 久久er99热精品一区二区 | 国产免费黄色网址 | 亚洲精品短视频 | 漂亮少妇高潮午夜精品 | 久久久久久中文 | 国产免费啪啪 | 国产丰满农村老妇女乱 | 日日狠狠久久偷偷四色综合免费 | 在线视频欧美日韩 | 一区二区三区激情 | 成人91免费 | chien国产乱露脸对白 | 淫欲av | 日韩电影二区 | 天堂在线一区 | 乱色精品无码一区二区国产盗 | 亚洲最大av网站 | 日韩 欧美 国产 综合 | 一区二区三区视频在线观看免费 | 久久影院一区二区 | 人妻一区二区三区 | 日韩欧美亚洲国产精品字幕久久久 | 女生隐私免费看 | 日韩三级黄色 | 天天插天天干天天操 | 国产精品一区二区免费看 | 香蕉视频免费在线播放 | 国产极品在线观看 | 四虎在线影院 | 97在线播放 | 国产女人水真多18毛片18精品 | 国产精品视频一区在线观看 | 春色av| 青娱乐青青草 | 91精品久久久久久久久中文字幕 | 日韩午夜在线播放 | 欧美成人二区 | 在线观看视频免费 | 四虎国产精品永久免费观看视频 | 国产日韩精品一区二区 | 久久综合成人 | 免费看一级黄色大全 | 丰满少妇麻豆av苏语棠 | www婷婷av久久久影片 | 国产精品久久久久9999 | 国产亚洲欧美一区二区三区 | 奴性白洁会所调教 | 黄色网战在线观看 | 久久精品tv| 激情综合站 | 脱女学生小内内摸了高潮 | 99久99| 欧美在线一二三四区 | 午夜影音 | 图片区亚洲色图 | 国产91色 | 欧美日韩一区二区三区四区五区 | 精品久久久久久中文字幕 | 亚洲精品在线免费观看视频 | fc2ppv在线播放| 欧美色乱 | 猛1被调教成公厕尿便失禁网站 | 久久久久亚洲视频 | 久久久久久无码精品人妻一区二区 | 久久久青青 | 丝袜熟女一区二区三区 | 国产美女精品视频国产 | 超碰综合在线 | 日韩一区二区不卡视频 | 精品婷婷色一区二区三区蜜桃 | 裸体男女树林做爰 | 俺也去在线视频 | www.超碰97| 亚洲综合网在线观看 | 国产成人精品免高潮在线观看 | 狠狠看| 日本免费一区二区三区最新 | 色综合久久88色综合天天免费 | jizjiz中国少妇高潮水多 | 日韩精品一区二区三区四区五区 | 波多野结衣在线播放 | 99草视频 | 91色在线| 欧美高清hd18日本 |