SQL語言的興起與語法標準
20世紀70年代,IBM開發出SQL,用於DB2
1981年,IBM推出SQL/DS數據庫
業內標準微軟和Sybase的T-SQL,Oracle的PL/SQL
SQL做爲關係型數據庫所使用的標準語言,最初是基於IBM的實如今1986年被批准的。 1987年,「國際標準化組織(ISO)」 把ANSI(美國國家標準化組織)SQL做爲國際標準。
SQL:ANSI SQL
SQL-1986, SQL-1989, SQL-1992, SQL-1999, SQL-2003,SQL-2008, SQL-2011html
SQL語言規範
- 在數據庫系統中,SQL語句不區分大小寫(建議用大寫)
- SQL語句可單行或多行書寫,以「;」 結尾
- 關鍵詞不能跨多行或簡寫
- 用空格和縮進來提升語句的可讀性
- 子句一般位於獨立行,便於編輯,提升可讀性
- 註釋:
- SQL標準:
/*註釋內容*/ : 多行註釋
-- 註釋內容 : 單行註釋,注意有空格
- MySQL註釋:
#
數據庫對象
- 數據庫的組件(對象):
數據庫、表、索引、視圖、用戶、存儲過程、函數、觸發器、事件調度器等
- 命名規則:
必須以字母開頭
可包括數字和三個特殊字符(# _ $)
不要使用MySQL的保留字
同一database(Schema)下的對象不能同名
SQL語句分類:
- DDL: Data Defination Language 數據定義語言 :命令後面跟database,table
CREATE,DROP,ALTER
- DML: Data Manipulation Language 數據操縱語言 : 命令後面跟record
INSERT,DELETE,UPDATE
- DCL:Data Control Language 數據控制語言
GRANT,REVOKE,COMMIT,ROLLBACK
- DQL:Data Query Language 數據查詢語言
SELECT
SQL語句構成
- SQL語句構成:
Keyword組成clause
多條clause組成語句
- 示例:
SELECT * :SELECT子句
FROM products : FROM子句
WHERE price>400 :WHERE子句
- 說明:一組SQL語句,由三個子句構成,SELECT,FROM和WHERE是關鍵字
注意點1:
- SQL語句的對象是大小寫敏感的,必須針對寫的一字不錯(好比數據庫名字,表的名字),可是其餘的語句大小寫不敏感,怎麼寫均可以(注意表中的字段名字大小寫不敏感,能夠隨意寫,不過通常仍是寫的和字段同樣比較好)
- SQL語言的多行註釋能夠寫在一個命令的中間,不過通常也不這樣寫,都是些在命令的前面或者後面。MySQL可用#註釋一行,這是本身獨有的註釋方式。
數據庫操做
- 建立數據庫:
CREATE DATABASE|SCHEMA [IF NOT EXISTS] 'DB_NAME';
CHARACTER SET 'character set name’COLLATE 'collate name'
- 修改數據庫:
ALTER DATABASE DB_NAME character set utf8;
- 刪除數據庫
DROP DATABASE|SCHEMA [IF EXISTS] 'DB_NAME';
- 查看支持全部字符集:
SHOW CHARACTER SET;
- 查看支持全部排序規則:
SHOW COLLATION;
- 獲取命令使用幫助:
mysql> HELP KEYWORD;
- 查看數據庫列表:
mysql> SHOW DATABASES;
表
表:二維關係mysql
- 設計表:遵循規範
- 定義:字段,索引
字段:字段名,字段數據類型,修飾符
約束,索引:應該建立在常常用做查詢條件的字段上
建立表
建立表:CREATE TABLE
(1) 直接建立
(2) 經過查詢現存表建立;新表會被直接插入查詢而來的數據
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_options] [partition_options] select_statement
(3) 經過複製現存的表的表結構建立,但不復制數據
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name { LIKE old_tbl_name | (LIKE old_tbl_name) }linux
- 注意:
Storage Engine是指表類型,也即在表建立時指明其使用的存儲引擎,同一庫中不一樣表可使用不一樣的存儲引擎
- 同一個庫中表建議要使用同一種存儲引擎類型
表操做1
- 查看全部的引擎:SHOW ENGINES
- 查看錶:SHOW TABLES [FROM db_name]
- 查看錶結構:DESC [db_name.]tb_name
SHOW COLUMNS FROM [db_name.]tb_name
- 刪除表:DROP TABLE [IF EXISTS] tb_name
- 查看錶建立命令:SHOW CREATE TABLE tbl_name
- 查看錶狀態:SHOW TABLE STATUS LIKE 'tbl_name’
- 查看庫中全部表狀態:SHOW TABLE STATUS FROM db_name
數據類型
數據類型:正則表達式
- 數據長什麼樣
- 數據須要多少空間來存放
系統內置數據類型和用戶定義數據類型
MySql支持多種列類型:
- 數值類型
- 日期/時間類型
- 字符串(字符)類型
選擇正確的數據類型對於得到高性能相當重要,三大原則:
- 更小的一般更好,儘可能使用可正確存儲數據的最小數據類型
- 簡單就好,簡單數據類型的操做一般須要更少的CPU週期
- 儘可能避免NULL,包含爲NULL的列,對MySQL更難優化
數據類型分類
更詳細可見官方文檔:
https://dev.mysql.com/doc/refman/8.0/en/data-types.htmlsql
- 整型
- tinyint(m) 1個字節 範圍(-128~127)
- smallint(m) 2個字節 範圍(-32768~32767)
- mediumint(m) 3個字節 範圍(-8388608~8388607)
- int(m) 4個字節 範圍(-2147483648~2147483647)
- bigint(m) 8個字節 範圍(+-9.22*10的18次方)
注1:加了unsigned,則最大值翻倍,如:tinyint unsigned的取值範圍爲(0~255)
注2:int(m)裏的m是表示SELECT查詢結果集中的顯示寬度,並不影響實際的取值範圍,規定了MySQL的一些交互工具(例如MySQL命令行客戶端)用來顯示字符的個數。對於存儲和計算來講,Int(1)和Int(20)是相同的
- BOOL,BOOLEAN:布爾型,是TINYINT(1)的同義詞。zero值被視爲假,非zero值視爲真
- 浮點型(float和double),近似值
float(m,d) 單精度浮點型 8位精度(4字節) m總個數,d小數位
double(m,d) 雙精度浮點型16位精度(8字節) m總個數,d小數位
例:設一個字段定義爲float(6,3),若是插入一個數123.45678,實際數據庫裏存的是123.457,但總個數還以實際爲準,即6位
- 定點數
在數據庫中存放的是精確值,存爲十進制
decimal(m,d) 參數 m < 65 是總個數,d < 30且 d < m 是小數位
MySQL5.0和更高版本將數字打包保存到一個二進制字符串中(每4個字節存9個數字)。例如,decimal(18,9)小數點兩邊將各存儲9個數字,一共使用9個字節:小數點前的數字用4個字節,小數點後的數字用4個字節,小數點自己佔1個字節
浮點類型在存儲一樣範圍的值時,一般比decimal使用更少的空間。 float使用4個字節存儲。double佔用8個字節由於須要額外的空間和計算開銷,因此應該儘可能只在對小數進行精確計算時才使用decimal——例如存儲財務數據。但在數據量比較大的時候,能夠考慮使用bigint代替decimal
- 字符串(char,varchar,_text)
char(n) 固定長度,最多255個字符 :查詢速度塊
varchar(n) 可變長度,最多65535個字符 :查詢速度慢
tinytext 可變長度,最多255個字符
text 可變長度,最多65535個字符
mediumtext 可變長度,最多2的24次方-1個字符
longtext 可變長度,最多2的32次方-1個字符
BINARY(M) 固定長度,可存二進制或字符,長度爲0-M字節
VARBINARY(M) 可變長度,可存二進制或字符,容許長度爲0-M字節
內建類型:ENUM枚舉, SET集合
- 二進制數據:BLOB
BLOB和text存儲方式不一樣,TEXT以文本方式存儲,英文存儲區分大小寫,而Blob是以二進制方式存儲,不分大小寫
BLOB存儲的數據只能總體讀出
TEXT能夠指定字符集,BLOB不用指定字符集
- 日期時間類型
date 日期 '2008-12-2'
time 時間 '12:25:36'
datetime 日期時間 '2008-12-2 22:06:44'
timestamp 自動存儲記錄修改時間
YEAR(2), YEAR(4):年份
注意:timestamp字段裏的時間數據會隨其餘字段修改的時候自動刷新,這個數據類型的字段能夠存放這條記錄最後被修改的時間
修飾符
全部類型:
• NULL 數據列可包含NULL值
• NOT NULL 數據列不容許包含NULL值
• DEFAULT 默認值
• PRIMARY KEY 主鍵
• UNIQUE KEY 惟一鍵
• CHARACTER SET name 指定一個字符集
數值型
• AUTO_INCREMENT 自動遞增,適用於整數類型
• UNSIGNED 無符號數據庫
建立(定義)表示例
- CREATE TABLE students (id int UNSIGNED NOT NULL PRIMARYKEY,name VARCHAR(20)NOT NULL,age tinyint UNSIGNED);
- DESC students;
- CREATE TABLE students2 (id int UNSIGNED NOT NULL ,name VARCHAR(20) NOT NULL,age tinyint UNSIGNED,gender ENUM('m','f') DEFAULT 'm' ,PRIMARY KEY(id,name));
- 注意,只要是char類型的,不管是字段中仍是表中的相對應的char類型中的數據,都須要加上單引號引發來,否則會報錯
- 上面3中定義的primary key是複合主鍵,查看help create table中能夠看到。
表操做2
DROP TABLE [IF EXISTS] 'tbl_name';
ALTER TABLE 'tbl_name'
字段:
添加字段:add
ADD col1 data_type [FIRST|AFTER col_name]
刪除字段:drop
修改字段:
alter(默認值), change(字段名), modify(字段屬性)
索引:
添加索引:add index
刪除索引:drop index
表選項
修改:
查看錶上的索引:SHOW INDEXES FROM [db_name.]tbl_name;
查看幫助:Help ALTER TABLEexpress
修改表示例:
ALTER TABLE students RENAME s1;
ALTER TABLE s1 ADD phone varchar(11) AFTER name;
ALTER TABLE s1 MODIFY phone int;
ALTER TABLE s1 CHANGE COLUMN phone mobile char(11);
ALTER TABLE s1 DROP COLUMN mobile;
ALTER TABLE s1 character set utf8;
ALTER TABLE s1 change name name varchar(20) character set utf8;
Help ALTER TABLE 查看幫助
ALTER TABLE students ADD gender ENUM('m','f')
ALETR TABLE students CHANGE id sid int UNSIGNED NOT NULL PRIMARY KEY;
ALTER TABLE students drop primary key ;
ALTER TABLE students ADD UNIQUE KEY(name);
ALTER TABLE students ADD INDEX(age);
ALTER TABLE students drop primary key ;
DESC students;
SHOW INDEXES FROM students;
ALTER TABLE students DROP age;
注意點2(DDL語句):
- 能夠進入數據庫之後用help create [database | table ...] 來查看幫助如何建立數據庫和表等等
- 建立數據庫database的時候能夠選擇要建立的字符集以及它的排序規則是什麼(建立的時候就能夠定義寫上),建立以後則用alter命令修改,
- 能夠用show character set命令來查看當前數據庫支持的字符集以及其對應的默認的排序規則都有哪些。(utf8,utf8mb4,latin1等等)
- show collation查看排序規則
- 用show create database DATABASE_NAME 來查看建立的數據庫的默認字符集是什麼
- help show,help alter命令來查看幫助
- 除了2中提到的查看數據庫字符集的方式,還能夠直接進入database對應的文件夾內(注意要進入到數據庫對應的文件夾下的子文件夾database目錄內),其中的*.opt文件中就記錄着當前對應database的字符集和排序方式。
- 不過這樣的方式每次建立一個新的數據庫都沒法指定本身想要的字符集和排序方式,能夠直接把它寫入到配置文件中,指定整個mysql服務的字符集和排序方式(進入數據庫以後能夠用status查看),具體的配置選項參考下面的變量或者官網的選項說明。
- 注意下劃線和橫線在配置選項中沒有區別(寫在my.cnf中的)
下面是源碼編譯時用Cmake選項修改過的mysql數據庫服務爲utf8mb4字符集的這些參數:
14:29[root@centos7 ~]# mysqladmin variable -p123456 | grep character
| character_set_client | utf8mb4
| character_set_connection | utf8mb4
| character_set_database | utf8mb4
| character_set_filesystem | binary
| character_set_results | utf8mb4
| character_set_server | utf8mb4
| character_set_system | utf8
| character_sets_dir | /app/mysql/share/charsets/
14:29[root@centos7 ~]# mysqladmin variable -p123456 | grep collation
| collation_connection | utf8mb4_general_ci
| collation_database | utf8mb4_general_ci
| collation_server | utf8mb4_general_ci
下面是二進制安裝未修改的默認的mysql字符集:
14:28[root@centos7 ~]# mysqladmin -S/data/mysql/3307/socket/mysql.sock variable | grep character
| character_set_client | latin1
| character_set_connection | latin1
| character_set_database | latin1
| character_set_filesystem | binary
| character_set_results | latin1
| character_set_server | latin1
| character_set_system | utf8
| character_sets_dir | /usr/local/mariadb-10.2.23-linux-x86_64/share/charsets/
14:36[root@centos7 ~]# mysqladmin -S/data/mysql/3307/socket/mysql.sock variable | grep collation
| collation_connection | latin1_swedish_ci
| collation_database | latin1_swedish_ci
| collation_server | latin1_swedish_ci
可在/etc/mysql/my.cnf中的[mysqld]下添加一行(只須要改這一項便可修改所有的,不過要重啓):
[mysqld]:
character-set-server = utf8mb4
1. 注意在,多實例的狀況下,若是啓動腳本中,mysqld330X的safe的參數選項選擇配置文件時添加了extra的話,這個位置的my.cnf是可以控制全部實例的,若是沒有加extra,這隻能進入到每個示例中去修改了。(相似於mysql鏈接時的命令的extra)
2. 建議的方式是/data/mysql/my.cnf中只寫相同的項目,而/data/mysql/330X/etc/my.cnf寫不一樣的項目
3. 不過須要注意優先級是按照覆蓋的方式來寫的,要注意/etc/my.cnf 這些其它的配置文件中不要寫上不想要的配置,否則若是/data/mysql/330X/etc/my.cnf中若是沒有寫這些在前面的配置文件中寫入過的選項的話,就會之前面的參數爲準了。可能會形成本身一些不想修改的選項被修改了。
4. 經測試果真按照所想的,在這裏優先級最高的(也就是最後使用的配置文件會把前面的配置給覆蓋掉)文件就是這個safe腳本參數extra後面指定的文件(注意以前不加extra的時候只用了這個配置文件,如今是額外用了這個配置文件,不過它是最後一個使用的,覆蓋掉前面的設置,所以優先級最高)。所以,就算前面的配置文件寫了家目錄,端口號等等,只要在最後的這個配置文件中也寫入並修改成本身想要的設置的話,前面配置中寫入的都會被覆蓋不使用。所以也不會影響使用~
5. 在這裏就能夠利用這種方式只寫一次修改所有實例的字符集了,寫在前面的總的配置文件中,extra中不寫這一項便可。
6. 注意用mysql鏈接的時候也能夠加上參數mysql -S/data/mysql/3307/socket/mysql.sock --default-character-set=utf8mb4 ,讓鏈接的客戶端的字符集和服務器端的字符集徹底一致
=======================================特別注意點:
注意此時修改了mysql服務器的字符集以後,以前已經建立的數據庫database的字符集以及已經存在的表中的某些數據類型的字段(好比char類型的可規定字符集的)已經建立了字符集的,這些字符集是不會改變的。
=====
這個修改只能讓新的建立的數據庫database和表table的字符集按照這個設置的默認字符集進行建立,而已經建立的那些字符集是不會改變的。
=====
通過測試,就算這個設置已經生效,可是若是一箇舊的數據庫database的字符集是老的字符集好比latin1,則在這個數據庫中建立的新的表的字符集仍然爲這個數據庫的老的字符集latin1,而並不是是utf8mb4.
=====
所以須要把舊的數據庫的字符集也修改成服務器設置的相同字符集,之後建立新的表的時候字符集纔會正確,查看數據庫database的字符集,能夠進入這個數據庫use以後用status命令來查看.
- drop database DATABASE_NAME 其實就是刪除對應的database的目錄,(同理drop table也就是刪除其對應的表的定義和數據文件)
- 不過注意不要用rm的方式刪除,要用命令的方式刪除纔可
- help create table可看到建立表的三種方式以及各類類型等,這裏就不解釋了
- 注意,只要是char類型的,不管是字段中仍是表中的相對應的char類型中的數據,都須要加上單引號引發來,否則會報錯;同時若是建立表的命令太長的話能夠直接回車換行再繼續書寫便可。
- 建立以後能夠用desc TABLE_NAME 查看錶的定義
- 用show create table TABLE_NAME 查看錶的字符集等相關信息(這個字符集建立的時候也能夠寫上,具體查看6中的幫助所寫哪些data類型須要字符集)
- 建立完表以後,在相對應的磁盤上的數據庫目錄下的database的目錄中就會增長一個表的名字相對應的.frm文件,這個文件就是表的定義的文件。
- 注意老版本的數據庫的數據都存放在數據庫目錄下的(不是database目錄下)的ibdata1文件中,無論是哪一個database下的哪一個表都往這裏存放,很是很差。而新版本已經分別放到對應的database目錄中的文件中了。
- 新版本的表對應存放的數據就在對應的database目錄中的另一個文件,就是.idb後綴文件中。
- show table status like 後面的表的名字,必須加上單引號引發來。能夠用匹配的方式(利用%和_符號)。命令後面能夠加上\G用於把每行豎行顯示。
- ++建立表的第二種方式++是比第一種方式多了一個參考select的命令的結果(select 命令選擇的字段的定義會被複制過來,原先字段內數據一樣會被一併複製過來,注意和第三種克隆方式的區別:克隆方式只克隆表的定義,不克隆數據;它把字段的定義做爲參考,加入新建立的表的字段定義中,注意其中有些信息會丟失,好比原先字段的主鍵信息等);
- 附加:在數據庫外面想要select數據庫內的表或者字段,能夠用DATABASE.TABLE中間的加點的方式來引用。
- ++建立表的第三種方式++直接就是克隆原先的表的定義過來,而且與第二種方式相比,會保留字段的主鍵信息等,至關於和被克隆的表的定義如出一轍;
- 可是須要注意,克隆的方式也會把被克隆的表的字符集的定義和順序一併克隆過來,不論當前的database的字符集是什麼,它只看原來的表的字符集,這一點尤爲要注意。能夠用show create table TABLE_NAME來查看。
- 另外有一點就是,表的默認字符集和字段(char類型的字段)的字符集能夠是不相同的,在create table的幫助中也能夠看到char類型的字段定義的時候是能夠定義字符集的,所以用克隆的方式就算用下面的方式把表的默認字符集改變了,可是克隆過來的字段字符集沒有變化,仍舊是原先數據庫默認字符集(latin1),此時輸入的字符(中文等)由於是在字段的record中,因此仍是會亂碼報錯。
- 還有就是上面提到的第二種方式會把select選中的字段中數據一併複製過來,可是會丟失一些字段的額外屬性;第三種方式克隆只會克隆表的定義,數據不復制,可是能保留字段的全部屬性
- 能夠建立完表字後用alter table TABLE_NAME character set utf8mb4命令修改表的字符集(注意和字段的字符集的區別)
- 表的修改不多去作,儘可能在表建立的時候想好要建立什麼字段。並且表之間的關聯最多不能超過3表。
- 注意建立表的時候表的字段中的選項有AUTO_INCREMENT參數,一樣表的選項中table_options也有這個參數,注意區分。
DML語句
DML: INSERT, DELETE, UPDATE
INSERT:
一次插入一行或多行數據
INSERT語法1
INSERT [L OW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [(col_name,...)] {VALUES | VALUE} ({expr | DEFAULT},...),(...),... [ ON DUPLICATE KEY UPDATE 若是重複更新之 col_name=expr [, col_name=expr] ... ]
簡化寫法:
INSERT tbl_name [(col1,...)] VALUES (val1,...), (val21,...)centos
INSERT語法2
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name SET col_name={expr | DEFAULT}, ... [ ON DUPLICATE KEY UPDATE col_name=expr [, col_name=expr] ... ]
INSERT語法3
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [(col_name,...)] SELECT ... [ ON DUPLICATE KEY UPDATE col_name=expr [, col_name=expr] ... ]服務器
UPDATE:
UPDATE [LOW_PRIORITY] [IGNORE] table_reference SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ... [WHERE where_condition] [ORDER BY ...] [LIMIT row_count]app
- 注意:必定要有限制條件,不然將修改全部行的指定字段
限制條件:
WHERE
LIMIT
- Mysql 選項:-U|--safe-updates| --i-am-a-dummy
DELETE:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [WHERE where_condition] [ORDER BY ...] [LIMIT row_count]
可先排序再指定刪除的行數
- 注意:必定要有限制條件,不然將清空表中的全部數據
限制條件:
WHERE
LIMIT
- TRUNCATE TABLE tbl_name; 清空表
注意點3(DML語句):
- insert命令後面的value的值必定要和前面的col寫入的順序一一對應,其中一次性能夠添加多個record,只須要每個value後面的值用小括號括起來,之間用逗號分隔開便可。
- 注意若是col的值沒有寫的話,表明後面要添加的value的值要包含全部的字段,同時要按照對應的表中字段的默認排序來寫(可用desc TABLE_NAME查看錶中的字段和默認排序從上到下。)
- 當前面的cols選定了要添加的記錄record中的字段時,剩下的沒有被選中的字段必須默認不能爲空值或者有其餘的屬性(好比說數值型的自動增加,或者有默認的值),否則添加字段的時候若是不能夠爲空值的字段即沒有特殊的其餘屬性又不在添加記錄的時候給它賦值,這個字段就會出現問題。
- 表中的字段儘可能不要讓它爲空值,要麼默認不爲空輸入的時候寫上,要麼默認給它一個值,以後再修改。總之儘可能不要爲空值。(注意定義字段的時候若是不寫上NOT NULL 或者 DEFAULT的話,這個字段默承認覺得空值)
- 添加字段的時候注意字符串和建立字段的時候的枚舉類型同樣,只要是字符類型的數據都要單引號引發來,特殊的:若是選定了cols可是insert命令中有些記錄record的某些字段並不賦值,能夠用null來把它設置爲空值。注意這裏null不須要加單引號。不過前提是這些字段能夠爲空值。
- 數據庫的data目錄下有一個隱藏的history日誌文件,它保留了數據庫內進行的操做的歷史命令。當退出數據庫後就會進行更新。
- insert student select * form db2.student2 ;(第三種語法,第二種語法只能添加一行的字段)
- 特別注意:表的記錄操做update和delete命令,修改刪除record的時候必定要加上限制條件,否則會把全部的row都給修改掉。
- 能夠在鏈接數據庫的時候加上-U選項,避免這種不加限制條件的語法進行批量修改的狀況發生(會把這種語句當作錯誤語句)
- 或者用別名的方式把mysql永遠加上-U選項
- 或者說在配置文件中的[mysql]欄中(能夠寫在/data/mysql/my.cnf中或者說/etc/my.cnf.d/目錄下的客戶端配置文件中等等。)添加一項:safe-updates [=1 | =ture | on |...]
- delete from TABLE_NAME [where_condition],若是不加條件就會把整個表給刪除掉。
- 注意條件的判斷語句參看下面的select中的命令,或者說查看官方解釋文檔http://dev.mysql.com/doc/refman/5.5/en/expressions.html
- 當刪除掉一行,再次添加新的行的時候,若是不指明行中含有的自動增加的數值型字段的值,則它會按照當前表中此字段最後的值來進行增加並添加。而被刪除掉而這一行就會跳過並空着。不過能夠添加的時候指明這個空着的值並添加一個記錄進去。
- delete form TABLE_NAME 命令刪除表的速度不如 truncate table TABLE_NAME,由於前者仍舊會記錄到日誌中,後者雖然快可是有必定的危險性,沒法回覆,全部慎用;不過它倆都是隻刪除表中數據,並未刪除表的定義。
- 注意update命令修改表中record的命令只能用set 字段=VALUE的方式,後面加上判斷條件where等。相似insert的第二中方式。
DQL語句
單表查詢
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[SQL_CACHE | SQL_NO_CACHE]
select_expr [, select_expr ...]
[FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[FOR UPDATE | LOCK IN SHARE MODE]
SELECT
- 字段顯示可使用別名:
col1 AS alias1, col2 AS alias2, ...
- WHERE子句:指明過濾條件以實現「選擇」的功能:
過濾條件:布爾型表達式
算術操做符:+, -, *, /, %
比較操做符:=,<=>(相等或都爲空), <>, !=(非標準SQL), >, >=, <, <=
BETWEEN min_num AND max_num
IN (element1, element2, ...)
IS NULL
IS NOT NULL
- 注意:下面的4 5 6 7用在 where 的++字段++ 後面,當作判斷符號
- DISTINCT 去除重複列
SELECT DISTINCT gender FROM students;
- LIKE:
% 任意長度的任意字符
_ 任意單個字符
- RLIKE:正則表達式,索引失效,不建議使用
- REGEXP:匹配字符串可用正則表達式書寫模式,同上
- 邏輯操做符:
NOT
AND
OR
XOR
- GROUP BY:根據指定的條件把查詢結果進行「分組」以用於作「聚合」運算
avg(), max(), min(), count(), sum()
HAVING: 對分組聚合運算後的結果指定過濾條件
- ORDER BY: 根據指定的字段對查詢結果進行排序
升序:ASC
降序:DESC
- LIMIT [[offset,]row_count]:對查詢的結果進行輸出行數數量限制
- 對查詢結果中的數據請求施加「鎖」
FOR UPDATE: 寫鎖,獨佔或排它鎖,只有一個讀和寫
LOCK IN SHARE MODE: 讀鎖,共享鎖,同時多個讀
select示例:
DESC students;
INSERT [INTO] students VALUES(1,'tom','m'),(2,'alice','f');
INSERT [INTO] students(id,name) VALUES(3,'jack'),(4,'allen');
SELECT * FROM students WHERE id < 3;
SELECT * FROM students WHERE gender='m';
SELECT * FROM students WHERE gender IS NULL;
SELECT * FROM students WHERE gender IS NOT NULL;
SELECT * FROM students ORDER BY name DESC LIMIT 2;
SELECT * FROM students ORDER BY name DESC LIMIT 1,2;
SELECT * FROM students WHERE id >=2 and id <=4
SELECT * FROM students WHERE BETWEEN 2 AND 4
SELECT * FROM students WHERE name LIKE ‘t%’
SELECT * FROM students WHERE name RLIKE '.*[lo].*';
SELECT id stuid,name as stuname FROM students
注意點4(DQL單表和基礎):
- select命令選擇字段的時候,能夠直接在選擇的字段後面加上別名,中間的AS符號能夠省略(能夠中文,若是用的utf8字符集的話,這裏不用as能夠直接加別名的緣由就是字段都是以逗號,分隔開的);一樣的,from關鍵字後面的表名也能夠加別名。
- 不過須要注意,字段加別名可在select命令結束並顯示結果的時候在字段欄中顯示別名;同時字段和表加了別名以後,在後面的命令中,就能夠用別名的方式再次使用這個表或者字段了
- 注意表名加了別名以後,在引用這個表中的字段(select後面,或者條件判斷中on,where having等)都要用這個表的別名方式來引用了。
- select整個語句也能夠做爲一個總體加別名,把這個select的結果(可看做是一個表,相似view)用這個別名來引用,嵌套等
- select語句的from關鍵字後面也能夠限定範圍(where,limit等等)。
- 注意where等斷定的時候有多種方式,最多見的就是後面跟的是"(數值型)字段 判斷符號(=>等) VALUE "
- 固然字符型字段也能夠判斷:"(字符型)字段 判斷符號(!=,<=>等等) 'string' " ,此時大於小於就是按照字符集排序方式的先後順序來判斷字符串的大小的(可用order by 查看順序)。同時必定要注意string外面要加上單引號引發來。
- where後面的字段後面的判斷符號還能夠用like來進行模糊匹配(或者精確匹配)
- 通過測試,在這數據庫裏的字符型的數據無論在哪都要加上引號,數值型的沒有要求。這個要求和命令無關,只要是在數據庫內操做輸入等都要按照這個規則而已。
- where 字段 is [not] null
- SQL注入:注意where後面的語句中能夠寫上一個永遠正確的語句好比 1=1(2=2等等) 而後用它與其餘的條件進行 OR的關係,就能夠達到繞過這個OR所跟的條件判斷的目的,從而來實現一些操做,好比繞過密碼輸入能夠寫語句: where password='' or 1=1 ;
- select 還支持數運算,where後面的語句也能夠用相似for的in方式(就至關於=符號,不過不用寫那麼多的OR了),好比where 字段 in (value1,value2,...)
- 正則表達式rlike也可用,但正則則表達式方式沒法使用索引,基本上不用。
- 排序分組限定(GROUP BY,ORDER BY,limit)也是在form關鍵字後面,它和where是同一類別的(同級)。
- 注意GROUP BY後面跟的也是字段,它會把整個表中這個字段中相同的record值的行給合併,而後按照前面select選擇的項目(通常就是聚合函數,若是選擇字段的話沒有意義了)進行顯示,把group by後面的字段放到顯示結果的第一列colume上。
- 用group by 的時候,select 後面的字段必定要包含有與group by 後面的字段1相同的字段(否則看不出來結果,雖然不寫也能夠),同時select 後面的字段必定要有2聚合函數(這個結果也能夠做爲別名,前面已經說過),否則也沒有意義了。
- group by 先分組以後,若是還要再次進行條件限定,此時用的關鍵字是having,(相似於where,只不過where是放在group by 前面的關鍵字,having 是放在後面的關鍵字),判斷的符號等基本和where一致。它倆均可以進行條件限定,視狀況選擇使用(也能夠同時使用,先where,而後group by 最後 having)
附加知識點:count()函數,對字段進行統計的時候count(字段名),其中記錄若是能夠爲空,則裏面的null值會不做爲統計結果,這一點須要注意。對於主鍵字段利用count(主鍵字段)和count(*)的結果則是一致的,都是統計這個表(若是有限定條件的話就是限定條件的)所擁有的全部記錄,所以簡單點能夠用count(*)來統計記錄總數。
- group by 後面能夠跟多個字段進行屢次分組,中間直接用逗號隔開便可。此時就是按照所寫字段的從左往右的順序一個一個分組。
- order by 排序也能夠與前面說的where,group by ,having 同時使用;同時它也像group by同樣能夠對多列按照從左往右的順序進行排序(由於排序並不會像group by同樣把字段中重複的值的行給換成一個,注意多列排序的時候最好不要與group by 同時使用)。
- limit命令用在select最後,能夠取出須要的行,limit OFFSET,ROW ; 其中offset 和 row都是數值,中間逗號隔開。
多表查詢
- 交叉鏈接:笛卡爾乘積
- 內鏈接:
等值鏈接:讓表之間的字段以「等值」創建鏈接關係;
不等值鏈接
天然鏈接:去掉重複列的等值鏈接
自鏈接
- 外鏈接:
左外鏈接:
FROM tb1 LEFT JOIN tb2 ON tb1.col=tb2.col
右外鏈接
FROM tb1 RIGHT JOIN tb2 ON tb1.col=tb2.col
- 子查詢:在查詢語句嵌套着查詢語句,性能較差
基於某語句的查詢結果再次進行的查詢
- 用在WHERE子句中的子查詢
- 用於比較表達式中的子查詢;子查詢僅能返回單個值
SELECT Name,Age FROM students WHERE Age>(SELECT avg(Age)
FROM students);
- 用於IN中的子查詢:子查詢應該單鍵查詢並返回一個或多個值從構成列表
SELECT Name,Age FROM students WHERE Age IN (SELECT Age
FROM teachers);
- 用於EXISTS
- 用於FROM子句中的子查詢
使用格式:
SELECT tb_alias.col1,... FROM (SELECT clause) AS tb_alias WHERE Clause;
示例:
SELECT s.aage,s.ClassID FROM (SELECT avg(Age) AS aage,ClassID
FROM students WHERE ClassID IS NOT NULL GROUP BY ClassID) AS s WHERE s.aage>30;
- 聯合查詢:UNION
SELECT Name,Age FROM students UNION SELECT Name,Age FROM
teachers;
SELECT查詢語句執行順序,基本上也就是select命令的書寫順序:
注意點5(DQL多表):
- 第一種多表合併最簡單的方式就是縱向合併,不過要保證這兩個表的字段數(或者說用select選擇後的字段數)數量要一致;
- 其中的字段的datatype並無要求多個表都要一致,只須要字段數同樣就行
- 這兩個表最終的顯示效果的標頭是按照第一個表的select選擇的字段(的別名)來顯示的。
- 縱向合併的關鍵字爲union,先後分別是select語句。,注意若是from關鍵字後多個表的表名若是有重名的(不一樣的數據庫中),要指明是哪一個數據庫。用點.符號便可。
- 注意,union先後的select語句若是徹底同樣(至關於本身union本身,兩個相同的),它並不會顯示兩遍結果出來,而僅僅是顯示一遍:由於union會自動合併內容徹底一致的相同的row,具備自動去重功能;所以用這個功能能夠直接本身鏈接本身來達到去重的效果。
- 橫向合併1,最簡單的就是一張表的全部記錄和另一張表的全部記錄一一對應分別組合,兩張表的字段數相加合併,同時組合數爲兩張表的記錄數的乘積
- 組合的命令爲cross join, 和 union相似 ,不過它的命令先後不須要都加上select語句,它的先後只須要表的名字便可,例如:select * from TABLE1 corss join TABLE2 ;
- 橫向合併2:內鏈接(TABLE 1 inner join TABLE2 on Condition)
- 內鏈接就是用於兩張表相關聯的部分進行連接,這裏和cross join 不一樣的就是它的命令以及後面加上了on的條件限定(這裏on就相似以前的where,having)
- 好比 select * rom TABLE1 inner join TABLE2 on TABLE1.COLUME2 = TABLE2.COLUME1 [and | or等等更多條件] ;
- 若是隻選定某些特定字段(若是不一樣名字段則不用標明表名,若是同名字段則要寫上表名,可用表名的別名)則能夠在上面命令的基礎上 在TABL1和TABLE2後面加上別名,而後前面的*號就能夠用別名後面加`.字段`的方式來引用不一樣的表的字段顯示了。
- 固然這個內鏈接也能夠用 「select 字段 from TABLE1 [ALIAS1] ,TABLE2 [ALIAS2] where TABLE1.COLUME2 = TABLE2.COLUME1 ; 」的舊命令方式來代替。
- 橫向合併3:左外鏈接和右外鏈接(TABLE1 left outer join TABLE2 on Condition)
- 它倆的命令和內鏈接的區別就在於吧inner換成left outer 或right outer 其餘都同樣
- 左外鏈接邏輯就是左邊的表格select選中的內容所有顯示出來,而右邊的表中select中只有符合後面on後面的判斷條件的record纔會顯示出來,而那些沒有匹配到on條件的顯示出的左邊的表的record,在右邊的表的這些字段中所有用null填充顯示出來。
- 右外鏈接和左外連接恰好相反,右邊的表所有顯示,左邊的表匹配的顯示,剩餘的補null(能夠把表換個位置都用左外連接同樣的結果)
- 橫向合併4:左外連接取補和右外鏈接取補(左右外連接condition條件增長)
- 左外連接取補就是在左外連接的基礎性上,把on後面的condition中的符合條件的這一部分給去除掉便可,能夠用某個字段爲空的方式來取補(右外鏈接取補相似)
- 好比左外連接 select * rom TABLE1 left outer join TABLE2 on TABLE1.COLUME2 = TABLE2.COLUME1
- 而後對它進行條件取補 select * rom TABLE1 left outer join TABLE2 on TABLE1.COLUME2 = TABLE2.COLUME1 and TABLE2.COLUME1 is null
- 這樣就實現了左外連接取補
- 橫向合併5:徹底外鏈接(左外鏈接 union 右外鏈接 )
- 它就是上面所寫的 ,只須要關鍵字 left 換成 right 而後 兩個select語句union便可,其餘的條件等等所有相同。
- 注意它利用了union自動去重的功能
- 子查詢:多種方式,用where方式的時候結果必須爲單值(看子查詢部分的例子)
- 橫向合併6:非交集部分(利用徹底外鏈接和子查詢的方式)
- 先把徹底外鏈接的select的表達式寫出來,把它看作爲一張表,(用小括號括起來)同時給它起一個別名
- 而後再次select 語句,並利用where判斷條件把兩個表中內鏈接的部分去掉(能夠利用!=符號方式)或者選中帶有空值的記錄(利用 or及is null ,用where創造兩個條件將兩邊的空值項篩選選出來)
- 上面寫的兩種方式是兩種思想,一種是利用徹底外鏈接去掉內鏈接的以後想法,一種是利用左右外鏈接取補以後的並集想法來書寫where後面的限定條件
- 按照第二中上面寫的OR的想法:select * from (橫向合併5中的徹底外鏈接)as a where a.TABLE2_COLUME1 is null or a.TABLE1_COLUME2 is null
- 這個過程當中注意不要有重名,各個部分該用別名的就用別名。邏輯上沒有那麼複雜。
- 多對多的表(好比說學生表和科目表,每一個學生能夠報多個科目,且每一個科目都有成績(這個成績在第三張表中),同時一個科目有多個學生能夠報)
- 多對多的表都有第三張表來表示對應關係,在上面的例子中第三張表就是成績表,裏面記錄着"記錄的ID(主鍵)""學生的ID" "科目的ID" "科目的成績",以這種方式來表示學生表和科目表的對應關係
- 在這裏想要把成績表中的學生和科目顯示出來而不是ID號的話,就要用3張表的內鏈接方式了。
- 能夠先鏈接兩張表的內鏈接 「select 字段 TABLE1 inner join TABLE2 on cONDITION1 」
- 而後直接在後面再鏈接第三張表,而前面的select利用表的別名來進行選擇字段便可「select 字段 TABLE1 inner join TABLE2 on cONDITION1 inner join TABLE3 on Condition2」
- 或者也能夠用另外的方式,就是先鏈接兩張表,而後小括號把它括起來做爲一個表(view)來看待,以後再按照對錶的操做方式對它進行操做便可,只是注意要多加別名,利用別名的方式來引用這個select命令結果的表
- 還有一種表的自內鏈接,好比說一個表三個字段爲"員工ID""員工姓名""員工上司ID",想要把員工的上司的名字給顯示出來,利用自內鏈接,這也是一種也是很常見的方法。
- 把這張表直接當作兩張表來使用,一張看作員工表,一張看作上司表,利用內鏈接,別名進行連接便可
- select alias1.員工ID [員工號],alias1.員工姓名 [員工名], alias2.員工姓名 [上司名] from TABLE as alias1 inner join TABLE alias2 on alias1.員工上司ID = alias2.員工ID ;
- 上面命令中alias2第二張表看做是上司表,員工名字就是上司名,中括號內的爲顯示出來的別名,爲了更加清楚。