MySQL-SQL語法基礎


一、客戶端命令

1.1、mysql命令

-u  -p  -S  -h  -P  -e 
mysql -uroot -p -e "show status"

1.2、mysqladmin命令

1.2.1、命令幫助及基礎語法

mysqladmin --help
mysqladmin -u<name> -p<password> commands

1.2.2、示例

mysqladmin version
mysqladmin status
mysqladmin ping
mysqladmin processlist
mysqladmin shutdown
mysqladmin variables

1.2、mysqldump命令

見備份與恢復

1.4、接受用戶命令

help 
\G 
ctrl+c  #5.7 以上版本,結束上條命令運行,類似linux 
ctrl+d  \q   exit quit
use  
source	source /root/world.sql

系統相關命令:

List of all MySQL commands:
Note that all text commands must be first on line and end with ';'
?         (\?) Synonym for `help'.
clear     (\c) Clear the current input statement. 
connect   (\r) Reconnect to the server. Optional arguments are db and host.
delimiter (\d) Set statement delimiter.	#存儲過程及函數
edit      (\e) Edit command with $EDITOR.
ego       (\G) Send command to mysql server, display result vertically.
exit      (\q) Exit mysql. Same as quit.
go        (\g) Send command to mysql server.
help      (\h) Display this help.
nopager   (\n) Disable pager, print to stdout.
notee     (\t) Don't write into outfile.
pager     (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print     (\p) Print current command.
prompt    (\R) Change your mysql prompt.
quit      (\q) Quit mysql.
rehash    (\#) Rebuild completion hash.
source    (\.) Execute an SQL script file. Takes a file name as an argument.
status    (\s) Get status information from the server.
system    (\!) Execute a system shell command.
tee       (\T) Set outfile [to_outfile]. Append everything into given outfile.
use       (\u) Use another database. Takes database name as argument.
charset   (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets.
warnings  (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.

二、SQL分類

SQL: 結構化查詢語言(Structured Query Language)

DDL : 數據定義語言(Data define Language)
DCL : 數據控制語言(Data Control Language)
DML : 數據操作語言(Data Manipulation Language)
DQL : 數據查詢語言(Data QueryLanguage)

三、DDL:數據定義語言

3.1、create  database語句

image

1)當創建的數據庫本身存在而且沒有寫明if not exists子句時,則創建數據庫的語句會報錯

2)create_specification子句指明創建的數據庫的屬性,並存儲在db.opt文件中

  • Character set屬性指明此數據庫的默認字符集
  • Collate屬性指明此數據庫的默認排序規則

3)可以直接通過mkdir的操作系統命令在數據目錄創建文件夾並授權,則MySQL會識別為一個數據庫,並在執行show databases命令時可以看到(mysql8.0不再支持)

3.1.1、示例

CREATE DATABSE wordpress CHARSET  utf8;	#可以指定字符集及排序規則

語法:CREATE DATABASE db_name CHARACTER SET  	charset_name COLLATE 	collation_name
CREATE DATABASE oldgirl CHARACTER SET gbk COLLATE 	gbk_chinese_ci;

show character set;	#找字符集和校對規則.

#改庫的字符集
ALTER DATABASE [db_name] CHARACTER SET  charset_name COLLATE collation_name
ALTER DATABASE oldgirl CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

#查看當前所在的庫
select database();

#查看當前連接的用戶
select user();

3.1.2、開發規范

(1)  庫名字必須小寫,不能有數字開頭,不要超過16個字符 *****
(2)  庫名必須和業務有關
(3)  建庫時必須添加字符集
(4)  生產中禁止DROP命令
(5)  做變更類操作,需要提前備份

3.2、drop  database語句(危險)

3.3、alter  database語句

如果修改了數據庫的默認字符集或排序規則,那數據庫中的所有存儲過程和函數都需要重新創建一遍

3.3.1、示例

#例如:更改庫的字符集(utf8 ----> utf8mb4)
alter database abc charset utf8mb4;
alter database abc character set utf8mb4;

3.4、create  table語句

建表語法:https://dev.mysql.com/doc/refman/5.7/en/create-table.html

create table students2(sid int,sname varchar(10));
create table test3.students2(sid int,sname varchar(10)); ##在test3這個數據庫下創建students2表
create table if not exists students2(sid int,sname varchar(10));

3.4.1、temporary關鍵詞

temporary關鍵詞表示創建的是臨時表,臨時表僅對本鏈接可見另外的數據庫鏈接不可見,當本鏈接斷開時,臨時表也自動被drop掉

mysql> create temporary table temp1(sid int,sname varchar(10));
mysql> insert into temp1 values(1,'a');
mysql> select * from temp1;
+------+-------+
| sid  | sname |
+------+-------+
|    1 | a     |
+------+-------+
1 row in set (0.00 sec)

mysql> \q
Bye

#本數據庫鏈接斷開后再鏈接,臨時表也不存在
[root@db01 ~]# mysql -uroot -pmysql
mysql> select * from abc.temp1;
ERROR 1146 (42S02): Table 'abc.temp1' doesn't exist

#另一個數據庫鏈接執行相同的查詢語句查不到數據 

3.4.2、常見數據類型

1)數字類

TINYINT   #-128~127   ,1-256
INT       # -2^31~2^31-1     2^32 正數

2)字符類

char(定長)    
varchar(變長)
enum('',''.....)		#枚舉類型

char和varchar區別?

char(11):定長長度的字符串類型
	(1)11 這個數字,表示的是字符顯示長度,11是個閾值,
	(2)存儲數據時,會立即分配11個字符串長度的磁盤空間,存不滿,用空格填充.	
	注釋:
		磁盤空間,utf8 每個字符都是占三個字節長度,utf8mb4,每個字符占4個字節
	(3)應用場景
	短字符串,固定長度的.

varchar(20): 可變長度的字符串類型
	(1)20這個數字,表示的是字符顯示長度,20是個閾值
	(2)存儲數據時,比如:zhangsan,SQL引擎會數一下多少個,然后再按照長度分配存儲空間,額外開辟1個字節存儲字符長度,超過255個字符,字符長度需要2個字節存儲
	(3) 應用場景
		變長長度的字符串存儲.

#char和varchar選擇問題?
	短字符串,固定長度的,選擇char
	變長長度的字符串,選擇varchar

enum('',''.....):枚舉類型

enum('heilongjiang','jilin','liaoning',.....)
		1             2         3
(1) 業務當中的數據,限定在某個范圍內的值時,值越多性能越好
(2) 不建議存儲數字: https://dev.mysql.com/doc/refman/8.0/en/enum.html
(3) enum 的值,相當於一個列表,會自動生成枚舉索引.
將來表中存儲數據時,只需要存儲索引號就可以.減少了磁盤空間的消耗,也減少了聚集索引樹的高度
(4)使用enum,盡量是一次性規划好,少去改enum
(5)必須開啟SQL_MODE嚴格模式(5.7以前)

3)時間類型

1、date
2、time 
3、year
4、datatime 
5、timestamp

#datetime與timestamp區別
datetime類型取值范圍:1000-01-01 00:00:00 到 9999-12-31 23:59:59
timestamp類型取值范圍:1970-01-01 00:00:00 到 2037-12-31 23:59:59(經過測試得出范圍為 1970-01-01 08:00:01 到2038-01-19 11:14:07)

4)二進制類

3.4.3、示例

#一個標准的建表語句:
USE abc;
CREATE TABLE stu(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '學號',
sname VARCHAR(20) NOT NULL COMMENT '學生姓名',
sage  TINYINT  UNSIGNED COMMENT '學生年齡',
gender ENUM('m','f','n') NOT NULL DEFAULT 'n' COMMENT '性別',
telnum CHAR(11) NOT NULL COMMENT '手機號',
intime DATETIME NOT NULL DEFAULT NOW()
)ENGINE INNODB CHARSET utf8;

mysql> desc stu;
+--------+---------------------+------+-----+-------------------+----------------+
| Field  | Type                | Null | Key | Default           | Extra          |
+--------+---------------------+------+-----+-------------------+----------------+
| id     | int(11)             | NO   | PRI | NULL              | auto_increment |
| sname  | varchar(20)         | NO   |     | NULL              |                |
| sage   | tinyint(3) unsigned | YES  |     | NULL              |                |
| gender | enum('m','f','n')   | NO   |     | n                 |                |
| telnum | char(11)            | NO   |     | NULL              |                |
| intime | datetime            | NO   |     | CURRENT_TIMESTAMP |                |
+--------+---------------------+------+-----+-------------------+----------------+
6 rows in set (0.00 sec)

#其他建表語句:
create table t1 like student;			#創建與student表結構相同的表
insert into t1 select * from student;	#將student表中的數據插入到t1中

create table t3 as select * from student;	#與 student表結構數據相同,但索引等約束條件不會攜帶過來

Ignore和replace表示在插入數據的過程中如果新表中碰到違反唯一約束的情況下怎么處理,ignore表示不插入,replace表示替換已有的數據,默認兩個關鍵詞都不寫則碰到違反的情況會報錯

3.4.4、表及列屬性

1)表屬性

ENGINE INNODB
#注:在 5.5以前,默認的引擎類型是MyISAM,5.5以后默認是InnoDB

CHARSET utf8;	

2)列屬性

NOT NULL: 非空約束
	作用: 此列不能錄入空值,我們建議盡量所有列都設置為非空,主要是影響了索引的應用
	如果實在不知道填寫什么值,可以使用0填充,一般情況會配合default來使用.
        create table students3(sid int,sname varchar(10),gender int default 0);

Unique key: 唯一鍵(索引)約束
	作用:此列錄入數據時,不能有重復值.
	例如:手機號,QQ號

primary key:主鍵(聚集索引)約束
	作用:此列數據錄入時,既非空又唯一
	一般情況下是id,而且是自動增長的列
	使用方法: NOT NULL AUTO_INCREMENT PRIMARY key
	開發規范要求: 在建表的時候一定要指定主鍵

Auto_increment:表示字段為整數或者浮點數類型的value+1遞增數值,value為當前表中該字段最大的值,默認是從1開始遞增;一個表中只容許有一個自增字段,且該字段必須有key屬性,不能含有default屬性,且插入負值會被當成很大的正數

Constraint表示為主鍵、唯一鍵、外鍵等約束條件命名,如果沒有命名則MySQL會默認給一個

Key/index表示索引字段

Foreign key:表示該字段為外鍵字段
CREATE TABLE `gender` (
 gender_id`int(11) NOT NULL,
 name varchar(10) DEFAULT NULL,
 PRIMARY KEY (gender_id)
)

create table students5(sid int not null primary key auto_increment,sname varchar(10) unique,gender int,constraint for_1 foreign key (gender) references gender(gender_id));

3.4.5、開發規范

(1) 表名不能大寫,數字開頭,16個字符串
(2) 表名和業務有關
(3) drop 語句禁止
(4) 選擇合適的數據類型
(5) 必須要有主鍵
(6) 列盡量非空約束
(7) 減少外鍵約束
(8) 必須設置存儲引擎和字符集
(9) 列必須要有注釋
(10) 對於非負數設置數據類型約束--無符號

3.5、drop  table語句(危險)

3.6、alter  table語句

3.6.1、示例

1)修改表的字符集

ALTER TABLE stu CHARSET utf8mb4;
SHOW CREATE TABLE stu;

2)修改表的存儲引擎

ALTER TABLE  stu ENGINE MYISAM;
ALTER TABLE  stu ENGINE INNODB;
#擴展:此命令除了可以修改引擎,還可以觸發InnoDB表的碎片整理
ALTER TABLE stu ENGINE tokudb;

3)修改表名

ALTER TABLE stu RENAME student;
DESC student;

4)添加列和列定義

#添加單列及定義
ALTER TABLE student  ADD  age INT;

#添加多列及定義
ALTER TABLE student ADD gender VARCHAR(20) , ADD  qq INT;
-----------------------------------------------------------------

#指定位置添加列
#表首列添加一列
ALTER TABLE student ADD classid VARCHAR(20) FIRST;

#在age列后面添加一個telnum列
ALTER TABLE student ADD telnum INT AFTER age;

#在sname列前面添加一個birthday列(沒有before的定義,轉換為某列的前面)
ALTER TABLE student ADD birthday VARCHAR(30)  AFTER sid;

5)刪除列及列定義

ALTER TABLE student DROP age;
ALTER TABLE student DROP gender;

6)修改列及列定義

#將birthday 數據類型替換為 DATETIME
ALTER TABLE student MODIFY birthday DATETIME ;
DESC student;

#將birthday列名字改為birth
ALTER  TABLE student CHANGE birthday birth DATETIME;	#同時可以更改數據類型

3.7、truncate  table語句(危險)

delete from test;     #邏輯刪除,一行一行刪。
truncate table test;  #物理刪除,pages(block),效率高。

3.8、create view語句

1)Create view語句是指將某個查詢數據的定義保留下來,以便隨時調用

2)view本身不存儲查詢結果,只是一個定義

3)當視圖被創建之后,則其定義就已經固定不會再改變,比如一個視圖是由select *創建的,則后續對表增加的字段不會成為視圖的一部分,而后續對表刪除字段則會導致查詢視圖失敗

4)創建的視圖默認情況下是屬於當前數據庫的,當要創建到另外的數據庫時則需要在視圖名前面加上數據庫名

5)視圖在滿足特定條件時是可以執行insert/update/delete語句的,條件就是視圖中的每一行和視圖對應的表中的每行數據都能一一對應起來

6)Alter view語句用來修改視圖的定義,本身的語法結構和create view相同,語句所起到的作用和create or replace view語句相同

7)Drop view語句用來刪除一個或多個視圖: drop view v_students_male;

CREATE VIEW test.v AS SELECT * FROM test2.t;
CREATE VIEW v_today (today) AS SELECT CURRENT_DATE; ##指定字段名
CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;

create view v_students_male as select sid,sname from students where sex=0;
Select * from v_students_male
create view v_students_female as select sid,sname from students where sex=1;
select * from v_students_female where sid>1;

create or replace view v_students_male as select sid,sname,sex from students where sex=0; ##添加or replace參數后,原視圖被替換

alter view v_students_male as select sid,sname from students where sex=0;

3.9、create index語句

create index idx_st_sname on students(sname); ##創建普通索引
create index idx_st_union on students(sname,sex); ##創建復合索引
create unique index idx_st_sid on students(sid); ##創建唯一索引
	mysql> insert into students values(1,‘eee’,0); ##插入重復數據失敗
	ERROR 1062 (23000): Duplicate entry '1' for key 'idx_st_sid'

#Comment string代表可以為索引添加最長1024的注釋
CREATE TABLE t1 (id INT);
CREATE INDEX id_index ON t1 (id) COMMENT 'MERGE_THRESHOLD=40';

3.10、rename  table語句

1)Rename table語句用來重命名一個或多個表名

2)當想讓兩個表名相互調換時,可以執行語句

RENAME TABLE old_table TO tmp_table,new_table TO old_table,tmp_table TO new_table;
3)Rename table能將表中的數據,索引,主鍵定義都自動轉換到新表下,但 視圖和對原表分配的權限不能自動轉換到新表,需要手動執行
rename table students to students_test;

3.11、DDL小結

3.11.1、庫的定義常用命令

create database
drop database 
alter  database

show databases;
show create database

3.11.2、表的定義常用命令

create table 
drop  table
alter  table

show tables 
show create table
desc 
show table status from abc;	#查看庫中表的狀態

image

四、DCL : 數據控制語言

常用DCL命令:

grant 
revoke 
lock
等

五、DML : 數據操作語言

5.1、insert語句

image

Insert into students values(1,'aaa');
Insert into students set sid=2,sname='bbb';
Insert into students select * from students_bak;
-----------------------------------------------------------------------------------------------------------

#Ignore關鍵詞代表insert語句如果違反主鍵和唯一鍵的約束條件,則不報錯而只產生警告信息,違反的行被丟棄,而不是整個語句回退;在數據類型轉換有問題時如果有ignore則只產生警告信息,而不是語句回退
insert ignore into students values(1,'bbb',0);
-----------------------------------------------------------------------------------------------------------

#Insert…select語句詳解
用於從另外的表中查出記錄並插入到目標表中
INSERT INTO tbl_temp2 (fld_id) SELECT tbl_temp1.fld_order_id FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
當目標表和select語句中的表相同時,則會先將select語句的結果存放在臨時表中,再插入到目標表中(注意執行順序)
mysql> insert into students select * from students;
-----------------------------------------------------------------------------------------------------------

#Insert on duplicate key update語句詳解
當insert語句中使用on duplicate keyupdate子句時,如果碰到當前插入的數據違反主鍵或唯一鍵的唯一性約束,則Insert會轉變成update語句修改對應的已經存在表中的這條數據。比如如果a字段有唯一性約束且已經含有1這條記錄,則以下兩條語句的執行結果相同
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
On duplicate key update子句后面可以跟多個修改,用逗號隔開
上述例子中如果b字段也有唯一性約束,則與此語句的執行結果相同,但一般應該避免出現對應多條的情況
UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;


mysql> create table students2(sid int primary key,sname varchar(20),sex int);
mysql> Insert into students2 values(1,'aaa',1);

mysql> Insert into students2 values(1,'bbb',0);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> insert into students2 values(1,'bbb',0) on duplicate key update sname='bbb';
Query OK, 2 rows affected (0.01 sec)

mysql> select * from students2;
+-----+-------+------+
| sid | sname | sex  |
+-----+-------+------+
|   1 | bbb   |    1 |
+-----+-------+------+
1 row in set (0.00 sec)

mysql> insert into students2 values(1,'ccc',0) on duplicate key update sname='ccc',sex=0;
Query OK, 2 rows affected (0.01 sec)

mysql> select * from students2;
+-----+-------+------+
| sid | sname | sex  |
+-----+-------+------+
|   1 | ccc   |    0 |
+-----+-------+------+
1 row in set (0.00 sec)

5.1.1、示例

1)規范的插入語句(所有字段列出,並與值對應)

INSERT INTO student(id ,NAME,sage,gender,telnum,intime,qq) VALUES (1,'zhangsan',18,'m','110',NOW(),'123456');

2)簡化寫法(不寫字段,值按字段順序錄入)

INSERT INTO student VALUES (2,'li4',19,'m','119',NOW(),'123455');

3)有default 或auto_increment,選擇性的錄入

INSERT INTO student(NAME,sage,telnum,qq) VALUES ('wang5',20,'120','123');

4)錄入多行數據(生產批量錄入建議方法)

如要錄入1000w行數據,我們通常會拆成多個工程(事務,拆成1w行作為一個工程),批量錄入

INSERT INTO student(NAME,sage,telnum,qq)
VALUES 
('ma6',20,'121','1232334'),
('zhao4',22,'231','1212312'),
('qian7',23,'2222','12312344');

5.2、update語句

image

#單表
update students set sname='abcd',gender='1' where sid=1;
Update students set sid=1 where sid=2; ##執行失敗,違反唯一性約束
#多表
update students,students2 set students.sname=students2.sname,students.gender=students2.gender where students.sid=students2.sid;
------------------------------------------------------------------------------------------------------

單表修改是指修改指定單個表中的已經存在數據的一個或多個列的數值;set短語后面跟要修改的列和值;
where子句表示限定要修改表中的哪些行數據,如果沒有where子句則表示所有行都要修改;order by子句表示update數據按照指定的順序進行;limit子句表示限定修改數據的行數

多表修改是指修改table_references指定的多個表中滿足條件的行數據,多表修改不允許使用order by和limit子句

Ignore關鍵詞表示當修改語句碰到違反唯一性約束條件等情況是,語句不會報錯回退而是報警告信息
Update ignore students set sid=1 where sid=2; ##執行成功但數據不會修改
------------------------------------------------------------------------------------------------------

#以下語句的col1只會比原值增加1
UPDATE t1 SET col1 = col1 + 1;

#Order by指定update數據的順序,在某些情況下可以避免錯誤的發生,比如t表中的id字段是有唯一約束的,則以下第一個語句執行會報錯,而第二個語句執行則正常
UPDATE t SET id = id + 1;
UPDATE t SET id = id + 1 ORDER BY id DESC;

mysql> update students2 set sid=sid+1; ##執行報錯
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY‘
mysql> update students2 set sid=sid+1 order by sid desc; ##執行成功
Query OK, 2 rows affected (0.04 sec)
Rows matched: 2 Changed: 2 Warnings: 0

#多表修改舉例(表之間通過where條件進行join操作)
UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;

切記: UPDATE 語句在SQL92標准中是必須加where,否則全表修改

5.2.1、示例

1)更改字段的值

UPDATE student SET gender='f' WHERE id=3; 

5.3、delete語句

image

image

#delete單表刪除舉例
Delete from students;
delete from students where sid=1;
Delete from students order by sid;
Delete from students limit 1; ##只刪除先找到的一行

#Delete語句中的order by子句決定了刪除數據的順序,配合limit子句后在某些情況下也非常有用,比如刪除最老的一條記錄:
DELETE FROM somelog WHERE user = 'jcole' ORDER BY timestamp_column LIMIT 1;

#多表刪除是指從一個或多個表中刪除滿足條件的數據,其中的table_references代表了多個表的join操作,例如以下兩個例子代表從t1和t2表中刪除滿足條件的數據
DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;
DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;

#對多表刪除語句而言,如果想對表使用別名,則只能在table_references子句中使用,否則會報錯
DELETE a1, a2 FROM t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id; ##正確
DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id; ##正確
DELETE t1 AS a1, t2 AS a2 FROM t1 INNER JOIN t2 WHERE a1.id=a2.id; ##錯誤
DELETE FROM t1 AS a1, t2 AS a2 USING t1 INNER JOIN t2 WHERE a1.id=a2.id; ##錯誤

切記:DELETE 語句在SQL92標准中是必須加where,否則全表修改

5.3.1、示例

1)刪除行記錄

DELETE FROM student WHERE id=6;

5.3.2、屏蔽delete操作

使用偽刪除,將delete轉換為update

#以學生表為例:
1)添加狀態列(1存在,0刪除)
alter table student add state int not null default 1;

2)使用update更新state為0,標識某行被刪除
update student set state=0 where id=6;
 
3)讓應用查詢不到偽刪除的行
select * from student where state=1;

5.3.3、生產刪除數據

生產中如何刪除數據:
如要執行:delete from students where sid=3;
1.開啟事務,數據刪除錯誤可以回滾
	set autocommit=off;
	rollback;	#刪除錯誤回滾
	commit;		#刪除正確提交
2.將要刪除的數據select出來,確保刪除正確
	select * from students where sid =3;
3.執行刪除動作
	delete from students where sid=3;

六、DQL : 數據查詢語言

6.1、select語句

image

#Order by和group by子句可以引用select_expr中的列,通過以下三種方式:
SELECT college, region, seed FROM tournament ORDER BY region, seed;
SELECT college, region AS r, seed AS s FROM tournament ORDER BY r, s;
SELECT college, region, seed FROM tournament ORDER BY 2, 3;
Order by子句表示查詢結果按照順序排列,默認是升序排列,可以指定DESC表明按照降序排列

#Having子句一般是跟在group by子句之后,代表限制分組之后的結果
SELECT user, MAX(salary) FROM users GROUP BY user HAVING MAX(salary) > 10;

#Limit子句用來限制查詢結果的條數,其后可以帶兩位>0的整數,第一位代表offset,第二位代表取多少行
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows,等同於select * from tbl limit 0,5
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15

#Select … into語句代表將查詢結果寫入文件中或者定義的參數變量中

#For update關鍵詞代表將查詢的數據行加上寫鎖,直到本事務提交為止

#Lock in share mode關鍵詞代表將查詢的數據行加上讀鎖,則其他的鏈接可以讀相同的數據但無法修改加鎖的數據

#ALL/Distinct關鍵詞代表是否將查詢結果中完全重復的行都查詢出來,ALL是默認值代表都查詢出來,指定distinct代表重復行只顯示一次
select count(*),count(all sid),count(distinct sid) from scores;

#HIGH_PRIORITY代表賦予讀操作較高的操作優先級

#Max_statement_time=N子句代表設置語句執行超時時間(毫秒)

#Straight_join關鍵詞代表強制優化器在表連接操作時按照語句中from子句中的表的順序執行
Sql_big_result/sql_small_result通常是和group by/distinct一起使用,其作用是事先告訴優化器查詢結果是大還是小,以便優化器事先准備好將查詢結果存放在磁盤臨時表或者快速臨時表中以便后續操作

#Sql_buffer_result強制將查詢結果存入臨時表中

#Sql_calc_found_rows關鍵詞代表要求查詢結果的同時計算結果的行數,以便后續通過SELECT FOUND_ROWS()直接獲取行數

#Sql_cache/sql_no_cache代表是否直接從query cache中獲取查詢結果


#Select…into語句
Select … into語句代表將查詢結果存入定義的變量或者文件
SELECT ... INTO var_list將查詢結果存入定義的變量
SELECT ... INTO OUTFILE將查詢結果按照一定的格式寫入到文件中
SELECT ... INTO DUMPFILE將查詢結果以一行的格式寫入到文件中,且只能寫入一行
當使用存入變量方法是,需要保證查詢結果返回一行,如果不返回數據則報no data錯誤,如果返回多行則報Result consisted of more than one row錯誤,當返回行數不確定時,可以用limit 1強制只返回一行
SELECT id, data INTO @x, @y FROM test.t1 LIMIT 1;
使用Select … into outfile'file_name'時,文件會創建在本地服務器上,所以要確保你的用戶能創建文件,而且此file_name不能已經存在在服務器上以免覆蓋其他文件

SELECT sid,sname,sex INTO OUTFILE '/tmp/students.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM students;
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
My.cnf配置文件中添加secure_file_priv=/tmp/后重啟再執行,成功

mysql> select * into dumpfile '/tmp/students3.txt' from students;
mysql> select * into dumpfile '/tmp/students4.txt' from students limit 1;

6.1.1、select簡單查詢

1)查看表中的所有數據(生產不要出現這條語句)

SELECT   *  FROM   world.city;

2)查詢表中某幾個字段

SELECT NAME,countrycode FROM world.city;

6.2、where語句

6.2.1、where + 等值查詢(=)

SELECT NAME FROM world.city WHERE countrycode='CHN';

6.2.2、where + 不等值查詢(> < >= <= <>)

SELECT * FROM world.city WHERE population < 100;

注意事項:

1.除了 <> 或 != ,都屬於范圍查詢,主鍵除外.
2.對於輔助(普通)索引列查詢,避免使用<> 或 !=

6.2.3、WHERE + 邏輯連接符 ( AND , OR)

1)查詢中國人口數大於500w的城市信息

SELECT id, NAME ,countrycode,population
FROM world.city 
WHERE countrycode='CHN' AND population > 5000000;
2)查詢中國吉林省的城市信息
SELECT * FROM world.city WHERE countrycode='CHN' AND district='jilin';
3)查詢中國和美國的城市信息
SELECT * FROM world.`city` WHERE countrycode ='CHN' OR countrycode='USA';

6.2.4、where + in

1)查詢中國和美國的城市信息

SELECT * FROM world.`city` WHERE countrycode IN ('CHN' ,'USA');

#說明:OR和IN屬於范圍查詢,我們一般替換為 UNION 或者 UNION ALL

6.2.5、WHERE + BETWEEN AND

1)查詢城市人口500w-600w的城市信息

SELECT * FROM world.city 
WHERE population>5000000 AND population<6000000;

SELECT * FROM world.city 
WHERE population BETWEEN 5000000 AND 6000000;

6.2.6、WHERE + LIKE 模糊查詢

1)查詢國家代號為CH打頭的城市信息

SELECT * FROM world.city WHERE countrycode LIKE 'CH%';

#注意: LIKE '%aa%'  不要出現
#搜索框類的應用,就是典型的%aa%,建議不要使用MySQL,使用ES

6.3、group  by語句(配合聚合函數)

6.3.1、常見聚合函數

SUM()    #統計總和
AVG()    #統計平均值
MAX()    #統計最大值
MIN()    #統計最小值
COUNT()  #統計數量

6.3.2、示例

1)統計世界上每個國家的總人口數.

SELECT countrycode,SUM(population) 
FROM   world.`city`
GROUP BY countrycode ;

2)統計中國各個省的總人口數量

SELECT  countrycode, district, SUM(population)   
FROM   world.city 
WHERE countrycode='CHN'
GROUP BY  district;

3)統計世界上每個國家的城市數量

SELECT  countrycode,  COUNT(id)
FROM  world.city
GROUP BY countrycode ;

4)統計中國各個省的平均人口數,顯示結果是大於平均人口數的城市信息

SELECT 
a.name AS '城市名', 
a.population AS ap,
a.countrycode AS '國家' , 
a.district AS '省' , 
AVG(a.population) AS '平均人口'
FROM   world.city AS a
WHERE a.countrycode='CHN'
GROUP BY  a.district
HAVING ap > '平均人口';		#對group by后的結果再次進行篩選

注意事項:以上語句在sqlyog里面是可以執行成功的,但是在mysql命令行執行出錯:

[world]>SELECT  a.name, a.district, a.countrycode, a.population ,  AVG(a.population) AS avg_po FROM world.city  AS a WHERE a.countrycode='CHN' GROUP BY a.district HAVING a.population > avg_po;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'world.a.Name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

#在嚴格模式下:
1. 在 select ,having,order by  中涉及到的列條件必須在group by存在
2. 如果不存在,可以用any_value(a.population)
3. 或者是設置sql_mode去掉only_full_group_by

可以使用如下的語句:

方法一:
SELECT  
any_value(a.population) AS avp,
any_value(a.countrycode) AS avc, 
a.district AS ad , 
AVG(a.population) AS avg_p
FROM   world.city AS a
WHERE a.countrycode='CHN'
GROUP BY  ad
HAVING avp > avg_p;

方法二:
set session  sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';   

set global   sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';   

6.4、 limit子句(常用來分頁)

LIMIT 10,5				#從第10行開始,取5行
LIMIT 5  OFFSET 10

6.4.1、示例

1)查詢中國人口數量排名前十的城市信息

SELECT * FROM city 
WHERE countrycode='CHN'
ORDER BY population DESC
LIMIT 10

6.5、多表連接查詢

#Select語句中的表連接
在MySQL中,join/inner join/cross join三者的意思是一樣的

#Join語句中表別名的用法
SELECT t1.name, t2.salary FROM employee AS t1 INNER JOIN info AS t2 ON t1.name = t2.name;
SELECT t1.name, t2.salary FROM employee t1 INNER JOIN info t2 ON t1.name = t2.name;

#From子句后面還可以跟子查詢,但子查詢必須帶別名
SELECT * FROM (SELECT 1, 2, 3) AS t1;

#當inner join或者表之間用逗號隔開,且沒有表之間的關聯字段,則代表結果是兩者的笛卡爾積

#STRAIGHT_JOIN和Join的用法大致相同,唯一不同是確保左表是先被讀取的,以保證優化器的讀取順序

Select語句中的表連接
SELECT * FROM students, scores; ##沒有關聯條件,表示笛卡爾積
SELECT * FROM students INNER JOIN scores ON students.sid=scores.sid;
SELECT * FROM students LEFT JOIN scores ON students.sid=scores.sid;
SELECT * FROM students LEFT JOIN scores USING (sid);
SELECT * FROM students LEFT JOIN students2 ON students.sid=students2.sid LEFT JOIN scores ON students2.sid=scores.sid;

#如果相對union語句的最后結果做排序或者limit限制,則需要將每個select語句用括號括起來,把order by或limit語句放在最后
(Select sid,sname from students) Union (Select sid,sname from students2) order by sid limit 2;

6.5.1、使用及條件

#作用:
要查詢的數據,是來自於多張表時,可以用多表連接

#多表連接公式:
1)數據來自多張表,優先想到多表連接join ON
2)關聯表寫join兩端
3)on條件寫兩表的關聯列
4)所有查詢條件select后,注意表名和別名
5)where過濾條件寫最后

#多表連接查詢的必要條件:
多表之間有直接或間接的關聯條件

6.5.2、示例

1)查詢一下世界上人口小於100人的城市,所在的國家信息(國家名,國土面積,所在大洲)

方法一: 傳統 where 連接方法
SELECT city.NAME,city.countrycode,city.population , country.NAME , country.continent, country.SurfaceArea
FROM city,country
WHERE city.Population<100 AND city.CountryCode=country.code;

方法二: join on 的連接方法
SELECT city.NAME,city.countrycode,city.population , country.NAME , country.continent, country.SurfaceArea
FROM city  JOIN   country
ON city.CountryCode=country.code
WHERE city.Population<100;

2)統計每個學生的所學課程總成績

SELECT  student.sname  , SUM(sc.score) 
FROM student
JOIN sc
ON student.sno=sc.sno
GROUP BY sc.sno;

3)統計zhang3,學習了幾門課

select  student.sname, count(sc.cno) from  student
join sc 
on student.sno=sc.sno
join course 
on sc.cno=course.cno
where student.sname='zhang3'
group by sc.sno;

4)查詢zhang3,學習的課程名稱有哪些?

SELECT student.sname,course.cname
FROM student   
JOIN sc 
ON student.sno=sc.sno
JOIN course
ON sc.cno=course.cno
WHERE student.sname='zhang3';

5)查詢oldguo老師教的學生名

SELECT teacher.tname,student.sname
FROM teacher
JOIN course
ON teacher.tno=course.tno
JOIN sc
ON course.cno=sc.cno
JOIN student
ON sc.sno=student.sno 
WHERE teacher.tname='oldguo';

6)統計oldguo所教課程的平均分數

SELECT teacher.tname,course.cname,AVG(sc.score)
FROM teacher 
JOIN course 
ON teacher.tno=course.tno
JOIN sc
ON course.cno=sc.cno
WHERE teacher.tname='oldguo';

6.6、子查詢

查詢里嵌入查詢,先執行子查詢,再執行外部查詢

6.6.1、示例

1)查詢一下世界上人口小於100人的城市,所在的國家信息(國家名,國土面積,所在大洲)

SELECT NAME , continent, SurfaceArea  FROM country  WHERE CODE IN (SELECT countrycode 
FROM city 
WHERE population<100);

2)學過python和linux兩門課程的學號和姓名

方法一;
SELECT course.cname,student.sno,student.sname 
FROM course
JOIN sc
ON course.cno=sc.cno
JOIN student
ON sc.sno=student.sno 
WHERE course.cname IN ('linux','python')

方法二:
SELECT course.cname,student.sno,student.sname ,COUNT(course.cname) AS cc
FROM course
JOIN sc
ON course.cno=sc.cno
JOIN student
ON sc.sno=student.sno 
WHERE course.cname IN ('linux','python')
GROUP BY student.sno
HAVING cc > 1;

方法三:
SELECT t.sn  ,COUNT(t.cc) AS ab FROM 
(SELECT course.cname AS cc,student.sno AS ss ,student.sname AS sn 
FROM course
JOIN sc
ON course.cno=sc.cno
JOIN student
ON sc.sno=student.sno 
WHERE course.cname IN ('linux','python'))t
GROUP BY t.sn
HAVING ab > 1;

6.7、 union [all]語句

將兩個結果集並成一個結果接,連接兩條select語句結果.union會將查詢的結果去重,而union all不會

6.7.1、示例

1)查詢中國和美國的城市信息

方法一:
SELECT * FROM city WHERE countrycode IN ('CHN','USA');

方法二:效率更高
SELECT * FROM city WHERE countrycode = 'CHN'
UNION ALL 
SELECT * FROM city WHERE countrycode = 'USA';

七、元數據獲取

7.1、information_schema

7.1.1、介紹

1.虛擬庫

2.開啟數據庫時產生的

3.不能被刪除和修改

4.庫中存儲的是視圖

5.此庫中的視圖也是不能被刪除和修改的,智能select查詢

7.1.2、作用

此庫中的視圖是用來,間接的查詢數據庫的"元數據"("基表"數據)

基表:數據是通過自動統計收集而來的.

基表:是不允許人為直接增\刪\改\查的

必須通過:專用的DDL,DCL實現增\刪\改,show語句和information_schema可以做查詢

7.2、information_schema.tables介紹

information_schema.tables記錄了整個MySQL數據庫中,所有的表的詳細屬性信息

常用字段信息:

TABLE_SCHEMA      #表所在的庫
TABLE_NAME        #表名字
ENGINE            #表的存儲引擎
TABLE_ROWS        #表的行數
AVG_ROW_LENGTH    #表的平均行長度(字節)
INDEX_LENGTH      #表的索引長度(字節)

information_schema.tables全表信息:

mysql> desc information_schema.tables;
+-----------------+---------------------+------+-----+---------+-------+
| Field           | Type                | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG   | varchar(512)        | NO   |     |         |       |
| TABLE_SCHEMA    | varchar(64)         | NO   |     |         |       |
| TABLE_NAME      | varchar(64)         | NO   |     |         |       |
| TABLE_TYPE      | varchar(64)         | NO   |     |         |       |
| ENGINE          | varchar(64)         | YES  |     | NULL    |       |
| VERSION         | bigint(21) unsigned | YES  |     | NULL    |       |
| ROW_FORMAT      | varchar(10)         | YES  |     | NULL    |       |
| TABLE_ROWS      | bigint(21) unsigned | YES  |     | NULL    |       |
| AVG_ROW_LENGTH  | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_LENGTH     | bigint(21) unsigned | YES  |     | NULL    |       |
| MAX_DATA_LENGTH | bigint(21) unsigned | YES  |     | NULL    |       |
| INDEX_LENGTH    | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_FREE       | bigint(21) unsigned | YES  |     | NULL    |       |
| AUTO_INCREMENT  | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_TIME     | datetime            | YES  |     | NULL    |       |
| UPDATE_TIME     | datetime            | YES  |     | NULL    |       |
| CHECK_TIME      | datetime            | YES  |     | NULL    |       |
| TABLE_COLLATION | varchar(32)         | YES  |     | NULL    |       |
| CHECKSUM        | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_OPTIONS  | varchar(255)        | YES  |     | NULL    |       |
| TABLE_COMMENT   | varchar(2048)       | NO   |     |         |       |
+-----------------+---------------------+------+-----+---------+-------+
21 rows in set (0.00 sec)

7.3、information_schema.tables應用

1)統計各個庫下表的個數

mysql> SELECT table_schema,COUNT(table_name) FROM information_schema.tables GROUP BY table_schema;
+--------------------+-------------------+
| table_schema       | COUNT(table_name) |
+--------------------+-------------------+
| abc                |                 2 |
| information_schema |                61 |
| mysql              |                31 |
| performance_schema |                87 |
| sys                |               101 |
| world              |                 3 |
+--------------------+-------------------+
6 rows in set (0.01 sec)

2)統計各個引擎表的個數

mysql> SELECT ENGINE,COUNT(table_name) FROM information_schema.tables GROUP BY ENGINE;
+--------------------+-------------------+
| ENGINE             | COUNT(table_name) |
+--------------------+-------------------+
| NULL               |               100 |
| CSV                |                 2 |
| InnoDB             |                35 |
| MEMORY             |                51 |
| MyISAM             |                10 |
| PERFORMANCE_SCHEMA |                87 |
+--------------------+-------------------+
6 rows in set (0.00 sec)

3)列出所有innodb引擎的表

mysql> SELECT  table_schema,table_name ,ENGINE FROM information_schema.tables WHERE ENGINE='innodb';

4)world的數據庫下每個表的行數(可以分析出庫中最大的表

mysql> SELECT table_name ,table_rows FROM information_schema.tables WHERE table_schema='world';
+-----------------+------------+
| table_name      | table_rows |
+-----------------+------------+
| city            |       4188 |
| country         |        239 |
| countrylanguage |        984 |
+-----------------+------------+
3 rows in set (0.00 sec)

5)統計每個庫占用的總空間大小

一張表占用空間大小計算公式:平均行長度*表的行數+索引長度

AVG_ROW_LENGTH * TABLE_ROWS+ INDEX_LENGTH

mysql> SELECT table_schema,SUM(AVG_ROW_LENGTH * TABLE_ROWS+ INDEX_LENGTH)/1024 AS Total_KB FROM information_schema.tables GROUP BY table_schema;
+--------------------+-----------+
| table_schema       | Total_KB  |
+--------------------+-----------+
| abc                |    0.0000 |
| information_schema |      NULL |
| mysql              | 2322.6455 |
| performance_schema |    0.0000 |
| sys                |   15.9961 |
| world              |  779.7744 |
+--------------------+-----------+
6 rows in set (0.02 sec)

6)information_schema.tables結合concat()函數

vim /etc/my.cnf
secure-file-priv=/tmp

SELECT CONCAT("alter table ",table_name," discard tablespace;") 
FROM information_schema.tables  WHERE table_schema='world' INTO OUTFILE '/tmp/discard.sql';

[root@db01 tmp]# cat discard.sql 
alter table city discard tablespace;
alter table country discard tablespace;
alter table countrylanguage discard tablespace;

7)全庫所有的表都單獨備份(分表備份)

mysqldump -uroot -p123 world city  > /bak/world_city.sql 

方法一:使用SQL結合concat函數
select concat("mysqldump -uroot -pmysql ",table_schema," ",table_name,"  > /bak/",table_schema,"_",table_name,".sql") 
from information_schema.tables where table_schema not in ('information_schema','performance_schema','sys') INTO OUTFILE '/tmp/bak.sh';
執行shell腳本

方法二:使用shell腳本
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/mysql/bin
MYUSER=root
MYSQL_PWD=mysql
MYCMD="mysql --user=$MYUSER"
MYDUMP="mysqldump --user=$MYUSER"
BACKDIR=/server/backup

[ -d $BACKDIR ] || mkdir -p $BACKDIR
for dbname in `$MYCMD -e "show databases;"|grep -vE 'Database|information_schema| performance_schema|sys' `
do
	mkdir $BACKDIR/${dbname}_$(date +%F) -p
	for table in `$MYCMD -e "show tables from $dbname;"|sed '1d'`
		do
			$MYDUMP $dbname $table|gzip >$BACKDIR/${dbname}_$(date +%F)/${dbname}_${table}.sql.gz
		done
done

八、show 語句

show databases;					
show tables;
show create database xxx
show create table 
show grants for 
show charset;
show collation;
show engines;
show [global] status ;         #看數據庫當前狀態
show variables like '%log%';   #看數據庫參數信息
show [full] processlist;        #看數據庫連接線程狀態
show engine innodb status \G   #看innodb存儲引擎總狀態
show master status             #主從復制中主庫信息
show slave status \G           #主從復制從庫狀態的
show binary logs               #可用的binlog文件名
show binlog events in ''       #binlog日志的事件信息
select @@log_error;            #查看某個參數的定義信息
select now();                  #查看當前時間
select database();             #查看當前use到的庫
select user();                 #當前登錄的用戶


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM