MySQL語句和命令大全

前言

這裏記錄的是這兩年學習工做過程當中遇到的經常使用的 MySQL 語句和命令,部分是網上收集來的,出處已經不記得了,這裏先謝過這些大佬。本文包括常見 SQL 語句,還有部分運維語句和命令,沒有作詳細的說明,更可能是給出一個例子。就這點語句固然還不能說是全,可是後續也會陸續增長完善。記錄得有些亂,有須要的能夠酌情提取。mysql

1、用戶鏈接、建立、權限、刪除

1. 鏈接MySQL操做

mysql -h 主機地址 -u 用戶名 -P端口號 -pc++

使用 SSL 鏈接sql

mysql --ssl-ca=ca.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem -h主機地址 -u用戶名 -pshell

2. 建立用戶

CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 數據庫

  • host 指定該用戶在哪一個主機上能夠登錄,若是是本地用戶可用localhost, 若是想讓該用戶能夠從任意遠程主機登錄,可使用通配符%.

3. 受權

GRANT [all privileges/某個權限] ON databasename.tablename TO 'username'@'host';bash

若是想讓該用戶能夠受權,用如下命令: 運維

GRANT all privileges ON databasename.tablename TO 'username'@'host' WITH GRANT OPTION;socket

4. 鎖定用戶

ALTER USER 'username'@'host' ACCOUNT LOCK;

解鎖ide

ALTER USER 'username'@'host' ACCOUNT UNLOCK;

常見場景:函數

1 建立讀寫權限的用戶

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, EXECUTE, CREATE VIEW, SHOW VIEW ON databasename.tablename TO 'username'@'host';

2 建立只讀權限用戶

GRANT SELECT,SHOW VIEW ON databasename.tablename TO 'username'@'host';

4. 設置與更改用戶密碼

方法一

SET PASSWORD FOR 'username'@'host' = PASSWORD('newpassword');

若是是當前登錄用戶用

SET PASSWORD = PASSWORD("newpassword");

方法二

ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';

5. 撤銷用戶權限

REVOKE [ALL/某個權限] ON databasename.tablename FROM 'username'@'host';

某個用戶權限能夠用命令SHOW GRANTS FOR 'username'@'host'; 查看.

5. 重命名用戶

rename user 'old_name'@'host' to 'new_name'@'host';

7. 刪除用戶

DROP USER 'username'@'host';

8. 要求使用ssl登錄

# 修改已存在用戶 
ALTER USER 'username'@'%' REQUIRE SSL;

# 建立用戶
create user username_ssl@'%' identified by 'password' require ssl;

刷新權限表

flush privileges;

2、數據庫與表顯示、建立、刪除

1. 數據庫查看&建立&刪除

-- 查看數據庫
show databases; 

-- 建立庫
create database [IF NOT EXISTS] <庫名> [character set='utf8'];

-- 刪除庫
drop database <庫名>;

2. 表查看、建立、刪除

-- 顯示數據表
use <庫名>;
show tables;

-- 建立表:
create table 表名 (字段設定列表) [engine=InnoDB] [charset=utf8mb4];

-- 查看建立表的 DDL 語句
show create table <表名>;

-- 顯示錶結構
desc <表名>;

-- 刪除表
drop table [IF EXISTS] <表名>; 

-- 臨時表
CREATE TEMPORARY TABLE <表名>(<字段定義>);

e.g.

CREATE TABLE
    USER
    (
        id INT NOT NULL AUTO_INCREMENT,
        stu_id INT NOT NULL,
        name VARCHAR(30) NOT NULL,
        phone VARCHAR(20),
        address VARCHAR(30) NOT NULL,
        age INT NOT NULL,
        PRIMARY KEY (id),
        UNIQUE KEY `un_stu_id` (stu_id),
        KEY `idx_name` (`name`) USING BTREE
    )
    ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

注意: 爲 text 等創建索引時要指定長度 e.g. KEY idx_text (f_text(64))

3、表複製、備份還原及清除

1. 複製表結構

含有主鍵等信息的完整表結構:

CREATE table 新表名 LIKE book;

只有表結構,沒有主鍵等信息:

create table 新表名 select * from books;
或
create table 新表名 as(select * from book);
或
create table 新表名 select * from books where1=2;

注: create table <t> select ... 會形成索引丟失

2. 將舊錶中的數據灌入新表

INSERT INTO <新表> SELECT * FROM <舊錶>;

3. 顯示建立表的DDL語句

show create table <表名>;

4. 清空表數據

truncate table <表名>;

5. 備份數據庫

備份單個庫

shell> mysqldump --single-transaction --master-data=2 --default-character-set=utf8 -u root -p <database_name> >database_name.sql

備份一個表

shell> mysqldump --single-transaction --master-data=2 --default-character-set=utf8 -u root -p <database_name> <table_name> > table_name.sql

備份多個庫

shell> mysqldump --single-transaction --master-data=2 --default-character-set=utf8 -u username -p --databases <dbname1> <dbname2> > Backup.sql

備份全部庫

shell> mysqldump --single-transaction --master-data=2 --default-character-set=utf8 -A -u root -p > back.sql

忽略某些庫表

--ignore-table=performance_schema.* --ignore-table=information_schema.* --ignore-table=sys.* --ignore-table=test.*

帶上壓縮

shell> mysqldump -A | gzip >> backup.sql.gz

6. 還原數據庫

shell> mysql -u root -p -f [database_name] < backup.sql

7. 從備份文件抽取數據

提取某個庫的全部數據

shell> sed -n '/^-- Current Database: `test_restore`/,/^-- Current Database:/p' mysql_back.sql

只提取建表語句

shell> sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `test1`/!d;q' mysql_back.sql

只提取數據

shell> grep -i 'INSERT INTO `test1`' mysql_back.sql

提取全部建庫表語句

shell> grep -iv 'INSERT INTO `' mysql_back.sql

8. 導出數據

<select語句> into outfile "dest_file";

9. 導入數據

load data infile "<file_name>" into table <table_name>;

4、修改表的列與表名

1. 給列改名

alter table <表名稱> change <舊字段名稱> <新字段名稱>

2. 給表改名

alter table <舊錶名稱> rename <新表名稱>

3. 修改某個表的字段類型及指定爲空或非空

alter table <表名稱> change <字段名稱> <字段名稱> <字段類型> [not null];

alter table <表名稱> modify <字段名稱> <字段類型> [not null];

4. 增長一個字段(一列)

alter table 表名稱 add column 字段名稱 字段類型;

加在某個字段後面

alter table 表名稱 add column 字段名稱 字段類型 after 某個字段;

加在最前

alter table 表名稱 add column 字段名稱 字段類型 first;

5. 更改一個字段名字(也能夠改變類型和默認值)

alter table <表名稱> change <原字段名稱> <新字段名稱 字段類型>;

6. 改變一個字段的默認值

alter table 表名稱 alter 字段名稱 set default 值;

該方法不會鎖表

7. 改變一個字段的數據類型

alter table <表名稱> change column <字段名稱> <字段名稱> <字段類型>;

8. 刪除字段

alter table <表名稱> drop column <列名>;

五 查詢表

SELECT [DISTINCT] <字段名稱,用逗號隔開/*>

FROM <left_table> [<join_type> JOIN <right_table> ON <鏈接條件>]

WHERE <where條件>

GROUP BY <分組字段>

HAVING <篩選條件>

ORDER BY <排序條件> [desc/asc]

LIMIT n[, m]

1. GROUP BY 與聚合函數 使用注意點

1 在不使用聚合函數的時候,group by 子句中必須包含全部的列,不然會報錯

正確: select name,age from test group by name,age; //和 select 同樣

2 在 group by 子句中不要加上聚合函數處的列名

2. having

SQL 標準
要求 having 必須引用 group 子句中的列或者用聚合函數處理過
後的列。

mysql 對這一標準進行了一些擴展,它容許 having 引
用 select 中檢索的列和外部查詢中的列。

having 中用到的條件要
麼在 group by 中出現,要麼在 select 的列中出現,要麼在外查
詢中出現。

3. from

from 子查詢時要給數據表指定一個別名。from (select ..) [as] 別名 where...

4. union

select 語句 union [all] select 語句

union 會去重

5. join 外鏈接查詢

select * from tableA A [left、right] join tableB B on A.id = B.id

6. join 交叉鏈接

select * from tableA,tableB

select * from tableA cross join tableB

逗號與 cross join 區別是逗號不能使用 on

結果會有 n * n 條記錄(笛卡爾乘積)

7. join 內鏈接

select * from tableA A inner join tableB B on A.id = B.id

select * from tableA A inner join tableB B using(id)

using(字段) 能夠合併相同字段,而且符合 A.id = B.id

內鏈接在沒有條件時和交叉鏈接沒有區別。

STRAIGHT_JOIN 能夠手動指定驅動表

六 索引的建立、刪除和查看

1. 建立索引

方法一

-- 普通索引
ALTER TABLE 表名稱 ADD INDEX index_name (column_list)
-- 惟一索引
ALTER TABLE 表名稱 ADD UNIQUE (column_list)
-- 主鍵索引
ALTER TABLE 表名稱 ADD PRIMARY KEY (column_list)

方法二

CREATE INDEX index_name ON 表名稱 (column_list)
CREATE UNIQUE INDEX index_name ON 表名稱 (column_list)

column_list 指出對哪些列進行索引,多列時各列之間用逗號分隔。
索引名index_name可選,缺省時,MySQL將根據第一個索引列賦一個名稱。
另外,ALTER TABLE容許在單個語句中更改多個表,所以能夠在同時建立多個索引。

2. 刪除索引

-- 刪除索引
DROP INDEX index_name ON 表名稱;
ALTER TABLE 表名稱 DROP INDEX index_name;
-- 刪除主鍵
ALTER TABLE 表名稱 DROP PRIMARY KEY;

3. 查看索引

show index from 表名稱;
show keys from 表名稱;

4. 手動選擇索引

  • USE INDEX : 向優化器提示如何選擇索引
  • IGNORE INDEX : 忽略索引
  • FORCE INDEX : 強制使用索引
select * from tableA USE INDEX (key1, key2) where key1=1 and key2=2

七 外鍵

1. 增長外鍵

建表時

constraint 外鍵名 foreign key(外鍵字段) references 關聯表名(關聯字段);

修改表

alter table 表名 add constraint 外鍵名 foreign key(外鍵字段名) references 外表表名(對應的表的主鍵字段名);

2. 刪除外鍵

ALTER TABLE table-name DROP FOREIGN KEY key-id;

八 流程控制&函數

1 內置函數&方法

1.1 if

IF(expr1,expr2,expr3)

若是 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),則 IF()的返回值爲expr2; 不然返回值則爲 expr3。

1.2 CASE when

SELECT CASE 1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END as testCol

1.3 IFNULL

IFNULL(expr1,expr2)

假如expr1 不爲 NULL,則 IFNULL() 的返回值爲 expr1; 不然其返回值爲 expr2。

2 自定義存儲過程&函數

2.1 查看

查詢數據庫中的存儲過程和函數

- 存儲過程
show procedure status;
select `name` from mysql.proc where db = '<dbname>' and `type` = 'PROCEDURE';

-- 函數
show function status;
select `name` from mysql.proc where db = '<dbname>' and `type` = 'FUNCTION'

查看存儲過程或函數的建立代碼

show create procedure <proc_name>;
show create function <func_name>;

九 視圖

1. 建立

create or replace view <視圖名>(<列名 1>,<列名 2>...) as <select 語句>;

2. 刪除

drop view <視圖 1> [,視圖 2....視圖 n];

十 觸發器

trigger_time: { BEFORE | AFTER } -- 事件以前仍是以後觸發
trigger_event: { INSERT | UPDATE | DELETE } -- 三個類型
trigger_order: { FOLLOWS | PRECEDES } other_trigger_name

假設定義一個觸發器,每次插入把 ctime 設爲當前時間

delimiter // -- 更改結束符
create trigger <觸發器名字>
before insert on <表名>
for each row
begin
set new.ctime=now();
end;//
delimiter ;

假設定義一個觸發器,每次更新把 mtime 設爲當前時間

delimiter // -- 更改結束符
create trigger <觸發器名字>
before update on <表名>
for each row
begin
set new.mtime=now();
end;//
delimiter ;

十一 查看狀態

# 查看狀態
status;
show status;

# innodb 狀態
show innodb status;

# 查看參數
show variables like '%參數名稱%';

# 查看隔離級別
select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+

十二 導出導入

1. 導出到文件

select * into outfile 文件地址 [控制格式] form tableA;

導出到 csv,並壓縮

shell> mysql -B -u帳號 -p -e "SELECT語句" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" | gzip > data.csv.gz

控制格式同導入文件

2. 導入文件

load data infile 文件名 [replace|ignore] into table 表名 [控制格式]
  • replaceignore: 表示對主鍵重複的數據處理方式
  • 控制格式 fields terminated by '\t' enclosed by '' escaped by '\\'

e.g.

SELECT * INTO OUTFILE '/tmp/data.txt' 
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM tableA;

十三 統計語句

1. 計算最大可能使用內存

MySQL >= 8

select
(@@key_buffer_size + @@query_cache_size + @@tmp_table_size
+ @@innodb_buffer_pool_size +
@@innodb_additional_mem_pool_size
+ @@innodb_log_buffer_size
+ @@max_connections * (
@@read_buffer_size + @@read_rnd_buffer_size
+ @@sort_buffer_size+ @@join_buffer_size
+ @@binlog_cache_size + @@thread_stack
)
)/1024/1024/1024 as max_mem_G;

MySQL < 8

select
(@@key_buffer_size + @@query_cache_size + @@tmp_table_size
+ @@innodb_buffer_pool_size
+ @@innodb_log_buffer_size
+ @@max_connections * (
@@read_buffer_size + @@read_rnd_buffer_size
+ @@sort_buffer_size+ @@join_buffer_size
+ @@binlog_cache_size + @@thread_stack
)
)/1024/1024/1024 as max_mem_G;

2. 數據大小

數據總大小

SELECT ROUND(SUM(DATA_LENGTH)/1024/1024/1024,2) as data_size_G,ROUND(SUM(INDEX_LENGTH)/1024/1024/1024,2) as index_G, ROUND(SUM(DATA_LENGTH+INDEX_LENGTH)/1024/1024/1024,2) as total_size_G,SUM(TABLE_ROWS) as rows FROM information_schema.TABLES;

某個庫大小

SELECT ROUND(SUM(DATA_LENGTH)/1024/1024/1024,2) as data_size_G,ROUND(SUM(INDEX_LENGTH)/1024/1024/1024,2) as index_G, ROUND(SUM(DATA_LENGTH+INDEX_LENGTH)/1024/1024/1024,2) as total_size_G,SUM(TABLE_ROWS) as rows FROM information_schema.TABLES WHERE TABLE_SCHEMA='庫名';

統計全部庫按大小排序

SELECT TABLE_SCHEMA, ROUND(SUM(DATA_LENGTH)/1024/1024/1024,2) as data_size_G,ROUND(SUM(INDEX_LENGTH)/1024/1024/1024,2) as index_G, ROUND(SUM(DATA_LENGTH+INDEX_LENGTH)/1024/1024/1024,2) as total_size_G,SUM(TABLE_ROWS) as rows FROM information_schema.TABLES group by TABLE_SCHEMA order by data_size_G desc;

3. 統計鏈接IP

select SUBSTRING_INDEX(host,':',1) as ip , count(*) from information_schema.processlist group by ip;

4. 查看鎖

mysql5.6

SELECT
    r.trx_id waiting_trx_id,
    r.trx_mysql_thread_id waiting_thread,
    r.trx_query waiting_query,
    b.trx_id blocking_trx_id,
    b.trx_mysql_thread_id blocking_thread,
    b.trx_query blocking_query
FROM
    information_schema.innodb_lock_waits w
INNER JOIN
    information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
INNER JOIN
    information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;



waiting_trx_id -- 請求的事物ID
waiting_thread -- 請求的線程ID
waiting_query -- 等待的SQL語句
blocking_trx_id -- 阻塞上面請求的事物的ID
blocking_thread -- 阻塞的線程ID
blocking_query -- 阻塞的當前的SQL,這個是沒法看到的,除非SQL尚未執行完成(不必定是該事物當中的最後一條SQL語句)

mysql5.7

select * from sys.innodb_lock_waits;

5. 查看沒有主鍵的表

SELECT
    table_schema, table_name
FROM
    information_schema.TABLES
    WHERE
    table_name NOT IN (
        SELECT DISTINCT
            TABLE_NAME
        FROM
            information_schema.COLUMNS
        WHERE
            COLUMN_KEY = 'PRI')
        AND table_schema NOT IN ('mysql' , 'information_schema','sys', 'performance_schema');

6. 索引合理性

SELECT
    t.TABLE_SCHEMA,t.TABLE_NAME,INDEX_NAME, CARDINALITY, TABLE_ROWS,
    CARDINALITY/TABLE_ROWS AS SELECTIVITY
FROM
    information_schema.TABLES t,
    (
        SELECT
            table_schema,
            table_name,
            index_name,
            cardinality
        FROM information_schema.STATISTICS
        WHERE (table_schema,table_name,index_name,seq_in_index) IN (
            SELECT
                table_schema,
                table_name,
                index_name,
                MAX(seq_in_index)
            FROM
                information_schema.STATISTICS
            GROUP BY table_schema , table_name , index_name
        )
    ) s
WHERE
    t.table_schema = s.table_schema
        AND t.table_name = s.table_name 
        AND t.table_schema = '數據庫名' -- 指定某一個庫名
ORDER BY SELECTIVITY;
  • SELECTIVITY越接近1,越合理
  • 由於聚合索引會在 statistics 表中產生多條數據,因此 MAX(seq_in_index) 能夠拿到完整索引那條

7. 統計processlist各個狀態數量

shell> mysql -uroot -p<password> -e 'show processlist \G' | grep 'State:' | sort | uniq -c | sort -rn

十四 運維語句&命令

1. 更新統計信息

analyze table <table_name>;

2. 從新整理表

optimize table <table_name>;

3. 檢查表(MyISAM)

check table <table_name>;

4. 修復表(MyISAM)

repair table <table_name>;

5. 批量檢查或修復表

# 檢查全部表
shell> mysqlcheck -u root -p<password> -A -c 

# 修復全部表
shell> mysqlcheck -u root -p<password> -A -c

6. 統計每秒慢日誌

shell> awk '/^# Time:/{print $3, $4, c;c=0}/^# User/{c++}' slowquery.log

7. 查看binlog日誌

基於position

mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS --start-position=<start_pos> --stop-position=<stop_pos> <mysql binlog文件> > result.sql

基於時間點

mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS --start-datetime='<開始時間>' --stop-datetime='<結束時間>' <mysql binlog文件> > result.sql

查看某個pos的日誌

mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS <mysql binlog文件> | grep -A '20' <pos>

8. 打開句柄數

統計各進程打開句柄數:

lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr | head -n 10

# 某個進程
lsof -n|awk '$2=="<某個進程的PID>" {print $2}'|sort|uniq -c|sort -nr | head -n 10

統計各用戶打開句柄數

lsof -n|awk '{print $3}'|sort|uniq -c|sort -nr

# mysql用戶
lsof -n|awk '$3 == "mysql" {print $3}'|sort|uniq -c|sort -nr

統計各命令打開句柄數

lsof -n|awk '{print $1}'|sort|uniq -c|sort -nr

9. 導出用戶權限(shell腳本)

#/bin/bash

user='username'
pass='password'
sock='socket'

expgrants()  
{  
  mysql -B -u"${user}" -p"${pass}" -S"${sock}" -N $@ -e "SELECT CONCAT(  'SHOW CREATE USER   ''', user, '''@''', host, ''';' ) AS query FROM mysql.user" | \
  mysql -u"${user}" -p"${pass}" -S"${sock}" -f  $@ | \
  sed 's#$#;#g;s/^\(CREATE USER for .*\)/-- \1 /;/--/{x;p;x;}' 
 
  mysql -B -u"${user}" -p"${pass}" -S"${sock}" -N $@ -e "SELECT CONCAT(  'SHOW GRANTS FOR ''', user, '''@''', host, ''';' ) AS query FROM mysql.user" | \
  mysql -u"${user}" -p"${pass}" -S"${sock}" -f  $@ | \
  sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/-- \1 /;/--/{x;p;x;}'   
}

而後執行腳本

10. 批量殺鏈接

方法一

select concat('KILL ',id,';') from information_schema.processlist where user='某個用戶' into outfile '/tmp/kill.txt';
source /tmp/kill.txt;

方法二

mysqladmin -uroot -p processlist|awk -F "|" '{if($3 == "要殺的鏈接的用戶")print $2}'|xargs -n 1 mysqladmin -uroot -p kill
相關文章
相關標籤/搜索