MySQL-初見


初識MySQL

MySQL是一個 關系型數據庫 管理系統,由瑞典MySQL AB 公司開發,屬於 Oracle 旗下產品。

MySQL 是最流行的關系型數據庫管理系統之一,在 WEB 應用方面,MySQL是最好的 RDBMS (Relational Database Management System,關系數據庫管理系統) 應用軟件之一。

關系型數據庫(SQL)

  1. MySQL,Oracle,DB2
  2. 通過表與表之間,行與行之間的關系進行存儲

非關系型數據庫(NoSQL)

  1. Redis,MongDB
  2. 非關系型數據庫,對象存儲

數據庫基本命令

--連接數據庫
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引擎在屋里文件上的區別:

  1. InnoDB 在數據庫表中只有一個*.frm文件,以及上級目錄下的idbdata1文件
  2. 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 數據查詢語言 )

  1. 查詢數據庫數據 , 如SELECT語句
  2. 簡單的單表查詢或多表的復雜查詢和嵌套查詢
  3. 是數據庫語言中最核心,最重要的語句
  4. 使用頻率最高的語句

語法

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;;

模糊查詢:比較操作符

注意:

  1. 數值數據類型的記錄之間才能進行算術運算 ;
  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;

  1. 等值連接中不要求屬性值完全相同,而自然連接要求兩個關系中進行比較的必須是相同的屬性組(屬性名可以不同),即要求必須有相同的值域。

  2. 等值連接不將重復屬性去掉,而自然連接去掉重復屬性,也可以說,自然連接是去掉重復列的等值連接(如圖所示)

排序查詢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:單頁面顯示條數]

嵌套查詢(子查詢)

  1. 在查詢語句中的WHERE條件子句中,又嵌套了另一個查詢語句
  2. 嵌套查詢可由多個子查詢組成,求解的方式是由里及外;
  3. 子查詢返回的結果一般都是集合,故而建議使用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 --最高分

數據庫事務

  1. 事務就是將一組SQL語句放在同一批次內去執行
  2. 如果一個SQL語句出錯,則該批次內的所有SQL都將被取消執行
  3. 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)

主鍵 : 某一個屬性組能 唯一 標識一條記錄

特點 :

  1. 最常見的索引類型
  2. 確保數據記錄的唯一性
  3. 確定特定數據記錄在數據庫中的位置
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;

索引原則

  1. 索引不是越多越好
  2. 不要對經常變動的數據加索引
  3. 小數據量的表建議不要加索引
  4. 索引一般應加在查找條件的字段

索引數據結構

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 [用戶名]


數據庫備份

  1. 保證重要數據不丟失
  2. 數據轉移

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)

數據導入:

  1. 命令行導入
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&amp;useUnicode=true&amp;characterEncoding=utf8&amp;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');


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM