軟件測試之MySQL數據庫必知必會,面試必備!

一、前言

1.1 數據庫概念及分類

首先,我們經常說的MySQL是一個數據庫管理系統,而非數據庫。數據庫是組織、存儲和管理數據的倉庫,存儲數據的容器。而數據庫管理系統是操縱和管理數據庫的大型軟件,建立、使用和維護數據庫。數據表是真正的數據存儲單元,其他對象的基礎。三者之間的關係爲:一個數據庫管理系統維護了多個數據庫,一個數據庫包含若干數據表

在這裏插入圖片描述

關於數據庫的分類,可能有很多種分類。一般來說,我們用到最多的就是關係型數據庫NoSQL數據庫。而其中關係型數據庫又是應用最爲廣泛的。

1.2 SQL語句概念及分類

SQL:一種結構化查詢語句,用於訪問和操作數據庫的標準計算機語言。通常用途爲操作數據庫對象(表、存儲過程、函數、索引),表記錄的增刪改查。SQL是一門弱語言不區分大小寫。通常,將SQL語句分爲下面五大類。

在這裏插入圖片描述

1.3 MySQL數據類型

MySQL支持多種數據類型,大致可以分爲四大類,如下圖所示。關於MySQL數據類型的詳細內容,請參考鏈接 MySQL常見的數據類型

在這裏插入圖片描述

二、常用SQL語句

2.1 數據庫相關SQL

  • 查詢所有數據庫
    show databases;
    
  • 創建數據庫
    create database 數據庫名稱;
    
  • 刪除數據庫
    drop database 數據庫名稱;
    
  • 查詢數據庫詳情、查看數據庫的字符集
    show create database 數據庫名稱;
    
  • 創建指定字符集數據庫
    ##創建數據庫語句後面用character set設置數據庫字符集,注意這裏是utf8,不是utf-8
    create database 數據庫名稱 character set gbk/utf8;
    
  • 選中數據庫
    use 數據庫名稱;
    

2.2 表相關SQL

如果不借助工具的情況下,在命令中輸入下面相關的命令,需要先使用use 數據庫名選擇要操作表所屬的數據庫。

  • 創建表
    ##創建數據庫表語句如下:
    CREATE TABLE IF NOT EXISTS 表名(
     字段名1 字段類型,
     字段名2 字段類型
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    ## 實際案例語句
    CREATE TABLE IF NOT EXISTS NUMBER(
      ID INT NOT NULL AUTO_INCREMENT,
      USERNAME VARCHAR(40),
      PRIMARY KEY (ID)
    )ENGINE=INNODB DEFAULT CHARSET=UTF8;
    
  • 查詢所有表
    show tables;
    
  • 查詢表詳情
    show create table 表名;
    
  • 查看錶結構
    desc 表名;
    
  • 刪除表
    drop table 表名;
    

2.3 修改表相關SQL

關於修改表相關的SQL,除了修改表前沒加alter table 表名,其他都是在該基礎添加的語句。這部分的SQL一般來說在實際工作中用的不多,因爲相關操作都可以藉助Navicat實現

  • 修改表名
    rename table 原表名 to 新表名;
    
  • 修改表引擎和字符集
    alter table 表名 engine=innodb/myisam charset=gbk;
    
  • 添加表字段(在最後)
    alter table 表名 add 字段名 字段類型;
    
  • 添加表字段(最前面)
    alter table 表名 add 字段名 字段類型 first;
    
  • 添加字段(某個字段後添加)
    alter table 表名 add 字段名A 字段A類型 after 字段名B;
    
  • 刪除表字段
    alter table 表名 drop 字段名;
    
  • 修改表字段名稱和類型
    alter table 表名 change字段名 原字段名 新字段名 新類型;
    

2.4 操作表記錄相關SQL

對於測試工程師而言,SQL語言中最常用的就是DML——數據操作語言,即爲增刪改查。而其中用到最多的就是DQL——數據查詢語句

  • 插入數據(全表插入)
    insert into 表名 values (字段1值,字段2值);
    insert into 表名 values (字段1值,字段2值),(字段1值,字段2值);
    
  • 插入數據(指定字段)
    insert into 表名 (字段1,字段2) values (值1,值2);
    insert into 表名 (字段1,字段2) values (值1,值2),(值1,值2);
    
  • 刪除數據
    #刪除指定數據
    delete from 表名 where 字段名=;
    
    #刪除表中全部數據
    delete from 表名;
    
  • 修改數據
    #修改指定值
    update 表名 set 字段名=值1 where 字段名=值2;
    
    #修改全部值
    update 表名 set 字段名=值1;
    
  • 查詢數據
    #查詢所有
    select * from 表名
    

三、DQL(查詢)詳解

DQL即爲數據查詢語句,也是使用最多的一種SQL語句。將該部分的內容分爲以下幾部分:其中最爲常用的是關聯查詢分組分頁排序條件查詢這幾種。對於其中常用的where 、group by、having、order by、limit,其順序爲:·select * from 表A join 表B on 條件 where 條件 group by 分組字段 having 聚合函數過濾 order by 排序字段 limit ...

3.1 條件查詢

  • 判斷是否爲空(is nullis not null
    # is null代表爲空  is not null代表不爲空
    #案例 查看圖書借閱表中歸還時間爲空的借閱記錄
    SELECT * FROM book_borrow WHERE return_time is NULL;
    
  • 比較運行符(>、<、>=、<=、!=、<>
    #分別代表大於、小於、大於等於、小於等於、不等於、不等於
    #案例 查看圖書表中圖書id大於2的圖書信息
    SELECT * FROM book WHERE book_id>2
    
  • andor
    ## 等同於 &&和 || ,表示同時滿足兩個條件和滿足兩個條件中一個
    
    ## 案例1:查詢圖書借閱表中用戶id和圖書id都爲1的圖書信息
    SELECT * FROM book_borrow WHERE user_id=1 AND book_id=1;
    
    ##案例2:查詢圖書借閱表中用戶id爲1或者圖書id爲1的圖書信息
    SELECT * FROM book_borrow WHERE user_id=1 OR book_id=1;
    
  • in 在某些可選值範圍內
    # select * from 表名 where 字段 in (值1,值2,值3);
    # 案例1 查詢圖書借閱表中讀者id在1,2,3範圍內
    SELECT * FROM book_borrow WHERE user_id in (1,2,3);
    
  • betweennot between
    # 字段 between 值1 and 值2;  字段在值1和值2之間
    #案例1:查詢圖書借閱表中讀者id在1-2範圍內,包含1和2
    SELECT * FROM book_borrow WHERE user_id BETWEEN 1 AND 2;
    
  • 模糊查詢 like _代表單個字符%代表0個或多個字符
    # 案例1 查詢圖書表中圖書名字爲兩個字符,且圖書名第一個字爲三的圖書信息
    SELECT * FROM book WHERE book_name LIKE '三_';
    
    # 案例2 查詢圖書表中圖書名以天才開頭的圖書信息
    SELECT * FROM book WHERE book_name LIKE '天才%';
    

3.2 別名、去重

  • 別名——使用as關鍵字或空格 給表名或字段別名
    # 案例 查詢圖書表中圖書名稱爲‘天才在左 瘋子在右’的作者
    SELECT b.author as 作者 FROM book b WHERE b.book_name ='天才在左 瘋子在右';
    
  • 去重——使用distinct對查詢出來的去重
    #案例 查詢員工表中所有的員工名稱,且不重複
    select  distinct employeeName from  employee;
    

3.3 排序、分頁查詢

  • 排序——order by (ASC 升序 默認、DESC 降序 )
    #案例:查詢學生表數據並以id降序、年齡升序排序
    select * from student order by id desc,age;
    
  • 分頁查詢——limit 跳過條數A 每頁數量B
    #案例 查詢學生表中年齡第三大的學生信息
    select * from student order by age desc limit 2,1;
    
    #分頁查詢sql的格式爲 start爲頁碼 pageSize是每頁顯示的條數
    select * from table limit (start-1)*pageSize,pageSize;
    

3.4 聚合函數、時間相關函數

  • 聚合函數——sum(字段名) 求和
    #案例 對分數表中分數進行求和
    SELECT SUM(a.score) FROM table_socre as a;
    
  • 聚合函數——avg(字段名) 平均值
    #案例 求分數表中分數平均值
    SELECT AVG(a.score) FROM table_socre as a;
    
  • 聚合函數——max(字段名) 最大值
    #案例 求分數表中最大值
    SELECT MAX(a.score) FROM table_socre as a;
    
  • 聚合函數——min(字段名) 最小值
    #案例 求分數表中最小值
    SELECT MIN(a.score) FROM table_socre as a;
    
  • 聚合函數——count(字段名) 統計數量
    #實例 查詢圖書表中圖書總數
    SELECT COUNT(*) as 圖書總數 FROM book
    
    注意點,count()函數的擴號中也可以填寫字段,如果
    字段的值爲0,則不參與合計
    
  • 時間函數——now() 當前年月日時分秒
    SELECT NOW();
    #輸出當前時間 2020-07-03 23:21:03
    
  • 時間函數——current_date() 當前時間年月日
    SELECT CURRENT_DATE();
    #輸出當前時間年月日 2020-07-03
    

3.5 分組與having

  • 分組——group by
    group by的常規用法是配合聚合函數,利用分組信息進行統計。
    #案例 以title字段分組,查詢每個分組中score的最大值
    SELECT t.t.title,MAX(score) FROM table_socre t GROUP BY t.title;
    
  • having——解決聚合函數過濾問題,一般配合group by一起使用。
    #案例 以title字段分組,查詢每個分組中score的最大值,並且通過最大值必須大於20來過濾數據
    SELECT t.t.title,MAX(score) FROM table_socre t GROUP BY t.title having MAX(score)>20;
    

3.6 子查詢

  • 寫在where/having後作爲查詢條件的值
    #案例 查詢員工工資最低的員工信息,由於可能最低有多個員工,所以需要先查詢出最低工資
    SELECT * FROM employees
    WHERE salary=(
        SELECT MIN(salary)
        FROM employees
    );
    
  • 臨時表——用在from後面,當做一個新表,新表必須有名稱
    #案例 將一個查詢結果作爲一個新表,讓後從這個新表中查詢數據
    select cou,name from (select count(*) AS cou,enabled AS name from `user` group by enabled ) as a where cou>0
    

3.7 關聯查詢

參考鏈接:Mysql中的關聯查詢(內連接,外連接,自連接)

  • 內連接—— 表A inner join 表B on 條件,特點:只查詢連接的表中能夠有對應的記錄的數據
    #查詢員工姓名及對應部門名稱 沒有部門的人員和沒有人員的部門都不顯示
    SELECT
    	e.empName,
    	d.deptName 
    FROM
    	t_employee e
    	INNER JOIN t_dept d ON e.dept = d.id;
    
  • 左外連接——表A left join 表B on 條件,特點:以左邊的表的數據爲基準,去匹配右邊的表的數據,如果匹配到就顯示,匹配不到就顯示爲null
    #查詢員工表中員工姓名及對應部門名稱,若員工沒有部門,則顯示null
    SELECT
    	e.empName,
    	d.deptName 
    FROM
    	t_employee e
    	LEFT JOIN t_dept d ON d.id = e.dept;
    
  • 右外連接——表A right join 表B on 條件,特點:與坐外連接類似,只是基準表變了,用右表去匹配左表。所以左外連接能做到的事情,右外連接也能做到。
    #查詢所有部門和對應的員工,如果部門沒有員工,則顯示null
    SELECT
    	e.empName,
    	d.deptName 
    FROM
    	t_employee e
    	RIGHT JOIN t_dept d ON d.id = e.dept;
    
  • 自連接——當前表與自身連接查詢
    #查詢員工以及他的上司的名稱,由於上司也是員工,所以這裏虛擬化出一張上司表
    SELECT
    	e.empName,
    	b.empName 
    FROM
    	t_employee e
    	LEFT JOIN t_employee b ON e.bossId = b.id;
    

四、約束、索引、存儲過程、事務

4.1 約束

MySQL中約束是一種限制,它通過對錶的行或列的數據做出限制,來確保表的數據的完整性、唯一性。

在這裏插入圖片描述

4.2 索引

MySQL中的索引是一種高效獲取數據的存儲結構——B+Tree;MySQL中索引的好處在於加快查詢速度,壞處就是降低了增刪改的速度,增大了表的文件大小(索引文件可能比數據文件還要大)。MySQL索引實現原理可以參考:mysql索引實現原理

#1.如何創建索引 注意:添加主鍵約束是,會自動創建主鍵字段的索引
create index 索引名 on 表名(字段);

#2.查看索引
show index from 表名;

#3.刪除索引
drop index 索引名 on 表名;

在這裏插入圖片描述

4.3 存儲過程

MySQL中存儲過程類似於函數,就是把一段代碼封裝起來,當要執行這一段代碼的時候,可以通過調用該存儲過程來實現。

#1.查看數據庫中的存儲過程
show procedure status;

#2.查看存儲過程的創建代碼
show create PROCEDURE 存儲過程名;

#3.創建存儲過程
CREATE PROCEDURE 名稱()
BEGIN
.........
END
#4.創建存儲過程,並執行存儲過程
#4.1創建存儲過程
drop procedure if exists proc_addNum;
create procedure proc_addNum (in x int,in y int,out sum int)
BEGIN
SET sum= x + y;
end

#4.2執行過程,out輸出返回值
call proc_addNum(2,3,@sum);
select @sum;

4.4 事務

參考鏈接:MySQL數據庫事務的四大特性以及事務的隔離級別

事務:是數據庫中執行SQL語句的工作單元,可以保證事務內的SQL語句要麼全部成功,要麼全部失敗。

在這裏插入圖片描述

五、相關面試題

對於軟件測試而言,在MySQL數據庫相關的面試題中,除了上面MySQL數據庫相關的概念,最重要的就是DQL語句的編寫。關於DQL相關語句的考題,可以直接參考牛客網中SQL實戰編程:牛客網SQL實戰

分組(group by) + 聚合函數篩選(having) + join on(關聯查詢)——第12題

#獲取部門中員工薪水最高相關信息
SELECT
	B.dept_no,
	B.emp_no,
	A.salary AS salary 
FROM
	salaries AS A
	JOIN dept_emp AS B ON A.emp_no = B.emp_no 
WHERE
	A.to_date = '9999-01-01' 
	AND B.to_date = '9999-01-01' 
GROUP BY
	B.dept_no 
HAVING
	A.salary = max( A.salary );

自連接——第19題

#查看薪水第二多的員工信息(不使用order by)

#思路一:查詢最大薪水,然後查詢小於最大薪水的薪水值中的最大值
SELECT
	e.emp_no,
	s.salary,
	e.last_name,
	e.first_name 
FROM
	employees e
	JOIN salaries s ON e.emp_no = s.emp_no 
	AND s.to_date = '9999-01-01' 
	AND s.salary = (
	SELECT
		max( salary ) 
	FROM
		salaries 
	WHERE
		salary < ( SELECT max( salary ) FROM salaries WHERE to_date = '9999-01-01' ) 
	AND to_date = '9999-01-01' 
	)

#思路二:對薪水錶自連接,使用s1.salary <= s2.salary查詢出第二多薪水
SELECT
	e.emp_no,
	s.salary,
	e.last_name,
	e.first_name 
FROM
	employees e
	JOIN salaries s ON e.emp_no = s.emp_no 
	AND s.to_date = '9999-01-01' 
	AND s.salary = (
	SELECT
		s1.salary 
	FROM
		salaries s1
		JOIN salaries s2 ON s1.salary <= s2.salary 
		AND s1.to_date = '9999-01-01' 
		AND s2.to_date = '9999-01-01' 
	GROUP BY
		s1.salary 
	HAVING
	count( DISTINCT s2.salary ) = 2 
	)

使用同一個表兩次、解題思路——第24題

#獲取員工其當前的薪水比其manager當前薪水還高的相關信息

#1.先查出員工的工號和薪水:
SELECT
	de.emp_no,
	sa.salary 
FROM
	dept_emp de,
	salaries sa 
WHERE
	de.emp_no = sa.emp_no 
	AND de.to_date = '9999-01-01' 
	AND sa.to_date = '9999-01-01'

#2.再查出經理的工號和薪水:
SELECT
	dm.emp_no manager_no,
	sal.salary 
FROM
	dept_manager dm,
	salaries sal 
WHERE
	dm.emp_no = sal.emp_no 
	AND dm.to_date = '9999-01-01' 
	AND sal.to_date = '9999-01-01'

#3.最後就是組合,看準條件,做好條件銜接
SELECT
	de.emp_no,
	dm.emp_no manager_no,
	sa.salary emp_salary,
	sal.salary manager_salary 
FROM
	dept_emp de,
	salaries sa,
	dept_manager dm,
	salaries sal 
WHERE
	de.emp_no = sa.emp_no 
	AND dm.emp_no = sal.emp_no 
	AND de.dept_no = dm.dept_no 
	AND de.to_date = '9999-01-01' 
	AND sa.to_date = '9999-01-01' 
	AND dm.to_date = '9999-01-01' 
	AND sal.to_date = '9999-01-01' 
	AND sa.salary > sal.salary

對於測試工程師而言,在面試中,應該不會遇到特別難的SQL題目。且工作中,對於SQL要求不會特別高,重點在於根據需求梳理好思路,然後編寫相關的SQL,對於其SQL的效率不回特別追求。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章