SQL基礎
數據類型
數值類型
tinyint : -128~127
int :-2^31~2^31-1
說明:手機號是無法存儲到int的。一般是使用char類型來存儲收集號
字符類型
char(11) :
定長 的字符串類型,在存儲字符串時,最大字符長度11個,立即分配11個字符長度的存儲空間,如果存不滿,空格填充。
varchar(11):
變長的字符串類型看,最大字符長度11個。在存儲字符串時,自動判斷字符長度,按需分配存儲空間。
enum('bj','tj','sh'):
枚舉類型,比較適合於將來此列的值是固定範圍內的特點,可以使用enum,可以很大程度的優化我們的索引結構。
時間類型
DATETIME
範圍爲從 1000-01-01 00:00:00.000000 至 9999-12-31 23:59:59.999999。
TIMESTAMP
1970-01-01 00:00:00.000000 至 2038-01-19 03:14:07.999999。
timestamp會受到時區的影響
二進制類型
屬性
列屬性
約束
約束(一般建表時添加):
**primary key** :主鍵約束
設置爲主鍵的列,此列的值必須非空且唯一,主鍵在一個表中只能有一個,但是可以有多個列一起構成。
**not null** :非空約束
列值不能爲空,也是表設計的規範,儘可能將所有的列設置爲非空。可以設置默認值爲0
**unique key** :唯一鍵
列值不能重複
**unsigned** :無符號
針對數字列,非負數。
其他屬性:
**key** :索引
可以在某列上建立索引,來優化查詢,一般是根據需要後添加
**default** :默認值
列中,沒有錄入值時,會自動使用default的值填充
**auto_increment**:自增長
針對數字列,順序的自動填充數據(默認是從1開始,將來可以設定起始點和偏移量)
**comment ** : 註釋
表屬性
存儲引擎:
InnoDB(默認的)
字符集和排序規則:
utf8
utf8mb4
DDL 數據定義語言
庫定義
1.創建數據庫
create database school;
create schema sch;
show charset;
show collation;
CREATE DATABASE test CHARSET utf8;
create database xyz charset utf8mb4 collate utf8mb4_bin;
建庫規範:
1.庫名不能有大寫字母
2.建庫要加字符集
3.庫名不能有數字開頭
4. 庫名要和業務相關
建庫標準語句
mysql> create database db charset utf8mb4;
mysql> show create database xuexiao;
2.刪除(生產中禁止使用)
mysql> drop database oldboy;
3.修改
SHOW CREATE DATABASE school;
ALTER DATABASE school CHARSET utf8;
注意:修改字符集,修改後的字符集一定是原字符集的嚴格超集
4.查詢
show databases;
show create database oldboy;
表定義
1.創建
create table stu(
列1 屬性(數據類型、約束、其他屬性) ,
列2 屬性,
列3 屬性
)
USE school;
CREATE TABLE stu(
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '學號',
sname VARCHAR(255) NOT NULL COMMENT '姓名',
sage TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '年齡',
sgender ENUM('m','f','n') NOT NULL DEFAULT 'n' COMMENT '性別' ,
sfz CHAR(18) NOT NULL UNIQUE COMMENT '身份證',
intime TIMESTAMP NOT NULL DEFAULT NOW() COMMENT '入學時間'
) ENGINE=INNODB CHARSET=utf8 COMMENT '學生表';
1. 表名小寫
2. 不能是數字開頭
3. 注意字符集和存儲引擎
4. 表名和業務有關
5. 選擇合適的數據類型
6. 每個列都要有註釋
7. 每個列設置爲非空,無法保證非空,用0來填充。
2.刪除(生產中禁用命令)
drop table t1;
3.修改
1.在stu表中添加qq列
DESC stu;
ALTER TABLE stu ADD qq VARCHAR(20) NOT NULL UNIQUE COMMENT 'qq號';
2.在sname後加微信列
ALTER TABLE stu ADD wechat VARCHAR(64) NOT NULL UNIQUE COMMENT '微信號' AFTER sname ;
3.修改數據類型
ALTER TABLE stu modify qq char(11) NOT NULL UNIQUE COMMENT 'qq號';
4.刪除qq號列
ALTER TABLE stu drop qq
4.表屬性查詢(DQL)
use school
show tables;
desc stu;
show create table stu;
CREATE TABLE ceshi LIKE stu;
DCL 數據控制語言
grant
revoke
DML 數據操作語言
1.insert
--- 最標準的insert語句
INSERT INTO stu(id,sname,sage,sg,sfz,intime)
VALUES
(1,'zs',18,'m','123456',NOW());
SELECT * FROM stu;
--- 省事的寫法
INSERT INTO stu
VALUES
(2,'ls',18,'m','1234567',NOW());
--- 針對性的錄入數據
INSERT INTO stu(sname,sfz)
VALUES ('w5','34445788');
--- 同時錄入多行數據
INSERT INTO stu(sname,sfz)
VALUES
('w55','3444578d8'),
('m6','1212313'),
('aa','123213123123');
SELECT * FROM stu;
2.update
DESC stu;
SELECT * FROM stu;
UPDATE stu SET sname='zhao4' WHERE id=2;
注意:update語句必須要加where。
3.delete
DELETE FROM stu WHERE id=3;
全表刪除:
DELETE FROM stu
truncate table stu;
區別:
delete: DML操作, 是邏輯性質刪除,逐行進行刪除,速度慢.
truncate: DDL操作,對與表段中的數據頁進行清空,速度快.
僞刪除:用update來替代delete,最終保證業務中查不到(select)即可
1.添加狀態列
ALTER TABLE stu ADD state TINYINT NOT NULL DEFAULT 1 ;
SELECT * FROM stu;
2. UPDATE 替代 DELETE
UPDATE stu SET state=0 WHERE id=6;
3. 業務語句查詢
SELECT * FROM stu WHERE state=1;
DQL 數據查詢語言(select)
-- select @@xxx 查看系統參數
SELECT @@port;
SELECT @@basedir;
SELECT @@datadir;
SELECT @@socket;
SELECT @@server_id;
SELECT NOW();
SELECT DATABASE();
SELECT USER();
SELECT CONCAT("hello world");
SELECT CONCAT(USER,"@",HOST) FROM mysql.user;
SELECT GROUP_CONCAT(USER,"@",HOST) FROM mysql.user;
https://dev.mysql.com/doc/refman/5.7/en/func-op-summary-ref.html?tdsourcetag=s_pcqq_aiomsg
1.group by + 常用聚合函數
根據 by後面的條件進行分組,方便統計,by後面跟一個列或多個列
常用聚合函數
**max()** :最大值
**min()** :最小值
**avg()** :平均值
**sum()** :總和
**count()** :個數
group_concat() : 列轉行
例子1:統計世界上每個國家的總人口數.
USE world
SELECT countrycode ,SUM(population) FROM city GROUP BY countrycode;
例子2: 統計中國各個省的總人口數量(練習)
SELECT district,SUM(Population) FROM city WHERE countrycode='chn' GROUP BY district;
例子3:統計世界上每個國家的城市數量(練習)
SELECT countrycode,COUNT(id) FROM city GROUP BY countrycode;
2.having
例子4:統計中國每個省的總人口數,只打印總人口數小於100
SELECT district,SUM(Population)
FROM city
WHERE countrycode='chn'
GROUP BY district
HAVING SUM(Population) < 1000000 ;
3.order by + limit
應用案例
1.查看中國所有的城市,並按人口數進行排序(從大到小)
SELECT * FROM city WHERE countrycode='CHN' ORDER BY population DESC;
2.統計中國各個省的總人口數量,按照總人口從大到小排序
SELECT district AS 省 ,SUM(Population) AS 總人口
FROM city
WHERE countrycode='chn'
GROUP BY district
ORDER BY 總人口 DESC ;
3.統計中國,每個省的總人口,找出總人口大於500w的,並按總人口從大到小排序,只顯示前三名
SELECT district, SUM(population) FROM city
WHERE countrycode='CHN'
GROUP BY district
HAVING SUM(population)>5000000
ORDER BY SUM(population) DESC
LIMIT 3 ;
LIMIT N ,M --->跳過N,顯示一共M行
LIMIT 5,5
SELECT district, SUM(population) FROM city
WHERE countrycode='CHN'
GROUP BY district
HAVING SUM(population)>5000000
ORDER BY SUM(population) DESC
LIMIT 5,5;
4.distinct:去重複
SELECT countrycode FROM city ;
SELECT DISTINCT(countrycode) FROM city ;
5.聯合查詢- union all
-- 中國或美國城市信息
SELECT * FROM city
WHERE countrycode IN ('CHN' ,'USA');
SELECT * FROM city WHERE countrycode='CHN'
UNION ALL
SELECT * FROM city WHERE countrycode='USA'
說明:一般情況下,我們會將 IN 或者 OR 語句 改寫成 UNION ALL,來提高性能
UNION 去重複
UNION ALL 不去重複
6.join 多表連接查詢
案例準備
use school
student :學生表
sno: 學號
sname:學生姓名
sage: 學生年齡
ssex: 學生性別
teacher :教師表
tno: 教師編號
tname:教師名字
course :課程表
cno: 課程編號
cname:課程名字
tno: 教師編號
score :成績表
sno: 學號
cno: 課程編號
score:成績
-- 項目構建
drop database school;
CREATE DATABASE school CHARSET utf8;
USE school
CREATE TABLE student(
sno INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '學號',
sname VARCHAR(20) NOT NULL COMMENT '姓名',
sage TINYINT UNSIGNED NOT NULL COMMENT '年齡',
ssex ENUM('f','m') NOT NULL DEFAULT 'm' COMMENT '性別'
)ENGINE=INNODB CHARSET=utf8;
CREATE TABLE course(
cno INT NOT NULL PRIMARY KEY COMMENT '課程編號',
cname VARCHAR(20) NOT NULL COMMENT '課程名字',
tno INT NOT NULL COMMENT '教師編號'
)ENGINE=INNODB CHARSET utf8;
CREATE TABLE sc (
sno INT NOT NULL COMMENT '學號',
cno INT NOT NULL COMMENT '課程編號',
score INT NOT NULL DEFAULT 0 COMMENT '成績'
)ENGINE=INNODB CHARSET=utf8;
CREATE TABLE teacher(
tno INT NOT NULL PRIMARY KEY COMMENT '教師編號',
tname VARCHAR(20) NOT NULL COMMENT '教師名字'
)ENGINE=INNODB CHARSET utf8;
INSERT INTO student(sno,sname,sage,ssex)
VALUES (1,'zhang3',18,'m');
INSERT INTO student(sno,sname,sage,ssex)
VALUES
(2,'zhang4',18,'m'),
(3,'li4',18,'m'),
(4,'wang5',19,'f');
INSERT INTO student
VALUES
(5,'zh4',18,'m'),
(6,'zhao4',18,'m'),
(7,'ma6',19,'f');
INSERT INTO student(sname,sage,ssex)
VALUES
('oldboy',20,'m'),
('oldgirl',20,'f'),
('oldp',25,'m');
INSERT INTO teacher(tno,tname) VALUES
(101,'oldboy'),
(102,'hesw'),
(103,'oldguo');
DESC course;
INSERT INTO course(cno,cname,tno)
VALUES
(1001,'linux',101),
(1002,'python',102),
(1003,'mysql',103);
DESC sc;
INSERT INTO sc(sno,cno,score)
VALUES
(1,1001,80),
(1,1002,59),
(2,1002,90),
(2,1003,100),
(3,1001,99),
(3,1003,40),
(4,1001,79),
(4,1002,61),
(4,1003,99),
(5,1003,40),
(6,1001,89),
(6,1003,77),
(7,1001,67),
(7,1003,82),
(8,1001,70),
(9,1003,80),
(10,1003,96);
SELECT * FROM student;
SELECT * FROM teacher;
SELECT * FROM course;
SELECT * FROM sc;
語法
查詢張三的家庭住址
SELECT A.name,B.address FROM
A JOIN B
ON A.id=B.id
WHERE A.name='zhangsan'
例子:
1.查詢一下世界上人口數量小於100人的城市名和國家名
SELECT b.name ,a.name ,a.population
FROM city AS a
JOIN country AS b
ON b.code=a.countrycode
WHERE a.Population<100
2.查詢城市shenyang,城市人口,所在國家名(name)及國土面積(SurfaceArea)
SELECT a.name,a.population,b.name ,b.SurfaceArea
FROM city AS a JOIN country AS b
ON a.countrycode=b.code
WHERE a.name='shenyang';
1.別名
列別名,表別名
SELECT
a.Name AS an ,
b.name AS bn ,
b.SurfaceArea AS bs,
a.Population AS bp
FROM city AS a JOIN country AS b
ON a.CountryCode=b.Code
WHERE a.name ='shenyang';
2.多表SQL練習
每位老師所教課程的平均分,並按平均分排序
SELECT te.tname,AVG(sc.score)
FROM teacher AS te
JOIN course AS co
ON te.tno=co.tno
JOIN sc
ON co.cno=sc.cno
GROUP BY te.tname
ORDER BY AVG(sc.score) DESC ;
7.information_schema.tables視圖
每次數據庫啓動,會自動在內存中生成I_S,以視圖的方式存儲數據庫一部分元數據信息視圖。I_S.tables 保存了所有表的數據字典信息
視圖:基於 SQL 語句的結果集的可視化的表,是一個虛擬表,其內容由查詢定義。
可理解爲是 別名
select語句的執行方法,不保存數據本身
I_S中的視圖,保存的就是查詢元數據的方法
MySQL教程之concat以及group_concat的用法
https://baijiahao.baidu.com/s?id=1595349117525189591&wfr=spider&for=pc
DESC information_schema.TABLES ——》 查看某張表的列情況
TABLE_SCHEMA ---->庫名
TABLE_NAME ---->表名
ENGINE ---->引擎
TABLE_ROWS ---->表的行數
AVG_ROW_LENGTH ---->表中行的平均行(字節)
INDEX_LENGTH ---->索引的佔用空間大小(字節)
如果沒有i_s,那麼2. 就會要進入到庫,統計表個數,表名。
假如有100個庫,一個個去弄就很麻煩。 因此利用i_s會方便很多
1.查詢整個數據庫中所有庫和所對應的表信息
SELECT table_schema,GROUP_CONCAT(table_name)
FROM information_schema.tables
GROUP BY table_schema;
這個group_contact 不能多行顯示,直接一列顯示多值
2.統計所有庫下的表個數
SELECT table_schema,COUNT(table_name)
FROM information_schema.TABLES
GROUP BY table_schema;
3.統計每個庫的佔用空間總大小
一張表大小=AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH
select table_schema,sum(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH ) from information_schema.tables group by table_shema;
4.查詢業務數據庫(系統表除外),所有非InnoDB表
select table_schema,table_name from information_schema.tables where engine !='InnoDB' and table_schema not in ('sys','performance_schema','information_schema','mysql');
44.查詢業務數據庫(系統表除外),所有非InnoDB表。將非InnoDB錶轉換爲InnoDB,然後把結果集導入到sql文件(前提是要允許安全目錄)
把批量的命令拼接出來,不同庫的不同表
前提:vim /etc/my.cnf
[mysqld]
secure-file-priv=/tmp
select concat("alter table ",table_schema,".",table_name," engine=innodb;") from information_schema.tables
where engine !='InnoDB'
and table_schema not in ('sys','performance_schema','information_schema','mysql')
into outfile 'tmp/alter.sql';
#mysql -uroot -p123456 </tmp/alter.sql
單表寫法:
mysql> alter table world.myt1 engine=innodb;
________________________________________________________
6.查詢所有innodb引擎的表及所在的庫
SELECT table_schema,table_name,ENGINE FROM information_schema.`TABLES`
WHERE ENGINE='innodb';
7.統計world數據庫下每張表的磁盤空間佔用
SELECT table_name,CONCAT((TABLE_ROWS*AVG_ROW_LENGTH+INDEX_LENGTH)/1024," KB") AS size_KB
FROM information_schema.tables WHERE TABLE_SCHEMA='world';
8.統計所有數據庫的總的磁盤空間佔用
SELECT
TABLE_SCHEMA,
CONCAT(SUM(TABLE_ROWS*AVG_ROW_LENGTH+INDEX_LENGTH)/1024," KB") AS Total_KB
FROM information_schema.tables
GROUP BY table_schema;
mysql -uroot -p123 -e "SELECT TABLE_SCHEMA,CONCAT(SUM(TABLE_ROWS*AVG_ROW_LENGTH+INDEX_LENGTH)/1024,' KB') AS Total_KB FROM information_schema.tables GROUP BY table_schema;"
9.生成整個數據庫下的所有表的單獨備份語句
模板語句:
mysqldump -uroot -p123 world city >/tmp/world_city.sql
SELECT CONCAT("mysqldump -uroot -p123 ",table_schema," ",table_name," >/tmp/",table_schema,"_",table_name,".sql" )
FROM information_schema.tables
WHERE table_schema NOT IN('information_schema','performance_schema','sys')
INTO OUTFILE '/tmp/bak.sh' ;
CONCAT("mysqldump -uroot -p123 ",table_schema," ",table_name," >/tmp/",table_schema,"_",table_name,".sql" )
10.107張表,都需要執行以下2條語句
ALTER TABLE world.city DISCARD TABLESPACE;
ALTER TABLE world.city IMPORT TABLESPACE;
SELECT CONCAT("alter table ",table_schema,".",table_name," discard tablespace")
FROM information_schema.tables
WHERE table_schema='world'
INTO OUTFILE '/tmp/dis.sql';
show 命令
show databases; #查看所有數據庫
show tables; #查看當前庫的所有表
SHOW TABLES FROM #查看某個指定庫下的表
show create database world #查看建庫語句
show create table world.city #查看建表語句
show grants for root@'localhost' #查看用戶的權限信息
show charset; #查看字符集
show collation #查看校對規則
show processlist; #查看數據庫連接情況
show index from #表的索引情況
show status #數據庫狀態查看
SHOW STATUS LIKE '%lock%'; #模糊查詢數據庫某些狀態
SHOW VARIABLES #查看所有配置信息
SHOW variables LIKE '%lock%'; #查看部分配置信息
show engines #查看支持的所有的存儲引擎
show engine innodb status\G #查看InnoDB引擎相關的狀態信息
show binary logs #列舉所有的二進制日誌
show master status #查看數據庫的日誌位置信息
show binlog evnets in #查看二進制日誌事件
show slave status \G #查看從庫狀態
SHOW RELAYLOG EVENTS #查看從庫relaylog事件信息
desc (show colums from city) #查看錶的列定義信息
補充
help 內置命令
mysql> help
\G 格式化輸出