命令行連接!
mysql -uroot -p123456 ---連接數據庫
sc delete mysql; 清空服務
update mysql.user set anthentication_string=password('123456')where user='root' and Host='localhost';--修改用戶密碼
flush privileges; --刷新權限
--所有的語句都是用;結尾
show databases; --查看所有的數據庫
mysql> use school --切換數據庫 use 數據庫名
Database changed
show tables; --查看數據庫中所有的表
describe student(表名); --顯示數據庫中所有的表的信息
create database westos; --創建一個數據庫
exit; --退出連接
--單行注釋(SQL的本來的注釋)
/* SQL多行注釋
hello
*/
數據庫xxx語言 CRUD 增刪改查!
DDL 定義
DML 操作
DQL 查詢
DCL 控制
2.操作數據庫
操作數據庫》操作數據庫中的表》操作數據庫表的數據
mysql中的關鍵字不區分大小寫
2.1操作數據庫
1.創建數據庫
CREATE DATABASE [if not EXISTS] person; --創建表,語句沒有中括號,中括號中的內容為如果沒有這個表的情況下創建表
2.刪除數據庫
DROP DATABASE if exists person;
--如果存在就刪除
3.使用數據庫
--table鍵的上面,如果你的表名或者字段名是一個特殊字符,就需要``括起來
use `school`
4.查看數據庫
show databases --查看所有的數據庫
2.2數據庫的列類型
數值
-
tinyint 十分小的數據 1個字節
-
smallint 較小的數據 2個字節
-
mediumint 中等大小數據 3個字節
-
int 標准的整數 4個字節 常用 int
-
bigint 較大的數據 8個字節
-
float 浮點數 4個字節
-
double 浮點數 8個字節(精度有問題!)
-
decimal 字符串形式的浮點數,用於金融計算的時候,一般用decimal
字符串
-
char 字符串固定大小的 0-255
-
varchar 可變字符串 0-65535 常用的 String
-
tingtest 微型文本 2^8-1
-
text 文本串 2^16-1 保存大文本
時間日期
-
date YYYY--MM-DD 日期
-
time HH:MM:ss 時間格式
-
datetime date YYYY--MM-DD HH:MM:ss 最常用的時間格式
-
timestamp 時間戳 1970.1.1到現在的毫秒數!
-
year 年份表示
null
-
沒有值,未知
-
==注意,不要使用NUll進行運算,結果為NUll
2.3數據庫的字段屬性(重點)
Unsigned 無符號:
-
無符號的整數
-
s聲明了該列不能聲明為負數
zerofill 0填充:
-
0填充的
-
不足的位數,使用0來填充,int(3),5 --005
auto_increment自增:
-
通常理解為自增,自動在上一條記錄的基礎上+1(默認)
-
通常用來設計唯一的主鍵·index,必須是整數類型
-
可以自定義設計主鍵自增的起始值和步長
非空 NUll not null
-
假設設置為 not null,如果不給它賦值,就會報錯!
-
NULL,如果不填寫值,默認就是null!
默認:
-
設置默認的值!
-
sex,默認值為男,如果不指定該列的值,則會有默認的值!
/* 每一個表,都必須存在以下五個字段!未來做項目用,表示一個記錄存在意義。
id 主鍵
`vestion` 樂觀鎖
is_delete 偽刪除
gmt_create 創建時間
gmt_update 修改時間
*/
2.4創建數據庫表(重點)
-- 目標:創建一個school數據庫
-- 創建學生表(列,字段) 使用SQL 創建
-- 學號 int 登陸密碼 varchar(20)姓名,性別varchar(2),出生日期(datetime),家庭住址email
-- 注意點,使用英文(),表的名稱和字段 盡量使用 ``括起來
-- AUTO_INCREMENT 自增
-- 字符串使用 單引號括起來!
-- 所有的語句后面加,(英文的),最后一個不用加
-- PRIMARY KEY(`id`) 主鍵是唯一的
CREATE TABLE `school`.`student` (
`id` INT(4) UNSIGNED ZEROFILL NOT NULL auto_increment COMMENT '學號',
`name` VARCHAR(20) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密碼',
`sex` VARCHAR(2) NOT NULL DEFAULT '男' COMMENT '性別',
`birthday` datetime DEFAULT NULL COMMENT '出生日期',
`address` VARCHAR(60) DEFAULT NULL COMMENT '住址',
`email` VARCHAR(50) default NULL COMMENT '郵箱',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT charset=utf8;
/*
格式:
create table `數據庫名`.`表名` (
·字段名· [類型varchar][屬性Unsigned 無符號 ][注釋 comment '學號'],
字段名· [類型varchar][屬性zerofill 0填充][注釋 comment '學號'],
字段名· [類型varchar][屬性 auto_increment自增 ][注釋 comment '學號'],
......
字段名· [類型varchar][屬性][注釋 comment '學號'],
PRIMARY KEY(`id`)
)[設置表類型 默認 ENGINE=INNODB][設置字符集charset=utf8]
*/
常用命令
SHOW create TABLE student; --查看student數據表定義的語句
DESC student; --顯示表的結構
SHOW CREATE DATABASE school; --查看創建數據庫的語句
2.5數據表的類型
-- 關於數據庫引擎 /* INNODB 默認使用 MYISAM 早些年使用的 */
MYISAM | INNODB | |
---|---|---|
事務支持 | 不支持 | 支持 |
數據行鎖定 | 不支持 | 支持 |
外鍵約束 | 不支持 | 支持 |
全文索引 | 支持 | 支持(全英文) |
表空間大小 | 較小 | 較大 約MYISAM2倍 |
常規使用操作:
-
MYISAM 節約空間,速度較快
-
INNODB 安全性高,事務的處理,多表多用戶操作
在物理空間存在的位置
所有的數據庫文件都存在data目錄下,一個文件夾就對應一個數據庫
本質還是文件的存儲!
MySQL引擎在物理文件上的區別
-
innoDB 在數據庫表中只有一個*。frm文件,以及上級目錄下的 ibdata1文件
-
MYISAM對應文件
-
-
*.frm -表結構的定義文件
-
*.MYD 數據文件(data)
-
*.MYI 索引文件(index)
-
設置數據庫表的字符集編碼
charset=utf8
不設置的話,會是mysql默認的字符集集編碼~不支持中文
在my.ini中配置默認的編碼
character-set-server=utf8
小技巧:通過 show create table student語句
顯示表信息后右鍵復制,粘貼到查詢面板上,就自動生成表的sql代碼。
2.6修改刪除表
修改
-- 修改表名: ALTER TABLE 舊表名 rename AS 新表名 ALTER TABLE user1 RENAME AS user -- 增加表的字段: ALTER TABLE 表名 ADD 字段名 列屬性 ALTER TABLE `user` ADD `age` INT(11) -- 修改表的字段(重命名,修改約束!): ALTER TABLE 表名 MODIFY 字段名 列屬性[] ALTER TABLE user1 MODIFY `age` VARCHAR(11)-- 修改約束 ALTER TABLE 表名 CHANGE `舊字段名` `新字段名` 列屬性 ALTER TABLE user1 CHANGE `age` `age1` INT(1) -- 重命名 -- 刪除表的字段 alter TABLE user1 DROP `age1` --刪除表(如果表存在再刪除) DROP TABLE IF EXISTS `user1`
==所有的創建和刪除操作盡量加上判斷,以免報錯==
if not exists 如果不存在就創建
if exists 如果存在就刪除
注意點:
-
``字段名,使用這個包裹!
-
注釋: -- /**/
-
sql關鍵字大小寫不敏感,建議寫小寫
-
所有的符號全部用英文
練習:
ALTER TABLE `user1` RENAME AS `user` --修改表名ALTER TABLE `舊表名` RENAME AS `新表名` ALTER TABLE `user` ADD `hobby` VARCHAR(20)-- 增加表的字段:ALTER TABLE `表名` ADD `字段名` 屬性 ALTER TABLE `user` MODIFY `hobby` INT(20) -- 修改表的字段 的類型和屬性 ALTER TABLE `user` CHANGE `hobby` `hobby1` VARCHAR(30) -- 修改表的字段名 與類型屬性 alter TABLE `user` DROP `hobby1` -- 刪除表的字段 DROP TABLE if EXISTS `user` -- 刪除表 show CREATE DATABASE person -- 查看創建數據庫的語句 show create table `student` -- 查看創建表的語句 DESC `student` -- 顯示表的結構 DROP DATABASE if exists person -- 刪除某個數據庫如果存在的話 show DATABASES -- 查看所有的數據庫 use `school` --使用數據庫
3.MySQL數據管理
3.1外鍵(了解即可)
方式一:在創建表的時候,增加約束(麻煩,復雜)
CREATE TABLE IF NOT EXISTS `school`.`grade` ( `gradeid` INT(10) NOT NULL auto_increment COMMENT '年級編號', `gradename` VARCHAR(10) not null COMMENT '年級名字', PRIMARY KEY(`gradeid`) )ENGINE=INNODB DEFAULT CHARSET=utf8 CREATE TABLE if not EXISTS`student` ( `id` int(4) unsigned zerofill NOT NULL AUTO_INCREMENT COMMENT '學號', `name` varchar(20) NOT NULL DEFAULT '匿名' COMMENT '姓名', `pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密碼', `sex` varchar(2) NOT NULL DEFAULT '男' COMMENT '性別', `gradeid` INT(10) NOT NULL auto_increment COMMENT '年級編號', `birthday` datetime DEFAULT NULL COMMENT '出生日期', `address` varchar(60) DEFAULT NULL COMMENT '住址', `email` varchar(50) DEFAULT NULL COMMENT '郵箱', PRIMARY KEY (`id`), 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 `表名` -- add constraint `約束名` foreign key(作為外鍵的列) references 哪個表(哪個字段);
刪除有外鍵關系的表的時候,必須要先刪除引用別人的表(從表),在刪除自己的表()
以上的操作都是物理外鍵,數據庫級別的外鍵,,我們不建議使用,避免數據庫過多造成困擾
最佳實踐
-
數據庫就是單純的表,只用來存數據,只有行和列
-
我們想使用多張表的數據,想使用外鍵,程序去實現
3.2DML語言(全部記住)
數據庫意義:數據存儲,數據管理
DML語言:數據操作語言
3.3添加 insert
-
insert
-- 插入語句(添加) -- insert into 表名([字段1,字段2,字段3])VALUES(`值1`),(`2`),(`3`) INSERT INTO `grade`(`gradename`)VALUES('大四'), -- 由於主鍵自增我們可以省略(如果不寫字段,它就會一一匹配) -- 一般寫插入語句,我們一定要數據和字段一一對應! -- 插入多個字段 INSERT INTO `grade` (`gradename`)VALUES('大二'),('大一')
語法:insert into 表名([字段1,字段2,字段3])VALUES(值1
),(2
),(3
)
注意事項:
-
字段和字段之間使用英文逗號隔開
-
字段是可以省略的,但是后面的值必須一一對應
-
可以同時插入多條數據,values后面的值,需要使用,隔開即可values(),(),....
3.4修改 update
-
update
update 修改誰(條件)set原來的值=新值
-- 修改學員名字,帶了簡介 UPDATE `student` SET `name`='趙武' WHERE id !=2; -- 不指定條件的情況下,會改動所有表! UPDATE `student` SET `name`='趙東' -- 修改多個屬性,逗號隔開 UPDATE `student` SET `name`='大哥',`age`=18,`adress`='三屯' WHERE id=1;
條件:where 運算符 id等語某個值,大於某個值,在某個區間內修改...
操作符 | 含義 | 范圍 | 結果 |
---|---|---|---|
= | 等語 | 5=6 | false |
<>或!= | 不等於 | 5<>6 | true |
> | |||
< | |||
<= | |||
>= | |||
between...and... | 在某個范圍內 | [2,5] | |
and | 我和你&& | 5>1&&1>2 | false |
or | 我或你|| | 5>1&&1>2 | true |
-- 通過多個條件定位數據 update `student` set `name`='狂神' where name='大哥' and sex='男'
語法:update 表名 set colnum_name=value,[colnum_name=value,...] where[條件]
注意:
-
colnum_name 是數據庫的列,盡量帶上``
-
條件,篩選的條件,如果沒有指定,則會修改所有的列
-
value,是一個具體的值,也可以是一個變量
-
多個設置的屬性之間,使用英文逗號隔開
3.5刪除 delete
-
delete
語法:delete from 表名 [where] 條件
-- 刪除數據(避免這樣寫,會全部刪除) delete from `student` --刪除指定數據 delete from `student` where id=1;
truncate 命令
作用:完全清空一個數據庫表,表的結構和索引約束不會變!
-- 清空數據庫 truncate `student`
delete 和truncate區別
-
相同點:都能刪除數據,都不會刪除表結構
-
不同點:
-
-
TRUNCATE 重新設置 自增列 計數器會歸零
-
TRUNCATE 不會影響事務
-
delete from `test` -- 不會影響自增 truncate table `test` -- 自增會歸零
了解即可:DELETE刪除的問題,重啟數據庫,現象
-
Innodb 自增列會從1開始(存在內存當中,斷電即失)
-
MyISAM 繼續從上一個自增量開始(存在文件中的,不會丟失)
4.DQL查詢數據(最重點)
4.1DQL
(Data Query LANGUAGE:數據查詢語言)
-
所有的查詢操作都用它 select
-
簡單的查詢,復雜的查詢它都能作~
-
數據庫中最核心的語言,最重要的語言
-
使用頻率最高的語句
select完整的語法:
select [ALL | distinct] {*|table.* |[table.field1[as alias1][table.field1[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}]; --指定查詢的記錄從哪條至哪條
注意:[]括號代表可選的,{}括號代表必選的
4.2指定查詢字段
-- 查詢全部的學生 select 字段 from 表 select * from student -- 查詢指定字段 SELECT `studentNo`,`studentName` from student -- 別名,給結果起一個名字,AS 給可以給字段起別名,也可以給表起 select `studentNo` AS 學號,`studentName` AS 學生姓名 FROM student AS 學生 --函數 concat(a,b) SELECT CONCAT('姓名:',studentName) AS 新名字 FROM student
語法:select 字段名 ... from 表名
有的時候,列名字不是那么的見名知意。我們起別名 As 字段名 as 別名 表名 as 別名
練習:
-- 查詢全部的學生 select 字段 from 表 SELECT * from student -- 查詢指定字段 SELECT `name`,`pwd` from student -- 別名,給結果起一個名字,AS 給可以給字段起別名,也可以給表起 SELECT `name` AS 名字, `pwd` AS 密碼 FROM student as 學生; --函數 concat(a,b) SELECT concat('名字:',name) AS 學生名單 from student;
去重 distinct
作用:去除select查詢出來的結果中重復的數據,重復的數據只顯示一條
-- 查詢一下有哪些同學參加了考試,成績 select * from result -- 查詢全部的考試成績 select `studentNo` from result --查詢有哪些同學參加了考試 select distinct `studentNo` from result --去除重復數據 select version() -- 查詢系統版本(函數) select 100*3-1 as 計算結果 --用來計算(表達式) select @@auto_increment_increment --查詢自增的步長(變量) --學員考試成績 +1分查看 select `studentNo`,`studentResult`+1 as '提分后' from result
數據庫中的表達式:文本值,列,NULL,函數,計算表達式,系統變量
select 表達式
from 表
4.3where條件子句
作用:檢索數據中符合條件
的值
邏輯運算符
運算符 | 語法 | 描述 |
---|---|---|
and && | a and b a&&b | 邏輯與,兩個都為真,結果為真 |
or || | a or b a||b | 邏輯或,有一個為真,結果為真 |
not ! | not a !a | 邏輯非,真為假!假為真! |
盡量使用英文字母
--查詢考試成績在95-100分之間 SELECT `studentNo`,`studentResult` from result where studentResult>=95 and studentresult<=100 SELECT `studentNo`,`studentResult` from result where studentResult>=95 && studentresult<=100 --模糊查詢(區間) select `studentno`,`studentresult` from result where studentresult between 95 and 100 -- 除了1000號學生之外的同學的成績 select `studentno`,`studentresult` from result where studentno!=1000; where not studentno=1000;
模糊查詢:比較運算符
運算符 | 語法 | 描述 |
---|---|---|
is null | a is null | 如果操作符為null,則結果為真 |
is not null | a is not null | 如果操作符為 not null,則結果為真 |
between | a between b and c | 若a在b和c之間,則結果為真 |
Like | a like b | 如果a能匹配到b則結果為真 |
In | a in(a1,a2,a3) | 假設a在a1,a2,a3其中的某一個值,結果為真 |
練習
-- 模糊查詢 -- 查詢姓劉的同學 -- like 結合(代表0-任意個字符) select `studentno`,`studentname` from result where studentname like '劉%' ; -- 查詢姓劉后面一個字符的 select `studentno`,`studentname` from result where studentname like '劉_' ; -- 查詢姓劉后面兩個字符的 select `studentno`,`studentname` from result where studentname like '劉__' ; -- 查詢名字中有加字的同學 select `studentno`,`studentname` from result where studentname like '%劉%' ; --------------------------------------------------------------- -- in 具體的一個或多個值 查詢1001 1002 1003學員的成績 select `studentno`,`studentname` from result where studentno IN(1001,1002,1003); select `studentno`,`studentname` from result where address in('北京'); ---------------null----not null-------------''--- -- 查詢地址為空的學生 select `studentno`,`studentname` from result where address is NULL or adress=''; -- 查詢沒有生日日期的學生 select `studentno`,`studentname` from result where birthday is null ;
4.4聯表查詢
/* 思路: 1.分析需求,分析查詢的字段來自哪些表,(連接查詢) 2.確定使用哪些連接查詢? 7種 確定交叉點,這兩個表中哪個數據是相同的 判斷條件:學生表中的studentno=成績表中的studentno join(連接的表) on (判斷的條件) 連接查詢 where 等值查詢 */ -- inner JOIN中間查詢 select s.studentno as 學號,studentname as 名字,subjectno as 排名,studentresult as 分數 from student as s inner join result as r on s.studentno=r.studentno -- right join右查詢 select s.studentno as 學號,studentname as 名字,subjectno as 排名,studentresult as 分數 from student as s RIGHT JOIN result as r on s.studentno=r.studentno -- left join右查詢 select s.studentno as 學號,studentname as 名字,subjectno as 排名,studentresult as 分數 from student as s left JOIN result as r on s.studentno=r.studentno
操作 | 描述 |
---|---|
inner join | 如果表中至少有一個匹配,就返回行 |
left join | 會從左表中返回所有的值,即使右表中沒有匹配 |
right join | 會從右表中返回所有的值,即使左表中沒有匹配 |
-- 查詢缺考同學信息 select s.studentno as 學號,studentname as 名字,subjectno as 排名,studentresult as 分數 from student as s left JOIN result as r on s.studentno=r.studentno where studentresult is null ; -- 我們要 查詢哪些數據 SELECT -- 需要從哪幾個表中查 FROM 表 xxx join 連接的表 on 交叉條件 -- 假設存在一種多張表查詢,慢慢來,先查詢兩張表增加然后再慢慢增加 -- FROM a left join b -- from a right join b -- 查詢 學號,姓名,科目名,成績, SELECT s.studentno ,studentname,subjectname,studentresult from student as s left join result r on s.studentno=r.studentno inner join subject as sub on r.subjectno=sub.subjectno
自連接
父類表:
categoryid | categoryName |
---|---|
2 | 信息技術 |
3 | 軟件開發 |
5 | 美術設計 |
子類表
categoryid | pid | categoryName |
---|---|---|
4 | 3 | 數據庫 |
6 | 3 | web開發 |
7 | 5 | ps技術 |
8 | 2 | 辦公信息 |
操作:查詢父類對應的子類關系。
父類 | 子類 |
---|---|
信息技術 | 辦公信息 |
軟件開發 | 數據庫 |
軟件開發 | web開發 |
美術設計 | ps技術 |
-- 創建表 CREATE TABLE `school`.`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','辦公信息'); show create table `category` desc `category` -- 查詢父子信息:把一張表看為兩個一模一樣的表 select a.`categoryName` as '父欄目', b.`categoryName` as'子欄目' FROM `category` as a,`category` as b where a.`categoryid`=b.`pid`;
4.5分頁和排序
分頁
4.6子查詢
where(這個值是計算出來的)
本質:在where語句中嵌套一個子查詢語句
-- 查詢java第一學年 課程成績排名前十的學生,並且分數要大於80的學生信息(學號,姓名,課程名稱,分數) SELECT s.`studentno`,`studentname`,`subjectname`,`studentresult` from student as s inner join result as r on s.`studentno`=r.`studentno` inner join `subject` as sub r.`subjectno`=sub.`subjectno` where `subjectname`='java第一學年' and `studentresult`>=80 order by `studentresult` desc limit 0,10 -- 查詢學生編號,學生姓名,和高等數學-2大於80分的編號 select s.`studentno`,`studentname` from student as s inner join result as r on s.`studentno`=r.`studentno` inner join subject as sub on r.`subjectno`=sub.`subjectno` where `subjectname`='高等數學-2' and `studentresult`>80 -- 子查詢 select s.`studentno`,`studentname` from student as s inner join result as r on s.`studentno`=r.`studentno` where `studentresult`>80 and `studentno`=( select `studentname` from subject where `subjectname`='高等數學-2' ) -- 再改造(由里及外) select `studentno`,`studentname` from student where `studentno`=( select `studentno` from result where `subjectno`=( select `subjectno` from `subject` where `subjectname`='高等數學-2' ) )
練習:
-- 練習:查詢c語言-1 前5名同學的成績的信息(學號,姓名,分數) select s.`studentno`,`studentname` from student as s inner join result as r on s.`studentno`=r.`studentno` inner join subject as sub on r.`subjectno`=`s.subjectno` where `subjectname`='c語言-1' ORDER BY `studentresult` DESC limit 0,5 -- 子查詢 select s.`studentno`,`studentname` from student as s inner join result as r on s.`studentno`=r.`studentno` where `subjectno`=( select `subjectno` from `subject` where `subjectname`='c語言-1' ) ORDER BY `studentresult` DESC limit 0,5 -- 嵌套查詢 select `studentno`,`studentname` from student where `studentno`=( select `studentno` from `result` where `subjectno`=( select `subjectno` from `subject` where `subjectname`='c語言-1' ) ) order by `studentresult` desc limit 0,5
4.7分組和過濾
-- 查詢不同課程的平均分,最高分,最低分,平均分大於80 -- 核心:(根據不同課程分組) SELECT s.`subjectname`,avg(`studentresult`) as 平均分,max(`studentresult`),min(`studentresult`) from result as s inner join `subject` as sub on s.`subjectno`=sub.`subjectno` GROUP BY r.`subjectno` -- 通過什么字段來分組 HAVING 平均分>80
4.8select小結
順序很重要
select 去重 要查詢的字段 from 表(注意:表和字段可以取別名) xxx join 要鏈接的表 on 等值判斷 where(具體的值,子查詢語句) group by(通過哪個字段來分組) having (過濾分組后的信息,條件和where是一樣的,位置不同) order by (通過哪個字段排序)[升序asc 降序desc] limit startindex, pagesize 業務層面: 查詢:跨表,跨數據
5.MySQL函數
5.1常用函數
----------常用函數------------------------------ -- 數學運算 select ABS(-8) -- 絕對值 ABS(X) select CEILING(9.4) -- 向上取整 ceiling(x) SELECT FLOOR(9.4) -- 向下取整 FLOOR(X) SELECT RAND() -- 返回一個0-1之間的隨機數 SELECT SIGN(10) -- 判斷一個數的符號 0-0 負數返回-1,整數返回1 -- 字符串函數 select char_length('即使再小的帆,也能遠航') -- 查字符串長度 CHAR_LENGTH(str) select CONCAT('','','') -- 拼接字符串 select `INSERT`('我愛變成hello',1,4,'超級熱愛編程') -- 查詢,從某個位置開始替換某個長度 SELECT LOWER('KuangShen') -- 小寫字母 select UPPER('KuangShen') -- 大寫字母 select INSTR('KuangShen',n) -- 但會第一次出現的子串的索引 SELECT REPLACE('狂神說堅持就能成功','堅持','努力') -- 一段字符串,替換指定字符串 select SUBSTR('狂神說堅持就能成功',4.6) -- 一段字符串,從第幾個字符開始,截取多少個字符 select reverse('清晨我上馬') -- 反轉字符串 -- 查詢 姓 周的同學, 改為 鄒 SELECT REPLACE(studentname,'周','鄒') from student where studentname like '周%' -- 時間和日期函數(記住) 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())-- 獲取秒 -- 系統 SELECT SYSTEM_USER() -- 用戶名 select user() -- 用戶名 select version() -- 版本
5.2 聚合函數(常用)
函數名稱 | 描述 |
---|---|
count() | 技術 |
sum() | 求和 |
avg() | 平均值 |
max() | 最大值 |
min() | 最小值 |
... |
=================聚合函數=================== -- 都能統計 表中的數據 select count(studentname) from student; -- count(字段),會忽略所有的null值 SELECT count(*) from student; --count(*),不會忽略null值,本質 計算行數 SELECT count(1) from result; -- count(1),不會忽略所有null值 本質 計算行數 SELECT sum(`studentresult`) as 總和 from result SELECT avg(`studentresult`) as 平均分 from result SELECT max(`studentresult`) as 最高分 from result SELECT min(`studentresult`) as 最低分 from result
5.3數據庫級別的MD5加密(擴展)
什么是MD5?
主要增強算法復雜度和不可逆性。
MD5不可逆,具體的值的MD5是一樣的。
MD5 破解網站的原理,背后有一個字典,MD5加密后的值 加密前的值
-- ==================測試MD5加密============================= CREATE TABLE `school`.`testmd5`( `id` INT(10) NOT NULL, `name` VARCHAR(10) NOT NULL, `pwd` VARCHAR(20) NOT NULL, PRIMARY KEY(`id`) )ENGINE=INNODB DEFAULT charset=utf8; -- 添加三個用戶信息 INSERT INTO `testmd5` VALUES(1,'趙東','123'),(2,'有錢','1'),(3,'帥氣','1'); -- 給用戶的全部密碼加密 UPDATE testmd5 SET pwd = md5(pwd) where id = 2 -- 添加信息的時候,給密碼加密 INSERT INTO `testmd5` VALUES(4,'小明',MD5('123')); -- 如何效驗,將用戶傳遞進來的密碼進行md5加密,用值來對比 SELECT * from testmd5 WHERE name ='小明' and pwd= MD5('123');
6.事務
6.1什么是事務
事務原則:ACID原則 原子性,一致性,隔離性,持久性
原子性(Atomicity)
要么都成功,要么都失敗
一致性(Consistency)
事務前后的數據完整性要保證一致
持久性(Durability)--- 事務提交
事務一旦提交則不可逆,被持久化到數據庫中!
隔離性(Isolation)
事務的隔離性是多個用戶並發訪問數據庫時,數據庫為每一個用戶開啟的事務,不能被其他事務的操作數據所干擾,事務之間相互隔離。
隔離所導致的一些問題
-- mysql 是默認開啟事務自動提交的 set autocommit =0 -- 關閉自動提交事務 set autocommit =1 -- 開啟自動提交事務(默認) -- 手動處理事務 set autocommit =0 -- 關閉自動提交 -- 事務開啟 start transaction -- 標記一個事務的開始,從這個之后的 sql 都在同一事務內 insert xxx insert xxxx -- 提交:持久化(成功!) COMMIT -- 回滾:回道原來的樣子(失敗!) ROLLBACK -- 事務結束 set atuommit=1 -- 開啟自動提交 -- 了解 savepoint 保存點名 -- 設置一個事務的保存點 rollback to savepoint 保存點名 -- 回滾到保存點 release savepoint 保存點名 -- 撤銷保存點
模擬事務
7.索引
7.1索引的分類
-
主鍵索引 (primary key)
-
唯一的標識,主鍵不可重復,只能有一個列作為主鍵
-
-
唯一索引(unique key)
-
避免重復的列出現,唯一索引可以重復,多個列都可以標識為唯一索引
-
-
常規索引(key/index)
-
默認的,index,key關鍵字來設置
-
-
全文索引(FUllText)
-
在特定的數據庫引擎下才有,MyISMA
-
快速定位數據
-
索引在校數據量的時候,用戶不大,但是在大數據的時候,區別十分明顯
7.2索引原則
-
索引不是越多越好
-
不要對經常變動數據加索引
-
小數據量的表不需要加索引
-
索引一般加在常用來查詢的字段上
索引的數據結構
Hash 類型的索引
Btree:innodb 的默認數據結構
8.權限管理和備份
8.1用戶管理
======================創建用戶=========================== -- 創建用戶 create user 用戶名 identified by ‘密碼’ create user kuangshen identified by '123456' -- 修改密碼(修改當前用戶名密碼)set password= password('新密碼') SET PASSWORD= PASSWORD('123456') -- 修改密碼(修改制定用戶名密碼) set password for root = password('123456') -- 重命名 rename user 原用戶名 to 新用戶名 rename user root to rootdouble -- 用戶授權 grant all privileges 全部的權限 庫.表 -- 除了給別人授權,其他都能夠干 grant all privileges on *.* to kuangshen -- 查詢權限 show grants FOR kuangshen -- 茶看制定用戶的權限 show grants for root@localhost -- root 用戶的權限 -- 撤銷權限 revoke 那些權限, 在哪個庫撤銷 給誰撤銷 revoke all privileges on *.* from kuangshen -- 刪除用戶 drop user kuangshen
8.2mysql備份
為什么要備份:
-
保證重要的數據不丟失
-
數據轉移
MySQL 數據庫備份的方式
-
直接拷貝物理文件
-
在可視化工具中手動導出
-
使用命令行導出 mysqldump 命令行使用
mysqldump -hlocalhost -uroot -p123456 school student >D:/1.sql 導出 從本地導出 用戶名 密碼 數據庫名 表名 》指向 path(導出的路徑) (導出多張表,在表名后空格 表名) # 導入 # 導出 # source 備份文件 source d:1.sql mysql -u用戶名 -p密碼 庫民<備份文件
9.規范數據庫設計
9.1為什么需要設計
當數據庫比較復雜的時候,我們就需要設計了
糟糕的數據庫設計:
-
數據冗余,浪費空間
-
數據庫插入和刪除都會麻煩、異常【屏蔽使用物理外界】
-
程序的性能差
良好的數據庫設計:
-
節省內存空間
-
保證數據庫的完整性
-
方便我們開發系統
軟件開發中,關於數據庫的設計
-
分析需求:分析業務和需要處理的數據庫的需求
-
概要設計L設計關系圖E-R圖
設計數據庫的步驟:
-
收集信息,分析需求
-
用戶表(用戶登陸注銷,用戶的個人信息,寫博客,創建分類)
-
分類表(文章分類,誰創建的)
-
文章表(文章的信息)
-
友鏈接(友鏈信息)
-
自定義表(系統信息,某個關鍵的子,或者一些主字段)
-
-
標識實體(把需求落地到每個字段)
-
標識實體之間的關系
-
寫博客user-->blog
-
創建分類user -->category
-
關注:user-->User
-
9.2三大范式
為什么需要數據規范化
-
信息重復
-
更新異常
-
插入異常
-
無法正常顯示信息
-
-
刪除異常
-
丟失有效的信息
-
三大范式
第一范式(1NF)
原子性:保證每一列不可再分
第二范式(2NF)
前提:滿足第一范式
每張表只描述一件事情
第三范式(3NF)
牆體:滿足第一范式和第二范式
第三范式需要確保數據表中的每一列數據都和主鍵直接相關,而不能間接相關。
(規范數據庫的設計)
規范性和性能的問題
關聯查詢的表不得超過三張表
-
考慮商業化的需求和目標(成本,用戶體驗!)數據庫的性能更加重要
-
在規范性能的問題的時候,需要適當的考慮一下規范性!
-
故意給某些表增加一些冗余的字段。(從多表查詢中變為單標查詢)
-
故意增加一些計算列(從大數據量降低為小數據量的查詢:索引)
10.JDBC(重點)
10.1數據庫驅動
驅動:聲卡、顯卡、數據庫
10.2JDBC
sun公司為了簡化開發人員的(對數據庫的同一)操作,提供了一個(java操作數據庫)規范,俗稱JDBC,這些規范的實現具體由具體的廠商去做
10.3第一個JDBC程序
1.創建一個普通項目
2.導入驅動,
3.編寫測試代碼
// 我的第一個JDBC程序 public class jdbcFirstDemo { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.加載驅動 Class.forName("com.mysql.jdbc.Driver"); //固定寫法,加載驅動 //2.用戶信息 和url //useUnicode=true 支持中文編碼 characterEncoding=utf8設置中文字符為utf8 useSSL=true 使用安全連接 String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=false"; String username="root"; String password="19941027"; //3.連接成功,數據庫對象 Connection connection = DriverManager.getConnection(url, username, password); //4.執行SQL對象 Statement Statement statement = connection.createStatement(); //5.執行SQL的對象去執行 sql 可能存在結果,查看返回結果 String sql="select * from student"; ResultSet resultSet = statement.executeQuery(sql); while(resultSet.next()){ System.out.println("id="+resultSet.getObject("id")); System.out.println("name="+resultSet.getObject("name")); System.out.println("password="+resultSet.getObject("pwd")); System.out.println("sex="+resultSet.getObject("sex")); System.out.println("birthday="+resultSet.getObject("birthday")); System.out.println("address="+resultSet.getObject("address")); System.out.println("email="+resultSet.getObject("email")); System.out.println("========================================"); } //5.關閉連接 resultSet.close(); statement.close(); connection.close(); } }
步驟總結:
-
加載驅動
-
連接數據庫DriverManager
-
獲得執行sql的對象, statment
-
獲得返回的結果集()
-
釋放連接
DriverManager
//DriverManager.registerDriver(new com.mysql.jdbc.Driver()); Class.forname("com.mysql.jdbc.Driver"); //推薦用第二種方式創建驅動 //原因:Driver底層是一個靜態代碼塊里面有創建Driver代碼,運行就會創建一次,如果用第一種就會創建兩次 Connection connection = DriverManager.getConnection(url, username, password); //Connection 代表數據庫 connection.rollback();//事務回滾 connection.commit();//事務提交 connection.setAutoCommit();//數據庫設置自動提交
URL
//2.用戶信息 和url //useUnicode=true 支持中文編碼 characterEncoding=utf8設置中文字符為utf8 useSSL=true 使用安全連接 String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=false"; // mysql --3306 //協議://主機:端口號/數據庫名?參數1&參數2&參數3 //oralce --1521 //jdbc:oracle:thin:@localhost:1521:sid
Statement執行SQL的對象 PrepareStatement執行SQL的對象
//5.執行SQL的對象去執行 sql 可能存在結果,查看返回結果 String sql="select * from student";//編寫sql statement.executeQuery(sql);//執行查詢操作,返回 ResultSet statement.execute(sql);//執行任何sql statement.executeUpdate(sql);//更新、插入、刪除。都是用這個,返回一個受影響的行數
ResultSet查詢的結果集:封裝了所有的查詢結果
釋放資源
// 我的第一個JDBC程序 public class jdbcFirstDemo { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.加載驅動 Class.forName("com.mysql.jdbc.Driver"); //創建驅動 //2.用戶信息 和url String url="jdbc:mysql://localhost:3306/school?useSSL=false&useUnicode=true&characterEncode=utf8"; //useUnicode=true 支持中文編碼 characterEncoding=utf8設置中文字符為utf8 useSSL=true 使用安全連接 String username="root"; String password="19941027"; //3.連接成功,創建數據庫對象 Connection connection = DriverManager.getConnection(url, username, password); //4.創執行sql語句的對象 Statement statement = connection.createStatement(); //5.寫sql語句,執行SQL語句 ,查詢,用execute 返回結果集 String sql="select * from student"; ResultSet resultSet = statement.executeQuery(sql); //6.遍歷查詢結果 while (resultSet.next()){ System.out.println(""); System.out.println(""); System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("============================="); } //7.釋放資源 resultSet.close(); statement.close(); connection.close(); } }
10.4 statement對象
數據庫配置文件
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=false username=root password=19941027
提取工具類
public class JdbcUtils { private static String dirver=null; private static String url=null; private static String username=null; private static String password=null; static { //獲取類加載器,后得到資源() try { InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"); Properties properties = new Properties(); properties.load(in); dirver=properties.getProperty("driver"); url=properties.getProperty("url"); username=properties.getProperty("username"); password=properties.getProperty("password"); //1.驅動只加載一次 Class.forName(dirver); } catch (Exception e) { e.printStackTrace(); } } //獲取連接 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, username, password); } //釋放連接資源 public static void release(Connection conn, Statement st, ResultSet rs){ if (rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (st!=null){ try { st.close(); } catch (SQLException e) { e.printStackTrace(); } } if (rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
測試增加數據
public class TestInsert { public static void main(String[] args) { //提升作用域,方便在finally后關閉資源 Connection conn=null; Statement st=null; ResultSet rs=null; //調用utils方法,連接數據庫 try { conn=JdbcUtils.getConnection();//獲取數據庫連接 st=conn.createStatement();//獲取執行sql對象 String sql="insert into student(id,`name`,`pwd`,`sex`,`birthday`,`address`,`email`) values (6,'趙龍','121212','男','1994-10-27','小別墅','11111111@qq.com')"; //增加數據的sql語句 //利用executeUpdate獲取結果,看結果是否大於0,是,代表插入數據成功 int i = st.executeUpdate(sql); if (i>0){ System.out.println("插入數據成功"); } } catch (SQLException e) { e.printStackTrace(); }finally { //調用關閉資源方法,關閉開啟的對象 JdbcUtils.release(conn,st,null);//因為增加沒有用到rs方法,所以可以用null代替值 } } }
刪除數據
public class TestDelete { public static void main(String[] args) { //提升作用域,方便在finally后關閉資源 Connection conn=null; Statement st=null; ResultSet rs=null; //調用utils方法,連接數據庫 try { conn=JdbcUtils.getConnection();//獲取數據庫連接 st=conn.createStatement();//獲取執行sql對象 String sql="delete from student where id=4 "; //增加數據的sql語句 //利用executeUpdate獲取結果,看結果是否大於0,是,代表插入數據成功 int i = st.executeUpdate(sql); if (i>0){ System.out.println("刪除成功"); } } catch (SQLException e) { e.printStackTrace(); }finally { //調用關閉資源方法,關閉開啟的對象 JdbcUtils.release(conn,st,null);//因為增加沒有用到rs方法,所以可以用null代替值 } } }
更新數據
public class TestUpdate { public static void main(String[] args) { Connection conn=null; Statement st=null; ResultSet rs=null; try { conn=JdbcUtils.getConnection(); st=conn.createStatement(); String sql="update student set `name`='帥哥',`sex`='女' where id=3"; //增加數據的sql語句 //利用executeUpdate獲取結果,看結果是否大於0,是,代表插入數據成功 int i = st.executeUpdate(sql); if (i>0){ System.out.println("更新成功"); } } catch (SQLException e) { e.printStackTrace(); }finally { //調用關閉資源方法,關閉開啟的對象 JdbcUtils.release(conn,st,null);//因為增加沒有用到rs方法,所以可以用null代替值 } } }
查找數據
public class TestSelect { public static void main(String[] args) { Connection conn=null; Statement st=null; ResultSet rs=null; try { conn = JdbcUtils.getConnection(); st=conn.createStatement(); String sql="select * from student where id=5"; rs=st.executeQuery(sql); while (rs.next()){ System.out.println(rs.getString("name")); System.out.println(rs.getString("sex")); } } catch (SQLException e) { e.printStackTrace(); }finally { JdbcUtils.release(conn,st,rs); } } }
SQL注入問題
存在漏洞,會被攻擊,導致數據泄露。SQL會被拼接
public class TestSelect { public static void login(String username,String password){ Connection conn=null; Statement st=null; ResultSet rs=null; try { conn = JdbcUtils.getConnection(); st=conn.createStatement(); // select * from student where `name`='狂神' and `pwd`='123456'; String sql="select * from student where `name`='"+username+"' and `pwd`='"+password+"'"; rs=st.executeQuery(sql); while (rs.next()){ System.out.println(rs.getString("name")); System.out.println(rs.getString("pwd")); } } catch (SQLException e) { e.printStackTrace(); }finally { JdbcUtils.release(conn,st,rs); } } public static void main(String[] args) { login("'or'1=1","'or'1=1"); } }
10.5 preparedStatement對象
preparedStatement可以防止sql注入。效率更高!
1.新增
public static void main(String[] args) { Connection conn=null; PreparedStatement st=null; ResultSet rs=null; //調用utils方法,連接數據庫 try { conn=JdbcUtils.getConnection();//獲取數據庫連接 //預編譯sql 先寫sql 然后不執行 使用?占位符代替參數 String sql="insert into student(id,`name`,`pwd`,`sex`,`birthday`,`address`,`email`) values(?,?,?,?,?,?,?)"; st=conn.prepareStatement(sql);//獲取執行sql對象 //手動給參數賦值 st.setInt(1,6); st.setString(2,"趙子龍"); st.setString(3,"123321"); st.setString(4,"男"); // new Date().getTime() 獲取時間戳 st.setDate(5,new java.sql.Date(new Date(1).getTime())); st.setString(6,"常山"); st.setString(7,"9999999.com"); //利用executeUpdate獲取結果,看結果是否大於0,是,代表插入數據成功 int i = st.executeUpdate(sql); if (i>0){ System.out.println("插入數據成功"); } } catch (SQLException e) { e.printStackTrace(); }finally { //調用關閉資源方法,關閉開啟的對象 JdbcUtils.release(conn,st,null);//因為增加沒有用到rs方法,所以可以用null代替值 } } }
2.刪除
public static void main(String[] args) { //提升作用域,方便在finally后關閉資源 Connection conn=null; PreparedStatement st=null; ResultSet rs=null; //調用utils方法,連接數據庫 try { conn=JdbcUtils.getConnection();//獲取數據庫連接 String sql="delete from student where id=? "; st=conn.prepareStatement(sql)//獲取執行sql對象 st.setInt(1,1); //利用executeUpdate獲取結果,看結果是否大於0,是,代表插入數據成功 int i = st.executeUpdate(sql); if (i>0){ System.out.println("刪除成功"); } } catch (SQLException e) { e.printStackTrace(); }finally { //調用關閉資源方法,關閉開啟的對象 JdbcUtils.release(conn,st,null);//因為增加沒有用到rs方法,所以可以用null代替值 } }
3.更新
public static void main(String[] args) { Connection conn=null; PreparedStatement st=null; ResultSet rs=null; try { conn=JdbcUtils.getConnection(); String sql="update student set `name`=?,`sex`=? where id=?"; st=conn.prepareStatement(sql); st.setString(1,"趙帥"); st.setString(2,"男"); st.setInt(3,2); //增加數據的sql語句 //利用executeUpdate獲取結果,看結果是否大於0,是,代表插入數據成功 int i = st.executeUpdate(sql); if (i>0){ System.out.println("更新成功"); } } catch (SQLException e) { e.printStackTrace(); }finally { //調用關閉資源方法,關閉開啟的對象 JdbcUtils.release(conn,st,null);//因為增加沒有用到rs方法,所以可以用null代替值 } } }
4.查詢
public static void main(String[] args) { Connection conn=null; PreparedStatement st=null; ResultSet rs=null; try { conn=JdbcUtils.getConnection(); String sql="select * from student where id=?"; st=conn.prepareStatement(sql); st.setInt(1,1); rs = st.executeQuery(); if (rs.next()){ System.out.println(rs.getString("name")); System.out.println(rs.getString("pwd")); } } catch (SQLException e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn,st,rs); } }
5.防止SQL注入
PreparedStatement 防止SQL注入的本質,把傳遞進來的參數當做字符
假設其中存在轉義字符,就直接忽略, ‘ 會被直接轉義
public static void main(String[] args) { login("趙龍","121212"); } public static void login(String username,String password){ Connection conn=null; PreparedStatement st=null; ResultSet rs=null; try { conn=JdbcUtils.getConnection(); String sql="select * from student where `name` =? and `pwd`=?"; st=conn.prepareStatement(sql); st.setString(1,username); st.setString(2,password); rs = st.executeQuery(); if (rs.next()){ System.out.println(rs.getString("name")); System.out.println(rs.getString("pwd")); } } catch (SQLException e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn,st,rs); } }
10.6使用idea連接數據庫
右側有datebase按鈕
10.7事務
10.9數據庫連接池
數據庫連接 -- 執行完畢-- 釋放
連接-- 釋放 十分浪費系統資源
池化技術:准備一些預先的資源,過來就連接預先准備好的