基本sql語句

標準SQL包含了4種基本的語句類別:html

DDL語句,數據定義語句,主要用來定義數據庫,表名,字段,例如create,drop,alter.
DML語句,數據操做語句,用來對數據記錄的增刪改查,還用來保證數據的一致xing。主要有select,delete,insert,update語句。
DCL語句,數據控制語句,用於控制不一樣數據對象訪問級別的語句。定義了數據庫、表、表、用戶的訪問權限和徹底級別。經常使用的語句包括grant、revoke等
TCL語句,事務控制語句,用來確保事務的特xing。
CREATE TABLE建表語句
在介紹建表語句以前,先簡單說明一下建立數據庫的語句。mysql

建立數據庫
數據庫建立以後,而後就是建表:git

複製代碼
建表語句的做用就是在數據庫建立一張二維表,所以在建表語句要指定每個字段名(二維表中的列名),還有要指定對填入這些字段的數據的限制(約束條件),同時建表語句還能夠指定這張表的字符集,以及以前規劃好的索引等。
create table tb1(
c1 int auto_increment primary key,
c2 varchar(20)
);
建立了tb1表,表中有兩列(兩個字段),
auto_increment: 指定字段c1爲自增字段,mysql中一個表中只能有一個自增字段,且須爲主鍵。
mysql> show create table tb1\G
1. row
Table: tb1
Create Table: CREATE TABLE tb1 (
c1 int(11) NOT NULL AUTO_INCREMENT,
c2 varchar(20) DEFAULT NULL,
PRIMARY KEY (c1)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)github

#查看建表語句,mysql會默認選擇表的存儲引擎和字符集
mysql> system ls /data/mysql/mytest/tb1.*
/data/mysql/mytest/tb1.frm /data/mysql/mytest/tb1.ibd
#在datadir對應的目錄下面會生成對應的表結構文件tb1.frm,和數據文件tb1.ibd。
複製代碼
MySQL支持在建表時指定temporary參數,這樣建立的表是臨時表,臨時表是基於會話級別的表。sql

複製代碼
#建立臨時表,臨時表使用show tables查不到其存在,可是能夠查看錶結構,也能夠向臨時表插入數據
mysql> create temporary table tb2(id int, info varchar(20));
Query OK, 0 rows affected (0.00 sec)數據庫

mysql> show tables;
+------------------+
| Tables_in_mytest |
+------------------+
| tb1 |
+------------------+
1 row in set (0.00 sec)瀏覽器

mysql> show create table tb2;
+-------+--------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------+
| tb2 | CREATE TEMPORARY TABLE tb2 (
id int(11) DEFAULT NULL,
info varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)ide

mysql> insert into tb2 values(1,"a");
Query OK, 1 row affected (0.00 sec)
#臨時表的表結構存在於/tmp/目錄下面
mysql> show variables like "tmpdir";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| tmpdir | /tmp |
+---------------+-------+
1 row in set (0.01 sec)
[root@test3 tmp]# pwd
/tmp
[root@test3 tmp]# ls
#sql2966_99_0.frm
#臨時表的數據文件在MySQL5.7以後由專門的文件存儲
mysql> show variables like "innodb%temp%";
+----------------------------+-----------------------+
| Variable_name | Value |
+----------------------------+-----------------------+
| innodb_temp_data_file_path | ibtmp1:12M:autoextend |
+----------------------------+-----------------------+
1 row in set (0.00 sec)
#臨時表有專門的存儲引擎
mysql> show variables like "default%tmp%";
+----------------------------+--------+
| Variable_name | Value |
+----------------------------+--------+
| default_tmp_storage_engine | InnoDB |
+----------------------------+--------+
1 row in set (0.00 sec)
#臨時表只對當前會話有效,當前會話斷開,臨時表會自動刪除,在其他的會話也看不到臨時表。
mysql> insert into tb2 values(1,"a");
ERROR 1146 (42S02): Table 'mytest.tb2' doesn't exist
mysql>
複製代碼
crate table語句還有不少參數可使用,這些只是基本的用法,能夠查看官方文檔,也能夠查看work bench中的介紹。函數

刪除數據庫和表
複製代碼
#刪除數據庫
mysql> drop database mytesti;
Query OK, 0 rows affected (0.00 sec)測試

#刪除表,和表結構一塊兒刪除
mysql> drop table tb1;
Query OK, 0 rows affected (0.02 sec)
#刪除表中的全部記錄,可是不刪除表結構
mysql> truncate tb4;
Query OK, 0 rows affected (0.04 sec)

#delete用來刪除表中的數據
mysql> delete table tb2;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'table tb2' at line 1
mysql> delete from tb2 where c = 1;
Query OK, 0 rows affected (0.00 sec)
複製代碼
修改表結構
複製代碼
#建立以下表
CREATE TABLE IF NOT EXISTS tb2 (
id INT,
NAME VARCHAR (20),
email VARCHAR (50)
);
#查看錶的結構以下:
mysql> desc tb2;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| NAME | varchar(20) | YES | | NULL | |
| email | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

#修改表名
// ALTER TABLE OLD_TB_NAME RENAME [TO] NEW_TB_NAME;
mysql> alter table tb2 rename to tb3;
Query OK, 0 rows affected (0.00 sec)
// TO能夠省略
mysql> alter table tb3 rename tb2;
Query OK, 0 rows affected (0.00 sec)

#修改字段數據類型(把id字段的int類型修改成varchar類型)
// ALTER TABLE TBNAME MODIFY 字段名 新屬xing
ALTER TABLE tb2 MODIFY id VARCHAR(10);
mysql> desc tb2;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | varchar(10) | YES | | NULL | |
| NAME | varchar(20) | YES | | NULL | |
| email | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

#修改字段名 (把上面的id字段名修改成user_id)
ALTER TABLE TBNAME CHANGE 舊字段名 新字段名 約束條件;
#須要注意的是這種方法不只能夠修改字段名,還能夠修改字段的數據類型。
ALTER TABLE tb2 change id user_id varchar(10);

#增長字段
//ALTER TABLE 表名 ADD 新字段名 date FIRST|AFTER 字段A名。 first表示新加的字段在A的前面,after表示在A的後面。
ALTER TABLE tb2 ADD birth date; #默認的新增字段是在最後插入的。
mysql> desc tb2;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| user_id | varchar(10) | YES | | NULL | |
| NAME | varchar(20) | YES | | NULL | |
| email | varchar(50) | YES | | NULL | |
| birth | date | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

#刪除字段
//ALTER TABLE 表名 DROP 字段名;
ALTER TABLE tb2 DROP user_id;

#字段排序:
ALTER TABLE TBNAME MODIFY 字段1 數據類型 FIRST|AFTER 字段2.

#更改表的存儲引擎:
ALTER TABLE 表名 engine = "存儲引擎名"

#刪除外鍵
ALTER TABLE 表名 FOREIGN KEY 外鍵別名。
複製代碼
insert插入數據
insert用於向表中插入數據。

insert插入數據
update更新數據
update更新語句通常於where條件句聯合使用。

mysql> update tb2 set name = "b" where id =3;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0

#若是不使用where條件語句限制,則更新表中全部的行
select查詢
在查詢以前先導入MySQL官方提供的employeeso庫數據。

下載地址:https://github.com/datacharmer/test_db/archive/master.zip

方法:直接下載zip壓縮包,而後直接導入employees.sql文件便可

導入的表,各個表之間的關係以下:

單表查詢

複製代碼
mysql> select * from employees limit 1;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------+--------+------------+
| 10001 | 1953-09-02 | Georgi | Facello | M | 1986-06-26 |
+--------+------------+------------+-----------+--------+------------+
1 row in set (0.00 sec)

mysql> select emp_no, concat(first_name, " ", last_name) as full_name, gender from employees limit 1;
+--------+----------------+--------+
| emp_no | full_name | gender |
+--------+----------------+--------+
| 10001 | Georgi Facello | M |
+--------+----------------+--------+
1 row in set (0.01 sec)

#查詢可使用*號代替表中全部的字段,也可使用對應字段的字符,只查詢出對應的要查詢的字段。
#concat函數,就是鏈接字符串,在這裏和as結合,鏈接了兩個字段,而且重命名爲full_name。
複製代碼
MySQL中有許多內嵌的函數能夠調用,詳細的函數列表參照:https://dev.mysql.com/doc/refman/5.7/en/string-functions.html 可使用Google瀏覽器打開,能夠翻譯爲中文!

單表查詢和一些條件語句結合:

查看錶中記錄的數量

複製代碼
mysql> select count() from employees;
+----------+
| count(
) |
+----------+
| 300024 |
+----------+
1 row in set (0.53 sec)
複製代碼
使用order by語句按照某字段排序:

order by
使用where條件語句:

where條件語句
查詢分組:

複製代碼
#一個報錯:
mysql> select emp_no, dept_no from dept_manager group by dept_no;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'employees.dept_manager.emp_no' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

#解決,更改sql_mode;
http://www.ywnds.com/?p=8184
複製代碼
group by分組
group by聚合函數,加上with rollup函數,會統計一個總的結果在最後一行。

複製代碼
mysql> select count(emp_no), dept_no from dept_manager group by dept_no with rollup;
+---------------+---------+
| count(emp_no) | dept_no |
+---------------+---------+
| 2 | d001 |
| 2 | d002 |
| 2 | d003 |
| 4 | d004 |
| 2 | d005 |
| 4 | d006 |
| 2 | d007 |
| 2 | d008 |
| 4 | d009 |
| 24 | NULL |
+---------------+---------+
10 rows in set (0.00 sec)
#加上having條件語句
mysql> select count(emp_no), dept_no from dept_manager group by dept_no with rollup having dept_no > "d006";
+---------------+---------+
| count(emp_no) | dept_no |
+---------------+---------+
| 2 | d007 |
| 2 | d008 |
| 4 | d009 |
+---------------+---------+
3 rows in set (0.00 sec)

複製代碼
查詢某個表的數據大小以及索引大小,以及數據和索引的總大小

複製代碼
USE information_schema;
select b.TABLE_NAME, b.ddata, b.dindex, sum(b.ddata)+SUM(b.dindex) as total from
(
SELECT
TABLE_NAME,
TRUNCATE (Data_length / 1024 / 1024, 2) AS ddata,
TRUNCATE (INDEX_LENGTH / 1024 / 1024, 2) AS dindex
FROM
TABLES where TABLE_NAME = 't_hk_stock_news') as b;

執行結果以下
+-----------------+--------+--------+--------+
| TABLE_NAME | ddata | dindex | total |
+-----------------+--------+--------+--------+
| t_hk_stock_news | 290.00 | 278.00 | 568.00 |
+-----------------+--------+--------+--------+
1 row in set (0.00 sec)
#這裏面有個構建的新字段,而後再根據構建的新字段求兩者的和。
複製代碼

聯合查詢

聯合查詢分爲:內鏈接和外鏈接,其中外鏈接又包含左鏈接和右鏈接。

內鏈接:

需求1:求出經理人員的工號,姓名,xing別,部門代號(暫時不考慮部門名稱)。(經理就是dept_manager中的員工)

複製代碼
#使用where條件語句聯合兩張表查詢
SELECT
e.emp_no,
concat( e.first_name, " ", e.last_name ),
e.gender,
dp.dept_no
FROM
employees AS e,
dept_manager AS dp
WHERE
dp.emp_no = e.emp_no;

#採用內聯合查詢的方法
SELECT
e.emp_no,
concat( e.first_name, " ", e.last_name ),
e.gender,
dp.dept_no
FROM
employees AS e
INNER JOIN dept_manager AS dp ON dp.emp_no = e.emp_no;
複製代碼
由上面這個查詢能夠體會一下的鏈接的含義: 把兩張或多張表中,相同的字段聯合起來的的查詢,當值相等時,就會查詢出其結果。

上面的查詢中,咱們再加入一張表,把部門的代號換爲部門名稱。

複製代碼
SELECT
e.emp_no,
concat( e.first_name, " ", e.last_name ),
e.gender,
dp.dept_no,
dep.dept_name
FROM
employees AS e,
dept_manager AS dp,
departments AS dep
WHERE
dp.emp_no = e.emp_no
AND dp.dept_no = dep.dept_no;

#使用inner聯合查詢的方式
SELECT
e.emp_no,
concat( e.first_name, " ", e.last_name ),
e.gender,
dp.dept_no,
dep.dept_name
FROM
employees AS e
INNER JOIN dept_manager AS dp ON dp.emp_no = e.emp_no
INNER JOIN departments AS dep ON dp.dept_no = dep.dept_no;
複製代碼
外鏈接: 外鏈接分爲左鏈接和右鏈接,這兩個鏈接的方式是同樣的,不一樣的是刷選數據的方式。

語法格式以下:

SELECT 字段名 FROM 表名1 LEFT| RIGHT 表名2
ON 表名1.字段名1 = 表名2.字段名2;
有如下的實例,咱們來理解如下左查詢和右查詢:

View Code
在上面的employyes庫中表關係圖中,咱們來作一個以下檢索。

要求求出普通員工的員工號,姓名(用一個字段顯示),xing別,最近的薪水,最近的一個部門,和最近的一個title。
(由於在titles,salries,dept_emp表中,同一個工號員工有多條數據,所以咱們能夠根據時間,選擇最近的員工)。

上面的需求一步一步拆解:先求出普通員工的工號,姓名,xing別和部門的代號,這個只涉及兩張表的查詢:

複製代碼
SELECT
e.emp_no,
concat( e.first_name, " ", e.last_name ) AS full_name,
e.gender,
dp.dept_no
FROM
employees AS e
LEFT JOIN dept_manager AS dp ON dp.emp_no = e.emp_no
WHERE
dp.dept_no IS NULL;

#這個表查詢處理有30萬條記錄,所以會比較慢,暫時不考慮xing能,爲了驗證這個結果,能夠設置where條件dp.dept_no IS NOT NULL,這樣查出來的結果是經理的我的信息,剛好是24條。
複製代碼
再求出員工的最近的薪水:

看一下薪水錶的數據:

複製代碼
mysql> select * from salaries where emp_no = "10002";
+--------+--------+------------+------------+
| emp_no | salary | from_date | to_date |
+--------+--------+------------+------------+
| 10002 | 65828 | 1996-08-03 | 1997-08-03 |
| 10002 | 65909 | 1997-08-03 | 1998-08-03 |
| 10002 | 67534 | 1998-08-03 | 1999-08-03 |
| 10002 | 69366 | 1999-08-03 | 2000-08-02 |
| 10002 | 71963 | 2000-08-02 | 2001-08-02 |
| 10002 | 72527 | 2001-08-02 | 9999-01-01 |
+--------+--------+------------+------------+
6 rows in set (0.00 sec)

#咱們要查詢獲得的是這個表中,salary最近的那個值,也就是時間距如今最近,須要注意的是,時間最近的薪水不必定是最高的!
mysql> select emp_no, max(from_date) from salaries group by emp_no limit 4;
+--------+----------------+
| emp_no | max(from_date) |
+--------+----------------+
| 10001 | 2002-06-22 |
| 10002 | 2001-08-02 |
| 10003 | 2001-12-01 |
| 10004 | 2001-11-27 |
+--------+----------------+
4 rows in set (0.11 sec)

#這樣咱們得出的是,每一個員工的最近的from_date,而後根據這兩個條件就能夠求出員工最近的薪水。(這張表用的是複合索引,暫時先不提)
#SQL語句以下
SELECT
a.emp_no, a.salary
from salaries a
WHERE a.from_date = (SELECT max(b.from_date) from salaries b WHERE a.emp_no = b.emp_no GROUP BY b.emp_no);
#咱們要的是員工的最近的薪水錶,而不是最高的薪水錶!
複製代碼
按照上面的方法咱們能夠求出,員工距離如今最近的部門代號,和title。

title的SQL語句仿照上面寫就能夠了,可是員工的部門職稱,須要再聯合一張表查詢,結果以下:

複製代碼
SELECT
a.emp_no,
a.dept_no,
dp.dept_name
FROM
dept_emp AS a,
departments AS dp
WHERE #WHERE條件句是一個and語句
from_date = (
SELECT #and語句的第一個條件是子查詢,
max(from_date)
FROM
dept_emp AS b
WHERE
a.emp_no = b.emp_no
GROUP BY
emp_no
)
AND dp.dept_no = a.dept_no #and語句的第二個條件語句
ORDER BY a.emp_no;

#查詢的結果就是每一個員工的最新職稱
複製代碼
把求出的三個查詢和最上面的普通員工信息的查詢聯合起來就是咱們要得道的SQL查詢:

最後的代碼
查詢的結果執行時,能夠加上limit函數,否則會很慢,至於優化問題,暫時先無論!

union聯合查詢

複製代碼
有兩張表以下:
mysql> select * from tb1;
+----+------+
| c1 | c2 |
+----+------+
| 1 | zhao |
| 2 | qina |
| 3 | b |
| 4 | c |
+----+------+
4 rows in set (0.00 sec)

mysql> select * from tb2;
+------+------+
| id | NAME |
+------+------+
| 1 | a |
| 3 | b |
| 4 | c |
| 5 | d |
| 6 | e |
+------+------+
5 rows in set (0.00 sec)

#使用UNION聯合查詢, 去重複,把重複的數值自動去掉
mysql> select from tb1
-> union
-> select
from tb2;
+------+------+
| c1 | c2 |
+------+------+
| 1 | zhao |
| 2 | qina |
| 3 | b |
| 4 | c |
| 1 | a |
| 5 | d |
| 6 | e |
+------+------+
7 rows in set (0.00 sec)
#使用all關鍵字,會把重複的行也查詢出來
mysql> select from tb1
-> union all
-> select
from tb2;
+------+------+
| c1 | c2 |
+------+------+
| 1 | zhao |
| 2 | qina |
| 3 | b |
| 4 | c |
| 1 | a |
| 3 | b |
| 4 | c |
| 5 | d |
| 6 | e |
+------+------+
9 rows in set (0.00 sec)
複製代碼
給查詢的結果加上行號:

查詢員工信息時,給查詢的結果加上行號。

添加查詢的行號
MySQL的一個排名問題:

複製代碼
#有以下的數據,按照成績排名:
mysql> select * from rank;
+------+-------+
| id | score |
+------+-------+
| 1 | 10 |
| 2 | 20 |
| 3 | 20 |
| 4 | 30 |
| 5 | 40 |
| 6 | 40 |
| 7 | 20 |
+------+-------+
7 rows in set (0.00 sec)
#成績有相同的,按照成績排名
set @prev_value = NULL;
set @rank_count = 0;

SELECT id, score,
CASE
WHEN @prev_value = score THEN @rank_count
WHEN @prev_value := score THEN @rank_count := @rank_count + 1
end as rank_column
from rank
ORDER BY score;

#若是咱們指望有一條SQL語句完成排名,能夠仿照上面的方法:mysql> SELECT id, score, -> CASE-> WHEN @prev1_value = score THEN @rank1_count-> WHEN @prev1_value := score THEN @rank1_count := @rank1_count + 1-> end as rank_column-> from rank, (SELECT @prev1_value := NULL, @rank1_count :=0 ) as rank_column-> ORDER BY score; #注意能夠測試一下加ORDER BY與不加ORDER BY的結果,會不同的!+------+-------+-------------+| id | score | rank_column |+------+-------+-------------+| 1 | 10 | 1 || 2 | 20 | 2 || 3 | 20 | 2 || 7 | 20 | 2 || 4 | 30 | 3 || 5 | 40 | 4 || 6 | 40 | 4 |+------+-------+-------------+7 rows in set (0.00 sec)SQL語句以下:SELECT id, score, CASEWHEN @prev1_value = score THEN @rank1_countWHEN @prev1_value := score THEN @rank1_count := @rank1_count + 1end as rank_columnfrom rank, (SELECT @prev1_value := NULL, @rank1_count :=0 ) as rank_columnORDER BY score;

相關文章
相關標籤/搜索