《一塊兒學mysql》1

自從達內畢業後就沒用過mysql,一直用的hive,hdfs 存儲數據,最近忽然又接觸到了關係型數據庫。本想隨便從網上
找個教程看看,可是都不是很滿意,pdf看着又難受,仍是本身個兒寫個筆記吧。
 
首先咱們來安裝mysql,我比較喜歡在linux下搞程序,由於我操做的線上環境都是centos,因此介紹在 centos下安裝mysql
 
mysql 的用戶管理,安全設置啥的就不介紹了,不想當DBA。
 
mysql 建表  
 
如今建咱們的第一張表 (關於數據類型的介紹 看這裏 )
 
首先進入數據庫
mysql -ujason -p123
MariaDB [(none)]> use jason;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Database changed
MariaDB [jason]>
 
建表
create table student(
id int(2),
phone_num int,
name char(2),
introduction char
)
 
建表時咱們並未指定intoduction字段的寬度,系統默認分配了1,phone_num也未指定,默認分配了11
MariaDB [jason]> desc student;
+--------------+---------+------+-----+---------+-------+
| Field        | Type    | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+-------+
| id           | int(2)  | YES  |     | NULL    |       |
| phone_num    | int(11) | YES  |     | NULL    |       |
| name         | char(2) | YES  |     | NULL    |       |
| introduction | char(1) | YES  |     | NULL    |       |
+--------------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec)
 
向數據庫中插入兩行數據並查看
MariaDB [jason]> insert into student values
    -> (1,15675698904,'jason','A boy from HB,like swimming'),
    -> (200,-15675698904,'dong','A boy from HB,like TKD');
Query OK, 2 rows affected, 6 warnings (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 6
 
MariaDB [jason]> select * from student;
+------+-------------+------+--------------+
| id   | phone_num   | name | introduction |
+------+-------------+------+--------------+
|    1 |  2147483647 | ja   | A            |
|  200 | -2147483648 | do   | A            |
+------+-------------+------+--------------+
2 rows in set (0.00 sec)
 
在建表時id,name 字段都進行了字段寬度設置(id int(2),name char(2)),爲什麼數據庫中顯示的信息不同?
mysql中數值類型和字符類型的寬度限制含義是不一樣的,對於字符傳來說,括號中的數字就指定了該字段能夠
存儲幾個「字符」——請注意是字符,而不是字節—— 若插入的字符串長度超過了這個長度,就會截斷, 對
於數值來說,當插入的數值長度不夠2時,會以0填充,請看下下面的例子
 
create table student2(
id int(5) zerofill    //只有當指定zerofill時才起做用
)
 
insert into student2
values(123),
(123456);
MariaDB [jason]> select * from student2;
+--------+
| id     |
+--------+
|  00123 |
| 123456 |
+--------+
 
那爲何咱們插入的手機號會變成了「2147483647」?
int字節長度爲 4字節,最大隻能存儲到21億多一些,當存儲的數值超過最大值時,就存儲int的最大值,另外,
21億是個十位數字,爲啥int默認寬度時 11,細心的朋友能夠發現,多出來的1位用來存儲 正負號
 
說到zerofill,乾脆再說一下unsigned,,unsigned 拋棄了負數,tinyint 原本是 -128-127,若是加上unsigned
標識,則tinyint 標識 0-255,被zerofill修飾的字段默認是unsigned,看例子說話
create table unsigned_test(id tinyint unsigned);
insert into unsigned_test values(-100),(200),(300);
MariaDB [jason]> select * from unsigned_test;
+------+
| id   |
+------+
|    0 |
|  200 |
|  255 |
+------+
 
既然有了char 來存儲字符串,爲啥還要有一個varchar?
 
首先,char 和varchar 所能存儲的最大字節數時不一樣的,char 最多255 字節,varchar最多65535字節,在底層
存儲兩者也是不同的,char在硬盤中每一個字段的存儲空間都是固定的,而varchar 則是根據須要來指定存儲空
間的,varchar 存儲時會多記錄一個信息——該字段佔多少個字節,這樣就帶來讀取方面的一個區別,char的讀
取速度快於varchar,話又說回來varchar省存儲空間,建議若是字段時定長的那麼選擇char作存儲。
 
將大量數據一次性插入msyql 
 
除了上面的方法 insert into table(col1,col2,...) values(...),(....),還有一種更高效的方法,load data infile ....
此次我不想刪表再從新建表了,咱們來直接修改表的字段信息
 
alter table student modify phone_num char(11);
alter table student change name name char(10);
alter table student change introduction intro varchar(100);
 
來看看修改後表成啥樣了
MariaDB [jason]> desc student;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| id        | int(2)       | YES  |     | NULL    |       |
| phone_num | char(11)     | YES  |     | NULL    |       |
| name      | char(10)     | YES  |     | NULL    |       |
| intro     | varchar(100) | YES  |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+
你們根據修改後的效果本身總結下上海嗎兩種方法如何使用
 
要導入的文件內容以下:
分別對應了id,name,intro,phone_num  請注意時沒有按着字段順序來的
root@kali:~/data# cat student
1,jasona,nothing,15675698905
2,jasons,nothing,15675698905
3,jasond,nothing,15675698905
 
接下來導入數據
load data infile '/root/data/student' into table student  
fields terminated by ',' lines terminated by '\n'
(id,name,intro,phone_num);
第一行指定了導入的文件和表,第二行指定了分隔符,第三方指定了文件裏的字段順序
 
執行上述語句可能會報錯 「acces  denied for user ...」,是由於該mysql 用戶無權限讀寫服務器的文件,用root
登錄mysql,執行以下語句
grant file on *.* to jason@'%'
 
load data 比insert 快20倍,是插入數據最快的方法,
 
在添加數據時禁用索引,能夠加快插入速度,mysql 此時只需考慮增長數據,不用考慮更新索引文件,操做以下:
alter table tablename disable keys;
load data .......
alter table tablename enable keys;
 
limit從指定位置返回數據 
 
limit 默認從偏移量爲0開始返回數據,可是能夠指定偏移量——limit 偏移量,條數,從 偏移量+1 條數據開始返回數據
MariaDB [jason]> select * from student limit 1;
+------+-------------+--------+---------+
| id   | phone_num   | name   | intro   |
+------+-------------+--------+---------+
|    1 | 15675698905 | jasona | nothing |
+------+-------------+--------+---------+
1 row in set (0.00 sec)
 
MariaDB [jason]> select * from student limit 1,1;
+------+-------------+--------+---------+
| id   | phone_num   | name   | intro   |
+------+-------------+--------+---------+
|    2 | 15675698905 | jasons | nothing |
+------+-------------+--------+---------+
 
關於日期的一些函數
 
date_format 指定日期返回的格式,%d 和 %e 都返回具體的某一天,可是若是天是小於10的,%d 會返回用0
填充的日期,%e 不以0填充
MariaDB [jason]> select date_format(now(),'%Y-%m- %d') from student limit 1;
+-------------------------------+
| date_format(now(),'%Y-%m-%d') |
+-------------------------------+
| 2019-04- 04                    |
+-------------------------------+
1 row in set (0.00 sec)
 
MariaDB [jason]> select date_format(now(),'%Y-%m-%e') from student limit 1;
+-------------------------------+
| date_format(now(),'%Y-%m- %e') |
+-------------------------------+
| 2019-04- 4                     |
+-------------------------------+
 
單獨返回日期中的年月日
MariaDB [jason]> select year(now()),month(now()),day(now()) from student limit 1;
+-------------+--------------+------------+
| year(now()) | month(now()) | day(now()) |
+-------------+--------------+------------+
|        2019 |            4 |          4 |
+-------------+--------------+------------+
1 row in set (0.00 sec)
 
從左側或右側取 n 位返回
 
MariaDB [jason]> select left(now(),10),right(now(),8) from student limit 1;
+----------------+----------------+
| left(now(),10) | right(now(),8) |
+----------------+----------------+
| 2019-04-04     | 21:35:19       |
+----------------+----------------+
 
建表時到底該選用哪一種類型的字符串,下面是一些小建議:
 
 1)不要將數字類型存儲成字符串,應將其存儲爲數字類型,數字類型效率高於字符串,好比工資,應將其設置
爲double,而不是varchar;空間上一個字符至少會佔據一個字節,而數字是按位存儲的;比較上也會帶來差別,
好比 「9」>"100",可是 9<100
 2)若是從效率考慮的話,應該選擇char而不是varchar
 3)從空間方面考慮,應該選擇varchar
 4)若是字段的種類是固定的,比方說性別,只有'男','女',應該選擇enum
 5)若是能夠在字段中存儲 m 個選項中的某n個,m>=n,能夠選用set
 6)另外還有text 和blob,blob中存儲的字節,不存在字符集(gbk,utf8)的概念,blob 在檢索時是大小寫敏感
的,varchar ,text,blob,最大都是支持 65535字節,建議使用varchar
 7)對於圖像的存儲,建議把圖片保存在一個文件夾下,而後mysql 保存圖片地址
 
enum和set上個例子
create table enum_set(
name char(4),
gender enum('m','f'),
hobby set('football','music','kungfu')
);
 
insert into enum_set values
('李小龍','f','kungfu'),
('甄子丹','m','kungfu,music');
MariaDB [jason]> select * from enum_set;
+-----------+--------+--------------+
| name      | gender | hobby        |
+-----------+--------+--------------+
| 李小龍    | f      | kungfu       |
| 甄子丹    | m      | music,kungfu |
+-----------+--------+--------------+
 
有木有發現mysql中varchar 和char 是不區分大寫寫的?
 
MariaDB [jason]> select * from student where name like 'Jason%' limit 2;
+------+-------------+--------+---------+
| id   | phone_num   | name   | intro   |
+------+-------------+--------+---------+
|    1 | 15675698905 | jasona | nothing |
|    2 | 15675698905 | jasons | nothing |
+------+-------------+--------+---------+
爲了讓它大小寫敏感,能夠這麼幹
MariaDB [jason]> select * from student where binary name like 'Jason%' limit 2;
Empty set (0.00 sec)
 
上面咱們作查詢的時候都是水平打印,要不要來個垂直打印?
 
MariaDB [jason]> select * from student limit 2 \G;
*************************** 1. row ***************************
       id: 1
phone_num: 15675698905
     name: jasona
    intro: nothing
*************************** 2. row ***************************
       id: 2
phone_num: 15675698905
     name: jasons
    intro: nothing
2 rows in set (0.00 sec)
關鍵就在末尾的 \G
 
mysql 引擎
 
首先咱們來查看一下建表語句
MariaDB [jason]> show create table student \G;
*************************** 1. row ***************************
       Table: student
Create Table: CREATE TABLE `student` (
  `id` int(2) DEFAULT NULL,
  `phone_num` char(11) DEFAULT NULL,
  `name` char(10) DEFAULT NULL,
  `intro` varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)
ENGINE=InnoDB 這句咱們在建表時並未添加,是mysql建表時默認設置的,engine 中文翻譯爲引擎,
引擎究竟是個啥玩意兒?咱們使用mysql要求各不相同,有人不須要事務功能,有人須要常常讀,有人
須要常常寫,update,這些不一樣的技術或功能就叫引擎,咱們來看看mysql默認有哪些引擎
MariaDB [jason]> show engines \G;
*************************** 1. row ***************************
      Engine: MRG_MyISAM
     Support: YES
     Comment: Collection of identical MyISAM tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 2. row ***************************
      Engine: CSV
     Support: YES
     Comment: Stores tables as CSV files
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 3. row ***************************
      Engine: MEMORY
     Support: YES
     Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 4. row ***************************
      Engine: MyISAM
     Support: YES
     Comment: Non-transactional engine with good performance and small data footprint
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 5. row ***************************
      Engine: SEQUENCE
     Support: YES
     Comment: Generated tables filled with sequential values
Transactions: YES
          XA: NO
  Savepoints: YES
*************************** 6. row ***************************
      Engine: Aria
     Support: YES
     Comment: Crash-safe tables with MyISAM heritage
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 7. row ***************************
      Engine: PERFORMANCE_SCHEMA
     Support: YES
     Comment: Performance Schema
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 8. row ***************************
      Engine: InnoDB
     Support: DEFAULT
     Comment: Percona-XtraDB, Supports transactions, row-level locking, foreign keys and encryption for tables
Transactions: YES
          XA: YES
  Savepoints: YES
8 rows in set (0.00 sec)
好多,暈死,咱們重點看看 InnoDB 和 MyISAM
 
InnoDB
 
InnoDB是一個 事務型的存儲引擎,有 行級鎖定和 外鍵約束
MySQL運行時Innodb會在內存中創建緩衝池,用於緩衝數據和索引。並且它沒有保存表的行數,當
SELECT COUNT(*) FROM TABLE時須要掃描全表。當須要使用數據庫事務時,該引擎固然是首選。因爲
鎖的粒度更小,寫操做不會鎖定全表,因此在併發較高時,使用Innodb引擎會提高效率。可是使用行級
鎖也不是絕對的,若是在執行一個SQL語句時MySQL不能肯定要掃描的範圍,InnoDB表一樣會鎖全表。
 
適用場景:
1)常常更新的表,適合處理多重併發的更新請求
2)支持事務
3)能夠從災難中恢復(經過bin-log日誌等)
4)外鍵約束。只有他支持外鍵
5)支持自動增長列屬性auto_increment
 
MyIsam
沒有提供對數據庫事務的支持,也 不支持行級鎖和外鍵,所以當INSERT(插入)或UPDATE(更新)數據時
即寫操做須要鎖定整個表,效率便會低一些
 
適用場景:
1)不支持事務的設計,可是並不表明着有事務操做的項目不能用MyIsam存儲引擎,能夠在service層
進行根據本身的業務需求進行相應的控制。
2)不支持外鍵的表設計。
3)查詢速度很快,若是數據庫insert和update的操做比較多的話比較適用。
4)成天 對錶進行加鎖的場景。
5)MyISAM極度強調快速讀取操做。
6)MyIASM中存儲了表的行數,因而SELECT COUNT(*) FROM TABLE時只須要直接讀取已經保存好
的值而不須要進行全表掃描。若是表的讀操做遠遠多於寫操做且不須要數據庫事務的支持,那麼
MyIASM也是很好的選擇。
 
其餘的引擎各位感興趣的話能夠百度下
 
如何設置引擎
1.在安裝mysql的文章中有my.cnf,能夠設置默認引擎
2.建表的時候在後面加上引擎類型,create table xx(id int)  ENGINE=InnoDB
3.alter table student engine=myisam
 
一些sql小技巧 
 
1)null
表中有些字段的值可能爲null,咱們來看看NUll的相關語法
 
MariaDB [jason]> select null=0,null>2,null = null,null is null,null is not null  from test limit 1;
+--------+--------+-------------+--------------+------------------+
| null=0 | null>2 | null = null | null is null | null is not null |
+--------+--------+-------------+--------------+------------------+
|   NULL |   NULL |        NULL |            1 |                0 |
+--------+--------+-------------+--------------+------------------+
 
null 與任何值的比較結果都是null,判斷一個值是否爲null,要用 is,is not 
 
2)between
MariaDB [jason]> select 5 between 4 and 6, 5 between 6 and 4;
+-------------------+-------------------+
| 5 between 4 and 6 | 5 between 6 and 4 |
+-------------------+-------------------+
|                 1 |                 0 |
+-------------------+-------------------+
between 語法的區間 m and n,必須是m<n
 
3)like
在查詢時咱們可能想要找 名字叫作 "張大山"的人,但是查詢時咱們忘記了名字的全稱,只記得姓張;也或
者是想統計下姓張的總共有多少人,這時候就要用到like語法來進行模糊匹配,模糊匹配有兩個通配符,
 
%:匹配任意字符任意屢次
_:匹配任意字符一次
 
比方說: name like ‘%張%’ 匹配name 中帶張的,只要name 中有張就行
              name like '張%'  匹配姓張的,只要姓張就行
              name like '張_'  匹配姓張的,可是名裏只帶一個字,張五,張六啥的
除了like mysql 中還有正則匹配, regexp,這個我在工做中基本沒用過,感興趣的朋友能夠百度下
 
在mysql 中使用變量
 
通常狀況下變量在java,python中才擁有,可是mysql 中也擁有變量,來看看mysql中變量的使用
1)變量聲明
法兒一:
MariaDB [jason]> select @avgid:=avg(id) from student;
+-----------------+
| @avgid:=avg(id) |
+-----------------+
|     2.000000000 |
+-----------------+
1 row in set (0.01 sec)
法兒二:
MariaDB [jason]> set @avgid2=3;
Query OK, 0 rows affected (0.00 sec)
 
2)變量使用
MariaDB [jason]> select * from student where id>@avgid;
+------+-------------+--------+---------+
| id   | phone_num   | name   | intro   |
+------+-------------+--------+---------+
|    3 | 15675698905 | jasond | nothing |
|    3 | 15675698905 | jasond | nothing |
|    3 | 15675698905 | jasond | nothing |
+------+-------------+--------+---------+
3 rows in set (0.00 sec)
 
MariaDB [jason]> select * from student where id=@avgid2 limit 1;
+------+-------------+--------+---------+
| id   | phone_num   | name   | intro   |
+------+-------------+--------+---------+
|    3 | 15675698905 | jasond | nothing |
+------+-------------+--------+---------+
1 row in set (0.01 sec)
 
mysql 腳本
 
想這樣一個問題,咱們操做mysql的語句一直是在交互界面執行的,生產中遇到天天執行的重複任務怎麼辦?
 
和其餘編程語言同樣,咱們能夠把要執行的sql寫在文件裏,而後每次去執行這個文件,
好比,aa.sql 
root@kali:~/code# cat aa.sql
select * from student limit 2;
 
能夠用如下兩個方法來執行這個文件
法兒一:
在mysql 交互界面
MariaDB [jason]> source /root/code/aa.sql
+------+-------------+--------+---------+
| id   | phone_num   | name   | intro   |
+------+-------------+--------+---------+
|    1 | 15675698905 | jasona | nothing |
|    2 | 15675698905 | jasons | nothing |
+------+-------------+--------+---------+
2 rows in set (0.00 sec)
 
法兒二:
在linux 終端
root@kali:~/code# mysql -ujason -p123  jason < aa.sql
id    phone_num    name    intro
1    15675698905    jasona    nothing
2    15675698905    jasons    nothing
相關文章
相關標籤/搜索