為什么要學習數據庫
以前在程序中存儲數據是一個變量,對象;數據都存儲在內存中,程序運行結束后就銷毀。
后來學習IO之后,將數據存儲在文件中,做到持久存儲,但是使用不方便。
學習專業的數據存儲軟件——數據庫軟件
數據庫概述
數據庫(DataBase/db)為了方便數據的存儲和管理,它將數據按照特定的規則存儲在磁盤上,就是一個存儲數據的倉庫
相關概念:
DB:數據庫;存儲數據的容器,他保存了一系列有組織的數據
DBMS:數據庫管理系統;又稱為數據庫軟件或數據庫產品,用于創建或管理DB。
常見的數據庫產品:
國外
-
MySQL 開源版本,也有付費版
-
Oracle數據庫 付費版
-
SQL Server(微軟)
-
DB2 (IBM)
國內(一般是政府項目使用)
-
南大通用GBASE: 天津南大通用數據技術股份有限公司
-
達夢:武漢達夢數據庫股份有限公司
-
人大金倉:北京人大金倉信息技術股份有限公司
-
神通:神舟通用公司
Mysql數據庫
MySQL是一個關系型數據庫管理系統,具有快速、可靠和易于使用的特點,支持多種操作系統,支持多種編程語言連接。
關系型數據庫?
以數據表為單位,表與表之間存在關聯關系
非關系型數據庫 redis:緩存(key:value)
結構化查詢語言(Structured Query Language)簡稱SQL,是一種特殊目的的編程語言,是一種數據庫查詢和程序設計語言,用于存取數據以及查詢、更新和管理關系數據庫系統。
三種語言
在sql語言中根據操作不同,又分為不同類型的sql語句:
DDL
DDL(數據定義語言):用于創建和修改數據庫表結構的語言。
創建刪除數據庫
-- 創建數據庫,并設置字符集編碼 并判斷數據庫是否存在
CREATE DATABASE IF NOT EXISTS test CHARSET utf8;
-- 刪除數據庫
DROP DATABASE test;
-- mysql數據庫一旦創建不能修改,只能修改字符集編碼
ALTER DATABASE test CHARSET gbk
創建數據庫表
/*表 表名列 特定信息 姓名、性別...行 數據 ? ? 張三 男
創建表的步驟確定表名:學生信息--學生表確定列名:學生的具體信息 姓名、性別、生日...列的數據類型:字符串型:char(n) 長度為n的定長字符串varchar(n) 最大長度為n的變長字符串日期時間類型:date 日期--年 月 日datetime 時間--年 月 日 時分秒數值:整數TINYINT 一個字節SAMALLINT 兩個字節MEDIUMINT 三個字節INT 四個字節BIGINT 八個字節浮點數decimal(M,D) M表示總長,D表示小數點后幾位TEXT列字符字符串 長文本類型
*/
-- 學生表 學號,姓名,性別,生日,電話,地址,身高,注冊時間
CREATE TABLE student(num INT,name VARCHAR(10),gender CHAR(1),birthday DATE,phone CHAR(11),address VARCHAR(30),height DECIMAL(3,2),reg_time DATETIME
)
?
-- 刪除表
DROP TABLE student
?
-- 創建表,并為列添加約束
/*學號 唯一,不能為空,而且只能有一個學號;可以添加主鍵約束(唯一不能重復,不能為空,一個表中只能有一個主鍵約束)PRIMARY KEY 設置主鍵AUTO_INCREMENT 設置主鍵列自動增長,只修飾主鍵列,而且為整數NOT NULL 不能為空約束 可添加到多個列UNIQUE 唯一約束 可添加到多個列DEFAULT '默認值' 添加默認值COMMENT '注釋' 添加注釋姓名,性別,生日,電話,地址,身高,注冊時間
*/
CREATE TABLE student(num INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(10) NOT NULL,gender CHAR(1) NOT NULL,birthday DATE,phone CHAR(11) NOT NULL UNIQUE,address VARCHAR(30),height DECIMAL(3,2) NOT NULL,reg_time DATETIME
)
?
-- 修改表名
RENAME TABLE student to stu
RENAME TABLE stu to student
?
-- 復制表結構
CREATE TABLE stu LIKE student
?
-- 修改表,添加列
ALTER TABLE student ADD id INT
?
-- 修改表,添加外鍵約束
ALTER TABLE student ADD CONSTRAINT 約束名 FOREIGN KEY(majorid) REFERENCES major(id)
DML
DML:數據操縱語言;常用語句insert,delete,update
-- insert 插入
/*方式1: INSERT INTO 表名(列1,列2……,列n) VALUES(值1,值2…..,值n);方式2: INSERT INTO 表名 set 列名1=值1,..列名n=值n;方式3: INSERT INTO 表名(列1,列2……,列n) VALUES(值1,值2…..,值n),(值1,值2…..,值n);方式4:INSERT INTO 表名(列1,列2……,列n) 查詢語句(查詢的列數與插入列數匹配)
*/
?
INSERT INTO student(NAME,gender,birthday,phone,address,height,reg_time) VALUES('王天樂','女','2004-5-3','2123456789322','漢中',1.75,'2024-5-3')
INSERT INTO student(NAME,gender,birthday,phone,address,height,reg_time) VALUES('Jim','女','2004-5-3','2123456789452','England',1.75,'2024-5-3')
?
INSERT INTO student(NAME,gender,birthday,phone,address,height,reg_time)VALUES('張三','男','2004-5-3','13488404582','漢中',1.75,'2024-5-3'),('李四','女','2004-5-5','13488404552','漢中',1.65,'2024-2-3'),('竇鑫銳','男','2001-5-3','13688404582','漢中',1.35,'2044-5-3')?
INSERT INTO stu(NAME,gender,birthday,phone,address,height,reg_time) SELECT NAME,gender,birthday,phone,address,height,reg_time FROM studentINSERT INTO student SET NAME='王天樂',gender='女',phone='2123456789321'
?
-- update 修改 需要注意條件的準確性,否則修改所有數據
UPDATE student SET address = '竇鑫銳' WHERE num = 1
-- delete 刪除
DELETE FROM student WHERE num=1
DQL
DQL:數據查詢語言查詢是使用頻率最高的一個操作,可以從一個表中查詢數據,也可以從多個表中查詢數據
-- 基本查詢語法
-- select 查詢的列 from 表名 where 條件 排序 數量限制 分組......
-- select 結果處理 from 表名
-- 結果處理
-- 查詢特定的列
SELECT num,NAME,gender FROM student
-- 查詢所有的列,在開發中一般不建議,使用哪些列查詢哪些
SELECT * FROM student
-- sql中+ - * / 只能做算數運算,+不能連接字符串
SELECT num+100,NAME FROM student
-- 去除查詢結果中重復數據,即查詢到所有列都相同
SELECT DISTINCT NAME,gender,birthday FROM student
查詢結果中使用函數
-
單行函數會對查詢的每條記錄進行操作
-
分組函數也稱為聚合函數,統計函數,把多行最終處理為一行
-- 字符函數
-- length():獲取參數值的字節個數
SELECT LENGTH(NAME) FROM student
-- char_length()獲取參數值的字符個數
SELECT CHAR_LENGTH(NAME) FROM student
-- concat(str1,str2,.....):拼接字符串 AS 后面為別名
SELECT num,CONCAT(NAME,':',gender) AS NAME FROM student
-- upper()/lower():將字符串變成大寫/小寫
SELECT UPPER(NAME),LOWER(NAME) FROM student
-- substring(str,pos,length):截取字符串 位置從1開始
SELECT SUBSTRING(NAME,2,3) FROM student
-- instr(str,指定字符):返回子串第一次出現的索引,如果找不到返回0
SELECT INSTR(NAME,'三') FROM student
-- trim(str):去掉字符串前后的空格或子串,trim(指定子串 from 字符串)
SELECT TRIM(NAME) FROM student
SELECT TRIM('張' FROM NAME) FROM student
-- lpad(str,length,填充字符):用指定的字符實現左填充將str填充為指定長度
SELECT LPAD(NAME,5,'a') FROM student
-- rpad(str,length,填充字符):用指定的字符實現右填充將str填充為指定長度
SELECT RPAD(NAME,5,'b') FROM student
-- replace(str,old,new):替換,替換所有的子串
SELECT REPLACE(NAME,'i','I') FROM student
-- 邏輯處理
-- case when 條件 then 結果1 else 結果2 end; 可以有多個when
SELECT NAME,(CASE WHEN height>=1.80 THEN '高個子'WHEN height>=1.50 THEN '正常身高'ELSE '低個子' END) AS height,gender FROM student
-- ifnull(被檢測值,默認值)函數檢測是否為null,如果為null,則返回指定的值,否則返回原本的值
SELECT NAME,IFNULL(adress,'暫未錄入') AS address FROM student
-- if函數:if else的 效果 if(條件,結果1,結果2)
SELECT NAME,IF(height>=1.80,'高個子','正常身高') AS height FROM student
-- 數學函數
-- round(數值,小數位數):四舍五入 不寫小數位數相當于只保留整數
SELECT NAME,ROUND(height,1) FROM student
-- ceil(數值):向上取整,返回>=該參數的最小整數
SELECT NAME,CEIL(height) FROM student
-- floor(數值):向下取整,返回<=該參數的最大整數
SELECT NAME,FLOOR(height) FROM student
-- truncate(數值,保留小數的位數):截斷,小數點后截斷到幾位,不會四舍五入
SELECT NAME,TRUNCATE(height,1) FROM student
-- mod(被除數,除數):取余,被除數為正,則為正;被除數為負,則為負
SELECT NAME,MOD(num,3) FROM student
-- rand():獲取隨機數,返回0-1之間的小數
SELECT NAME,RAND() FROM student
-- 日期函數
-- now():返回當前系統日期+時間
SELECT NAME,NOW() FROM student
-- curdate():返回當前系統日期,不包含時間
SELECT NAME,CURDATE() FROM student
-- curtime():返回當前時間,不包含日期
SELECT NAME,CURTIME() FROM student
-- 可以獲取指定的部分,年、月、日、小時、分鐘、秒YEAR(日期列),MONTH(日期列),DAY(日期列) ,HOUR(日期列) ,MINUTE(日期列)SECOND(日期列)
SELECT NAME,YEAR(reg_time),MONTH(reg_time),DAY(reg_time) FROM student
-- str_to_date(字符串格式日期,格式):將日期格式的字符轉換成指定格式的日期
SELECT STR_TO_DATE('2001-2-6','%Y-%m') FROM student
-- date_format(日期列,格式):將日期轉換成字符串
SELECT DATE_FORMAT(birthday,'%y-%m') FROM student
-- datediff(big,small):返回兩個日期相差的天數
SELECT DATEDIFF(CURDATE(),birthday) FROM student
-- 分組函數/聚合函數、統計函數
-- sum,avg一般處理數值類型的值,max,min,count可處理任意類型的值
-- sum(列名)求和
SELECT SUM(height) FROM student
-- avg(列名)平均值
SELECT AVG(height) FROM student
-- max(列名)最大值
SELECT MAX(height) FROM student
-- min(列名)最小值
SELECT MIN(height) FROM student
-- 計數count(*)、count(1)、count(列名),列的值為空不統計,推薦使用第一個
SELECT COUNT(*) FROM student
-- 條件查詢 select 結果列 from 表名 where 條件SELECT * FROM student WHERE num=1
-- and 必須滿足所有條件
SELECT * FROM student WHERE gender='男' AND height>=1.70 AND address='漢中'
-- or 滿足一個條件即可
SELECT * FROM student WHERE gender='男' OR height>=1.70-- 不等于 != / <>
SELECT * FROM student WHERE gender!='男'
SELECT * FROM student WHERE gender<>'男'-- 模糊查詢 LIKE 字符 %字符% 通配符
SELECT * FROM student WHERE NAME LIKE '張%'
SELECT * FROM student WHERE NAME LIKE '%三%'-- between and 兩者之間,包含臨界值
SELECT * FROM student WHERE height BETWEEN 1.70 AND 2.0-- in 判斷某字段的值是否屬于in列表中的某一項
SELECT * FROM student WHERE height IN(1.75,1.85,1.95)
-- not 取非
SELECT * FROM student WHERE height NOT IN(1.75,1.85,1.95)-- is (not) null 為(非)空
SELECT * FROM student WHERE address IS NULL
SELECT * FROM student WHERE address IS NOT NULL
-- union 合并多個查詢結果,可以去除重復項
SELECT num,NAME,gender FROM student WHERE gender='男'
UNION
SELECT num,NAME,gender FROM student WHERE height>1.60
-- union all 合并多個查詢結果,但是不去重
SELECT num,NAME,gender FROM student WHERE gender='男'
UNION ALL
SELECT num,NAME,gender FROM student WHERE height=1.75
-- 排序
-- order by 排序列 ASC/DESC ASC代表的是升序,DESC代表的是降序,如果不寫,默認是升序
SELECT * FROM student ORDER BY height
SELECT * FROM student ORDER BY height ASC
SELECT * FROM student ORDER BY height DESC
?
-- 多個條件排序
SELECT * FROM student ORDER BY height DESC,birthday ASC
-- 什么排序都不寫默認按照主鍵升序排列
SELECT * FROM student
-- 數量限制 limit 開始位置(開始位置為0),查詢的數量 實際使用場景為數據分頁顯示,一次只查詢一部分數據,提高查詢效率
SELECT * FROM student LIMIT 0,2
SELECT * FROM student LIMIT 2,2
SELECT * FROM student LIMIT 4,2
-- limit 在sql語句的末尾出現
-- 分組查詢 在分組函數中也可以使用分組函數來進行相應的操作
-- 將某類數據分到一個組中進行處理,例如性別查詢
-- 查詢男生,女生各有多少人,按照性別分組
-- GROUP BY 分組條件(列名) 用誰分組誰就可以出現在結果中
SELECT COUNT(*),gender FROM student GROUP BY gender
-- 統計每年出生的人數
SELECT COUNT(*)AS number,YEAR(birthday) FROM student GROUP BY YEAR(birthday)
SELECT COUNT(*)AS number,DATE_FORMAT(birthday,'%Y')AS YEAR FROM student GROUP BY DATE_FORMAT(birthday,'%Y')
-- 分組統計姓名,查詢哪些姓名重復
-- where 是對原始表中的數據進行過濾
-- HAVING在GROUP BY后面使用,可以直接對分組后的數據進行查詢
SELECT * FROM (SELECT COUNT(*)AS number,NAME FROM student GROUP BY NAME)AS t WHERE t.number>1
SELECT COUNT(*)AS number,NAME FROM student GROUP BY NAME HAVING number>1
多表設計_關聯查詢
數據庫設計范式,好的數據庫設計,事半功倍,不會有歧義
第一范式
第一范式是最基本的范式(確保每列保持原子性)。如果數據庫表中的所有字段值都是不可分解的原子值,就說明該數據庫表滿足了第一范式。
第二范式
簡單的來說就是要有主鍵;也就是要求其他字段都依賴于主鍵
通過主鍵可以精確的定位到某一行的數據
第三范式
不用的信息可以放在不同的表中,如果兩張表有關系的話,只需要在另一張表中放另一張表的主鍵進行關聯,關聯表中其他的非主鍵信息就不需要了。
外鍵
外鍵:引用另外一個數據表的某條記錄。
外鍵列類型與主鍵列類型保持一致
數據表之間的關聯/引用關系是依靠具體的主鍵(primary key)和外鍵(foreign key)建立起來的.
-
當主表中沒有對應的記錄時,不能將記錄添加到從表
-
不能更改主表中的值而導致從表中的記錄孤立
-
從表存在與主表對應的記錄,不能從主表中刪除該行
-
刪除主表前,先刪從表
關聯查詢
關聯查詢也稱多表查詢
-- 查詢學生信息 學號,姓名,性別,生日,專業
-- 如果不佳任何關聯條件,會導致出現笛卡爾乘積現象
SELECT * FROM student,major-- 內連接,只把滿足條件的篩選出來
SELECT * FROM student,major WHERE majorid=id
SELECT * FROM student s INNER JOIN major m ON s.majorid=m.id-- 外連接,
-- 左外連接 把左邊表中所有數據查詢出來,右邊表中只會查詢滿足條件的
SELECT * FROM student s LEFT JOIN major m ON s.majorid=m.id-- 右外連接 把右邊表中所有數據查詢出來,左邊表中只會查詢滿足條件的
SELECT * FROM student s RIGHT JOIN major m ON s.majorid=m.id-- 統計每個專業的學生
SELECT COUNT(s.num),m.name FROM student s RIGHT JOIN major m ON s.majorid=m.id GROUP BY m.name-- GROUP_CONCAT() 把同一組中,多個課程名稱連接起來
-- 查詢學生選課
SELECTs.num,s.name,s.gender,m.name,GROUP_CONCAT(c.name) cnameFROM student s LEFT JOIN major m ON s.majorid = m.midLEFT JOIN student_course sc ON s.num = sc.student_numLEFT JOIN course c ON c.id = sc.courseidGROUP BY s.num,s.name,s.gender,m.name
-- 自連接
SELECT * FROM AREA ap JOIN AREA ac ON ap.id = ac.pid JOIN AREA ax ON ac.id = ax.pid
-- 子查詢 在一個查詢語句中又出現了查詢語句
-- 子查詢可以出現在from 或者where后面
-- from之后稱為表子查詢(結果一般魏多行多列)把查詢結果當作一張表
-- where 標量子查詢(結果集只有一行一列)
-- 列子查詢(結果集只有一列多行)
-- 查詢身高最高的學生 標量子查詢
SELECT * from student WHERE height=(SELECT MAX(height) FROM student)
-- 列子查詢
SELECT * from student WHERE height IN(SELECT height FROM student WHERE height=1.65 OR height=1.75)
-- 查詢姓名重復 表子查詢
SELECT * FROM (SELECT COUNT(*)AS number,NAME FROM student GROUP BY NAME)AS t WHERE t.number>1