前言
本片博客使用mysql數據庫進行數據操作,使用Navicat for mysql 這個IDE進行可視化操作。每個SQL語句都是親身實驗驗證的,並且經過自己的思考的。能夠保證sql語句的可運行性。
sql語句的命令不區分大小寫,但儲存的數據是區分大小寫的。在這里我們統一使用英文小寫進行命令編輯。如果喜歡大寫的可以使用IDE編輯器的一鍵美化功能,可以統一轉化為大寫。並且會對你的sql語句進行美化,例如自動換行等。
創建刪除(數據庫、表)
- 創建數據庫
create database <數據庫名>;
-- 創建名為dbtest數據庫
create database dbtest;
use dbtest;
- 創建表
create table 表名(字段);- comment 是注釋的意思
- primary key(stu_id) 把stu_id設置為主鍵,主鍵的設置可以細分為三種方式,后面再寫
- ENGINE=InnoDB 把儲存引擎設置為InnoDB
- charset=utf8mb4 編碼格式設置utf8mb4,utf8mb4是超集合,完全兼容utf8,不需要做特殊轉換
-- 創建表
create table `t_student`(
`stu_id` char(12) not null COMMENT '學生id',
`stu_name` varchar(12) not null comment '學生姓名',
`stu_sex` tinyint(2) unsigned default null comment '性別:0(男),1(女)',
`stu_age` tinyint(3) unsigned DEFAULT NULL COMMENT '年齡',
PRIMARY KEY (`stu_id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='學生基本信息表';
mysql中的數據類型
類型 | 包含 |
---|---|
數值類型 | 整數類型(TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT)、浮點數類型(float、double)、定點數類型(decimal) |
日期/時間類型 | YEAR、TIME、DATE、DATETIME、TIMESTAMP |
字符串類型 | CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM 和 SET 等 |
二進制類型 | BIT、BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB |
增加
插入數據
插入已知行(少數行數據
- 使用insert values 插入數據
-- 插入數據 insert values
insert into `t_student`
(`stu_id`,`stu_name`,`stu_sex`,`stu_age`)
values(1,"hjk","0",18);
- 使用 insert set 插入數據
-- insert set
insert into `t_student`
set `stu_id`=3,`stu_name`='hjk',`stu_sex`=1,`stu_age`=18
- 從另一個表查詢的數據插入新表 insert from,這個查詢出來的數據要與插入到表里的字段有對應關系,例如查尋出來的數據如果有字段"stu_address"你如果直接插入就會不成功!
insert into `t_student` select `stu_id`,`stu_name`,`stu_sex`,`stu_age` from `t_student01`;
插入很多行數據(10萬條)
使用存儲過程插入數據,在我們做實驗時可能需要很多數據進行操作,但是一條一條手動加時不太容易實現的,我們可以使用其他方法插入數據(例如:連接jdbc,進行操作),但是這個插入的是幾乎相同的數據,在這里我們使用存儲過程並通過調用存儲過程實現插入大量數據!
- 創建存儲過程
- delimiter ## 定義結束符號,##是你自定義的符號可以是其他的符號(如:$、%、&),在最后end不要忘了寫。
- 其實中間就是一個while循環,變量為i。
- 可以在定義的時候輸入參數,這個我沒有定義。
-- 插入大量數據,使用存儲過程
delimiter ##
create procedure insert_pro()
begin
declare i int default 4;
while i <=100000 do
insert into `t_student` values(i,'hjk','0','20');
set i = i+1;
end while;
end ##
- 使用存儲過程,創建存儲過程后並沒有效果,只有使用后才有效果
-- 使用存儲過程
call insert_pro();
- 刪除存儲過程
-- 刪除儲存過程
DROP PROCEDURE IF EXISTS insert_pro;
刪除
這里只記錄刪除表和刪除數據庫,其他的會在每個創建后面寫,例如給表添加字段,那相應的會在后面寫如何刪除字段
刪除表
-- 刪除表
drop table `t_student`;
刪除數據庫
-- 刪除dbtest數據庫
drop database dbtest;
刪除表數據
DELETE FROM <表名> [WHERE 子句] [ORDER BY 子句] [LIMIT 子句]
刪除stu_id為1的數據
delete from `t_student` where `stu_id`="1";
清空表中所有數據
truncate table `t_student`;
修改改
修改表結構(6種約束)
添加主鍵(三種方式)
- 創建表時,行級添加主鍵
create table `t_student`(
`stu_id` char(12) not null PRIMARY KEY COMMENT '學生id',
`stu_name` varchar(12) not null comment '學生姓名',
`stu_sex` tinyint(2) unsigned default null comment '性別:0(男),1(女)',
`stu_age` tinyint(3) unsigned DEFAULT NULL COMMENT '年齡'
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='學生基本信息表';
- 創建表時表級添加主鍵 就是在文章剛開始的時候創建的那個表
- 表外添加主鍵
-- 最后添加主鍵
alter table `t_student` add primary key(`stu_id`);
- 刪除主鍵
-- 刪除主鍵約束
alter table `t_student` drop primary key;
添加外鍵約束
外鍵約束經常和主鍵約束一起使用,用來確保數據的一致性!
外鍵需要用兩個表添加,一個是主表一個是從表。在這里我們使用主表位t_student表,從表位t_coruse表;一種是創建表時創建外鍵約束,一種時后面添加外鍵約束;
第一種:
"constraint fk_course_id foreign key(stu_id
) references t_student(stu_id
)"創建名為fk_course_id的外鍵,使t_course表里的cou_id字段參照t_student表里的stu_id字段,在這里邏輯不對,重點是說語法。
create table t_course(
`cou_id` char(8) primary key,
`stu_id` char(12) not null,
`cou_name` varchar(12) not null,
`semester` smallint ,
`credit` smallint,
constraint fk_course_id foreign key(`stu_id`) references t_student(`stu_id`)
);
第二種:
添加外鍵使表里最好不要有數據,不然可能會創建失敗
alter table t_student
add constraint fk_student_id foreign key(`stu_id`) references t_course(`cou_id`);
- 刪除外鍵約束
在那個表添加的外鍵,去哪個表刪除
alter table t_course
drop foreign key fk_course_id;
添加唯一檢查默認值非空約束
例如在t_student表的stu_name列添加唯一約束
- 創建表時添加唯一約束
-- 創建表
create table `t_student`(
`stu_id` char(12) not null PRIMARY KEY COMMENT '學生id',
`stu_name` varchar(12) unique,
`stu_sex` tinyint(2) unsigned default null comment '性別:0(男),1(女)',
`stu_age` tinyint(3) unsigned DEFAULT NULL COMMENT '年齡',
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='學生基本信息表';
- 建表后添加唯一性約束
alter table `t_student`
add constraint un_age unique(`stu_age`);
- 刪除唯一性約束
alter table `t_student`
drop index un_age;
==其實寫道這里應該也能看出來,他們的語法格式幾乎是一樣的都是可以直接在(1)、創建表時在字段后面添加改約束的關鍵字,(2)、在創建表時在最后用constraint添加並命名、(3)、在創建表后使用alter add添加約束,所以后面的幾種約束就不詳細寫了。
- 檢查約束
檢查年齡是否大於1小於150
建表時在字段后面直接添加
check(`stu_age`>0 and `stu_age`<150)
- 后續添加
alter TABLE `t_student` add constraint check_age check(`stu_age`<100);
- 刪除檢查約束
alter table `t_student` drop check check_age;
非空約束和默認值的約束修改和上面的不太一樣,時使用change修改
- 默認值約束
在最開始創建表的時候就有幾個字段定義位默認值為null,這里不重復了,定義其他默認值就替換null就行了,這個null就是沒有定義的意思。 - 修改默認值約束
alter TABLE `t_student` change column `stu_sex` `stu_sex` tinyint(2) default '1';
- 刪除默認值約束,默認值改為null就行了
alter TABLE `t_student` change column `stu_sex` `stu_sex` tinyint(2) default null;
- 非空約束
在創建表的時候主鍵有一個not null約束就是非空約束了。 - 添加非空約束
ALTER TABLE <數據表名> CHANGE COLUMN <字段名> <字段名> <數據類型> NOT NULL; - 刪除非空約束
ALTER TABLE <數據表名> CHANGE COLUMN <字段名> <字段名> <數據類型> NULL;
修改表數據
- 修改表數據
UPDATE <表名> SET 字段 1=值 1 [,字段 2=值 2… ] [WHERE 子句 ] [ORDER BY 子句] [LIMIT 子句]
-- 沒有條件全部修改
update `t_student` set `stu_name` = 'kjh' ,`stu_age` = '19';
-- 有條件只修改符合條件的
update `t_student` set `stu_name` = 'kjh' ,`stu_age` = 25
where `stu_id` = 10;
查詢
- 去重,例如某一列含有大量數據,我們需要統計都出現過那些數據,統計出所有的數據反而不方便我們只需要統計一次這樣的數據。
統計數據表中出現的所有的年齡
select distinct `stu_age` from `t_student`;
對年齡和姓名去重
select distinct `stu_name`, `stu_age` from `t_student`;
- 查詢所有數據的所有字段
select * from `t_student`;
- 條件查詢,查詢名字為hjk的
select * from `t_student` where `stu_name` = 'hjk';
- 使用count(*)統計名字為hjk的個數
select count(*) from `t_student` where `stu_name` = 'hjk';
- 子查詢
子查詢操作符:操作符可以是比較運算符和 IN、NOT IN、EXISTS、NOT EXISTS 等關鍵字
select * from `t_student` where `stu_id` in
(select `stu_id` from `t_student` where `stu_age`=18);
子查詢語句可以嵌套在 SQL 語句中任何表達式出現的位置
在 SELECT 語句中,子查詢可以被嵌套在 SELECT 語句的列、表和查詢條件中,即 SELECT 子句,FROM 子句、WHERE 子句、GROUP BY 子句和 HAVING 子句。
SELECT (子查詢) FROM 表名;
SELECT * FROM (子查詢) AS 表的別名;
SELECT * FROM (SELECT * FROM result) AS Temp;
- 分頁查詢
從第十的數據開始查,向后查出20個數據。
select * from `t_student` limit 10,20;
- 排序,按照年齡大小升序,默認是升序asc排列,降序需要在order by 字段后添加 desc
select * from `t_student` order by `stu_age`;
- 模糊查詢
查詢名字為h開頭的數據,默認匹配不區分大小寫,就是為H開頭的也能查出來,但是可以在like后面加binary區分大小寫
select * from `t_student` where `stu_name` like 'h%';
查詢名字不為h開頭的數據
select * from `t_student` where `stu_name` not like 'h%';
通配符%和_的區別:
%代表后面可以匹配任意個字符。
_僅替代一個字符
%”通配符可以到匹配任意字符,但是不能匹配 NULL。也就是說 “%”匹配不到數據表中值為 NULL 的記錄
如果查詢內容中包含通配符,可以使用“\”轉義符
- 范圍查詢 between
select * from `t_student` where `stu_age` between 17 and 19;
- 空值查詢 空值條件不時等於null而是is null進行判斷
select * from `t_student` where `stu_age` is null;
- 分組查詢
單獨使用 GROUP BY 關鍵字時,查詢結果會只顯示每個分組的第一條記錄
select `stu_name`,`stu_sex` from `t_student` group by `stu_age`;
和group_count(字段)一起使用
select `stu_name`,GROUP_CONCAT(`stu_sex`) from `t_student` group by `stu_age`;
- having條件查詢
having和where區別
一般情況下,WHERE 用於過濾數據行,而 HAVING 用於過濾分組。
WHERE 查詢條件中不可以使用聚合函數,而 HAVING 查詢條件中可以使用聚合函數。
WHERE 在數據分組前進行過濾,而 HAVING 在數據分組后進行過濾 。
WHERE 針對數據庫文件進行過濾,而 HAVING 針對查詢結果進行過濾。也就是說,WHERE 根據數據表中的字段直接進行過濾,而 HAVING 是根據前面已經查詢出的字段進行過濾。
WHERE 查詢條件中不可以使用字段別名,而 HAVING 查詢條件中可以使用字段別名。
having查詢,這個是正確的,因為代表所有的字段,那當然肯定包含這個having條件的這個字段,但是如果這個地方換成具體的字段,並且沒有stu_name那就會報錯了。
having通常和group by一起使用
select * from `t_student` having `stu_name` = 'hjk';
數據庫視圖和索引
視圖
MySQL 視圖(View)是一種虛擬存在的表,同真實表一樣,視圖也由列和行構成,但視圖並不實際存在於數據庫中。行和列的數據來自於定義視圖的查詢中所使用的表,並且還是在使用視圖時動態生成的。
數據庫中只存放了視圖的定義,並沒有存放視圖中的數據,這些數據都存放在定義視圖查詢所引用的真實表中。使用視圖查詢數據時,數據庫會從真實表中取出對應的數據。因此,視圖中的數據是依賴於真實表中的數據的。一旦真實表中的數據發生改變,顯示在視圖中的數據也會發生改變。
視圖可以從原有的表上選取對用戶有用的信息,那些對用戶沒用,或者用戶沒有權限了解的信息,都可以直接屏蔽掉,作用類似於篩選。這樣做既使應用簡單化,也保證了系統的安全。
視圖並不同於數據表,它們的區別在於以下幾點:
- 視圖不是數據庫中真實的表,而是一張虛擬表,其結構和數據是建立在對數據中真實表的查詢基礎上的。
- 存儲在數據庫中的查詢操作 SQL 語句定義了視圖的內容,列數據和行數據來自於視圖查詢所引用的實際表,引用視圖時動態生成這些數據。
- 視圖沒有實際的物理記錄,不是以數據集的形式存儲在數據庫中的,它所對應的數據實際上是存儲在視圖所引用的真實表中的。
- 視圖是數據的窗口,而表是內容。表是實際數據的存放單位,而視圖只是以不同的顯示方式展示數據,其數據來源還是實際表。
- 視圖是查看數據表的一種方法,可以查詢數據表中某些字段構成的數據,只是一些 SQL 語句的集合。從安全的角度來看,視圖的數據安全性更高,使用視圖的用戶不接觸數據表,不知道表結構。
- 視圖的建立和刪除只影響視圖本身,不影響對應的基本表.
為什么創建視圖
例如學生表里面有學生id、姓名等,課程表有學生所選課程、上課時間等。如果我們查看課程表是是需要學生姓名和課程上課時間就行,不需要其他的一些沒有用的信息。這樣我們就可以建一個關於這兩個表的視圖,我們可以直接根據這個視圖獲取信息。
創建視圖
CREATE VIEW <視圖名> AS <SELECT語句>
- 創建一個關於學生名字的視圖
create view view_student_name
as select `stu_name` from `t_student`;
- 查看視圖信息,和查詢表是幾乎一樣的,我們可以把視圖看成不是表的表
select * from view_student_name;
- 查看視圖結構
-- 以表的結構顯示
desc view_student_name;
-- 以sql語句顯示
SHOW CREATE VIEW 視圖名;
- 創建基於多表的視圖
-- 隨便創個表
create table `t_course`(
`cou_id` int(11) primary key,
`s_id` char(12)
);
-- 創建多表視圖
create view v_stu_cou (`stu_id`,`cou_id`)
as select `stu_id`,`cou_id` from `t_student` s,`t_course` c
where s.stu_id=c.s_id;
-- 查看視圖結構
desc v_stu_cou
- 修改視圖
ALTER VIEW <視圖名> AS <SELECT語句>
- 刪除視圖
-- 直接刪除,可能已經不存在,會報錯
drop view v_stu_cou;
-- 判斷是否存在,再刪除
drop view if exists v_stu_cou;
索引
索引是一種特殊的數據庫結構,由數據表中的一列或多列組合而成,可以用來快速查詢數據表中有某一特定值的記錄
通過索引,查詢數據時不用讀完記錄的所有信息,而只是查詢索引列。否則,數據庫系統將讀取每條記錄的所有信息進行匹配
可以把索引比作新華字典的音序表,例如,要查一個字,如果不使用音序,就需要從字典的全部頁碼中逐頁來找。但是,如果提取拼音出來,構成音序表,就只需要從音序表確定的那幾頁頁的音序表中直接查找。這樣就可以大大節省時間。
索引的優缺點
索引有其明顯的優勢,也有其不可避免的缺點。
優點
索引的優點如下:
通過創建唯一索引可以保證數據庫表中每一行數據的唯一性。
可以給所有的 MySQL 列類型設置索引。
可以大大加快數據的查詢速度,這是使用索引最主要的原因。
在實現數據的參考完整性方面可以加速表與表之間的連接。
在使用分組和排序子句進行數據查詢時也可以顯著減少查詢中分組和排序的時間
缺點
增加索引也有許多不利的方面,主要如下:
創建和維護索引組要耗費時間,並且隨着數據量的增加所耗費的時間也會增加。
索引需要占磁盤空間,除了數據表占數據空間以外,每一個索引還要占一定的物理空間。如果有大量的索引,索引文件可能比數據文件更快達到最大文件尺寸。
當對表中的數據進行增加、刪除和修改的時候,索引也要動態維護,這樣就降低了數據的維護速度。
MySQL支持以下幾種類型的索引。
(1)B-Tree索引
(2)哈希索引
(3)空間數據索引(R-Tree)
(4)全文索引
(5)其他索引類別
創建索引
CREATE <索引名> ON <表名> (<列名> [<長度>] [ ASC | DESC])
一個表可以創建多個索引,但每個索引在該表中的名稱是唯一的
- 可以再創建表時創建索引
直接在創建表時的字段最后添加 index(字段名)
CREATE TABLE `t_student` (
`stu_id` char(12) NOT NULL COMMENT '學生id',
`stu_name` varchar(12) NOT NULL COMMENT '學生姓名',
`stu_sex` tinyint(2) unsigned DEFAULT NULL COMMENT '性別:0(男),1(女)',
`stu_age` tinyint(3) unsigned DEFAULT NULL COMMENT '年齡',
PRIMARY KEY (`stu_id`),
KEY `stu_id` (`stu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='學生基本信息表'
創建唯一索引,還是同樣的位置,添加成unique index(字段)
- 通過show create table 表名 查看會發現,我們寫sql那個位置變為 KEY
stu_id
(stu_id
);
查看索引
show index from `t_student`;
- 索引參數說明
參數 | 說明 |
---|---|
Table | 表示創建索引的數據表名 |
Non_unique | 表示該索引是否是唯一索引。若不是唯一索引,則該列的值為 1;若是唯一索引,則該列的值為 0。 |
Key_name | 表示索引的名稱 |
Seq_in_index | 表示該列在索引中的位置,如果索引是單列的,則該列的值為 1;如果索引是組合索引,則該列的值為每列在索引定義中的順序。 |
Column_name | 表示定義索引的列字段。 |
Collation | 表示列以何種順序存儲在索引中。在 MySQL 中,升序顯示值“A”(升序),若顯示為 NULL,則表示無分類。 |
Cardinality | 索引中唯一值數目的估計值。基數根據被存儲為整數的統計數據計數,所以即使對於小型表,該值也沒有必要是精確的。基數越大,當進行聯合時,MySQL 使用該索引的機會就越大 |
Sub_part | 表示列中被編入索引的字符的數量。若列只是部分被編入索引,則該列的值為被編入索引的字符的數目;若整列被編入索引,則該列的值為 NULL |
Packed | 指示關鍵字如何被壓縮。若沒有被壓縮,值為 NULL |
Null | 用於顯示索引列中是否包含 NULL。若列含有 NULL,該列的值為 YES。若沒有,則該列的值為 NO |
Index_type | 顯示索引使用的類型和方法(BTREE、FULLTEXT、HASH、RTREE) |
Comment | 顯示評注 |
刪除索引
DROP INDEX <索引名> ON <表名>
drop index stu_id on `t_student`;