MySQL(最終版)

文章目錄

MySQL

1. 爲什麼要使用數據庫

Java程序在運行的過程中對於數據進行存儲操作,變量,對象,數組,集合,雙邊隊列…數據是保存到內存中,數據存儲是瞬時的,程序退出,電腦異常。都會導致數據丟失並且不可逆。
 文件存儲數據,XML,JSON,其他文件。可操作性比較差,API繁瑣,不同的文件有不同的解析方式,而且在內存佔用和效率問題上很難達到兩全程度。

存在的一些問題:
 1. 文件保存的數據沒有數據類型區分,都是字符串。
 2. 數據存儲量是較小的,有一定限制的。
 3. 沒有安全限制。
 4. 文件操作沒有備份,回滾,數據保護機制

2. 什麼是數據庫

數據庫按照特定的數據結構,來進行數據的組織,存儲,管理和查詢,數據庫軟件。可以長期存儲,有安全限制,數據恢復,並且數據存儲可拓展

數據庫分類:
  網狀結構數據庫
  層次結構數據庫
  關係結構數據庫【重點】
   Oracle,MySQL,DB2,SQL Server
   通過表結構方式來進行數據的存儲操作。–> XLS表格
  非關係型數據庫
   MongDB Redis
    使用哈希表結構方式,Key-Value數據存儲方式
   ES
   ElastecSearch

3. 數據庫管理系統

數據庫管理系統
 DataBase Management System
 DBMS
 操作和管理數據大型軟件,用於管理,建立,使用和查詢數據。

Oracle
 賊牛皮,安全性,穩定性,數據存儲複雜程度…可以完全符合工業要求
 貴
DB2
 IBM公司,不是很多見
SQL Server
 MS公司推出的關係型數據庫
SQLite
 輕量級數據庫,源碼1W行C語言,手機通訊錄

4. MySQL

4.1 MySQL歷史簡介

MySQL數據庫默認編碼集 Latin1 ==> 西歐
 瑞典的一個公司開發的!! MySQL AB公司
 MySQL支持插件!!!
 社區
  InnoDB跨時代的存儲引擎
 MySQL性能是非常不錯的!!!
  美國小鷹號航空母艦數據存儲都是使用MySQL

MySQL 隸屬於Oracle公司,免費提供使用的數據庫軟件。目前流行的版本是 MySQL 5.5 5.6 5.7,最新版本是8.0
 實際開發中我們要考慮穩定性,兼容性,普適性

4.2 MySQL獲取和安裝
【詳見】 Windows下安裝MySQL5.7

5. SQL

5.1 SQL語句概述

SQL是數據庫通用查詢數據,不管是MySQL,Oracle,SQL Server都是支持標準SQL語句。不同數據庫都會有自己特定的一些SQL語言。
 SQL簡單來分類
  C Create
  R Read
  U Update
  D Delete

5.2 MySQL基本操作
cmd > mysql -hlocalhost -uroot -p123456
# mysql指目前需要操作連接的數據庫
# -hlocalhost -h host端口,當前數據庫所處的服務器ip地址,域名或者主機名
# localhost 表示本地,如果是本地連接可以省略
# -uroot -u user用戶 root表示用戶
# -p -password 密碼

# 推薦方式
cmd > mysql -uroot -p
Enter password: ******
-- 展示當前數據庫中所有的數據表
mysql > show databases;

-- 創建數據庫
-- CREATE DATABASE DBName;
mysql > create database nzgp2001;
-- 創建數據庫過程修改編碼集
mysql > create database nzgp2002 character set latin1;
mysql > create database nzgp2003 character set gbk;

-- 查看創建數據庫的詳細內容
mysql > show create database nzgp2001;

-- 修改數據庫的編碼集
mysql > alter database nzgp2002 character set gbk;

-- 刪除對應數據庫
mysql > drop database nzgp2002;

-- 選擇使用數據庫
mysql > use nzgp2001;

-- 讓MySQL告知當前使用的數據庫是哪一個
# 讓MySQL告知當前使用的數據庫是哪一個
mysql > select database();

6. MySQL開發工具使用

Navivcat for MySQL 非常不錯
SQLyog 小海豚
MySQL WorkBench 免費,MySQL官網提供
IDEA Java IDE提供了數據庫操作支持

7. 查詢語句【重點】DQL

7.1 基本格式
select 查詢內容 from 從哪裏查;
-- 查詢內容 字段名 列明
-- 從哪裏查 表名
7.1.1 基本查詢,字段表名
-- * 所有字段全部展示
-- 不建議,如果採用select * 方式整個數據庫數據的時間非常長,浪費資源
select * from t_employees;

-- 查詢指定的字段
select EMPLOYEE_ID, FIRST_NAME, LAST_NAME from t_employees;
7.1.2 查詢結果字段進行數據計算
-- 查詢員工ID號,員工的名字(FristName LastName) 用戶年限
select EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY * 12
from t_employees;

-- 這裏允許使用+ - * / 可以完成字段和字段直接的算術運算
-- %在SQL語句中不是取餘,而是佔位符!!
7.1.3 去重查詢 distinct
-- 查詢結果中存在相同內容,第二個數據不要
select distinct MANAGER_ID
from t_employees;

-- 不去重
select MANAGER_ID
from t_employees;
7.1.4 字段別名
-- 字段名 as '別名'
select EMPLOYEE_ID as 'ID', FIRST_NAME as '名', LAST_NAME  as '姓', SALARY * 12 as '年薪'
from t_employees;
7.2 排序查詢 order by
規則 效果
asc 指定條件升序
desc 指定條件降序
-- 基本格式
select fieldName from tbName order by fieldName asc/desc;
-- 在查詢結果展示中,按照執行的字段作爲標記完成升序和降序
7.2.1 單一條件排序
select EMPLOYEE_ID, FIRST_NAME, SALARY -- 查詢展示的字段有哪些
from t_employees -- 從哪裏查詢
order by SALARY asc ; -- order by 指定字段要求排序 升序

select EMPLOYEE_ID, FIRST_NAME, SALARY -- 查詢展示的字段有哪些
from t_employees -- 從哪裏查詢
order by SALARY desc ; -- order by 指定字段要求排序 降序
7.2.2 多字段條件排序
-- 第一條件是工資降序,當第一條件出現一致情況下,使用第二條件進行二次排序
select EMPLOYEE_ID, FIRST_NAME, SALARY -- 查詢展示的字段有哪些
from t_employees -- 從哪裏查詢
order by SALARY desc, EMPLOYEE_ID desc; -- order by 指定字段要求排序 工資降序 ID降序
7.3 條件查詢 where
7.3.1 基本格式
select fieldName from tbName where condition;
-- 從指定數據表中,按照where之後指定條件,查詢對應的字段數據
-- where條件是一個是一個boolean類型結果
7.3.2 等值判斷 =
-- Java等於判斷是用的是 == 或者更嚴謹的情況,會使用 equals
-- 數據庫中使用 = 在where條件之後是一個等值判斷

-- 查詢在員工表內容,工資等於11000 對應的id號,名,和工資
select EMPLOYEE_ID, FIRST_NAME, SALARY
from t_employees
where SALARY = 11000;
7.3.3 不等值判定(> < >= <= != <>)
-- 查詢在員工表內容,工資大於10000 對應的id號,名,和工資
select EMPLOYEE_ID, FIRST_NAME, SALARY
from t_employees
where SALARY > 10000;

-- 查詢在員工表內容,工資大於10000 對應的id號,名,和工資
select EMPLOYEE_ID, FIRST_NAME, SALARY
from t_employees
where SALARY >= 10000;

-- 查詢在員工表內容,部門ID不等於80 對應的id號,名,工資和部門ID
select EMPLOYEE_ID, FIRST_NAME, SALARY, DEPARTMENT_ID
from t_employees
where DEPARTMENT_ID <> 80;

-- 查詢在員工表內容,部門ID不等於80 對應的id號,名,工資和部門ID
select EMPLOYEE_ID, FIRST_NAME, SALARY, DEPARTMENT_ID
from t_employees
where DEPARTMENT_ID != 80;
7.3.4 邏輯判斷(and, or, not)
-- 查詢在員工表內容,要求工資大於10000並且部門編號爲80 對應的ID號,名,工資和部門ID
select EMPLOYEE_ID, FIRST_NAME, SALARY, DEPARTMENT_ID
from t_employees
where SALARY > 10000 and DEPARTMENT_ID = 80;

-- 查詢在員工表內容,要求工資小於2500或者部門編號爲90 對應的ID號,名,工資和部門ID
select EMPLOYEE_ID, FIRST_NAME, SALARY, DEPARTMENT_ID
from t_employees
where SALARY < 2500 or DEPARTMENT_ID = 90;
7.3.5 區間 between and
-- 要求between min and max 在min <==> max範圍以內,而且要求小值之前,大值不然會報
-- 錯,這裏區間範圍是包含指定的邊界

-- 區間範圍
select EMPLOYEE_ID, FIRST_NAME, SALARY
from t_employees
where SALARY between 8000 and 10000;
7.3.6 NULL值判斷
-- is null 指定當前的字段是null
-- is not null 指定當前字段不是null

-- 找出所有提成爲null的數據
select FIRST_NAME, COMMISSION_PCT
from t_employees
where COMMISSION_PCT is null;

-- 找出所有提成不是null的數據
select FIRST_NAME, COMMISSION_PCT
from t_employees
where COMMISSION_PCT is not null;
7.3.7 枚舉查詢 in
-- 查詢部門編號爲60, 70, 90員工名字和對應部門編號
-- in查詢效率較低,推薦使用多條件拼接完成查詢操作
select FIRST_NAME, DEPARTMENT_ID
from t_employees
where DEPARTMENT_ID in(70, 60, 90);
7.3.8 模糊查詢 like
-- LIKE
-- _ 匹配一個字符
-- % 匹配任意長度字符

-- 查詢FIRST_NAME,要求FIRST_NAME字段D字母開頭後面有4個字符
select FIRST_NAME
from t_employees
where FIRST_NAME like 'D____';

-- -- 查詢FIRST_NAME,要求FIRST_NAME字段帶有D字母就可以,而且不區分大小寫
select FIRST_NAME
from t_employees
where FIRST_NAME like '%D%';
7.3.9 分支結構查詢
case
	when condition1 then ret1
	when condition2 then ret2
	when condition3 then ret3
end
-- 從case開始,到end結束。滿足條件對應一個結果,類似於Java中的switch case

-- 查詢姓名,工資已經對應工資劃分的等級LEVEL
select FIRST_NAME, SALARY,
case
    when SALARY >= 10000 then 'A'
    when SALARY >= 8000 and SALARY < 10000 then 'B'
    when SALARY >= 6000 and SALARY < 8000 then 'C'
    when SALARY >= 4000 and SALARY < 6000 then 'D'
    else 'E'
end as 'LEVEL'
from t_employees;
7.4 時間查詢
-- 語法
select 時間函數([參數列表]);
-- 查詢時間情況下,得到的是一個單列單表(虛表)
時間函數 功能描述
sysdate() 當前系統時間(年,月,日, 時,分,秒)
CURRENT_TIMESTAMP() 當前系統時間(日,月,年,時,分,秒)
curdate() 當前日期
curtime() 當前時間
week() 指定日期是這一年的第幾周
hour() 指定日期是今天第幾個小時
minite() 指定日期是小時的第幾分鐘
second() 指定日期是分鐘的第幾秒
select sysdate();
select CURRENT_TIMESTAMP();
select curdate();
select curtime();
select week('2019-11-23');
select now();
select second(sysdate());
select minute(sysdate());
select hour(sysdate());
7.5 字符串應用
方法 功能描述
concat(str1, str2, str3…) 拼接多個字符串
insert(str, pos, len, newStr) 在指定字符串位置pos,長度限制len,插入新字符串
lower(str) 大寫轉小寫
upper(str) 小寫轉大寫
substring(str,pos, len) 指定字符串,從pos位置開始,長度限制len
select concat('你好', ' MySQL', ' Oracle公司產品');
select insert('ABCDEFG', 3, 3, '你好');
select upper('abcdefg');
select lower('ABCDEF');
select substring('ABCDEFG', 2, 5);
7.6 內置方法
方法 功能描述
sum() 指定字段一列總會
avg() 指定字段一列平均值
max() 指定字段一列中的最大值
min() 指定字段一列中的最小值
count() 指定字段有多少行
-- 工資總和
select sum(SALARY)
from t_employees;

-- 工資平均數
select avg(SALARY)
from t_employees;

-- 工資最大值
select max(SALARY)
from t_employees;

-- 工資最小值
select min(SALARY)
from t_employees;

-- 當前有多少員工計數
select count(*)
from t_employees;

-- 當前有多少員工計數
-- count(1) 蜜汁比count(*) 快一點
select count(1)
from t_employees;

-- 統計有多少人有績效
select count(COMMISSION_PCT)
from t_employees;
7.7 分組查詢
select fieldName
from tbName 
where condition_ 
group by 分組要求;
-- group by是一個分組關鍵字

-- 查詢各部門人數是多少
-- 1. 需要按照department_id進行分組
-- 2. 計數需要使用count, 根據用戶的employee_id進行計數操作
select department_id, count(employee_id)
from t_employees
group by department_id;

-- 查詢各部門的平均工資
-- 1. 需要按照department_id進行分組
-- 2. 平均工資使用avg方法計算
select department_id, avg(salary)
from t_employees
group by department_id;

-- 查詢各部門,各崗位的人數
-- 1. 需要按照department_id進行分組
-- 2. 需要按照崗位job_id進行分組
-- 3. 記錄人數,count(employee_id)
select department_id, job_id, count(employee_id)
from t_employees
group by department_id, job_id;

-- [42000][1055] Expression #1 of SELECT list is not in GROUP BY
-- clause and contains nonaggregated column 'company.t_employees.department_id'
-- which is not functionally dependent on columns in GROUP BY clause;
-- this is incompatible with sql_mode=only_full_group_by
-- 如果使用group by要求分組字段一定是查詢要求字段,這裏需要根據查詢結果進行分組
select department_id
from t_employees
group by job_id;
7.8 分組過濾查詢
select fieldName
from tbName 
where condition_ 
group by 分組要求
having 過濾規則;
-- having是在 group by 之後的條件過濾

-- 查詢指定100,50,30,80最高工資
-- 1. 需要按照department_id進行分組
-- 2. 最高工資
-- 3. 限制manager_id = 100
-- 4. 限制department_id號爲100,50,30,80
select department_id, max(salary)
from t_employees
where manager_id = 100
group by department_id
having department_id in (100, 50, 30, 80);
7.9 限定查詢
select fieldName
from tbName
limit 限制;

-- limit [offset_start], row_count

-- 查詢員工表中前10個數據,員工first_name, employee_id
select employee_id, first_name
from t_employees
limit 10;

-- 查詢員工表中10個數據,要求offset爲3,員工first_name, employee_id
-- 起始行從0開始
select employee_id, first_name
from t_employees
limit 3,10;

-- 【重點】
-- limit核心用法,分頁查詢
-- pageCount 當前是第幾頁
-- itemCount 一頁展示多少個元素
-- select * from tbName limit (pageCount - 1) * itemCount, itemCount;

-- 展示第一頁10條數據
select employee_id, first_name
from t_employees
limit 0, 10;

-- 展示第二頁10條數據
select employee_id, first_name
from t_employees
limit 10, 10;

-- 展示第三頁10條數據
select employee_id, first_name
from t_employees
limit 20, 10;
7.10 基本查詢總結
select fieldName
from tbName
where condition_
group by 分組
having 分組過濾
order by 排序 [asc/desc]
limit offset, count;

-- from 數據來源,從那張表中查詢數據
-- where 查詢數據的條件
-- group by 分組
-- having 分組之後條件約束
-- select 查詢指定的字段
-- order by 排序要求
-- limit 限制結果行數
7.11 子查詢[重點,難點]
7.11.1 基本格式
select fieldName
from tbName
where (子查詢結果);
7.11.2 子查詢結果作爲條件判斷約束
-- 查詢工資高於Jack的員工id和姓名
-- 1. 找出Jack的工資
-- 2. 得到Jack工資,作爲條件查詢對應的員工信息
select salary
from t_employees
where first_name = 'Jack';

select employee_id, first_name
from t_employees
where salary > 8400;

-- 整合爲子查詢
-- 條件判斷
select employee_id, first_name
from t_employees
where salary > (select salary
                from t_employees
                where first_name = 'Jack');

7.11.3 子查詢結果作爲枚舉限制 in
-- 查詢和Jack同部門的員工信息
-- 1. 找出Jack的部門編號
select department_id
from t_employees
where first_name = 'Jack';

-- 2. 根據Jack的部門編號,使用in枚舉查詢,限制條件
select employee_id, first_name
from t_employees
where department_id in (80);

-- 整合爲子查詢
select employee_id, first_name
from t_employees
where department_id in (select department_id
                        from t_employees
                        where first_name = 'Jack');

7.11.3 子查詢結果作爲一張表,從表內查詢指定數據
-- 查詢員工表中工資前五名的員工信息
-- 1. 找到員工的id,first_name,工資降序
select employee_id, first_name
from t_employees
order by salary desc;

select employee_id, first_name
from (select employee_id, first_name
      from t_employees
      order by salary desc) as temp
limit 5;
7.11 合併查詢[僅瞭解]
union

-- 合併,要求查詢要求的字段個數一致
-- 去重
select employee_id, first_name
from t_employees
union
select job_id, job_title
from t_jobs;

-- 合併,要求查詢要求的字段個數一致
-- 不去重
select department_id, first_name
from t_employees
union all
select manager_id, department_name
from t_departments;
7.12 表連接查詢【重點】
7.12.1 基本格式
select fieldName
from tbName1
連接符 tbName2
on 條件
7.12.2 笛卡爾乘積【避免】
-- 笛卡爾乘積,沒有約束條件,數據庫匹配發生相乘關係,結果也不是預期結果
-- 無意義結果
select employee_id, first_name
from t_employees
inner join t_jobs;
7.12.3 內連接查詢 inner join on 兩張表
-- 查詢所有部門部門名,和對應的員工信息id和first_name
select t_departments.department_name,
       t_employees.employee_id,
       t_employees.first_name -- 查詢內容
from t_employees -- 從員工表中查詢
         inner join t_departments -- 內連接部門表
                    on t_employees.department_id = t_departments.department_id;
-- 條件限制員工表中的部門Id = 部門表中的部門id

-- 查詢所有部門部門名,和對應的員工信息id和first_name
-- 給予表格一個別名,方便使用
select d.department_name,
       e.employee_id,
       e.first_name -- 查詢內容
from t_employees e-- 從員工表中查詢
         inner join t_departments d-- 內連接部門表
                    on e.department_id = d.department_id; -- 條件限制員工表中的部門Id = 部門表中的部門id
7.12.4 內連接查詢 inner join on 四張表
-- 查詢所有員工對應的ID號,名字,部門名稱,和國家對應名字
select te.employee_id, te.first_name, td.department_name, tc.country_name
from t_employees te
    inner join t_departments td on te.department_id = td.department_id
    inner join t_locations tl on td.location_id = tl.location_id
    inner join t_countries tc on tl.country_id = tc.country_id;
7.12.5 內連接查詢 inner join on 五張表
-- 查詢所有員工對應的ID號,名字,工作職稱,部門名稱,和國家對應名字
select te.employee_id, te.first_name, tj.job_title, td.department_name, tc.country_name
from t_employees te
    inner join t_jobs tj on te.job_id = tj.job_id
    inner join t_departments td on te.department_id = td.department_id
    inner join t_locations tl on td.location_id = tl.location_id
    inner join t_countries tc on tl.country_id = tc.country_id;	
7.12.6 左外連接 left join on
-- 左外連接 左表是主表,要求左表完整顯示,右表匹配左表數據,如果右表沒有數據匹配,顯示null

-- 查詢所有的員工信息ID,first_ame,已經對應的部門名字
select te.employee_id, te.first_name, td.department_name
from t_employees te
         left join t_departments td on te.department_id = td.department_id;
7.12.7 右外連接 right join on
-- 右外連接查詢,右表是主表,要求右表完整展示,左表匹配右表數據,如果左表沒有數據匹配,顯示null

-- 查詢所有部門對應員工信息,員工信息沒有顯示null
select td.department_name,te.employee_id, te.first_name
from t_employees te
         right join t_departments td on te.department_id = td.department_id;

8. DML語句

8.1 增加 insert
create table person(
    id int,
    name varchar(30),
    salary float(8, 2),
    age int
);

-- 規矩插入
insert into person(id, name, salary, age) VALUE (1, '騷磊', 100.5, 16);

-- 省略所有的字段名,按照字段順序添加
insert into person value (2, '茂林', 20.5, 50);

-- 指定字段數據插入
insert into person(name, age) value ('騷傑', 66);

-- 禁止字段數據類型和插入數據類型不一致!!!
insert into person(name, age) value ('66', '23333333');
insert into person(name, age) value ('66', '你在整一個試試???');
8.2 修改 update 【慎用】
-- Unsafe query: 'Update' statement without 'where' updates all table rows at once
-- 沒有任何約束的情況下,當前指定數據表中的所有數據行全部執行修改操作
-- 一定要帶有where條件約束
update person set id = 10;

-- OK
update person set id = 10 where name = '騷磊';
-- 可以同時修改多個數據,不同的字段賦值操作使用 逗號隔開
update person set id = 20, age = 10, salary = 200000.01 where name = '騷磊';
8.3 刪除 delete【慎用】
-- Unsafe query: 'Delete' statement without 'where' clears all data in the table
delete from person;

-- 根據條件約束刪除是允許的
delete from person where name = '66';
8.4 truncate 清空整表數據
-- 清空整表數據,並且會影響到一定數據約束,例如auto_increment 自增長
truncate table person;

9. 庫表操作

9.1 創建數據庫
-- dbName數據庫的名字,可以約束編碼集[是情況而定]
create database dbName [character set charset];
9.2 刪除數據庫
-- 刪除指定數據庫
drop database dbName;
9.3 修改數據庫
-- 修改數據庫編碼集
alter database dbname character set utf8;
9.4 數據類型
9.4.1 數值類型
類型 大小 範圍(有符號) 範圍(無符號) 用途
INT或INTEGER 4 字節 (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整數值
DOUBLE 8 字節 (-1.797E+308,-2.22E-308) (0,2.22E-308,1.797E+308) 雙精度浮點數值
DOUBLE(M,D) 8個字節,M表示長度,D表示小數位數 同上,受M和D的約束 DUBLE(5,2) -999.99-999.99 同上,受M和D的約束 雙精度浮點數值
DECIMAL(M,D) 對DECIMAL(M,D) ,如果M>D,爲M+2否則爲D+2 依賴於M和D的值,M最大值爲65 依賴於M和D的值,M最大值爲65 小數值
9.4.2 日期類型
類型 大小 範圍 格式 用途
DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
TIME 3 ‘-838:59:59’/‘838:59:59’ HH:MM:SS 時間值或持續時間
YEAR 1 1901/2155 YYYY 年份值
DATETIME 8 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和時間值
TIMESTAMP 4 1970-01-01 00:00:00/2038 結束時間是第 2147483647 秒北京時間 2038-1-19 11:14:07,格林尼治時間 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和時間值,時間戳
9.4.3 字符串類型
類型 大小 用途
CHAR 0-255字符 定長字符串 char(10) 10個字符
VARCHAR 0-65535 字節 變長字符串 varchar(10) 10個字符
BLOB(binary large object) 0-65 535字節 二進制形式的長文本數據
TEXT 0-65 535字節 長文本數據
9.5 創建表
-- 1. 選擇使用的數據庫

create table tbName
(
    fieldName1 fieldType1,
    fieldName2 fieldType2,  
    fieldName3 fieldType3,  
    fieldName4 fieldType4
);
-- 可以加入約束,字符集和存儲引擎

10. 數據約束

10.1 默認值 default
-- 創建數據表的過程中,指定字段可以帶有默認值,如果用戶沒有指定數據的情況下,當前
-- 字段會採用默認值方式來進行數據賦值操作。
-- default
create table person1
(
    id int,
    name varchar(50),
    country varchar(50) default 'PRC' -- 默認值字段
);

desc person1;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(11)     | YES  |     | NULL    |       |
| name    | varchar(50) | YES  |     | NULL    |       |
| country | varchar(50) | YES  |     | PRC     |       |
+---------+-------------+------+-----+---------+-------+

-- 不給予帶有默認值字段對應的數據,會採用默認值方式賦值當前子彈
insert into person1(id, name) value (1, '騷磊');

-- 給予當前帶有默認值字段數據賦值操作,會採用給予的數據賦值當前字段
insert into person1(id, name, country) value (2, '航海中路彭于晏', '中華人民共和國');
10.2 非空 not null
-- not null 非空,要求當前字段必須有對應的數據,如果沒有賦值報錯
-- NN
-- 實際使用中必要字段!!!

create table person2
(
    id int,
    name varchar(50) not null,
    country varchar(50) default 'PRC' -- 默認值字段
);

+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(11)     | YES  |     | NULL    |       |
| name    | varchar(50) | NO   |     | NULL    |       |
| country | varchar(50) | YES  |     | PRC     |       |
+---------+-------------+------+-----+---------+-------+


insert into person2(id, name) VALUE (1, '46號技師');
-- ERROR Field 'name' doesn't have a default value
insert into person2(id) VALUE (2);
10.3 唯一 unique
-- 字段使用unique約束,當前字段中保存的數據在當前表內不可以重複

create table person3
(
    id int unique,
    name varchar(50) not null,
    country varchar(50) default 'PRC' -- 默認值字段
);

+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(11)     | YES  | UNI | NULL    |       |
| name    | varchar(50) | NO   |     | NULL    |       |
| country | varchar(50) | YES  |     | PRC     |       |
+---------+-------------+------+-----+---------+-------+

insert into person3(id, name) value (1, '哆啦A磊');
-- ERROR Duplicate entry '1' for key 'id'
-- 對應當前ID值已經存在,不能再次插入相同id數據
insert into person3(id, name) value (1, '老騷');

-- id使用unique限制唯一,但是null不作爲唯一判斷範圍以內
insert into person3(name) value ('老騷');
insert into person3(name) value ('超超');
insert into person3(id, name) value (null, '賤賤的我就長大了');
insert into person3(id, name, country) value (null, '賤賤的我就長大了',null);
10.4 主鍵 primary key
-- 主要要求唯一,非空!!!
-- primary key 主鍵
-- 主鍵一般用於在開發中涉及到數據的唯一性參照物,但是不能使用帶有業務邏輯要求數據作爲
-- 主鍵,例如 性別 年齡 工資....

create table person4
(
    id int primary key,
    name varchar(50) not null,
    country varchar(50) default 'PRC' -- 默認值字段
);

+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(11)     | NO   | PRI | NULL    |       |
| name    | varchar(50) | NO   |     | NULL    |       |
| country | varchar(50) | YES  |     | PRC     |       |
+---------+-------------+------+-----+---------+-------+

insert into person4(id, name) value (1, '騷磊');
-- ERROR Duplicate entry '1' for key 'PRIMARY'
-- 對應使用primary key修飾的主鍵id已存在。
insert into person4(id, name) value (1, '騷磊');
-- ERROR Field 'id' doesn't have a default value
insert into person4(name) value ('騷磊');
-- ERROR Column 'id' cannot be null
insert into person4(id, name) value (null, '騷磊');
10.5 自增長 auto_increment
-- 自增長修飾字段會在數據添加的過程中自動賦值疊加操作
-- auto_increment修飾的字段必須是一個Key
-- AI ==> auto_increment
create table person5
(
    id int primary key auto_increment,
    name varchar(50) not null,
    country varchar(50) default 'PRC' -- 默認值字段
);

+---------+-------------+------+-----+---------+----------------+
| Field   | Type        | Null | Key | Default | Extra          |
+---------+-------------+------+-----+---------+----------------+
| id      | int(11)     | NO   | PRI | NULL    | auto_increment |
| name    | varchar(50) | NO   |     | NULL    |                |
| country | varchar(50) | YES  |     | PRC     |                |
+---------+-------------+------+-----+---------+----------------+

-- 自增長字段會從1開始
insert into person5(name) value ('郭德綱'); -- id = 1
insert into person5(name) value ('于謙'); -- id = 2

-- 自增長可以指定數值,而且存在影響自增長計數情況
insert into person5(id, name) value (5, '高峯'); -- id = 5
insert into person5(name) value ('欒雲平'); -- id = 6

-- 自增長可以指定數值,而且存在影響自增長計數情況 
insert into person5(id, name) value (8,'岳雲鵬'); -- id = 8
insert into person5(name) value ('孫越'); -- id = 9

-- 指定id爲7,但是當前id數據小於自增長,不影響自增長結果 數據保存排序
insert into person5(id, name) value (7, '郭麒麟'); -- id = 7
insert into person5(name) value ('閻鶴祥'); -- id = 10;

-- 刪除數據 
delete from person5 where id = 7;
delete from person5 where id = 10;

-- 被刪除的id可以指定使用
insert into person5(id, name) value (7, '郭麒麟'); -- id = 7
-- delete刪除不會印象自增長計數
insert into person5(name) value ('閻鶴祥'); -- id = 11
delete from person5 where id = 11;

-- 清空數據表,同時會重置自增長
truncate person5;

-- 數據庫徹底關閉,會影響到自增長保存
10.6 外鍵約束
create table employee
(
    id int primary key auto_increment,
    name varchar(50) not null,
    deptName varchar(50)
);

-- 這裏會導致數據冗餘問題。並且存在資源的浪費
insert into employee(name, deptName) value ('騷磊', '帥部');
insert into employee(name, deptName) value ('彭于晏', '帥部');
insert into employee(name, deptName) value ('吳彥祖', '帥部');
insert into employee(name, deptName) value ('燒餅', '騷氣無敵部');
insert into employee(name, deptName) value ('岳雲鵬', '賤到無敵部');
insert into employee(name, deptName) value ('曾小賢', '賤到無敵部');
insert into employee(name, deptName) value ('孟鶴堂', '騷氣無敵部');

drop table employee;

-- 部門表
create table dept
(
    id int primary key auto_increment,
    deptName varchar(50) not null
);

-- 員工表,員工表中存在字段和部門表有直接聯繫,deptId ==》 dept表內的id
create table employee
(
    id int primary key auto_increment,
    name varchar(50) not null,
    deptId int
);

-- 準備部門表數據
insert into dept(deptName) value ('帥部');
insert into dept(deptName) value ('賤到無敵部');
insert into dept(deptName) value ('騷氣無敵部');

-- 插入員工數據
insert into employee(name, deptId) value ('騷磊', 1);
insert into employee(name, deptId) value ('彭于晏', 1);
insert into employee(name, deptId) value ('吳彥祖', 1);
insert into employee(name, deptId) value ('燒餅', 3);
insert into employee(name, deptId) value ('岳雲鵬', 2);
insert into employee(name, deptId) value ('曾小賢', 2);
insert into employee(name, deptId) value ('孟鶴堂', 3);

-- 內連接聯表查詢目標數據
select e.id, e.name, d.deptName
from nzgp2001.employee e
inner join dept d on  d.id = e.deptId;

-- 1. 目前數據存儲效率是高於第一種方法
-- 2. 數據存儲的複雜度,修改操作都是高於第一種方法

-- 當前數據插入操作是完全就可以執行,但是郭德綱的數據在存儲到數據表中之後
-- 部門ID號是不合理的!!!
insert into employee(name, deptId) value ('郭德綱', 4);

-- SQL語句可以執行,但是存在部門表刪除後,對應的員工數據存儲存在隱患
delete from dept where id = 3;

drop table dept;
drop table employee;

-- 使用外鍵約束

-- 部門表 【主表】
create table dept
(
    id int primary key auto_increment,
    deptName varchar(50) not null
);

-- 員工表,員工表中存在字段和部門表有直接聯繫,deptId ==》 dept表內的id
-- 【從表】
create table employee
(
    id int primary key auto_increment,
    name varchar(50) not null,
    deptId int,
    -- 外鍵聲明約束
    -- constraint 聲明使用關鍵字
    -- fk_emp_dept 外鍵名稱 fk ==> foreign key emp ==> employee dept ==> 部門表
    -- foreign key 外鍵聲明關鍵字(從表外鍵字段) deptId employee表內的外鍵是deptId
    -- references 選擇當前外鍵關聯的主表字段關鍵字 主表(字段) dept(id)
    constraint fk_emp_dept foreign key (deptId) references nzgp2001.dept(id)
);

-- 準備部門表數據
insert into dept(deptName) value ('帥部');
insert into dept(deptName) value ('賤到無敵部');
insert into dept(deptName) value ('騷氣無敵部');

-- 插入員工數據
insert into employee(name, deptId) value ('騷磊', 1);
insert into employee(name, deptId) value ('彭于晏', 1);
insert into employee(name, deptId) value ('吳彥祖', 1);
insert into employee(name, deptId) value ('燒餅', 3);
insert into employee(name, deptId) value ('岳雲鵬', 2);
insert into employee(name, deptId) value ('曾小賢', 2);
insert into employee(name, deptId) value ('孟鶴堂', 3);

-- Cannot add or update a child row: a foreign key constraint fails (`nzgp2001`.`employee`,
-- CONSTRAINT `fk_emp_dept` FOREIGN KEY (`deptId`) REFERENCES `dept` (`id`))
-- 該數據條件時會檢查主表,詢問主表中是否存在指定的字段數據
insert into employee(name, deptId) value ('郭德綱', 4);

-- Cannot add or update a child row: a foreign key constraint fails (`nzgp2001`.`employee`,
-- CONSTRAINT `fk_emp_dept` FOREIGN KEY (`deptId`) REFERENCES `dept` (`id`))
-- 修改部門id爲3的數據,改爲10,deptId == 10 在主表中不存在
update employee set deptId = 10 where deptId = 3;

-- Cannot delete or update a parent row: a foreign key constraint fails (`nzgp2001`.`employee`,
-- CONSTRAINT `fk_emp_dept` FOREIGN KEY (`deptId`) REFERENCES `dept` (`id`))
-- 刪除主表數據行,需要詢問從表中是否有使用當前主表數據的數據行,如果有,無法刪除。
delete from nzgp2001.dept where nzgp2001.dept.id = 3;

update nzgp2001.dept set id = 10 where id = 3;

-- 使用外鍵約束操作優勢和問題
-- 優勢:
--      1. 主表從表關聯性更強
--      2. 主表從表數據操作時存在更多約束
--      3. 操作規範性更強’

-- 問題:
--      1. 從表操作過程中添加和修改約束過強,需要首先操作主表
--      2. 主表操作過程中刪除和修改約束過程,需要首先操作從表
--      3. 整個數據庫更新,刪除操作過於繁瑣,並且後期維護壓力過大

-- 外鍵約束雖然可以從SQL語句的語法上約束一定操作,但是會導致更多的問題,在開發中不允許使用。
10.7 級聯操作
-- 在外鍵約束的情況下,操作主表和從表都有很多約束
-- SQL中引入的級聯操作
-- 級聯刪除 on delete cascade
-- 級聯修改 on update cascade
-- 主表操作執行刪除或者修改時,對於外鍵約束的從表會對應操作。

drop table dept;
drop table employee;

-- 使用外鍵約束

-- 部門表 【主表】
create table dept
(
    id int primary key auto_increment,
    deptName varchar(50) not null
);

-- 員工表,員工表中存在字段和部門表有直接聯繫,deptId ==》 dept表內的id
-- 【從表】
create table employee
(
    id int primary key auto_increment,
    name varchar(50) not null,
    deptId int,
    -- 外鍵聲明約束
    -- constraint 聲明使用關鍵字
    -- fk_emp_dept 外鍵名稱 fk ==> foreign key emp ==> employee dept ==> 部門表
    -- foreign key 外鍵聲明關鍵字(從表外鍵字段) deptId employee表內的外鍵是deptId
    -- references 選擇當前外鍵關聯的主表字段關鍵字 主表(字段) dept(id)
    constraint fk_emp_dept foreign key (deptId) references nzgp2001.dept(id)
    on delete cascade -- 級聯刪除
    on update cascade -- 級聯修改
);

-- 準備部門表數據
insert into dept(deptName) value ('帥部');
insert into dept(deptName) value ('賤到無敵部');
insert into dept(deptName) value ('騷氣無敵部');

-- 插入員工數據
insert into employee(name, deptId) value ('騷磊', 1);
insert into employee(name, deptId) value ('彭于晏', 1);
insert into employee(name, deptId) value ('吳彥祖', 1);
insert into employee(name, deptId) value ('燒餅', 3);
insert into employee(name, deptId) value ('岳雲鵬', 2);
insert into employee(name, deptId) value ('曾小賢', 2);
insert into employee(name, deptId) value ('孟鶴堂', 3);

-- 主表中有外鍵約束的字段數據發生修改,從表中對於字段同時發生修改,級聯修改
update dept set id = 10 where id = 3;

-- 主表字段刪除,從表中使用主表約束的數據行也需要刪除
delete from nzgp2001.dept where id = 1;

11. 數據表修改 alter

11.1 添加字段
-- 默認在最後一個字段之後添加
alter table employee add age int;
11.2 修改字段
-- 修改字段對應數據類型和約束
alter table employee modify name char(50) not null;
11.3 修改字段
-- 修改字段名字,對應數據類型和約束問題
alter table employee change name userName varchar(50) not null;
11.4 刪除字段
-- 刪除對應的字段
alter table employee drop age;
11.5 修改表名
-- 修改表名字
rename table employee to emp;

12 事務

12.1 什麼是事務

操作數據庫,修改,刪除【慎用】,修改刪除操作過程中,如果出現操作失誤,會導致數據丟失或者全部被毀,而且沒有Ctrl + Z
 數據庫操作中操作失誤是很常見的,數據庫開發中設置有事務處理機制,也就是所謂回滾。

12.2 模擬銀行轉賬
12.2.1 正確情況
-- 轉賬1000過程
update acount set money = money - 1000 where id = 1;
update acount set money = money + 1000 where id = 2;
12.2.2 異常情況
-- 錯誤情況:轉賬1000過程
update acount set money = money - 1000 where id = 1;
-- 斷電,斷網,電腦被砸了,數據丟失了,網絡傳輸中斷了。。。。
-- 第一句SQL語句是沒有執行成功的

-- 一切都恢復了!!!
update acount set money = money + 1000 where id = 2;
12.3 事務的概念

事務可以認爲是SQL語句處理的最小單元,具有一定的原子性,是由一條或者多條SQL語句組成,事務執行完成,那麼所有的SQL語句全部執行,都要執行成功。一旦出現任何一個SQL語句異常,回到事務執行之前,事務執行失敗。

12.4 事務的邊界
-- 開始:
-- 	當前事務,當前一整套和業務邏輯相關的內容一起執行
-- 	一旦執行 set autocommit = 0; 數據庫SQL語句執行不再立即執行,而且一種類似於Stream流狀態,需要等待提交生效,但是操作的過程中數據庫可觀察。
	set autocommit = 0;
	start transaction;
	
-- 結束
-- 	1. 確認沒有問題
	commit; -- 顯式提交
-- 	隱式方式提交: 一條創建,刪除SQL語句,或者數據庫正常關閉

-- 2. 回滾操作
	rollback; -- 顯式回滾
-- 自動回滾,執行創建,刪除語句失敗,或者數據庫非正常退出
12.5 事務操作演示
-- 開啓事務
set autocommit = 0;
update acount set money = money - 2000 where id = 1;
select * from acount;

update acount set money = money + 2000 where id = 2;
select * from acount;

-- 確認無誤,SQL語句提交執行
commit;

-- 開啓事務
set autocommit = 0;
update acount set money = money - 2000 where id = 1;
select * from acount;

update acount set money = money + 2000 where id = 2;
select * from acount;

-- 發現問題,手動提交rollback 回滾
rollback;

-- 開啓事務
start transaction;
update acount set money = money - 2000 where id = 1;
select * from acount;

update acount set money = money + 2000 where id = 2;
select * from acount;

commit ;
12.6 事務的特徵

原子性
 事務操作是一個整體,所有的SQL語句完成一個事務,事務只有兩種可能性,執行成功,或者失敗。

一致性
 事務操作如果失敗,其中所有的數據操作過程,全部會回到原來的起點。

隔離性
 在事務情況下,查詢數據是一種事務處理過程中數據展示情況,但是在實際的數據庫中是沒有發送數據的變化的。只有事務提交之後纔會更改

持久性
 事務一定執行成功,對於數據庫的操作影響是持久性的。

13.權限管理

13.1 創建用戶
-- 用戶名 saolei 密碼 123456
create user 'saolei' identified by '123456';
13.2 授權用戶
-- 授權操作所有nzgp2001庫權限
grant all on nzgp2001.* to 'saolei';
13.3 撤銷授權
-- 撤銷saolei用戶所有nzgp2001數據庫權限
revoke all on nzgp2001.* from 'saolei';
13.4 刪除用戶
-- 刪除用戶
drop user 'saolei';

14. 視圖

14.1 什麼是視圖
 	視圖,是一個虛擬表,通過查詢語句,從一個表或者多個表中查詢得到的一個結果,可以作爲一個視圖使用,使用的效果和真實表一致。可以在視圖中使用update,delete,insert操作,可以提供數據庫的安全性,同時便於用戶操作。
14.2 視圖的特點

優點:
 1. 簡單化,數據所見即所得
 2. 安全,用戶有且只能修改操作當前可見數據
 3. 邏輯獨立性,這裏使用使用的一張虛擬表,所有操作並不會對數據庫真實表結構導致影響。

缺點:
 1. 性能較差,不管是SQL操作還是針對數據存儲的性能
 2. 修改不方便,複雜視圖在操作中是無法修改的

14.3 創建視圖和使用視圖
14.3.1 創建視圖
-- 語法
-- create view 視圖名 as 查詢數據結果[查詢語句]
-- 創建視圖
create view empInfo as
select employee_id, first_name, last_name, email, salary
from t_employees;
14.3.2 視圖使用
-- empInfo不是一張真實存在的表,而是一個自定義查詢結果的視圖
select *
from empInfo
where employee_id = 150;


-- 利用視圖中的結果進行排序操作
select *
from empInfo
order by salary desc;

-- 修改視圖中的數據,原表數據會受到影響
update empInfo
set first_name = 'Jame',
    last_name  = 'Martin'
where employee_id = 100;

select *
from empInfo;

select *
from t_employees;

-- 視圖原表數據發送修改,視圖中數據也會修改
update t_employees
set first_name = 'Steven',
    last_name  = 'King'
where employee_id = 100;

select *
from empInfo;
14.3.3 修改視圖
-- Table 'empInfo' already exists
-- 當前視圖已經存在
-- [驗證]
create view empInfo as
select employee_id, first_name, last_name, salary
from t_employees;

-- 修改當前視圖的結構
alter view empinfo
as
select employee_id, first_name, last_name, salary
from t_employees;
14.3.4 刪除視圖
-- 刪除不會影響原始數據
drop view empInfo;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章