注:該MySql系列博客僅為個人學習筆記。
在使用MySql的時候,基本都是用圖形化工具,如navicat。最近發現連最基本的創建表的語法都快忘了...
所以,想要重新系統性的學習下MySql,為后面學習MySql的一些高級查詢,MySql性能和SQL語句的優化等打個基礎。
用博客來記錄下學習的過程,方便以后查閱和加強記憶。有錯誤的地方還請指出!
一、MySql的基本操作命令
注: <>表示參數、[]表示可選項
連接數據庫:mysql> mysql -u<username> -p<password>;
顯示所有數據庫:mysql> show databases;
選擇數據庫:mysql> use <database name>;
創建一個數據庫:mysql> create database <database name> [charset <charset>];
刪除一個數據庫:mysql> drop database <database name>;
修改數據庫名:mysql無法直接修改數據庫名!
顯示所有表:mysql> show tables;
刪除一張表:mysql> drop table <table name>;
修改表名:mysql> rename table <table name> to <new table name>;
清空表:mysql> truncate <table name>;
truncate和delete的區別:truncate相當於刪表再重建一張相同結構的表,操作后得到一張全新表;delete只是刪除數據,而且是按照行來刪除,如果表中有自增型字段,其影響還在。
查看表結構:mysql> desc <table name>;
快速建一張相似的表:mysql> create table <table name> like <another table>;
查看建表語句:mysql> show create table <table name>;
設置服務器編碼(臨時性的):mysql> set names <charset>;
注意對數據庫進行操作時,保持編碼的一致性,否則會導致一些不明不白的問題;
一般我們的doc窗口是gbk編碼的,所以我們要告訴數據庫服務器我們客戶端使用的是gbk編碼:set names gbk;這樣我們插入的數據就會按照gbk來解碼,否則輕微的亂碼,嚴重的直接報錯。
set names gbk;
相當於:
set character_set_client = gbk;
set character_set_connection = gbk;
set character_set_result = gbk;
將SQL語句以日志形式記錄到sql文件:tee <location>;
二、基本SQL語句
1.插入語句:
插入指定字段數據:mysql> insert into <table>(filed1,filed2,filed3...) values(v1,v2,v3...);
插入所有字段數據:mysql> insert into <table> values(v1,v2,v3...vn);
修改語句:mysql> update <table> set <filed1=v1> where <expression>;
刪除語句:mysql> delete from <table> where <expression>;
刪除所有數據:mysql> delete from <table>; 只是刪除數據;
2.查詢語句:
查詢某些字段:mysql> select filed1, filed2,filed3 from <table> [where <expression>];
盡量不要使用select * from <table>,因為會查出許多不必要的字段來,會占用內存;取出自己想要的行和列即可;
3.修改表
增加一列:mysql> alter table <table> add <field> <type> [other] '';
在某列后增加一列:mysql> alter table <table> add <field> <type> [other] after <field1>;
添加到第一列:mysql> alter table <table> add <field> <type> [other] first;
刪除某一列:mysql> alter table <table> drop <field>;
修改某一列的參數:mysql> alter table <table> modify <field> <type> [other];
修改列名(必須帶上參數):mysql> alter table <table> change <old field> <new field> <type> [other];
①.增加一列:mysql> alter table <table> add <field> <type> [other] '';
②.在某列后增加一列:mysql> alter table <table> add <field> <type> [other] after <field1>;
③.添加到第一列:mysql> alter table <table> add <field> <type> [other] first;
④.刪除某一列:mysql> alter table <table> drop <field>;
⑤.修改某一列的參數:mysql> alter table <table> modify <field> <type> [other];
⑥.修改列名(必須帶上參數):mysql> alter table <table> change <old field> <new field> <type> [other];
4.批量導出數據:
從同一數據庫導入:INSERT INTO <table> SELECT field1,field2,field2,..., FROM <another table>;
從不同數據庫導入:INSERT INTO <database.table> SELECT field1,field2,field2,..., FROM <another database.table>;
步奏①:查看表結構及數據
步奏②.在另一個數據庫里新建一個stu表,選取student中的某些字段
步奏③.從attendance數據庫的student表中將特定字段的數據導入到test數據庫的stu表中:
三、MySql三大列類型
推薦博客:MySQL 請選擇合適的列!
1.數值型
整型:tinyint smallint mediuint int bigint
tinyint: 占一個字節8位(1byte=8bit),有符號為-128 - 127 (-2n-1 - 2n-1-1),無符號為0 - 255(0 - 2n-1); 有符號時,正數第一位為0,負數第一位為1; 負數=絕對值-128;
int系列(整型)的類型聲明時的參數:(M) unsigned zerofill
#unsigned: 無符號類型;
#(M) + zerofill : M表示數據的寬度(不是大小), (M)參數必須和zerofill配合使用才有意義,不夠位時用0填充,要配合zerofill使用才有效果,單獨使用是沒有意義的(如int(11));也就是說就算設置了int(20),也沒有影響,除非使用zerofill。而且使用了zerofill后,建的字段默認就為unsigned,看第二張圖。
#smallint(0 - 65535) 只能存5位數,卻可以填充20個0....
小數型:浮點型/定點型
float(M,D),decimal(M,D)
float和decimal都是變長類型,要用多大,就分多大,不要無謂的分太大了。
① float(浮點)要么占4個字節,要么8個字節
M叫"精度" --> 代表"總位數",D代表"標度",代表小數位(小數點右邊的位數)
#小數點后面超出位數則四舍五入:
#小數點左邊是不能超出位數的:
float 能存 10^38 - 10^-38
如果M<=24,占4個字節,否則占8個字節
#float的精確度有時會有損失:所以對精確度要求高的數據是不能用float來存儲的,如銀行存錢!float在內部是用二進制表示的如:7.22用32位二進制是表示不了的,會被當做整型處理。所以就不精確了。
② decimal(定點):定點是把整數部分,和小數部分分開存儲的,比float精確。
#測試小數位:說明小數位還是會被四舍五入的
#但是decimal的精確度比float高:decimal是將整數部分和小數部分分開存儲的,所以比float精確。只是將最后一位進行了四舍五入
*銀行存錢既不是用的float也不是decimal,是用整型來存儲,錢會被換成分來存儲;者不防也是一種好的設計方式。
*在指定decimal的精度時,也不是隨便指定一個長度就行的,看下表:(此部分查看了一些博客,眾說紛紜,可能不正確)
DECIMAL(18,9)使用9個字節,小數點前4個字節,小數點1個字節,小數點后4個字節;
DECIMAL(8,2)使用5個字節,小數點前3個字節(6位),小數點1個字節,小數點后1個字節。
DECIMAL(9,2)使用6個字節,小數點前4個字節(7位),小數點1個字節,小數點后1個字節。(所有小數點后一般存兩位,小數點前要合理選擇)
#下面是MySql手冊的說法
2.字符串型
① char(M):定長類型(0 <= M <= 255 注意M是長度,不是字節數) 能存儲固定M個長度,不足用空格補至M個
char類型的查詢速度快,在查找行記錄時,因為都是定長,完全可以通過行數和行的長度(即M)計算出文件指針的偏移量,所以查詢速度快;
但是數據必須在限定的長度(M)范圍內;char(M) 如果不夠M個長度,會在末尾用空格補至M個長度,所以會存在浪費的情況。
#不能超出范圍(嚴格模式下):
#char(M)如果不夠M個長度,會在末尾用空格補齊,而取出數據的時候,會去掉右側的空格,看測試:
② varchar(M):變長類型(0 <= M <= 65535 注意M是長度,不是字節數) 存儲0-M個字符
*varchar(M)類型數據前會有一個前綴碼,用於保存數據的長度,每次從磁盤文件中讀取數據的時候,就是先讀取這個前綴碼的數值(比如2),然后文件指針往后偏移2個長度,讀取出數據。
*varchar(M)類型數據如果不夠M個長度,不會像char那樣用空格補齊,但是varchar前面有1-2兩個字節(因為varchar長度范圍在0-65535,最多占兩個字節)用來標志該列內容的長度。所以就算存儲空數據,該列至少占一個字節。
注意char(M)和varchar(M)的M只代表字符長度,不代表字節數,不管是中文還是英文,都是長度;char和varchar類型占的字節跟使用的字符編碼有關
③ text:變長類型,跟varchar類似[varchar(65535) = text ],會有1-4個字節用於存儲文本長度值,blob同理。
四種類型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT
text類型, 可以存比較大的文本段,搜索速度稍慢;因此,如果不是特別大的內容,建議用char,varchar來代替
text不用加默認值,加了也沒有用
④ blob
BLOB是一個二進制大對象,可以容納可變數量的數據。有4種BLOB類型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它們只是可容納值的最大長度不同。
blob一般用來存儲圖像、音頻等二進制數據,也可以存文本類型。
blob的最大意義在於防止因為字符集的問題,導致信息丟失。比如:一張圖片中有0xFF字節,這個在ASCII字符集中為非法,在入庫的時候就會被過濾掉,但如果存成blob類型,就是以二進制形式存儲,存進去的是什么,取出來的還是什么,數據不會丟失。
text和blob都不怎么常用,其存儲的字符量大,查詢速度稍慢。一般來說varchar足夠。
#blob和text類型都不能設置默認值.
#但是是可以有非空約束的
⑤NCHAR、NVARCHAR、NTEXT。
這三種從名字上看比前面三種多了個“N”。它表示存儲的是Unicod數據類型的字符。我們知道字符中,英文字符只需要一個字節存儲就足夠了,但漢字眾多,需要兩個字節存儲,英文與漢字同時存在時容易造成混亂,Unicode字符集就是為了解決字符集這種不兼容的問題而產生的,它所有的字符都用兩個字節表示,即英文字符也是用兩個字節表示。nchar、nvarchar的長度是在1到4000之間。和char、varchar比較起來,nchar、nvarchar則最多存儲4000個字符,不論是英文還是漢字;而char、varchar最多能存儲8000個英文,4000個漢字。可以看出使用nchar、nvarchar數據類型時不用擔心輸入的字符是英文還是漢字,較為方便,但在存儲英文時數量上有些損失。所以一般來說,如果含有中文字符,用nchar/nvarchar,如果純英文和數字,用char/varchar。
3.日期時間類型
*可以使用任何常見格式指定DATE、DATETIME和TIMESTAMP值,'YYYY-MM-DD HH:MM:SS'或'YY-MM-DD HH:MM:SS'格式的字符串。
*允許“不嚴格”語法:任何標點符都可以用做日期部分或時間部分之間的間割符。例如,'98-12-31 11:30:45'、'98.12.31 11+30+45'、'98/12/31 11*30*45'和'98@12@31 11^30^45'是等價的。
*'YYYYMMDDHHMMSS'或'YYMMDDHHMMSS'格式的沒有間割符的字符串,假定字符串對於日期類型是有意義的。例如,'19970523091528'和'970523091528'被解釋為'1997-05-23 09:15:28',但'971122129015'是不合法的(它有一個沒有意義的分鍾部分),將變為'0000-00-00 00:00:00'。
*包含兩位年值的日期會令人模糊,因為世紀不知道。MySQL使用以下規則解釋兩位年值:
00-69范圍的年值轉換為2000-2069。
70-99范圍的年值轉換為1970-1999。
①date 日期 存儲'2016-09-04'類型
MySQL用'YYYY-MM-DD'格式檢索和顯示DATE值。支持的范圍是'1000-01-01'到 '9999-12-31'。
#如果你為一個DATE對象分配一個DATETIME或TIMESTAMP值,結果值的時間部分被刪除,因為DATE值未包含時間信息。
②time 時間
MySQL以'HH:MM:SS'格式檢索和顯示TIME值(或對於大的小時值采用'HHH:MM:SS'格式)。
TIME值的范圍可以從'-838:59:59'到'838:59:59'。小時部分會如此大的原因是TIME類型不僅可以用於表示一天的時間(必須小於24小時),還可能為某個事件過去的時間或兩個事件之間的時間間隔(可以大於24小時,或者甚至為負)。
#time不能隨意指定連接符:'HHMMSS'、'HH:MM:SS'、'HH:MM'、'D HH:MM:SS',這里D表示日,可以取0到34之間的值。無效TIME值被轉換為'00:00:00'。
#可以看出,最終都變成HH:MM:SS格式了;D表示日,在當前小時基礎上加上D天;CURRENT_TIME函數用於獲取當前時間
③datetime
MySQL以'YYYY-MM-DD HH:MM:SS'格式檢索和顯示DATETIME值。支持的范圍為'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。
datetime即date跟time的組合,參照上面。
④year 年
YEAR類型是一個單字節類型用於表示年。MySQL以YYYY格式檢索和顯示YEAR值。范圍是1901到2155。非法YEAR值被轉換為0000。
說明下year是如何用一個字節存儲1901-2155的,一個無符號字節能存0-255,即266種變化,year的基數是1900年,從1-255 》 1901-2155,再加一種0000即為266種年份,所以year占用的一個字節是這樣使用的。
兩位長度,范圍為'00'到'99'。'00'到'69'和'70'到'99'范圍的值被轉換為2000到2069和1970到1999范圍的YEAR值。
⑤timestamp 時間戳
TIMESTAMP列的顯示格式與DATETIME列相同。換句話說,顯示寬度固定在19字符,並且格式為YYYY-MM-DD HH:MM:SS。
特性:
在CREATE TABLE語句中,可以用下面的任何一種方式聲明第1個TIMESTAMP列:(注意是第一個timestamp列,其它列會有所區別,見MySql手冊)
用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP子句,列為默認值使用當前的時間戳,並且自動更新。
不使用DEFAULT或ON UPDATE子句,與DEFAULT CURRENT_TIMESTAMP ON UPDATECURRENT_TIMESTAMP相同。
用DEFAULT CURRENT_TIMESTAMP子句不用ON UPDATE子句,列為默認值使用當前的時間戳但是不自動更新。
不用DEFAULT子句但用ON UPDATE CURRENT_TIMESTAMP子句,列有默認值0並自動更新。
用常量DEFAULT值,列有給出的 默認值。如果列有一個ON UPDATE CURRENT_TIMESTAMP子句,它自動更新,否則不。
換句話說,你可以為初始值和自動更新的值使用當前的時間戳,或者其中一個使用,或者兩個皆不使用。
#不使用DEFAULT或ON UPDATE子句,與DEFAULT CURRENT_TIMESTAMP ON UPDATECURRENT_TIMESTAMP相同。
#使用默認插入當前時間:(用DEFAULT CURRENT_TIMESTAMP子句不用ON UPDATE子句,列為默認值使用當前的時間戳但是不自動更新。)
#使用默認值和自動更新:(用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP子句,列為默認值使用當前的時間戳,並且自動更新。)
#雖然我們也可以用char(M),或varchar(M)來存儲日期/時間,比如char(19)來存儲YYYY-MM-DD HH:MM:SS''datetime類型;也許會認為char查詢速度快,剛好占用19個字節,也不會浪費空間;但其實不是這樣的;我們最好專列專用,存什么類型的數據就用什么類型,存日期就用日期類型,MySql是對其做了優化的,效率高,存儲空間利用高,而且我們也會給我們后面的解析造成一定影響,多做些工作。根據某些需求,我們可以用int來存儲時間戳,以提高效率。
#從下表可以看出,用datetime只占了8個字節,char(19)占了19個字節。
四、MySql建表
建表的過程就是一個聲明列的過程;
建表的時候,不防讓所有列都為定長,這樣每行數據也都是定長,可以極大的提高查詢速度。如果在一張表中,只有一兩列是變長類型,其余都是定長類型,雖然能節省一點空間,但查詢速度會下降幾個數量級,豈不是很可惜,在不浪費太多空間的前提下,盡量以空間換時間。
在計算機的優化中,空間與時間是一對矛盾,優化無非就是:時間換空間、空間換時間。
一般來說對於字符長度較大的列[如varchar(1500), text],其數據也不會經常變動,我們可以將該列單獨拿到一個表中,使用外鍵關聯起來。
在開發中,我們把頻繁用到的數據最好使用定長,存到主表,優先考慮效率;不經常用到和比較占用空間的數據如個人介紹等長文本數據存到另一種表中(輔助表),關聯起來,主要考慮空間。
選擇數據類型的原則:
(4)NULL列不便於比較,NULL是什么都沒有,''這是為空,空和NULL是有區別的。判斷列是否為NULL要使用IS NULL 或者 IS NOT NULL
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MySql基礎篇基本完了,算是復習完了,接下來會專門學習查詢語句!