MySQL系列(一)---基礎知識大總結
前言:本文主要為mysql基礎知識的大總結,mysql的基礎知識很多,這里作簡單概括性的介紹,具體的細節還是需要自行搜索。當然本文還有很多遺漏的地方,后續會慢慢補充完善。
目錄
數據庫和數據庫軟件
- 數據庫是保存有組織數據的容器
- DBMS是為管理數據庫而設計的軟件管理系統,MYSQL、ORACLE 等是數據庫管理系統
MYSQL
- MYSQL是一種數據庫管理軟件
- 開放源碼,免費使用
MYSQL命令
- CREATE DATABASE NAME 創建數據庫
- USE DATABASE 選擇數據庫
- DROP DATABASE NAME 直接刪除數據庫
- SHOW DATABASES 顯示可用數據庫列表
- SHOW TABLES 顯示數據庫中的表的列表
- SHOW COLUMNS FROM TABLE 與 DESCRIBE TABLE 等效,顯示表的字段信息
- SHOW GRANTS 顯示授予用戶的安全權限
- SHOW ERRORS SHOW WARNINGS 顯示服務器錯誤和警告信息
SQL
- STRUCTURED QUERY LANGUAGE 結構化查詢語言,一種專門用於與數據庫通信的語言
- 不是DBMS專有的語言,很多DBMS都支持SQL,但是不同DBMS對SQL的實現不同
- DBMS支持的SQL語法不能完全適用於其他DBMS
- SQL語句不區分大小寫
- 多條語句需要分號分隔,單條語句可以不用分號
- 通常SQL語句用大寫,標識符(比如表名 列名 數據庫名)用小寫
創建表
- CREATE TABLE user (id INT NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL,password VARCHAR (50) NOT NULL DEFAULT 1,PRIMARY KEY(id)) ENGINE =INNODB
檢索列
- SELECT username FROM user
- SELECT username,password FROM user
- SELECT * FROM user 建議不是要所有的列,不用'*',要不然這種操作是很耗性能的
- SELECT DISTINCT username FROM user 只返回不同的username,比如有兩行用戶名是一樣的,只顯示一行記錄
限制結果
- SELECT * FROM TABLE LIMIT 5 檢索前五行
- SELECT * FROM TABLE LIMIT 5,5 檢索6到10
結果排序
- SELECT * FROM user ORDER BY username,以username的字母順序排列
- SELECT * FROM user ORDER BY username,password ,如果username有相同的,那么username相同的再按password排列,如果username都是唯一,這個時候password不起作用
- SELECT * FROM user ORDER BY username DESC ,降序排列,默認是升序ASC
- SELECT * FROM user e ORDER BY username DESC,password 此時按照username降序排列,如果username相同的行按照password升序排列
- SELECT * FROM user ORDER BY username LIMIT 1 混合使用ORDER 和 LIMIT
- SELECT * FROM user WHERE username ='jiajun' ORDER BY password 這里ORDER要在WHERE 之后
過濾數據
- SELECT * FROM user WHERE username <> 'jiajun' 不等於 和 != 效果相同
- SELECT * FROM user WHERE id BETWEEN 1 AND 10 檢索1到10的記錄,包括1和10
- SELECT * FROM user WHERE username IS NULL 查找列無值的行,這里的無值不等於 值為0 和 空字符串
- SELECT * FROM user WHERE id=1 OR username='jiajun' AND password='666' 執行順序是 WHERE id=1 OR (username='jiajun' AND password='666')AND的優先級更高,但是建議添加括號
- SELECT * FROM user WHERE id IN (1,2) 效果和SELECT * FROM user WHERE id=1 OR id =2 如果要實現這種效果,建議使用第一種,語法更清晰,而且一般執行更快
- SELECT * FROM user WHERE id NOT IN (1,2)
通配符過濾
- SELECT * FROM user WHERE username LIKE 'jia%' ,匹配jia開頭的username,不管后面有多少字符,jia和jiajun都是匹配,可以配置MySQL是否區份大小寫,如果區份大小寫,也就是jiajun是不匹配的 。注意LIKE '%'是不能匹配值為NULL的
- SELECT * FROM user WHERE username LIKE 'jia_' , _只能匹配一個字符,也就是匹配jiaj不匹配jiajun
- 通配符匹配是效率不高,如果其他方式能有相同的效果,建議用其他效果,並且最好不要將通配符放在開始處,因為這樣是很慢的
正則表達式過濾
- SELECT * FROM user WHERE username REGEXP '.ia' ,正則表達式, . 匹配任意一個字符
- SELECT * FROM user WHERE username REGEXP 'jun' 匹配包含jun的username,'jiajun'和'jun'都匹配
- SELECT * FROM user WHERE username REGEXP 'jiajun|jiaj' ,'|'和'OR' 效果一樣
- SELECT * FROM user WHERE username REGEXP ‘[123]jun’ ,匹配包含'1jun'或者'2jun'或者'3jun'
- [^123]123除外
- [1-9],[A-Z],用'-'表示范圍
- 匹配特殊字符(比如'.'和'_')可以采用'\'轉義,比如匹配有'.'的可以這樣表示'\.'
拼接字段
- SELECT CONCAT(username,'(',password,')') FROM user,將兩個字段拼接到一起,查詢結果是一列,行值 jiajun(666)
- SELECT CONCAT(username,')',password,')') AS up FROM user,為拼接后的一列設置字段名
算數運算
- SELECT price*count AS all FROM TABLE 將單價和數量相乘,列名為all
函數
- 函數可移植性不高,也就是一個函數支持一個DBMS,但不一定支持另一個DBMS,比如支持MYSQL而不支持ORACLE。所以使用函數的要寫好注釋。
文本處理函數
- LENGTH() 返回串長度
- LOWER()將串轉換為小寫
- UPPER()將串轉換為大寫
- LTRIM()去掉串左邊的空格
- RTRIM()去掉串右邊的空格
日期和時間處理函數
-
CURDATE() 2017-07-22
-
CURTIME()16:20:19
-
NOW() 2017-07-22 16:20:19
-
DATE() 返回日期的日期部分 SELECT DATE(NOW()) 2017-07-22
-
DATE_FORMAT() 返回格式化的日期和時間串
-
HOUR() 返回一個時間的小時部分
-
MINUTE() 返回一個時間的分鍾部分
-
MONTH() 返回一個日期的月份部分
-
NOW() 返回當前日期和時間
-
SECOND() 返回一個時間的秒部分
-
TIME() 返回一個日期時間的時間部分
-
YEAR() 返回一個日期的年份部分
日期函數注意點
- SELECT * FROM TABLE WHERE date='2017-7-22' ,如果DATE的類型是DATATIME類型,那么表里一條記錄存放的格式應該是2017-07-22 16:20:19,此時這條記錄不會被篩選出來,篩選的是2017-07-22 00:00:00
- 可以采用DATE函數 SELECT * FROM TABLE WHERE DATE(date)='2017-7-22'
- 時間范圍 可以采用DATE函數 SELECT * FROM TABLE WHERE DATE(date) BETWEEN '2017-7-1' AND ''2017-7-31
數組處理函數
- ABS() 返回一個數的絕對值
- COS() 返回一個角度的余弦
- EXP()返回一個數的指數值
- MOD()返回除操作的余數
- PI() 返回圓周率
- RAND()返回一個隨機數
- SIN()返回一個角度的正弦
- SQRT() 返回一個數的平方根
- TAN() 返回一個角度的正切
聚集函數
- SELECT AVG(student_score) AS AVG_ PRIVE FROM score 求平均值
- SELECT COUNT(*) FROM TABLE 表里記錄數
- SELECT COLUMN(name) FROM TABLE 表里列有值的記錄數 ,值為NULL不計數
- SELECT MAX(score) FROM TABLE 查找最大值
- SELECT MIN(score) FROM TABLE 查找最小值
- SELECT SUM(count) FROM TABLE 返回指定列的和 SUM(price*count)同樣適用
數據分組
- SELECT AVG(score) FROM score GROUP BY class_id 檢索不同課的平均分
- SELECT AVG(score) FROM score GROUP BY class_id, dep_id ,GROUP BY 后面可以多個字段
- SELECT AVG(score) FROM score GROUP BY class_id ,SELECT 的字段必須是GROUP BY 后面的字段或者是聚合函數,在這里根據class_id分最后,class_id相同合並成一行,但是這里面的合並的這些score不同,如何能合並成一行
- 如果分組列有NULL值的,將列值為NULL的分為一組
- GROUP BY 要在WHERE之后,ORDER BY 之前,也就是先過濾再分組再排序
- SELECT COUNT(*) FROM TABLE GROUP BY id HAVING COUNT(*)>3 ,分組后,對分組再進行過濾。
子查詢
- SELECT * FROM student WHERE class_id IN (SELECT class_id FROM teacher WHERE teacher_id=6) ,子查詢過濾,WHERE里面嵌套子查詢
- SELECT name ,(SELECT score FROM score WHERE studen.student_id=score.student_id) AS score FROM student 計算字段字段使用子查詢
- 不建議使用太多的子查詢,會影響性能
主鍵
- 唯一標識自己的一列或一組列,唯一區別表中的一行
- 主鍵不能為空
- 任意兩行的主鍵值必須不同
- 主鍵不是必須的,但是建議每個表中有一個主鍵,這樣操作管理更方便
- 主鍵值最好不更新
- 一個表的主鍵只能有一個
外鍵
- 一個表的主鍵指向另一個表的外鍵,比如說student表的主鍵student_id,在score表中也有,並且是score表的外鍵
- 外鍵保持了數據完整性和一致。,比如你在student表里面修改了student_id后,則score的student_id也會聯動更新。並且score表中插入的student_id必須是student表里有的
聯結
- SELECT name,score FROM score,student 兩個表進行聯結,此時進行的是笛卡爾積,就是說結果的行數score表行數*student表的行數
- SELECT name,score FROM score,student WHERE student.student_id=score.student_id,在上面的基礎上,加上WHERE進行過濾
- SELECT name,score FROM score INNER JOIN student ON student.student_id=SOCRE.student_id 內部聯結
- 外部聯結,LEFT OUTER JOIN 和 RIGHT OUTER JOIN ,有時候內部聯結的時候會出現聯結條件不匹配的行,而LEFT JOIN 保證了保證左邊表的所有行,右聯結同理
- FULL JOIN效果LEFT JOIN + RIGHT JOIN一致,左表不匹配的右表不匹配的都會列出
- 不要聯結太多的表,這樣會降低性能
- 聯結的時候可能因為兩個表有相同的列,因為沒有做好限制導致相同的列的出現兩次,所以這是需要的地方,這也是所謂的自然聯結
別名
- SELECT CONCAT(username,'(',password,')') AS MES FROM user,這里采用CONCAT將兩個字段拼接在一起,並且給拼接后的字段起一個別名MES
- 同樣表也可以起別名SELECT name,score FROM score AS A,student AS B WHERE A.student_id=B.student_id
組合查詢
- 利用UNION將多個SELECT語句的結果組合起來,可以理解成同一個表頭的表垂直拼接在一起
- 每個查詢必須包含相同的列數,而且字段類型要兼容。
- SELECT score FROM score WHERE NAME='jiajun' OR score BETWEEN 95 AND 100 和 SELECT score FROM score WHERE NAME='jiajun' UNION SELECT score FROM score WHERE score BETWEEN 95 AND 100 作用等效。
- 上面的是單表查詢,用了UNION感覺復雜了,但是如果用於不同表的查詢的連接會更簡單。
- 如果A查詢查到5行,B查詢查到4行,由於有重復的,會去掉相同的行,最后剩下8行,如果需要的話可以用UNION ALL
插入數據
- INSERT INTO user VALUES ('jiajun','666') 和 INSERT INTO user (username,password) VALUES ('jiajun','666'),在表里只有username和password兩個字段是等效,前一種方式必須值的個數和順序必須和字段的個數順序一致,而后者,因為給出列和值,只要一一對應就好
- INSERT INTO user VALUES ('jiajun','666'),('jiajia','666') 插入多行
- INSERT INTO user VALUES (SELECT username ,password FROM olduser),檢索出olduser的行然后插入到user表,這里注意的還是列的問題,后面的SELECT語句后的字段名並不重要,不需要和user表對應,因為只是將檢索的列值按順序插入到user表,並不在意olduser的字段名。同時列的數目和順序也是需要注意的
更新數據
- UPDATE user SET password ='666',money='6666' WHERE username='jiajun',需要注意的是WHERE一定不要漏,要不然會更新表中的所有行
- 在更新多行的時候如果中途出現錯誤,會將更新的恢復回原來的值,如果要做到即使中途發生錯誤也要繼續更新可以采用 IGNORE關鍵字,UPDATE IGNORE user
刪除數據
- 如果想刪除一個列的值,SET username=NULL就行了
- 如果想要刪除一行,DELETE FROM user WHERE username='jiajun'
- 如果想要刪除整個表的行 DETELTE FROM user,注意這個表不會刪除,只是所有記錄清空。TRUNCATE user,也有相同的效果,不同的是他是先刪除表,然后重新建立一個表
更新表
- ALTER TABLE user ADD phone CHAR(20) 添加一列
- ALTER TABLE user DROP COLUMN phone 刪除一列
- ALTER TABLE user CONSTRAINT wai_jian FOREGIN KEY (class_id) REFERENCES class (class_id) 定義外鍵
- ALTER TABLE user ADD PRIMARY KEY (id)添加主鍵
- 修改前做好備份,表的更改不能撤銷
刪除表
- DROP TABLE user
重命名表
- RENAME TABLE user TO users
視圖
- 當我們查詢后出現一個結果,我們可以包裝成一個虛擬表,也就是視圖,我們可以把他當成表使用
- 視圖本身不包含數據,數據是從其他表檢索出來
- 使用視圖可以重用SQL,並且可以保護數據,可以授予用戶部分數據權限而不是全部數據
- 如視圖中存在分組(GROUP BY)、聯結、子查詢、並(UNOIN)、聚合函數(SUM/COUNT等)、計算字段、DISTINCT等都不能對視圖進行更新操作
- CREATE VIEW my_view AS SELECT name,score FROM student ,創建視圖
- DROP VIEW MY_VIEW 刪除視圖
存儲過程
- 有時候SQL也需要有IF ELSE,我們可以把多條SQL語句封裝在一起形成存儲過程,這樣不僅簡單安全而且性能也會更高
- 存儲過程並不顯示結果,只是將結果返回給你指定的變量。
- 過程是這樣的,創建一個存儲過程,使用存儲過程,將參數傳入,SELECT參數輸出結果
- 參數類型 IN 傳遞給存儲過程,OUT從存儲過程傳出,INOUT對存儲過程傳入傳出。結果將返回給OUT變量
- CREATE PROCEDURE pro(IN PARAM INT,OUT PARAM2 INT)BEGIN SELECT COUNT(*) FROM user WHERE id=PARAM INTO PARAM2 END; 創建存儲過程
- CALL PRO (666,@PARAM2);SELECT @PARAM2;調用並且會輸出PARAM2
- SHOW CREATE PROCEDURE PRO顯示存儲過程的CREATE語句
- SHOW PROCEDURE STATUS列出所有存儲過程
觸發器
- 事件發生時自動執行某些語句,在INSERT UPDATE DELETE之前之后需要做一些操作,這時候可以使用觸發器
- 一個表最多6個觸發器,插入刪除更新的前后。
- CREATE TRIGGER my_trigger AFTER INSERT ON user FOR EACH ROW BEGIN SELECT NEW.id END,創建名為my_trigger的觸發器,在對user表,每插入一行,將id顯示出來
- 在觸發器中可以引用NEW新的虛擬表,訪問插入的行。可以引用OLD虛擬表,訪問被刪除的行。
- DROP TRIGGER my_trigger 刪除觸發器
- 只有表支持觸發器,視圖不支持
- 觸發器中不能調用存儲過程
我覺得分享是一種精神,分享是我的樂趣所在,不是說我覺得我講得一定是對的,我講得可能很多是不對的,但是我希望我講的東西是我人生的體驗和思考,是給很多人反思,也許給你一秒鍾、半秒鍾,哪怕說一句話有點道理,引發自己內心的感觸,這就是我最大的價值。(這是我喜歡的一句話,也是我寫博客的初衷)
作者:jiajun 出處: http://www.cnblogs.com/-new/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。如果覺得還有幫助的話,可以點一下右下角的【推薦】,希望能夠持續的為大家帶來好的技術文章!想跟我一起進步么?那就【關注】我吧。