初識MySQL
MySQL是一個 關系型數據庫 管理系統,由瑞典MySQL AB 公司開發,屬於 Oracle 旗下產品。
MySQL 是最流行的關系型數據庫管理系統之一,在 WEB 應用方面,MySQL是最好的 RDBMS (Relational Database Management System,關系數據庫管理系統) 應用軟件之一。
關系型數據庫(SQL)
- MySQL,Oracle,DB2
- 通過表與表之間,行與行之間的關系進行存儲
非關系型數據庫(NoSQL)
- Redis,MongDB
- 非關系型數據庫,對象存儲
數據庫基本命令
--連接數據庫
mysql -u root -p [密碼]
--查詢所有數據庫
show databases;
--切換數據庫
user [數據庫名];
--查看所有表
show tables;
--顯示表信息
describe [表名];
--創建數據庫
create database [數據庫名];
--查看創建數據庫的語句
show create database school;
--查看創建表的定義語句
show create table student;
--查看表結構
desc student;
--查看SQL執行的狀況EXPLAIN
EXPLAIN select * from user
--操作數據庫
--操作數據庫> 操作數據庫中的表>操作表中的數據
MySQL中的SQL語句不區分大小寫
--創建數據庫
create database [if not exists] westos;
--刪除數據庫
drop database [if exists] student;
--使用數據庫
--如果表名或庫名是一個特殊字符,就需要帶 ``符
user `westos`;
創建數據庫表
整數:
tinyint 十分小的數據 1個字節
smallint 較小數據 2個字節
mediumint 中等大小的數據 2個字節
int 標准的整數 4個字節
bigint 較大的數據 8個字節
浮點數:
float 浮點數 4個字節
double 浮點數 8個字節(精度問題)
金融計算的時候一般使用decimal:
decimal 字符串形式的浮點數
字符串
char 字符串固定大小 0~255
varchar 可變字符串 0~65535 常用 String
tinytext 微型文本 2^8~1
text 文本串 2^16~1 保持大文本
時間格式
date YYYY-MM-DD 日期格式
time HH:mm:ss 時間格式
datetime YYYY-MM-DDHH:mm:ss 最常用的時間格式
timestamp 時間戳 1970.1.1 到現在的毫秒數
year 年份表示
null
沒有值 未知
不要使用null進行運算
創建數據庫表完整語句
CREATE TABLE IF NOT EXISTS `t_te_user`(
`id` INT(4) NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(30) NOT NULL ,
`pwd` VARCHAR(20) NOT NULL ,
`sex` VARCHAR(30) NOT NULL ,
`address` VARCHAR(100) DEFAULT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
--格式
CREATE TABLE [IF NOT EXISTS] `表名`(
`字段名` 列類型 [屬性] [索引] [注釋],
`字段名` 列類型 [屬性] [索引] [注釋],
`字段名` 列類型 [屬性] [索引] [注釋],
`字段名` 列類型 [屬性] [索引] [注釋],
)[表類型][字符集][注釋]
--設置數據庫表的字符集編碼
CHARSET=utf8
不設置的話,會是mysql默認的字符集編碼,不支持中文!
注意點
- 字段名盡量使用``符號包裹
- 注釋使用--符號
- SQL大小寫不敏感,但是建議寫小寫
- 所有的標點符號,使用英文
數據庫引擎
數據庫引擎
InnoDB | MYISAM | |
---|---|---|
事務支持 | 支持 | 不支持 |
數據行鎖定 | 支持 | 不支持 |
外鍵約束 | 支持 | 不支持 |
全文索引 | 不支持 | 支持 |
表空間的大小 | 較大,約為2倍 | 較小 |
MYISAM:節約空間,速度最快
InnoDB:安全性高,事務的處理,多表多用戶操作
在物理空間的位置
所有的數據庫文件都存放在data目錄下,一個文件夾就代表一個數據庫
Windows默認安裝目錄在C:\Program Files\
本質還是文件存儲
MySQL引擎在屋里文件上的區別:
- InnoDB 在數據庫表中只有一個*.frm文件,以及上級目錄下的idbdata1文件
- MYISAM 對應的文件: *.frm-表結構的定義文件, .MYD-數據文件(data),.MYI-索引文件(index)
修改和刪除表字段
--修改表名
ALTER TABLE [舊表名] RENAME AS [新表名]
--新增字段
ALTER TABLE [表名] ADD [字段名][類型]
--修改字段約束(如:int變成varchar)
ALTER TABLE [表名] MODIFY [字段名][字段約束]
--字段重命名
ALTER TABLE [表名] CHANGE [舊字段名][新字段名]
--最終結論: change用來字段重命名,不能修改字段類型和約束;
--modify不用來字段重命名,只能修改字段類型和約束;
--刪除
--刪除字段
ALTER TABLE [表名] DROP [字段名]
--刪除表
DROP TABLE IF EXISTS [表名]
--所有的刪除和修改盡量都加上判斷(`if exists`),避免報錯
MySQL數據管理
外鍵
概念
如果 公共 關鍵字在一個關系中是主關鍵字,那么這個公共關鍵字被稱為另一個關系的外鍵。
由此可見,外鍵表示了兩個關系之間的相關聯系。以另一個關系的外鍵作主關鍵字的表被稱為主表,具有此外鍵的表被稱為主表的從表。
在實際操作中,將一個表的值放入第二個表來表示關聯,所使用的值是第一個表的主鍵值(在必要時可包括復合主鍵值)。此時,第二個表中保存這些值的屬性稱為外鍵(foreign key)。
建表時指定外鍵約束
-- 創建外鍵的方式一 : 創建子表同時創建外鍵
-- 年級表 (id\年級名稱)
CREATE TABLE `grade` (
`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年級ID',
`gradename` VARCHAR(50) NOT NULL COMMENT '年級名稱',
PRIMARY KEY (`gradeid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
-- 學生信息表 (學號,姓名,性別,年級,手機,地址,出生日期,郵箱,身份證號)
CREATE TABLE `student` (
`studentno` INT(4) NOT NULL COMMENT '學號',
`studentname` VARCHAR(20) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`sex` TINYINT(1) DEFAULT '1' COMMENT '性別',
`gradeid` INT(10) DEFAULT NULL COMMENT '年級',
`phoneNum` VARCHAR(50) NOT NULL COMMENT '手機',
`address` VARCHAR(255) DEFAULT NULL COMMENT '地址',
`borndate` DATETIME DEFAULT NULL COMMENT '生日',
`email` VARCHAR(50) DEFAULT NULL COMMENT '郵箱',
`idCard` VARCHAR(18) DEFAULT NULL COMMENT '身份證號',
PRIMARY KEY (`studentno`),
KEY `FK_gradeid` (`gradeid`),
CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
-- 創建外鍵方式二 : 創建子表完畢后,修改子表添加外鍵
ALTER TABLE `student`
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`);
--注意 : 刪除具有主外鍵關系的表時 , 要先刪子表 , 后刪主表
-- 刪除外鍵
ALTER TABLE student DROP FOREIGN KEY FK_gradeid;
-- 發現執行完上面的,索引還在,所以還要刪除索引
-- 注:這個索引是建立外鍵的時候默認生成的
ALTER TABLE student DROP INDEX FK_gradeid;
以上內容都是 物理外鍵
數據庫級別的外鍵,不建議使用,避免數據庫過多造成困擾
以后使用外鍵都是在應用層實現(代碼實現)
DML語言
--INSERT新增詳解
--插入命令格式:
insert into [表名]([字段名],[字段名]) values([值],[值])
--注意事項:
--一般寫插入語句,字段和數據一定要一一對應
--字段或值之間用英文逗號隔開
--’ 字段1,字段2…’ 該部分可省略 , 但添加的值務必與表結構,數據列,順序相對應,且數量一致 .
--可同時插入多條數據 , values 后用英文逗號隔開
--UPDATE修改詳解
--修改命令格式:
UPDATE [表名] SET [字段名]=[修改值] WHERE `id`='4';
--注意:
--where語句之后為篩選條件 , 如不指定則修改該表的所有列數據
--DELETE刪除詳解
--刪除命令格式:
DELETE FROM 表名 [WHERE 條件匹配];
--注意:
--where后為篩選條件 , 如不指定則刪除該表的所有列數據
--TRUNCAT刪除詳解
--刪除命令格式:
TRUNCATE TABLE [表名];
--作用:用於完全清空表數據 , 但表結構 , 索引 , 約束等不變 ;
--注意:區別於DELETE命令
--相同 :
--都能刪除數據 , 不刪除表結構 , 但TRUNCATE速度更快
--不同 :
--使用TRUNCATE TABLE 重新設置AUTO_INCREMENT計數器,自增會歸零
--使用TRUNCATE TABLE不會對事務有影響
了解即可:「DELETE刪除的問題, 重啟數據庫, 現象
●InnoDB 自增列會重1開始(存在內存當中的, 斷電即失)
●MyISAM 繼續從上一一個自增量開始(存在文件中的,不會丟失)
DQL查詢數據
DQL( Data Query Language 數據查詢語言 )
- 查詢數據庫數據 , 如SELECT語句
- 簡單的單表查詢或多表的復雜查詢和嵌套查詢
- 是數據庫語言中最核心,最重要的語句
- 使用頻率最高的語句
語法
SELECT [ALL | DISTINCT]
{* | table.* | [table.field1[as alias1][,table.field2[as alias2]][,...]]}
FROM table_name [as table_alias]
[left | right | inner join table_name2] -- 聯合查詢
[WHERE ...] -- 指定結果需滿足的條件
[GROUP BY...] -- 指定結果按照哪幾個字段來分組
[HAVING] -- 過濾分組的記錄必須滿足的次要條件
[ORDER BY ...] -- 指定查詢記錄按一個或多個條件排序
[LIMIT {[offset,]row_count | row_countOFFSET offset}];
-- 指定查詢的記錄從哪條至哪條
單表查詢
--查詢表的全部信息
select * from [表名]
--查詢指定字段信息
select [字段],[字段] from [表名]
--查詢指定字段並取別名
select [字段] as [別名],[字段] as [別名] from [表名]
--字符串拼接函數 Concat(a,b)
select concat('姓名:',[字段]) from [表名]
--去除重復數據 關鍵字:DISTINCT
select DISTINCT [字段名]from [表名]
--其他查詢
select version() --查詢系統版本
select 100*3-1 as --計算結果
select @@auto_increment_increment --查詢自增步長
--學員考試成績集體提分一分查看
SELECT studentno,StudentResult+1 AS '提分后' FROM result;
--數據庫中的表達式 : 一般由文本值 , 列值 , NULL , 函數和操作符等組成
WHERE條件子句
可以簡單的理解為 : 有條件地從表中篩選數據
搜索條件可由一個或多個邏輯表達式組成 , 結果一般為真或假
--查詢id等於1的用戶
select * from user where id=1;
--查詢id等於1並且姓名是金角大王的用戶
select * from user where id=1 and name='金角大王';
--查詢id=1 或者 id=2的用戶
select * from user where id=1 or id=2;;
模糊查詢:比較操作符
注意:
- 數值數據類型的記錄之間才能進行算術運算 ;
- 相同數據類型的數據之間才能進行比較 ;
IS NULL
--查詢email為空的用戶
select * from user where email is null;
IS NOT NULL
--查詢email不為空的用戶
select * from user where email is not null;
BETWEEN
--區間模糊查詢between and 查詢id大於4小於50的用戶
select * from user where id between 4 and 50
LIKE
--一般搭配通配符%使用
--查詢姓名是金字開頭的用戶
select * from user where name like '金';
--查詢名字中間有佳字的用戶
select * from user where name like '%佳%';
IN
--匹配多個結果 具體的一個或多個值
--查詢id=1,2,3的用戶
select * from user where id in (1,2,3);
聯表查詢
JOIN
連接查詢
如需要多張數據表的數據進行查詢,則可通過連接運算符實現多個查詢
內連接 inner join
查詢兩個表中的結果集中的交集
格式:
select a.*,b.* from user a
inner join student b on a.id=b.id;
左外連接 left join
以左表作為基准,右邊表來一一匹配,匹配不上的,返回左表的記錄,右表以NULL填充
格式:
select a.*,b.* from user a
left join student b on a.id=b.id;
右外連接 right join
以右表作為基准,左邊表來一一匹配,匹配不上的,返回右表的記錄,左表以NULL填充
格式:
select a.*,b.* from user a
right join student b on a.id=b.id;
等值連接
SELECT s.*,r.*
FROM `user` s , `student` r
WHERE r.studentno = s.studentno
自連接
數據表與自身進行連接
將一張表拆成兩張表
-- 創建一個表
CREATE TABLE `category` (
`categoryid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主題id',
`pid` INT(10) NOT NULL COMMENT '父id',
`categoryName` VARCHAR(50) NOT NULL COMMENT '主題名字',
PRIMARY KEY (`categoryid`)
) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
-- 插入數據
INSERT INTO `category` (`categoryid`, `pid`, `categoryName`)
VALUES('2','1','信息技術'),
('3','1','軟件開發'),
('4','3','數據庫'),
('5','1','美術設計'),
('6','3','web開發'),
('7','5','ps技術'),
('8','2','辦公信息');
--查詢方式一
select a.categoryName as '父',b.categoryName as'子'
from category as a,category as b
where a.categoryid=b.pid;
--查詢方式二
select a.categoryName as '父',b.categoryName as'子'
from category as a
inner join category as b on a.categoryid=b.pid;
-
等值連接中不要求屬性值完全相同,而自然連接要求兩個關系中進行比較的必須是相同的屬性組(屬性名可以不同),即要求必須有相同的值域。
-
等值連接不將重復屬性去掉,而自然連接去掉重復屬性,也可以說,自然連接是去掉重復列的等值連接(如圖所示)
排序查詢ORDER BY
排序查詢和分頁查詢的關鍵字在整個SQL語句的最后面,其語法位置是固定不變的,不能放在where
或者having
的前面
升序:ASC
語法:
select * from [表名]
order BY id asc
降序:BESC
語法:
select * from [表名]
order BY id desc
分組查詢GROUP by
語法:
select * from user
GROUP by [分組的字段]
分組查詢之后使用HAVING來過濾分組之后的數據
select * from user
GROUP by sex
HAVING age>20
分頁查詢Limit
語法:
select * from [表名]
limit [起始值],[每頁大小]
查找規律可以推導出計算每頁的公式:
第一頁 : limit 0,5 公式:(1-1)*5
第二頁 : limit 5,5 公式:(2-1)*5
第三頁 : limit 10,5 公式:(3-1)*5
…
第N頁 : (N-1)*頁面大小
limit (pageNo-1)*pageSzie,pageSzie
[pageNo:頁碼,pageSize:單頁面顯示條數]
嵌套查詢(子查詢)
- 在查詢語句中的WHERE條件子句中,又嵌套了另一個查詢語句
- 嵌套查詢可由多個子查詢組成,求解的方式是由里及外;
- 子查詢返回的結果一般都是集合,故而建議使用IN關鍵字;
語法:
select * from [表名]
where id in ( select id from [表名] )
MySQL常用函數
常用函數
數學函數
select abs(-8) --絕對值
select CEILING(9.4); --向上取整
select RAND(); --返回隨機數
select SIGN(0); --符號函數:負數返回-1 正數返回1 0返回0
字符串函數
select CHAR_LENGTH('你就是根基吧'); --字符串長度
select CONCAT('鄭','在','稿');--合並字符串
select INSERT('你就是根基吧',4,2,'鄭在稿'); --替換字符串
select LOWER("SKSSSS");--小寫
select UPPER('ssssss'); --大寫
select LEFT('hello,word',5); --從左邊截取
select RIGHT('hello,word',5); --從右邊截取
select REPLACE('狂神說堅持就能成功','堅持','成功');--替換字符串
select SUBSTR('狂神說堅持就能成功',4,6);--截取字符串
select REVERSE('狂神說堅持就能成功'); --反轉
時間日期函數
--日期和時間函數
select CURRENT_DATE();--獲取當前日期
select CURDATE();--獲取當前日期
select NOW();--獲取當前日期和時間
select LOCALTIME();--獲取當前日期和時間
select SYSDATE();--獲取當前日期和時間
--獲取年月日時分秒
select YEAR(NOW());
select MONTH(NOW());
select DAY(NOW());
select HOUR(NOW());
select MINUTE(NOW());
select SECOND(NOW());
聚合函數
函數名稱 描述 :
~
COUNT() 返回滿足Select條件的記錄總和數,如 select count(*) 【不建議使用 *,效率低】
~
SUM() 返回數字字段或表達式列作統計,返回一列的總和。
~
AVG() 通常為數值字段或表達列作統計,返回一列的平均值
~
MAX() 可以為數值字段,字符字段或表達式列作統計,返回最大的值。
~
MIN() 可以為數值字段,字符字段或表達式列作統計,返回最小的值。
COUNT()
格式:
select count([字段]) from [表名] --會忽略所有null
select count(*) from [表名] --不會忽略null
select count(1) from [表名] --不會忽略null
一般情況下count(1)比count(*)速度快
其他聚合函數
格式:
select sum(id) from user --求和
select AVG(id) from user --平均分
select MIN(id) from user --最小分
select MAX(id) from user --最高分
數據庫事務
- 事務就是將一組SQL語句放在同一批次內去執行
- 如果一個SQL語句出錯,則該批次內的所有SQL都將被取消執行
- MySQL事務處理只支持InnoDB和BDB數據表類型
ACID
原子性(Atomic)
要么全部成功,要么全部失敗
一致性(Consist)
事務執行前后數據的完整性要保持一致
隔離性(Isolated)
事務在並發訪問的時候,為每個用戶開啟單獨事務,事務與事務之間要保持隔離
持久性(Durable)
事務一旦提交便不可逆
隔離導致的問題
臟讀
一個事務讀取了另一個沒有提交的事務
事務A讀取了事務B更新的數據,然后B回滾操作,那么A讀取到的數據是臟數
幻讀
在同一個事務內,讀取到了別人插入的數據,導致前后讀出來結果不一致
不可重復讀
在同一個事務內,重復讀取表中的數據,表數據發生了改變
事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果不一致。
基本語法
-- 使用set語句來改變自動提交模式
SET autocommit = 0; /*關閉*/
SET autocommit = 1; /*開啟*/
-- 注意:
--- 1.MySQL中默認是自動提交
--- 2.使用事務時應先關閉自動提交
-- 開始一個事務,標記事務的起始點
START TRANSACTION
-- 提交一個事務給數據庫
COMMIT
-- 將事務回滾,數據回到本次事務的初始狀態
ROLLBACK
-- 還原MySQL數據庫的自動提交
SET autocommit =1;
-- 保存點
SAVEPOINT 保存點名稱 -- 設置一個事務保存點
ROLLBACK TO SAVEPOINT 保存點名稱 -- 回滾到保存點
RELEASE SAVEPOINT 保存點名稱 -- 刪除保存點
索引
MySQL官方對索引的定義為: 索引(index)是幫助MySQL高效獲取數據的數據結構
顯示表的索引信息
show index from [表名]
1
創建索引
create index [索引名] on [表]([字段])
索引分類
主鍵索引 (Primary Key)
主鍵 : 某一個屬性組能 唯一 標識一條記錄
特點 :
- 最常見的索引類型
- 確保數據記錄的唯一性
- 確定特定數據記錄在數據庫中的位置
ALTER TABLE tbl_name ADD PRIMARY KEY (col_list);
// 該語句添加一個主鍵,這意味着索引值必須是唯一的,且不能為NULL。
唯一索引 (Unique Key)
作用 : 避免同一個表中某數據列中的值重復
與主鍵索引的區別:
- 主鍵索引只能有一個
- 唯一索引可能有多個
ALTER TABLE tbl_name ADD UNIQUE index_name (col_list);
--這條語句創建索引的值必須是唯一的。
常規索引 (Index)
作用 : 快速定位特定數據
注意 :
- index 和 key 關鍵字都可以設置常規索引
- 應加在查詢找條件的字段
- 不宜添加太多常規索引,影響數據的插入,刪除和修改操作
CREATE TABLE `result`(
-- 省略一些代碼
INDEX/KEY `ind` (`studentNo`,`subjectNo`) -- 創建表時添加
)
ALTER TABLE tbl_name ADD INDEX index_name (col_list);
--添加普通索引,索引值可出現多次。
全文索引 (FullText)
作用 : 快速定位特定數據
1
2
全文索引 (FullText)
作用 : 快速定位特定數據
注意 :
- 只能用於MyISAM類型的數據表
- 只能用於CHAR , VARCHAR , TEXT數據列類型
- 數據量小的情況下全文索引不生效
- 適合大型數據集
-- 創建后添加全文索引
ALTER TABLE [表名] ADD FULLTEXT INDEX [索引名]([列名]);
--全文索引的使用:
select * from student where MATCH([全文索引列名]) AGAINST ([查找的內容])
強制索引
如果查詢優化器忽略索引,您可以使用FORCE INDEX提示來指示它使用索引。
1
強制索引
如果查詢優化器忽略索引,您可以使用FORCE INDEX提示來指示它使用索引。
以下說明了FORCE INDEX提示語法:
SELECT *
FROM table_name
FORCE INDEX (index_list)
WHERE condition;
索引原則
- 索引不是越多越好
- 不要對經常變動的數據加索引
- 小數據量的表建議不要加索引
- 索引一般應加在查找條件的字段
索引數據結構
hash類型的索引:查詢單條快,范圍查詢慢
btree類型的索引:b+樹,層數越多,數據量指數級增長(我們就用它,因為innodb默認支持它)
索引刪除方法
DROP INDEX index_name ON tbl_name;
// 或者
ALTER TABLE tbl_name DROP INDEX index_name;
ALTER TABLE tbl_name DROP PRIMARY KEY;
權限管理
創建用戶命令格式:
CREATE USER [用戶名] IDENTIFIED BY '[密碼]'
修改當前用戶:
set password=password('[密碼]')
修改指定用戶密碼:
set password for [用戶名]=password('[密碼]')
重命名
rename user [舊用戶名] to [新用戶名]
賦予用戶全部權限
--用戶授權ALL PRIVILEGES全部的權限,庫.表 on to 用戶名
-- 除了給別的用戶授權的權限沒有 其他都能做
GRANT ALL PRIVILEGES ON *.* TO [用戶名]
查詢用戶權限
show GRANTS for [用戶] -- 普通用戶
show GRANTS for root@localhost -- 查看root用戶權限
撤銷用戶權限
REVOKE ALL PRIVILEGES ON *.* from [用戶名]
刪除用戶
DROP [用戶名]
數據庫備份
- 保證重要數據不丟失
- 數據轉移
MySQL數據庫備份方法:
mysqldump命令行導出
mysqldump -u用戶名 -p密碼 庫名 表名 > 文件名(D:/a.sql)
-- 導出
1. 導出一張表 -- mysqldump -uroot -p123456 school student >D:/a.sql
mysqldump -u用戶名 -p密碼 庫名 表名 > 文件名(D:/a.sql)
2. 導出多張表 -- mysqldump -uroot -p123456 school student result >D:/a.sql
mysqldump -u用戶名 -p密碼 庫名 表1 表2 表3 > 文件名(D:/a.sql)
3. 導出所有表 -- mysqldump -uroot -p123456 school >D:/a.sql
mysqldump -u用戶名 -p密碼 庫名 > 文件名(D:/a.sql)
4. 導出一個庫 -- mysqldump -uroot -p123456 -B school >D:/a.sql
mysqldump -u用戶名 -p密碼 -B 庫名 > 文件名(D:/a.sql)
數據導入:
- 命令行導入
2. 在登錄mysql的情況下:-- source D:/a.sql
source 備份文件
3. 在不登錄的情況下
mysql -u用戶名 -p密碼 庫名 < 備份文件
數據庫設計三大范式
第一范式 (1st NF)
第一范式的目標是確保每列的原子性,如果每列都是不可再分的最小數據單元,則滿足第一范式
第二范式(2nd NF)
第二范式(2NF)是在第一范式(1NF)的基礎上建立起來的,即滿足第二范式(2NF)必須先滿足第一范式(1NF)。
第二范式要求每個表只描述一件事情
第三范式(3rd NF)
如果一個關系滿足第二范式,並且除了主鍵以外的其他列都不傳遞依賴於主鍵列,則滿足第三范式.
第三范式需要確保數據表中的每一列數據都和主鍵直接相關,而不能間接相關。
規范化和性能的關系
關聯查詢的表不得超過三張表
- 為滿足某種商業目標 , 數據庫性能比規范化數據庫更重要(成本,用戶體驗)
- 在數據規范化的同時 , 要綜合考慮數據庫的性能
- 通過在給定的表中添加額外的字段,以大量減少需要從中搜索信息所需的時間(增加冗余
JDBC
創建項目導入依賴,寫代碼
/**
* 測試JDBC程序
*/
@SpringBootTest
public class JdbcFirstDemoTest {
@Test
public void TestJDBC() throws Exception {
//加載驅動
Class.forName("com.mysql.jdbc.Driver");//固定寫法
//用戶信息和url
String password="123456";
String username="root";
String url="jdbc:mysql://localhost:3306/jtdb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=true";
//連接成功和數據庫對象
Connection connection = DriverManager.getConnection(url, username, password);
//執行SQL對象
Statement statement = connection.createStatement();
//使用對象去運行SQL 存在結果 返回對象
ResultSet resultSet = statement.executeQuery("select * from user");
//遍歷結果
while (resultSet.next()){
System.out.println(resultSet.getObject("id"));
System.out.println(resultSet.getObject("name"));
System.out.println(resultSet.getObject("age"));
System.out.println(resultSet.getObject("sex"));
}
//釋放連接
resultSet.close();
statement.close();
connection.close();
}
}
connection對象詳解
connection 代表數據庫,數據庫相關操作都在這里面.
如:設置事務自動提交,事務開啟,回滾等等
connection.setAutoCommit(false);//關閉自動提交
connection.commit();//提交
connection.rollback();//回滾
statement對象詳解
statement.execute("");//執行所有類型的SQL
statement.executeQuery("");//執行查詢SQL
statement.executeUpdate("");//新增 修改 刪除
resultSet結果集詳解
獲取指定類型的數據
resultSet.getObject();//不知道字段類型時使用
resultSet.getDate();//字段是時間類型
resultSet.getString();//字段是varchar
resultSet.getInt();
resultSet.getBoolean();
遍歷,指針
resultSet.next();//指針下移一位
resultSet.beforeFirst();//指針移到最前面
resultSet.afterLast();//指針移到最后面
resultSet.previous();//指針上移一位
resultSet.absolute(1);//指針移動到指定位置
編寫JDBC工具類
/**
* JDBC工具類
*/
public class JdbcUtil {
private static String url;
private static String username;
private static String password;
static {
//反射讀取配置文件 src目錄下
InputStream inp = JdbcUtil.class.getClassLoader().getResourceAsStream("JDBC.properties");
try {
Properties properties = new Properties();
properties.load(inp);//從輸入流中讀取配置信息
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
Class.forName(properties.getProperty("Driver"));//加載數據庫驅動
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
//獲取連接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
//釋放連接
public static void release(Connection connection, Statement statement, ResultSet resultSet){
if (connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}if (statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}if (resultSet != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
SQL注入
SQL注入即是指web應用程序對用戶輸入數據的合法性沒有判斷或過濾不嚴,攻擊者可以在web應用程序中事先定義好的查詢語句的結尾上添加額外的SQL語句,在管理員不知情的情況下實現非法操作,以此來實現欺騙數據庫服務器執行非授權的任意查詢,從而進一步得到相應的數據信息;
//SQL預編譯 insert into user(id,name,age,sex) values (?,?,?,?)
PreparedStatement preparedStatement = connection.prepareStatement("insert into user(id,name,age,sex) values (?,?,?,?)");
//手動給參數賦值
preparedStatement.setInt(1,100);
preparedStatement.setString(2,"金角銀角");
preparedStatement.setInt(3,12);
preparedStatement.setString(4,"男");
//執行
int i = preparedStatement.executeUpdate();
System.out.println("執行結果:"+i);
JDBC操作事務
@Test
public void Test2() {
//加載驅動
try {
Class.forName("com.mysql.jdbc.Driver");//固定寫法
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//用戶信息和url
String password="123456";
String username="root";
String url="jdbc:mysql://localhost:3306/jtdb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=true";
//連接成功和數據庫對象
Connection connection = null;
PreparedStatement preparedStatement=null;
try {
connection = DriverManager.getConnection(url, username, password);
//關閉數據庫自動提交 自動會開啟事務
connection.setAutoCommit(false);
//SQL預編譯 insert into user(id,name,age,sex) values (?,?,?,?)
preparedStatement = connection.prepareStatement("insert into user(id,name,age,sex) values (?,?,?,?)");
//手動給參數賦值
preparedStatement.setInt(1,100);
preparedStatement.setString(2,"金角銀角");
preparedStatement.setInt(3,12);
preparedStatement.setString(4,"男");
//執行
int i = preparedStatement.executeUpdate();
System.out.println("執行結果:"+i);
connection.commit();//提交事務
} catch (SQLException throwables) {
try {
connection.rollback();//回滾
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
} finally {
try {
preparedStatement.close();
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
數據庫連接池
數據庫連接>執行>釋放 十分浪費資源
池化技術:准備一些預選准備的資源,需要時就直接連接准備好的
編寫連接池,只需要實現一個接口DataSource,各大廠商需要讓自己的連接池實現這個接口
目前市場上常見的連接池有DBCP連接池, C3P0連接池, Druid連接池
無論使用什么數據源,本質還是一樣的,DataSource接口不會變
使用C3P0連接池
導入依賴
<!--C3P0連接池 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
編寫C3P0配置文件
創建c3p0-config.xml配置文件 文件名必須是c3p0-config.xml
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jtdb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=true</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>
<!-- This app is massive! -->
<named-config name="intergalactoApp">
<property name="acquireIncrement">50</property>
<property name="initialPoolSize">100</property>
<property name="minPoolSize">50</property>
<property name="maxPoolSize">1000</property>
<!-- intergalactoApp adopts a different approach to configuring statement caching -->
<property name="maxStatements">0</property>
<property name="maxStatementsPerConnection">5</property>
<!-- he's important, but there's only one of him -->
<user-overrides user="master-of-the-universe">
<property name="acquireIncrement">1</property>
<property name="initialPoolSize">1</property>
<property name="minPoolSize">1</property>
<property name="maxPoolSize">5</property>
<property name="maxStatementsPerConnection">50</property>
</user-overrides>
</named-config>
</c3p0-config>
編寫工具類
/**
* C3P0連接池
*/
public class JdbcUtilsC3P0 {
private static DataSource dataSource=null;
static {
dataSource = new ComboPooledDataSource();
}
//獲取連接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
測試
//測試C3P0連接池
@Test
public void TEst4() throws SQLException {
Connection connection = JdbcUtilsC3P0.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select * from user");
//遍歷結果
while (resultSet.next()){
System.out.println(resultSet.getObject("id"));
System.out.println(resultSet.getObject("name"));
System.out.println(resultSet.getObject("age"));
System.out.println(resultSet.getObject("sex"));
}
}
數據庫級別的MD5
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用於確保信息傳輸完整一致。是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流編程語言普遍已有MD5實現。將數據(如漢字)運算為另一固定長度值,是雜湊算法的基礎原理,MD5的前身有MD2、MD3和MD4。
實現數據加密
1.對所有password進行加密
update testmd5 set pwd = md5(pwd);
2.對單挑記錄進行加密
INSERT INTO testmd5 VALUES(3,'kuangshen2','123456')
update testmd5 set pwd = md5(pwd) where name = 'zwt';
3.新增數據自動加密
3.新增數據自動加密
INSERT INTO testmd5 VALUES(4,'kuangshen3',md5('123456'));
4.查詢登錄用戶信息(MD5對比加密以后的密碼)
SELECT * FROM testmd5 WHERE `name`='kuangshen' AND pwd=MD5('123456');