我的GitHub | 我的博客 | 我的微信 | 我的郵箱 |
---|---|---|---|
baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
目錄
數據庫管理系統操作
查看版本號
-- 登錄前
mysql -V
mysql --help | grep Ver
-- 登錄后
select version();
status;
啟動及關閉服務
-- 啟動服務
net start mysql
mysqld --console
-- 關閉服務
net stop mysql
mysqladmin -uroot shudown
登錄及退出
-- 登錄
mysql [-D 所選擇的數據庫名] [-h 主機名] -u 用戶名 -p
mysql -u root -p
-- 退出
exit;
quit;
\q;
其他
-- 登錄前查看本地 MySQL 服務是否啟動
netstat -an|find "3306"
-- 登錄后查看MySQL端口號
show global variables like 'port';
數據庫操作
創建數據庫 create
create database db_name;
create database db_name character set gbk;
-- 創建一個使用字符集並帶校對規則的數據庫
create database db_name character set utf-8 collate utf8_bin;
查看數據庫 show/select
show databases;
-- 查看創建數據庫時的定義信息
show create database db_name;
-- 查看當前所選的數據庫
select database();
其他操作 alter/drop/use
-- 修改數據庫字符編碼
alter database db_name character set utf8;
-- 刪除數據庫
drop database db_name;
-- 進入(切換)數據庫,對於表的操作需要先進入庫
use db_name;
數據庫-表操作
MySQL有三大類數據類型,分別為數字、日期/時間、字符串,這三大類中又更細致的划分了許多子類型:
- 數字類型
- 整數: tinyint、smallint、mediumint、int、bigint
取值范圍如果加了unsigned,代表無符號,則可存儲的最大值翻倍
int(m) 里的 m 是表示 SELECT 查詢結果集中的顯示寬度,並不影響實際的取值范圍 - 浮點數: float、double、real、decimal
- 整數: tinyint、smallint、mediumint、int、bigint
- 日期和時間: date、time、datetime、timestamp、year
- 字符串類型
- 字符串: char、varchar
- 文本: text、tinytext、mediumtext、longtext
- 二進制: blob、tinyblob、mediumblob、longblob
創建表 create
create table if not exists `user_accounts` (
`id` int(100) unsigned NOT NULL AUTO_INCREMENT primary key,
`password` varchar(32) NOT NULL DEFAULT '' COMMENT '用戶密碼',
`reset_password` tinyint(32) NOT NULL DEFAULT 0 COMMENT '用戶類型:0-不需要重置密碼;1-需要重置密碼',
`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手機',
`create_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
`update_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
-- 創建唯一索引,不允許重復
UNIQUE INDEX idx_user_mobile(`mobile`)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8
COMMENT='用戶表信息';
數據類型的屬性解釋
NULL
:數據列可包含NULL值NOT NULL
:數據列不允許包含NULL值DEFAULT
:默認值PRIMARY KEY
:主鍵AUTO_INCREMENT
:自動遞增,適用於整數類型UNSIGNED
:是指數值類型只能為正數(即無符號的)CHARACTER SET name
:指定一個字符集COMMENT
:對表或者字段說明
查看表 show/desc
-- 查看當前數據庫中所有表
show tables
-- 查看當前數據庫表建表語句
show create table tableName
-- 查看表結構,也可用全稱describe
desc tableName
刪除表 delete/truncate/drop
-- 清空表中的數據,不刪除表;可以回退,可以帶 where 條件的刪除
delete from tableName;
-- 刪除表中的所有數據,不刪除表;無法回退,默認所有的表內容都刪除,刪除速度比delete快
truncate table tableName;
-- 刪除整張表
drop table tableName;
DROP TABLE IF EXISTS tableName;
其他操作 rename
-- 重命名表
alter table oldName rename newName;
rename table oldName to newName;
-- 修改表的字符集
alter table tableName character set gbk;
數據庫-表-列操作 alter
添加列 add
-- 語法:alter table 表名 add [column] 列名 列數據類型 [after 插入位置];
alter table students add address char(60);
alter table students add column birthday date after age;
alter table students add `weeks` varchar(5) not null default "" after `number`;
修改列 change/modify
-- 語法:alter table 表名 change 列名稱 列新名稱 新數據類型;
alter table students change tel telphone char(13) default "-";
alter table students change name name char(16) not null;
-- 修改 COMMENT 前面必須得有類型屬性
alter table students change name name char(16) COMMENT '這里是名字';
-- change用於修改列名字,需要重建表;僅修改列屬性的時候建議使用modify,不需要重建表
alter table meeting modify `weeks` varchar(20) NOT NULL DEFAULT '' COMMENT '開放日期';
alter table meeting modify `id` INT NOT NULL;
-- FIRST 表示放在第一列的位置
alter table `user` modify COLUMN `id` varchar(50) NOT NULL FIRST;
刪除列 drop
-- 語法:alter table 表名 drop 列名稱;
alter table students drop birthday;
數據庫-表-記錄操作
插入記錄 insert into
-- 語法:INSERT INTO 表名稱 [(列1, 列2,...)] VALUES (值1, 值2,...)
INSERT INTO Persons (LastName, Address) VALUES ('JSLite', 'shanghai');
INSERT INTO meeting SET a=1,b=2;
-- 如果要插入所有字段可以省寫列列表,直接按表中字段順序寫值列表
insert into employee values (1,'ceo',800,'公司老大'), (2,'cto',300,'技術老大');
-- 插入一條數據,如果已存在就更新address和update_at字段,字符和日期型數據應包含在單引號中
INSERT INTO students (id,address,update_at) VALUES (3,'gz','2020-10-17') ON DUPLICATE KEY UPDATE id=VALUES(id), address=VALUES(address), update_at='2020-10-18';
-- 將一個表的數據插入到另外一個表:INSERT INTO 目標表 (列1,列2...) SELECT 字段1, 字段2, ... FROM 來源表;
INSERT INTO orders (num, title) SELECT m.user_id, m.title FROM meeting m where m.id=1;
更新記錄 update set
-- 語法:UPDATE 表名稱 SET 列名稱 = 新值 [WHERE]
UPDATE orders set title='新標題' WHERE id=1;
-- WHERE子句指定應更新哪些行。如沒有WHERE子句,則更新所有的行
update employee set salary = 3000 where name='張飛';
update employee set salary = 4000,job='ccc' where name='關羽';
update employee set salary = salary + 1000 where name='劉備';
update employee set salary = 5000;
-- 設置字段的值為另一個結果取出來的字段
update user set name = (select name from user1 where user1.id = 1 ) where id = (select id from user2 where user2 .name='小蘇');
刪除記錄 delete from
-- 語法:DELETE FROM 表名稱 [WHERE]
DELETE FROM Person WHERE LastName = 'JSLite'
DELETE from meeting where id in (2,3);
-- 如果不使用where子句,將刪除表中所有數據(不刪除表本身)
DELETE FROM table_name
DELETE * FROM table_name
-- 使用truncate刪除表中記錄和使用delete有所不同,參看mysql文檔
truncate table employee;
查找記錄 select from
-- 語法:SELECT 列名稱 FROM 表名稱 [WHERE]
select name,english from exam;
select * from exam;
-- 只拉一條數據(據說limit能優化性能)
SELECT * FROM users where id=3 limit 1
-- 過濾重復數據
select distinct english from exam;
-- 在所有學生數學分數上加10分顯示
select name, math+10 from exam;
-- 使用別名表示學生總分(as可以省略),統計每個學生的總分
select name as 姓名 ,english+math+chinese 總成績 from exam;
SELECT s.id from station s WHERE id in (13,14) and id not in (4);
-- 結果集顯示 Persons表的 LastName、FirstName字段,Orders表的OrderNo字段
SELECT p.LastName, p.FirstName, o.OrderNo FROM Persons p, Orders o WHERE p.Id_P = o.Id_P
-- 中英文混合排序最簡單的辦法;ci是 case insensitive, 即 “大小寫不敏感”
SELECT tag, COUNT(tag) from news GROUP BY tag order by convert(tag using gbk) collate gbk_chinese_ci;
SELECT tag, COUNT(tag) from news GROUP BY tag order by convert(tag using utf8) collate utf8_unicode_ci;
數據庫-表-索引操作
索引的建立對於 MySQL 的高效運行是很重要的,索引可以大大提高 MySQL 的檢索速度。
索引分單列索引
和組合索引
:
- 單列索引:即一個索引只包含單個列,一個表可以有多個單列索引,但這不是組合索引
- 組合索引:即一個索引包含多個列
建立索引會占用磁盤空間的索引文件。實際上,索引也是一張表,該表保存了主鍵與索引字段
,並指向實體表的記錄
。
索引也有它的缺點:雖然索引大大提高了查詢速度
,同時卻會降低更新表的速度
,因為更新表時,MySQL 不僅要保存數據,還要保存索引文件。
建立索引的時機
在WHERE
和JOIN
中出現的列需要建立索引,但也不完全如此:
- MySQL 只對
<
<=
=
>
>=
BETWEEN
IN
使用索引 - 某些時候的
LIKE
也會使用索引 - 在LIKE以通配符
%
和_
作為 開頭 查詢時,MySQL 不會使用索引
普通索引 index
普通索引的索引值可出現多次
-- 方式一,創建表的時候直接指定索引,語法:INDEX [indexName] (columnName[(length)])
CREATE TABLE tableName(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` CHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`id`),
INDEX indexName (title(8))
-- length:BLOB和TEXT類型必須指定 length;CHAR、VARCHAR類型時,length 可以小於字段實際長度
-- 【INDEX indexName (title)】:可忽略 length,但是不能忽略 columnName 外的小括號
-- 【INDEX (title)】:忽略 indexName 時,indexName 取 columnName 的值
);
-- 方式二,修改表結構方式添加索引,語法:ALTER table tableName ADD INDEX indexName(columnName[(length)])
ALTER table tableName ADD INDEX indexName(title(6))
-- 方式三,直接創建索引,語法:CREATE INDEX indexName ON tableName (columnName[(length)])
CREATE INDEX indexName ON tableName (title(6))
唯一索引 unique
唯一索引的值必須唯一,但允許有空值;如果是組合索引,則列值的組合必須唯一。
CREATE TABLE tableName(
...,
-- 方式一:UNIQUE INDEX [indexName] (columnName[(length)])
-- UNIQUE [indexName] (columnName[(length)])
);
-- 方式二:ALTER table tableName ADD INDEX indexName(columnName[(length)])
-- 方式三:CREATE UNIQUE INDEX indexName ON tableName (columnName[(length)])
主鍵索引 primary key
主鍵索引需要確保索引值必須是唯一的,且不能為NULL。
CREATE TABLE tableName (
-- AUTO_INCREMENT:自動增長;NOT NULL:非空約束
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
-- 方式一:創建表的時候指定,主鍵名indexName其實就是【PRIMARY】
PRIMARY KEY (`id`)
)
-- 方式二:ALTER table tableName ADD PRIMARY KEY(columnName[(length)])
ALTER TABLE tableName ADD PRIMARY key (id);
全文索引 fulltext
-- ALTER TABLE tableName ADD FULLTEXT indexName (columnName[(length)])
-- 給 user 表中的 description 字段添加全文索引
ALTER TABLE user ADD FULLTEXT (description);
刪除索引 drop
-- 刪除主鍵時只需指定 PRIMARY KEY,刪除其他索引時,須指定索引名
DROP INDEX indexName ON tableName;
ALTER TABLE tableName DROP INDEX indexName;
ALTER TABLE tableName DROP PRIMARY KEY;
多列索引
-- ALTER TABLE tableName ADD INDEX indexName (column1, column2, column3)
ALTER TABLE user ADD INDEX name_city_age (name(10),city,age);
顯示索引信息
-- 列出表中的相關的索引信息
SHOW INDEX FROM tableName;
幾個關鍵字
過濾 where
select * from exam where name='張飛';
select * from exam where name like '張%';
select * from exam where math > 90;
-- IN 操作符允許我們在 WHERE 子句中規定多個值
select * from exam where math in(75,76,77);
select * from exam where math between 80 and 100;
select * from exam where math > 70 and chinese > 80;
select name 姓名, math+english+chinese 總分 from exam where math+english+chinese > 230;
排序 order by
ORDER BY 語句用於根據指定的列對結果集進行排序
- DESC - 按照降序對記錄進行排序
- ASC - 按照順序(升序)對記錄進行排序(默認)
-- Company在表Orders中為字母,則會以字母順序(升序)顯示公司名稱;后面跟上 DESC 則為降序顯示
SELECT Company, OrderNumber FROM Orders ORDER BY Company
SELECT Company, OrderNumber FROM Orders ORDER BY Company DESC
-- 首先根據Company以降序顯示,然后根據OrderNumber以順序顯示
SELECT Company, OrderNumber FROM Orders ORDER BY Company DESC, OrderNumber ASC
-- 對姓張的學生根據總成績按從高到低的順序輸出
select name 姓名,chinese+math+english 總成績 from exam where name like '張%' order by 總成績 desc;
分組查詢 group by
-- 對訂單表中商品歸類后,顯示每一類商品的總價
select product,sum(price) from orders group by product;
-- 查詢購買了幾類商品,並且每類總價大於100的商品
select product 商品名,sum(price)商品總價 from orders group by product having sum(price)>100;
-- 查詢單價小於100而總價大於150的商品的名稱
select product from orders where price<100 group by product having sum(price)>150;
邏輯運算 and or not
SELECT * FROM Persons WHERE FirstName='Thomas' AND LastName='Carter';
DELETE from meeting where id in (2,3) and user_id in (5,6);
SELECT * FROM Persons WHERE firstname='Thomas' OR lastname='Carter'
-- NOT 操作符總是與其他操作符一起使用,用在要過濾的前面。
SELECT vend_id, prod_name FROM Products WHERE NOT vend_id = 'DLL01' ORDER BY prod_name;
合並結果集 union
合並兩個或多個 SELECT 語句的結果集
-- 列出所有在中國表和美國表的不同的雇員名
SELECT E_Name FROM Employees_China UNION SELECT E_Name FROM Employees_USA
-- 列出 meeting 表中的 pic_url,station 表中的 number_station 別名設置成 pic_url 避免字段不一樣報錯
-- 按更新時間排序
SELECT id,pic_url FROM meeting UNION ALL SELECT id,number_station AS pic_url FROM station ORDER BY update_at;
-- 通過 UNION 語法同時查詢了 products 表 和 comments 表的總記錄數,並且按照 count 排序
SELECT 'product' AS type, count(*) as count FROM `products` union select 'comment' as type, count(*) as count FROM `comments` order by count;
重命名 as
-- 重命名列名或者表名,語法:select columnName as 列昵稱 from tableName as 表昵稱
-- 把Employee表命名為 emp,命名一個表之后,你可以在下面用 emp 代替 Employee
SELECT * FROM Employee AS emp
-- 列出表 Orders 字段 OrderPrice 列最大值,結果集列不顯示 OrderPrice 顯示 LargestOrderPrice
SELECT MAX(OrderPrice) AS LargestOrderPrice FROM Orders
-- 顯示表 users_profile 中的 name 列
SELECT t.name from (SELECT * from users_profile a) AS t;
聚合函數
統計個數 count
-- 語法:SELECT COUNT("字段名") FROM "表格名"
SELECT COUNT (Store_Name) FROM Store WHERE Store_Name IS NOT NULL;
-- 統計一個班級共有多少學生
select count(*) from exam;
select count(*) from exam where math > 70;
select count('什么有效的值都可以') as totals from exam;
最值 max/min
-- MAX 函數返回一列中的最大值,NULL 值不包括在計算中
SELECT MAX(OrderPrice) AS LargestOrderPrice FROM Orders
select max(ifnull(chinese,0) + ifnull(english,0) + ifnull(math,0)) from exam;
求和 sum
-- 將符合條件的記錄的指定列進行求和操作
select sum(math) from exam;
select sum(math),sum(math)/count(*) 平均分 from exam;
-- sum僅對數值起作用,否則會報錯;計算時,只要有null參與計算,整個計算結果都是null;可以用ifnull處理
select sum(ifnull(chinese,0)+ifnull(english,0)+ifnull(math,0)) from exam;
平均值 avg
-- 計算符合條件的記錄的指定列的值的平均值
select avg(math) from exam;
select avg(ifnull(chinese,0) + ifnull(english,0) + ifnull(math,0)) from exam;
多表設計與多表查詢
外鍵約束 foreign key
表是用來保存現實生活中的數據的,而現實生活中數據和數據之間往往具有一定的關系,我們在使用表來存儲數據時,可以明確的聲明表和表之前的依賴關系
,命令數據庫來幫我們維護這種關系,像這種約束就叫做外鍵約束
。
create table dept(
id int primary key auto_increment,
name varchar(20)
);
create table emp(
id int primary key auto_increment,
name varchar(20),
dept_id int,
-- 定義外鍵約束:foreign key(本表的列名) references 引用的表名(引用的表中的列名)
foreign key(dept_id) references dept(id)
);
多表設計
不同場景下的多表設計思路:
- 一對一:在任意一方保存另一方的主鍵作為外鍵
- 一對多:在
多的一方
保存一的一方
的主鍵做為外鍵 - 多對多:創建
第三方關系表
保存兩張表的主鍵作為外鍵,保存他們對應關系
多表查詢 join
笛卡爾積查詢
將兩張表的記錄進行一個相乘
的操作查詢出來的結果就是笛卡爾積查詢
如果左表有 n 條記錄,右表有 m 條記錄,笛卡爾積查詢出有n*m
條記錄,其中往往包含了很多錯誤的數據,所以這種查詢方式並不常用。
select * from dept,emp;
內連接查詢 inner
-- 查詢的是左邊表和右邊表都能找到對應記錄的記錄
select * from dept,emp where dept.id = emp.dept_id;
select * from dept inner join emp on dept.id=emp.dept_id;
左/右外連接查詢 left/right
-- 左外連接查詢:在內連接的基礎上,增加左邊表有而右邊表沒有的記錄
select * from dept left join emp on dept.id=emp.dept_id;
-- 右外連接查詢:在內連接的基礎上,增加右邊表有而左邊表沒有的記錄
select * from dept right join emp on dept.id=emp.dept_id;
全外連接 union
-- 全外連接查詢:在內連接的基礎上,增加左邊表有而右邊表沒有的記錄,和右邊表有而左表表沒有的記錄
select * from dept full join emp on dept.id=emp.dept_id;
-- mysql 不支持全外連接,我們可以使用 union 關鍵字模擬全外連接
select * from dept left join emp on dept.id = emp.dept_id
union
select * from dept right join emp on dept.id = emp.dept_id;
多表查詢實例
創建表a
create table a(id int primary key,job varchar(20));
insert into a values(1,'AA'), (2,'BB'), (3,'CC');
select * from a;
創建表b
create table b(id int ,name varchar(20) ,foreign key(id) references a(id));
insert into b values(1,'bqt'), (2,'bqt2'), (2,'bqt3');
select * from b;
PS:
被參照的a(id)必須定義為unique才可以被參照,否則報錯(邏輯錯誤)。
插入數據的id必須在被參照的表中已經存在,否則報錯(邏輯錯誤)。
笛卡爾積查詢
select * from a,b;
內連接查詢
select * from a,b where a.id = b.id;
select * from a inner join b on a.id=b.id;
左外連接查詢
select * from a left join b on a.id=b.id;
右外連接查詢
select * from a right join b on a.id=b.id;
PS:由於右邊表參照左邊表,所以不存在右邊表有而左邊表沒有的記錄。
全外連接查詢
select * from a left join b on a.id = b.id
union
select * from a right join b on a.id = b.id;
2020-04-07