MySQL 筆記(一)

mysql-001 MySQL安裝: (5.0為例) 原始來源:http://dk.spot.idv.tw/database/mysql-note-1

開始前請留意5.0的原廠說明,很多說明上所提到的用法可能無法很正確的達到效果,原因是功能保留或功能尚未完整實作,因此這些語法可以被接受,但可能無法實作。

此部份只簡單說明讓MySQL可以Run起來,詳細設定請參閱使用說明書

Windows版本安裝(快速安裝法):

  1. 下載noinstall版本的壓縮檔案,並解壓縮到你要放置的地方,以我為例,我放置在C:\mysql這個位置(如果解壓後請跟該資料夾名稱)
  2. 進入C:mysql資料夾,複製my-medium.ini為my.ini,打開my.ini進行編輯,在[mysqld]底下加入底下兩個設定basedir=C: \\mysql
    datadir=C:\\mysql\\data
  3. 接著進入bin資料夾,執行底下指令進行測試(請於文字模式下執行)cd C:\mysql\bin
    mysqld-nt.exe --console
  4. 如果最後畫面沒有顯示錯誤表示正常運行(通常會看到一堆InnoDB訊息這是正常的),請關閉文字模式執行視窗,並再次以文字模式進入bin資料夾,執行下面指令
    mysql-nt.exe --install
  5. 如果看到successed表示成功了 ,接著在文字模式下輸入:
    C:>net start mysql
    看到啟動表示沒問題了
  6. MySQL4之後字碼成為重要的注意項目,在windows 文字模式下,client屬於big5,所以如果你想要用文字模式下操作資料庫,就必須在my.ini中的[client]底下加入:
    --default-character-set=big5
    然後重新啟動服務
  7. 如果你要預設建立的資料表為big5,請在my.ini中加入底下兩行:-default-character-set=big5
    --default-collation=big5_chinese_ci
    如果要使用utf8,則第一行改成utf8,第二行改成utf8_generl_ci,其他校對字集可以在mysql clinet中使用show collation來查詢

Linux版本安裝:

如果你是RH系列或FC系列,請抓取rpm版本,指令如下:

#rpm -ivh mysql-版本.rpm

注意,4.1之後官網將rpm分成server、client、max三個主要套件,server是必須安裝的, client是用戶工具,max則是附帶的更多功能,基本上RH系列或FC系列上面都會預設搭載MySQL,所以要安裝前請先留意有沒有舊版本,建議使用 yum指令來進行安裝,如下:

#yum install mysql

如果要檢查現在的版本你可以用

#yum list mysql

如果不想使用舊版本要改用新的,Google一下版本轉換注意的事項(最重要的就是備份拉),接著移除舊版,並安裝新版本

#yum remove mysql

#yum localinstall mysql-新版本.rpm

記得有分三個主要套件,最後啟動服務

#service mysqld start

如果要預設字碼字集,必須先找出my.cnf,通常在/etc/my.cnf,打開編輯,在[mysqld]下方加入底下兩行

default-character-set=utf8

default-collation=utf8_general_ci

再來於[client]底下加入

default-character-set=utf8

然後重開mysqld就可以了

由Client Tool登入MySQL資料庫 :

mysql -u [username] -h [hostname] -p[password] [databasename]

資料庫的使用:

mysql> use 資料庫;

不管是更換資料庫或者剛要使用資料庫,皆使用use這個指令


列出資料表的欄位屬性:

mysql> describe 資料表;

上面describe指令,可以列出後方資料表的欄位屬性


查詢SELECT:

  • 基本語法:

SELECT 欄位1[,欄位2,欄位3,...]

FROM 資料表

欄位是列出的資料表中的欄位,FROM後面資料表是要查詢的資料表,這個部分只是基本的語法,下面會加入更多的用法。

  • 以字串取代固定出現的文字:

SELECT '字串',欄位1[,欄位2,欄位3,...]

FROM 資料表

輸入的字串會被每一筆列出的資料都列出

  • 重複只列出一筆:

SELECT DISTINCT 欄位1[,欄位2,...]

FROM 資料表

預設上重複的資料通通會被列出,也就是用ALL的結果,如果加上DISTINCT則,當資料出現兩筆以上相同時,只會列出一筆

  • 條件限制:

SELECT 欄位

FROM 資料表

WHERE 條件

WHERE用來設定要列出的條件

ex:

SELECT *
FROM testtb
WHERE field1>0;

    1. 條件的判斷子:
      <, =, >, <=,>=,<>,is,is not,in,not in
      其中比較需要解釋的是<>,這代表不等於的意思,而is與is not,則用於判斷null的值,in與not in則用於比對一個集合的時候
    2. 欄位 between ... and ...:
      這個應該也算判斷子之一,用於比對欄位的值介於某個範圍之間
      ex:
      SELECT *
      FROM testtb
      WHERE field1 between 0 and 100 ;
    3. 集合的比對:
      ex:
      SELECT *
      FROM testtb
      WHERE field1 in (1,2,3,4,5,6,7);
      只要field1的值有出現1,2,3,4,5,6,7,則符合條件
    4. null的判斷:
      ex:
      SELECT *
      FROM testtb
      WHERE field1 is null ;
    5. 日期的判斷:
      直接使用大於、小於、等於方式來判斷日期條件,但要注意必須使用完整日期格式
      ex:
      select 欄位1[,欄位2[,欄位3...]
      from 資料表
      where 欄位>'2002-06-01';
    6. 字串比對:
      使用like來比對字串,萬用字元%與 _ 底線用來表示如下:
      %:0個以上的任何字串元
      _:1 個任何字元
      ex:
      SELECT *
      FROM testtb
      WHERE field1 like '%字串_';
      這代表要找出field1中,中間出現字串兩字,前面可以有任何字元或者沒有字元,但後面必須要有一個任何字元
    7. 子查詢:
      又稱巢狀查詢,這個部分後面在說明,子查詢也是條件的一種
  • 一般函式:
    函式的使用情形很多,可以當作條件,也可以處理欄位的值,也能使用在新增資料上,通常會把欄位放在函式之內來對欄位的值進行處理
    ex:
    SELECT lower(name)
    FROM student;
    上面範例列出所有學生資料,並將姓名全部轉為小寫

    底下為一般常用的函式列表:
    • 字串函數
      lower(str):轉小寫字母
      upper(str):轉大寫字母
      length():計算內容長度
      char_length(str):計算字串長度
      ascii(c):計算字元的ascii
      locate(substr,str[,pos]):搜尋出現位置,pos指定開始位置(第一個字位置為1)
      replace(str,from_str,to_str):字串取代,str為內容,from_str為要尋找的字串樣式,to_str為要取代的字串樣式
    • 數學函數
      abs(n):取絕對值
      ceiling(n):無條件進位
      floor(n):無條件捨去
      PI():PI常數(圓週率)
      round(x,d):x為數值,d為四捨五入位數(d可為負)
      power(x,y):x的y次方
      sqrt(n):開更號
      mod(n,m):取餘數
    • 時間函數
      dayofmonth(d):由日期中取得日的部分
      month(d):由日期中取得月的部分
      year(d):由日期中取得年的部分
      now():取得現在日期時間
      quarter(d):由日期中計算目前的季數
      Hour(t):由時間中取得小時的部分,以24小時為單位
      minute(t):由時間中取得分的部分
      second(t):由時間中取得秒的部分
    • 常用函數
      rand():0-1之間的亂數,亂數放大FLOOR(i+RAND()*(i+j)),rand(N) N類似亂數種子,但與亂數種子不同,同樣的值會產生同樣的亂數
      database():目前的資料庫名稱
      user():目前的使用者名稱
  • 排序:
    ORDER BY子句 SELECT 欄位1[,欄位2,欄位3....]
    FROM 資料表
    ORDER BY 欄位1[,欄位2,....] 排序可以同時對多個欄位進行排序,由左而右為排序優先,反向排序則在排序欄位後方加上DESC,預設為由小而大

    利用rand()函式隨機排序:
    SELECT *
    FROM tb_name
    ORDER BY rand();
  • 群組:
    GROUP BY子句 SELECT 欄位1[,欄位2,欄位3....]
    FROM 資料表
    GROUP BY 欄位1[,欄位2,....] 群組通常會與集總函式一起使用,但也不一定要有集總函式,集總函式下面說明,群組可以多欄位進行,群組的用意在於將相同欄位值的資料集合在一起,這與集總函式有呼應的意味

    注意:當使用GROUP BY時,SELECT後方出現的欄位必須都在GROUP BY指定欄位中,或者是集總函式,舉個例子,找出供應商商品價格平均小於50的資料,列出供應商代碼(supp_code),平均價格
    ex:
    SELECT supp_code,AVG(price)
    FROM products
    GROUP BY supp_code
    HAVING AVG(price)<50;
  • 集總函式:
    以字面的意思來看,就可以知道這些函式用來做資料群的計算, 常見的集總函式有COUNT( ),SUM(),AVG( ),MAX( ),MIN( ),STD( ),COUNT( )算出筆數,SUM( )總和,AVG( )平均,MAX( )取最大值,MIN( )取最小值,STD( )計算標準差 ,使用方法如下
    ex:
    SELECT COUNT(*)
    FROM testtb
    GROUP BY field1;
    ex:
    SELECT SUM(price)
    FROM testtb
    GROUP BY field1;

    GROUP BY與集總函式合用,可以以群組為單位進行計算,上方第二個例子,對price欄位進行總和計算,以field1欄位為群組,當不指定GROUP BY時,則全部資料為一個群組,也就是不分群

    集總函式對於null的資料會忽略不計 (count()例外)
  • 集總函式的條件判斷 :
    HAVING 子句 SELECT 欄位1[,欄位2,欄位3]
    FROM 資料表
    HAVING 集總函式條件判斷 與集總函式有關,所以通常出現這樣的條件判斷,一定會有GROUP BY子句相隨,下面例子找出價格平均大於50的群組,以field1為群組
    ex:
    SELECT field1
    FROM testtb
    GROUP BY field1
    HAVING AVG(price)>50

    HAVING實際上可用於一般條件,但未進行優化,所以如果要使用在一般條件上,儘量不要使用
  • 集總函式的排序:
    以指定欄位位置作為order by的指定
    ex:
    SELECT COUNT(*),class
    FROM student
    GROUP BY class
    ORDER BY 1;
    以別名指定
    SELECT COUNT(*) as std_q,class
    FROM student
    GROUP BY class
    ORDER BY std_q;
  • 數學運算:
    ex:
    SELECT field1*10/2,field2+10
    FROM testtb;
    欄位是可以進行數學運算的,甚至兩個欄位進行運算,條件中也可以使用
  • 別名alias:
    分為欄位別名與資料表別名 SELECT 欄位 as 欄位別名
    FROM 資料表 as 資料表別名 使用時機:通常會使用欄位別名都是在於要更換欄位顯示的名稱,或者要列出的並不是欄位,像是集總函式計算結果,而資料表別名,通常用於子查詢,而且是比較複雜的子查詢
  • 合併:
    合併的發展是由Cartesian Product卡笛森乘機所 衍伸出來的Cross Join,是指資料交叉結合的結果,例如:兩張表格一張表有10筆資料,另一張表有20比資料,第一張表格的每筆資料與第二張表格結合共會產生20筆,全部的資料合併一共會產生10 x 20筆資料,但這樣的資料通常沒有太大的作用,所以發展出Inner Join,Outer Join,Natural Join,Theta Join等..
    • INNER JOIN
      INNER JOIN是針對條件符合的資料值來進行合併,只有符合條件才列出
      語法:
      SELECT *
      FROM Table1 INNER JOIN Table2 ON Table1.field1=Table2.field2
    • EQUI JOIN:
      EQUI是代表等於的意思,根據兩個欄位的值如果相等,則該兩筆資料合併在一起,可歸屬INNER JOIN的一種
      SELECT *
      FROM Table1,Table2
      WHERE Table1.field1=Table2.field2 範例:
      Table1
      field1 field2 field3
      0 A X
      1 B Y
      2 B Z
      Table2
      field1 field2 field3
      5 1 X
      2 1 Y
      3 2 Z
      合併結果:
      field1 field2 field3 field1 field2 field3
      1 B Y 5 1 X
      1 B Y 2 1 Y
      2 B Z 3 2 Z
    • NATURAL JOIN:
      NATURAL JOIN是根據兩張表格相同欄位來進行合併,相同欄位的值如果相同則該兩筆資料合併,實際上NATURAL JOIN是NATURAL INNER JOIN的簡寫,NATURAL同時可以使用於INNER JOIN與OUTER JOIN中,此部份不常用請查詢MYSQL 5.1的使用手冊,這裡只討論NATURAL INNER JOIN的部份
      語法:
      SELECT *
      FROM Table1 NATURAL JOIN Table2
    • THETA JOIN
      THETA JOIN是根據資料值的<,<=,>,>=,=等大小的關係進行合併,我認為他是INNER JOIN的一種,所以列在一起
      語法:
      SELECT *
      FROM Table1,Table2
      WHERE Table1.field1>Table2.field2
      以上面的例子來說結果為:
      field1 field2 field3 field1 field2 field3
      2 B Z 5 1 X
      2 B Z 2 1 Y
    • OUTER JOIN
      外部又分為LEFT OUTER JOIN與RIGHT OUTER JOIN,實際上這兩種都是一樣的,只是方向的問題而已,與INNER JOIN的差別在於,OUTER JOIN會把指定的一方沒有符合條件的也列出,所已有方向性
      • LEFT OUTER JOIN
        由字面來看叫做左外部合併,顧名思義左邊比較重要,所以左邊的表格資料不管有沒有符合條件都必須列出,而右邊表格如果沒有資料對應則以NULL值填入
        語法:
        SELECT *
        FROM Table1 LEFT OUTER JOIN Table2 ON Table1.field1=Table2.field2
        以上面的例子來說結果為:
        field1 field2 field3 field1 field2 field3
        0 A X null null null
        1 B Y 5 1 X
        1 B Y 2 1 Y
        2 B Z 3 2 Z
      • RIGHT OUTER JOIN
        剛好與LEFT OUTER JOIN方向顛倒,也就是右邊的資料要全部列出
        語法:
        SELECT *
        FROM Table1 RIGHT OUTER JOIN Table2 ON Table1.field1=Table2.field2

合併不一定只有兩個表格進行,可以多個表格同時進行合併,不舉例子了,發揮想像力..Orz

  1. 子查詢(巢狀查詢):(Mysql4.1之後才有支援,Mysql5趨於完備)
    上面有提過,巢狀查詢是條件的一種,所以會使用在WHERE之中當作一種條件,事實上這只是針對常用的部分,子查詢subqueries在Mysql中可以用在很多地方,但大部分還是針對條件的部分,我也只說明條件中如何使用
    1. 語法:
      SELECT *
      FROM table
      WHERE table.field OP (subqueries)
      OP指判斷子,subsqeries指巢狀查詢
    2. 條件判斷子:IN,NOT IN,EXISTS,NOT EXISTS
      • IN與NOT IN:
        這個與原本用在WHERE中的IN與NOT IN是相同的意思,只是集合改由子查詢來代替,要注意的是,欄位型態必須相同。
      • EXISTS與NOT EXISTS:
        EXISTS 這個的邏輯有點難說明,他是以第一層查詢的資料,每次抓取一筆進入第二層查詢進行比對,如果有資料存在(EXISTS),則條件成立,NOT EXISTS剛好相反,如果第二層沒有查到資料,則條件成立。事實上,IN與NOT IN也是相同的作法,只是在想法上可以改成子集合方式來思考比較容易理解。
      • SQL語法中,子查詢使用等於、大於、小於等符號來進行比對是有限制的,只能針對單一個值,例如你確定子查詢查出的值一定只有一筆,這樣的狀況下便可以使用,但如果為多比,就沒辦法這樣做了,必須改用IN與NOT IN或者EXISTS與NOT EXISTS來處理

 

 

MySQL 筆記(二)

開始前的說明:

  • 中括弧[ ]代表可有可無,大括弧{ }代表一定要有,| 代表或者,也就是多選一,點點點 ... 代表可以多個
  • 斜體字為語法,字體大寫是語法部分,小寫則為可以設定或者自行命名,或者另外有其他的解釋必須分開討論者

資料庫建立:

CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_specification [, create_specification] ...]

說明:DATABASE與SCHEMA是相同的作用,都是建立資料庫的意思,IF NOT EXISTS是當資料庫存在時,則不建立,如果資料庫存在但沒有加上此語法,會出現錯誤db_name就是要建立的資料庫名稱了

create_specification說明:

[DEFAULT] CHARACTER SET charset_name
| [DEFAULT] COLLATE collation_name

DEFAULT 可以省略,事實上整個create_specification都可以省略,建立時會以資料庫預設作為設定,這個語法用來指定資料庫的字碼與字集,charset_name是字集名稱,collation_name是校對字集名稱,MySQL5.0所提供的字集可以用 show collation語法來查詢,如果需要查詢某個字碼的校對字集也可以使用show collation like '%字碼%'來查詢

ex:

CREATE DATABASE test_db
CHARACTER SET utf8,COLLATE utf8_general_ci;

資料庫修改:

修改資料庫設定只需要將CREATE改成ALTER就可以了,其餘語法相同

資料庫刪除:

DROP {DATABASE | SCHEMA} [IF EXISTS] db_name

資料庫的刪除是簡單的,IF EXISTS是當資料庫存在時則進行刪除,如果資料庫不存在,不會出現錯誤訊息


資料表建立:

建立的語法分為三種:

    1. CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
      (create_definition,...)
      [table_option ...]
    2. CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
      [(create_definition,...)]
      [table_option ...]
      select_statement
    3. CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
      { LIKE old_tbl_name | (LIKE old_tbl_name) }

TEMPORARY 代表建立的資料表是暫時的,離線之後就會消失, IF NOT EXISTS 與建立資料庫相同,create_definition與table_option用於定義這個資料表,下面再一起說明,第二種語法中的 select_statement是用來,進行查詢語法,將查詢結果直接寫入這個剛建立的資料表中,第三種語法LIKE old_tbl_name與(LIKE old_tbl_name)是相同的,建立一個相同於old_tbl_name(已經存在的資料表)的資料表

基本上表格建立語法分為三大部分:

CREATE ...........
(
column-wide的限制
table-wide的限制
)
table屬性設定

第一、column-wide限制

這裡所說的限制是指關聯式資料庫三大限制的限制,包含1.值域限制domain constraints 2.key值必須唯一,且不可為null 3.被參考的欄位必須唯一,且不可為null,可已有多行限制,每行限制以逗號隔開,語法如下:

col_name data_type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
[UNIQUE [KEY] | [PRIMARY] KEY] [COMMENT 'string'] [reference_definition]

reference_definition:

REFERENCES tbl_name [(index_col_name,...)]
[MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
[ON DELETE reference_option]
[ON UPDATE reference_option]

reference_option:

RESTRICT | CASCADE | SET NULL | NO ACTION

說明:
column_name欄位名稱,data_type欄位資料型態,Null與Not Null就不需說明了吧,DEFAULT指定預設值,AUTO_INCREMENT自動編號,只能使用在I整數資料型態上,而且一個表格只能有一個,通常用來當作PK使用,UNIQUE KEY與PRIMARY KEY指定該欄位為唯一索引或者主鍵,COMMENT 'string' 這是註解,reference_definition這個是設定外來鍵的語法,目前只有InnoDB套件可以使用,其中MATCH FULL、MATCH PATAIL、MATCH SIMPLE三個部分似乎還沒實作,也就是說這三個不能使用,因為我在說明文件上翻不到相關資料,怪哉∼,tbl_name要參考的資料表名稱,後方接著要參考的欄位名稱(index_col_name),ON UPDATE與ON DELETE是指被參考的資料更新與刪除時,該做什麼樣的動作,也就是reference_option的部分,RESTRICT表示不允許被參考資料更新,NO ACTION表示參考者不做任何動作,CASCADE表示被參考者做什麼樣的事情,參考者就跟著做,SET NULL這個很明顯了,當被參考者改變時,參考者設為NULL。(喔~~實在很複雜,好長的一段語法)

ex:

CREATE TABLE test_tbl(
pid int NOT NULL AUTO_INCREMENT PRIMARY KEY,
name char(30) NOT NULL COMMENT '這是註解')

外來鍵不寫範例了,因為應用性質不大,只適用於InnoDB,雖然其他引擎也會接受這樣的語法,但卻沒有任何作用。

第二、table-wide的限制:

實際上與column-wide大同小異,語法如下:

[CONSTRAINT [symbol]] PRIMARY KEY [index_type](index_col_name,...)
| [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name,...) [reference_definition]
| {INDEX|KEY} [index_name] [index_type] (index_col_name,...)
| [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY][index_name] [index_type] (index_col_name,...)
| {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name](index_col_name,...)
| CHECK (expr)

說明:
限制(CONSTRAINT)是可以命名的,symbol就是自己指定的限制名稱,用以刪除限制可以指定名稱,通常table-wide的PK與FK設定都是用於複合鍵值,也就是說多個欄位組成的Key,但習慣上,大家都喜歡直接在table-wide限制上設定PK與FK,因為不管複合的或者單一的PK 或FK都可以在這裡設定,但複合的PK或FK卻不能在column-wide上設定,FULLTEXT是全文索引(只有MyISAM支援), SPATIAL這個空間檢索,這樣說好像怪怪的,這個是用於地理資訊相關的資料索引,我沒研究過Orz,最後CHECK是檢查某欄位的值是否符合條件,括弧內放條件,如果條件不符,則資料不會寫入,不過測試後似乎無效...= =",在說明文件中說"The CHECK clause is parsed but ignored by all storage engines",也就是CHECK是會被分析的,但會被所有資料庫引擎忽略,這.....暈倒,根本沒有作用,應該是為了下一版準備的語法。

ex:

CREATE TABLE student(
stud_num int AUTO_INCREMENT,
stud_name char(10) NOT NULL,
reg_date timestamp DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT pk PRIMARY KEY(stud_num) );

第三、table屬性設定:

{ENGINE|TYPE} [=] engine_name
| AUTO_INCREMENT [=] value
| AVG_ROW_LENGTH [=] value
| [DEFAULT] CHARACTER SET charset_name
| CHECKSUM [=] {0 | 1}
| COLLATE collation_name
| COMMENT [=] 'string'
| CONNECTION [=] 'connect_string'
| DATA DIRECTORY [=] 'absolute path to directory'
| DELAY_KEY_WRITE [=] {0 | 1}
| INDEX DIRECTORY [=] 'absolute path to directory'
| INSERT_METHOD [=] { NO | FIRST | LAST }
| MAX_ROWS [=] value
| MIN_ROWS [=] value
| PACK_KEYS [=] {0 | 1 | DEFAULT}
| PASSWORD [=] 'string'
| ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
| UNION [=] (tbl_name[,tbl_name]...)

ENGINE 與TYPE是相同的作用,=之後指定要使用哪一種引擎,指定的引擎套件必須已經安裝否則無法使用, AUTO_INCREMENT指定自動編號起使值,AVG_ROW_LENGTH指定平均資料的長度,通常用在這個table存放的資料屬於巨量的資料時,DEFAULT CHARACTER SET指定預設的字集,COLLATE指定校對字集,CHECKSUM是檢查和如果設定為1,則會自動檢查以確保資料的正確,但效能會大大的降低,不建議使用,而且只能用於MyISAM引擎,COMMENT是備註,只能設定60個字元以內,CONNECTION的作用不是很清楚,有點類似COMMENT,有點類似FTP連線公告,MAX_ROWS最多可存放的資料筆數,MIN_ROWS設定最少可放筆數,但MIN_ROWS我覺得怪怪的,因為如果設定了這個,在資料還沒寫入之前,筆數會是0,這樣不就有問題了?不瞭解為什麼,或許是用於刪除資料時,資料不可少於這個設定,PACK_KEYS如果設定為1,則會建立一個索引來增加查詢速度,但會大大降低新增、修改效能,如果設定DEFAULT,則只針對CHAR與VARCHAR型態欄位進行索引, PASSWORD這個不是用以設定密碼,而是用來進行編碼使用的字串,資料會與PASSWORD所指定的字串混和編碼後寫入frm檔案中, DELAY_KEY_WRITE如果設定為1,則資料修改會當表格關閉時才會寫入,ROW_FORMAT指定資料寫入儲存模式,這裡不說明了,不建議使用,UNION用於MERGE引擎,也不說明拉。忘了說明一下多個table屬性設定請用逗號隔開,或者換行也可以。


ex:

CREATE TABLE student(
stud_num int AUTO_INCREMENT,
stud_name char(10) NOT NULL,
reg_date timestamp DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT pk PRIMARY KEY(stud_num) )
TYPE=Innodb
CHARACTER SET big5;

資料表修改:

ALTER [IGNORE] TABLE tbl_name
alter_specification [, alter_specification] ...

alter_specification:

增加

ADD [COLUMN] column_definition [FIRST | AFTER col_name ]
| ADD [COLUMN] (column_definition,...)
| ADD {INDEX|KEY} [index_name] [index_type] (index_col_name,...)
| ADD [CONSTRAINT [symbol]] PRIMARY KEY [index_type](index_col_name,...)
| ADD [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY] [index_name] [index_type] (index_col_name,...)
| ADD [FULLTEXT|SPATIAL] [INDEX|KEY] [index_name](index_col_name,...)
| ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name,...) [reference_definition]

修改

| ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
| CHANGE [COLUMN] old_col_name column_definition[FIRST|AFTER col_name]
| MODIFY [COLUMN] column_definition [FIRST | AFTER col_name]

刪除

| DROP [COLUMN] col_name
| DROP PRIMARY KEY
| DROP {INDEX|KEY} index_name
| DROP FOREIGN KEY fk_symbol

table屬性設定

| DISABLE KEYS
| ENABLE KEYS
| RENAME [TO] new_tbl_name
| ORDER BY col_name
| CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
| [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
| DISCARD TABLESPACE
| IMPORT TABLESPACE
| table_option ...

資料表的修改實際上與建立是很相似的,增加欄位或者限制,則前方加上ADD,不同的地方在於 [FIRST | AFTER col_name ]這是指定新增的欄位要放在那個欄位的前面或者後面,當然不指定的狀況下會放在最後的欄位之後。

修改欄位分為三種方法,第一種使用ALTER語法來設定或者刪除預設值,第二種CHANGE語法,這是MySQL自訂的語法,要注意的是,這個語法需要寫兩次欄位名稱,第一個欄位為原本的欄位名稱,第二個為新的欄位名稱,其餘與建立欄位相同,但如果不需要更改欄位名稱,則兩個欄位名稱都指定相同即可,第三種使用MODIFY語法,這是Oracle使用的語法,也是比較多人使用的語法,後方跟建立欄位相同寫法

刪除欄位或限制,使用DROP語法來進行,這部分應該不用說明了蠻簡單的,要注意一點,就是如果索引與外來鍵建立時沒有命名,可能會無 法刪除。

欄位屬性設定部分,DISABLE KEYS這個功能是停止更新索引的建立,這用於大量資料寫入時,因為需要大量索引建立而拖慢速度的問題,而ENABLE KEYS則剛好相反,當需要大量寫入具有索引的欄位時,可以先停止索引更新,資料寫入完畢之後在打開ENABLE KEYS,MYSQL會使用較快速的演算法來更新索引,ORDER BY可以預先指定資料表資料的排序方式,也就是說當使用SELECT進行查詢時,不需要指定ORDER BY他就會幫你把他排好,但是有一點需要注意,再修改ORDER BY之後所新增的資料或者刪除的資料並不會照你所要求的方式來進行排序的動作,而是照原本系統的方式來排,也就是會自動排在最後面,DISCARD TABLESPACE與IMPORT TABLESPACE是用於INNODB來增加ibd檔案的空間,這個部分我比較不清楚,因為還沒去研究過Innodb的細節,其餘的資料表屬性部分都跟建立資料表雷同。

資料型態:

分類 資料型態

佔用長度
(byte)

說明 可存範圍
布林 BOOL,BOOLEAN TINYINT的別名
整數 TINYINT[(M)][UNSIGNED][ZEROFILL] 1 整數 -128~127
0~255
SMALLINT[(M)][UNSIGNED][ZEROFILL] 2 整數 -32768to32767
0to65535
MEDIUMINT[(M)][UNSIGNED][ZEROFILL] 3 整數 -8388608to8388607
0to16777215
INT[(M)][UNSIGNED][ZEROFILL] 4 整數 -2147483648 to 2147483647
0to4294967295
BIGINT[(M)][UNSIGNED][ZEROFILL] 8 整數
SERIAL

整數,同等於
BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY

  • M值:此值表示儲查詢時的最大顯示寬度(Maximum Display Sise)但卻不會限制可儲存的數字位數,但在某些特殊狀況下,無法達到這樣的效果,而導致內容不正確,尤其是複雜的查詢動作(例子:例如指定INT(4),表示可以放入9999(四位數)以下的數字,如果超出四位數,例如10000,此時資料還是會記錄下來)
  • AUTO_INCREMENT 屬性:此屬性可以指定在整數欄位上,但必須有出現NOT NULL、PRIMARY KEY、UNIQUE三種屬性之一時,另外此AUTO_INCREMENT屬性一個資料表只能出現一次
  • INSERT資料時,AUTO_INCREMENT欄位如果沒有指定值,而且沒有指定NULL,此時會進行自動編號,此欄位依然可以手動指定編號
  • 上次插入自動編號的值,如果需要取得,可以透過LAST_INSERT_ID()函式取得
  • 經常性插入與刪除資料的表格來說,自動編號有可能被用完,也就是達到資料型態的最大可接受範圍,此時自動編號就無法繼續編號,而且無法插入任何資料
浮點數 FLOAT[(M,D)]
[UNSIGNED][ZEROFILL]
4 浮點數,M為全部位數,D為小數點位數(不含小數點),自動四捨五入,例如: FLOAT(5,3)欄位存入12345.7891,5代表取得位數,3代表小數點,出現警告訊息,查詢結果會是45.789,

-3.402823466E+38 to -1.175494351E-38,0
and
1.175494351E-38 to 3.402823466E+38

DOUBLE[(M,D)]
[UNSIGNED][ZEROFILL]
8 雙倍精度浮點數,M為全部位數,D為小數點位數(不含小數點),自動四捨五入
DECIMAL[(p[,s])][ZEROFILL]
整數與浮點數的混和型態,p為精度precision,s為小數點位數scale(不含小數點) p<65,s<30
REAL DOUBLE的別名
NUMERIC,DEC DECIMAL別名
  • M與整數的作用相同,影響顯示方式,但是D的指定確會影響存入的資料,但相同的,雖然可以放入比較長的數值,可是卻有可能出現錯誤的情況
  • DECIMAL格式屬於字串方式儲存,佔用空間較大,MySQL以二進位方式來處理數字部分,儲存DECIMAL採小數點之前與之後分開,所以欄位占用的空間,會隨著指定不同而不同
日期時間 DATE 3 日期 1000-01-01 to 9999-12-31
TIME 3 時間(24小時制) +-838:59:59
DATETIME 8 日期時間混合
YEAR 1 年份 1900 to 2155
TIMESTAMP(M) 4 時間標籤,M可以指定時間標籤的長度,書上都是這麼寫的,但我測試之後完全沒有任何反應
  • 系統變數sql_mode中與日期相關的設定,ALL_INVALID_DATES指定允許儲存明顯有誤的日期格式,NO_ZERO_DATE指定不允許存入0000-00-00的日期格式,NO_ZERO_IN_DATE指定月份與日期不允許使用0
  • TIMESTAMP在新增資料沒有指定值,或者指定NULL給TIMESTAMP時,自動填入現在的timestamp
  • 在同資料表中,如果有多個TIMESTAMP欄位,當資料插入時沒有指定TIMESTAMP欄位資料時,只有第一個TIMESTAMP欄位會自動填入現在的timestamp,其他必須強制指定NULL才能存入現在的timestamp
  • TIMESTAMP雖然方便,但主要用於內部管理,例如得知資料最後修改日期等,如果是資料中要使用日期,儘量採用DATETIME格式
  • 幾個常用的TIMESTAMP語法:
    • TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 欄位新增記錄與修改記錄自動填入時間
    • TIMESTAMP TIMESTAMP DEFAULT CURRENT_TIMESTAMP 與上面的簡寫
    • TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 新增記錄時存入0,只有更新紀錄時才會存入時間
    • TIMESTAMP DEFAULT 'yyyy-mm-dd hh:mm:ss' ON UPDATE CURRENT_TIMESTAMP 新增記錄時,採用自訂日期存入,更新時自動存入時間
字串 CHAR(M) <255 固定字串
VARCHAR(M) <65535 可變長度字串
TINYTEXT <255 可變長度字串
TEXT(M) <(2^16)-1 可變長度字串
MEDIUMTEXT <(2^24)-1 可變長度字串
LONGTEXT <(2^32)-1 可變長度字串
  • M為允許顯示的字元長度,存入資料時,可存入最大長度資料,但顯示時則以M的指定作為限制
  • CHAR指定之後,如果存入的資料長度未達欄位長度,則資料後方自動補上空白,取出時,自動去除後方空白,另外存入資料時會自動去除前方空白
  • 在MySQL5.0.3之前的版本,CHAR的M值如果指定大於3的值會自動轉型為VARCHAR,如果大於255則自動轉型為TEXT,不過,MYSQL5.0.3之後,建立資料表時,指定超過該型態的最大值視為錯誤
  • VARCHAR在早期版本中只能支援256個字元,但在MySQL5.0.3之後則可以支援到65535個字,utf-8的字集則可以支援到21,844 characters,因為utf-8最大可以達到 3個bytes寬度
  • 存入資料的長度大於欄位長度時,則刪除尾巴多出的長度
  • TEXT中的M值可以不指定,因為M值對TEXT來說意義不大,TEXT可以表達的長度太長了
  • VARCHAR如果存入資料前方或後方具有空白字元,空白字元會存入欄位之中,與CHAR不同(MySQL5.0.3之後)
  • 字元屬性皆可以指定字集與校對(文字排序方式),指定與法如下
    VARCHAR(n) CHARACTER SET charset COLLATE sortorder
  • 拉丁字集:Latin1是MySQL預設字集,Latin-1就是ISO-8859-1,包含西歐常用的文字
  • Unicode:包含UTF-16(UCS-2)與UTF-8
    • UTF-16是採用雙位元方式儲存,此種字集不管什麼樣的字都是雙為元表示,包含原本的單一位元文字也必須使用雙位元,而UTF-16常常於字元中出現0byte的編碼,這樣的編碼常常導致一些程式語言誤判,因為0byte是程式語言中當作結束字元用的文字
    • UTF-8採用可變長度方式儲存,字元長度為2~4個byte,所有ACSII 字元與原本編碼相同,可以表達歐系所有字集與亞洲大部分國家的字集,此種編碼長度沒有固定,因此在程式語言處理字串時變得比較不容易,但這也是他的優點,因為長度隨編碼方式而有不同,比起固定長度來說,可以節省不少空間
  • BIG5字集:繁體中文所採用的字集,其中big5_chinese_ci這個校對方法,可以讓中文依照筆畫進行排序
  • 每一種字集都有對應的排序方法一般稱為校對,校對方式不同字集不可以混用,如要查訊相對應的校對方法,可以下達SHOW COLLATION命令查詢,此命令也可以看到所有字集
二進位 BIT[(M)] 1bit M為bit數,二進位型態,M<=64(不指定預設為1)
BINARY(M) <255 固定長度二進位型態
VARBINARY(M) <65535 可變長度二進位型態
TINYBLOB <255 可變長度二進位型態
BLOB[(M)] <(2^16)-1 可變長度二進位型態
MEDIUMBLOB <(2^24)-1 可變長度二進位型態
LONGBLOB <(2^32)-1 可變長度二進位型態
  • 二進位資料型態主要用來存放一些檔案類型的資料,例如將圖片存入資料庫中,此時需要將圖片轉為二進位資料,並寫入資料庫中,這樣的方式好處在於容易管理,但是也有缺點,就是會讓存取效率明顯降低
  • BINARY與CHAR相似,VARBINARY與VARCHAR相似,其中M都是用來呈現資料最大長度的指定(長度採用byte計算),不同的是字元型態儲存時以字元排列儲存,某些時候不考慮大小寫,但是二進位型態則考慮原始資料編碼進行儲存,大小寫有別
  • BLOG中的M是指定資料儲存的長度用的,在指定長度之外將被刪除
  • 關於bit的資料顯示方法,當 SELECT進行二進位欄位查詢時,會以十進位方式顯示出來,如果一定要顯示二進位資料,必須透過BIN這個function來轉換,而對二進位欄位進行加減的動作,MySQL會先將數字部分轉為二進位在進行計算
  • 特殊的寫入資料表示方法b'111'代表十進位7,b'1010'代表十進位10
其他 ENUM('a','b'[,'c'.....]) 1~2 列舉 最多65535個字
SET('a','b'[,'c'.....]) 1~8 集合 最多255個字串
列舉是多選一,而集合是多選多

這些資料型態,通常被分為六大部分整數、浮點數、字元、二進位、日期、其他。

  • 整數 :可以在資料型態後方加上UNSIGNED與 ZEROFILL,當不帶符號UNSIGNED時,可以儲存的範圍會更大,要注意ZEROFILL,當加上此項目時,預設UNSIGNED會自動加入,因為以零填滿當然不會有負號,例如:1->001,不過在我測試的過程中,ZEROFILL似乎很不給面子,沒有效果Orz。
  • 浮點數 :也可以使用UNSIGNED與ZEROFILL項目。
  • 字元:後方的n項目,可以指定這個欄位需要多少字元長度,要注意的是,在5.0.3之後中文字不再是 2個長度,而是1個,也就是說當我指定char(10),不再只是存放5個中文字,而是10個中文字或者10個英文字,他的認定來自於使用的字集,char屬於固定長度字串,當指定 5的長度時,不管存入的資料長度多常,這個欄位都會佔據5的長度,有很多人對這個有疑問,因為如果我存入3個英文字,接著使用length( )或者char_length( )去測量,明明就是長度3,怎麼會是5,這是因為MySQL很雞婆,當顯示結果時,會自動幫你去空白,所以測量結果與規定不符,VARCHAR(n)屬於變動長度字串,在5.0.3之前這個n最大只能有255,但是現在是65535,根據不同的長度設定,MySQL會自動轉換成其他較大的變動文字欄位型態,ex:VARCHAR(256)會自動轉為TINYTEXT..,另外只要是文字欄位型態,皆可以設定該欄位的CHARACTER SET與COLLATE..(字集與校對有時間另外寫說明)
  • 二進位 :二進位資料基本上跟字串是很相似的,因為二進位的資料顯示在 畫面上時,為根據目前畫面上所採用的編碼來顯示文字,這有點類似用文字編輯器去打開執行檔或者圖片檔案一樣,會看到一些亂碼有時甚至出現怪異的中文字,實際上不管是文字或者檔案內容,最後都會存成二進位資料,只是對內容的認定上不同,而產生不同的結果,像一份JPG圖片,如果以文字來認定,他會是一份很亂的亂碼,但如果以圖片來認定,他就會是一張漂亮的圖片,所以在二進位資料型態欄位內存入文字,我們並沒有辦法判別他的差異性,畢竟我的查詢的畫面是文字畫面。

    但這樣的欄位對我們而言有什麼樣的作用呢?既然他是以二進位來儲存資料,所以我們可以拿他來存放圖片、檔案等等的資料,當然,如果你由console畫面來做,這是比較難的,但如果你透過程式來處理,這樣就可以很輕鬆的達成,因為透過程式將圖片或者檔案先全部轉成二進位編碼,接著將資料塞進二進位欄位中存放,這樣就可以了,但該如何還原該圖片或者檔案呢?可以將資料撈出後,對顯示的畫面送出mine-type,告知畫面這個二進位內容屬於什麼樣類型的資料,如果是圖片則以圖片方式顯示,如果是檔案則以檔案的方式顯示,這樣就ok了,不過實際上大部分的人不會這樣做,通常會把檔案圖片與資料庫分開管理,但塞檔案圖片內容到資料庫內的支持者還是大有人在,尤其是與應用程式配合的設計,這樣可以防止資料被大量複製。

    bit型態,以bit為單位進行二進位資料存放,可以直接存入二進位整數,也可以使用字元方式來存放(實際上字元與二進位整數是一體的兩面), BINARY固定長度二進位,這個與CHAR類似,VARBINARY與VARCHAR類似,其餘對應字元型態都類似,只是對資料的認定不同而已,但在二進位資料欄位不能使用CHARACTER SET與COLLATE的設定,因為他不是被認定為字元
  • 日期 :因為日期在資料庫中是一 種常用的資料,所以通常會將日期也設定一份資料型態,實際上這樣的日期跟字串有點類似,但處理資料的方法上有些不同,DATE存放日期格式以年-月-日方式來存放,資料輸入時可以使用多種標準日期方式輸入,ex:1999/01/01或者1999- 01-01都是可以的,TIME是時間,DATETIME就是日期跟時間混和型態,YEAR則是年份,年份可以指定採用二碼或者四碼,ex:YEAR (2) 或者 YEAR(4),預設為四碼,最容易搞混的是TIMESTAMP這個資料型態,這是時間標籤,他是以連續的數字來記錄,例如:1999-01-01 17:30:55 則會以19990101173055來存放,書上以及說明文件上都寫著可以指定顯示的長度,也就是以TMIESTAMP(M)這樣的方式來指定,但是我測試老半天,殘念...,不知道是我版本上的問題,還是...不需要考慮那麼多,反正不指定也很好用..^^a

    另外,TIMESTAMP還有幾個地方需要說明,首先是建立資料表時可以採用DEFAULT CURRENT_TIMESTAMP來指定預設使用當下時間標籤來存放,也就是當你輸入資料時,不給TMIESTAMP欄位資料,他會自動存入插入資料的時間,除了這個還可以指定ON UPDATE CURRENT_TIMESTAMP,但是這樣的TIMESTAMP欄位一個資料表只能有一個,但是如果有另外一個 TMIESTAMP欄位也需要有這樣的功能怎麼辦?其實有解決方法,也就是在輸入資料時,給予另外一個TMIESTAMP欄位null值,你會很訝異的,這個欄位竟然也自動採用現在時間來紀錄,沒錯...只需要指定null或者採用NOW()函數來給值就可以達到相同的效果(這是來自於原廠說明的方法)
  • 最後其他資料型態 :其實這被列為其他的資料型態enum與set我為把他歸納在字串上,他類似使用索引方式來對應資料,存放在資料表上的資料是以整數方式來存放,但會對應一組字串的值來檢查是否符合值域範圍,enum屬於互斥的值,而SET不是,例如:enum('男','女 '),代表這個欄位只能出現男或者出現女,但是男女不可同時出現,而set('男','女')則可以同時出現,也就是說這個SET的欄位可以是'男' or '女' or '男','女',這是兩者的不同,後者SET少用,因為這樣的資料庫設計不是很正確,但偶而為了方便這樣做是可以被接受的。另外,這兩個型態後方可以加上 CHARACTER SET與COLLATE的設定

建立資料表的基本範例:

CREATE TABLE test(
_int INT NOT NULL AUTO_INCREMENT,
_tinyint TINYINT UNSIGNED,
_float FLOAT(5,2),
_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
_char CHAR(10) CHARACTER SET big5 COLLATE big5_bin,
_enum ENUM('m','f') CHARACTER SET big5)
TYPE=MyISAM
AUTO_INCREMENT=10;

刪除資料表:

DROP TABLE [IF EXISTS] tb_name;

 

 

MySQL 筆記(三)

資料新增: INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
VALUES ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

新增語法LOW_PRIORITY、DELAYED等等的項目實際上是很少用到的, 通常只會用到底下部分:

INSERT INTO tbl_name[(col_name,...)]
VALUES({expr|DEFAULT})

ex:加上欄位的寫法:

INSERT INTO student(name,std_num,sex)
VALUES('John','E0001','M');

ex:不加欄位寫法:

INSERT INTO student
VALUES('John','E0001','M');
    1. 加上欄位的話,某些不需要輸入值的欄位可以不需要列出,前面欄位與後面值位置對應,如果 採用不加欄位的寫法,則全部欄位的值皆必須要列出,不需要值的欄位則給null或者可以指定DEFAULT
    2. LOW_PRIORITY:
      等待所有讀取資料表結束才進行寫入,也就是說先寫到buffer中等待,當使用LOW_PRIORITY,DELAYED項目會自動啟用
    3. DELAYED:
      先將要寫入的值寫到buffer之中,這個項目通常被忽略的,也就是預設上就是如此
    4. IGNORE:
      當寫入資料發生錯誤時,不顯示任何錯誤訊息
    5. HIGH_PRIORITY:
      與LOW_PRIORITY相反,也就是說不等待其他讀取完成才進行寫入,但 這樣的動作有可能導致正在讀取的人資料錯誤 ,此項目會凌駕--low-priority-updates這個啟動選項,也就是當指定HIGH_PRIORITY時,啟動選項--low-priority-updates會失效
    6. ON DUPLICATE KEY UPDATE col_name=value...:
      這個語法是用於指定當KEY值重複時,該筆資料的值更改為指定的值

連續新增:
不見得每次只能新增一筆資料,可以使用逗號將每一筆的值分開,一次執行新增動作,如下

ex:
INSERT INTO tbl_name (a,b,c)
VALUES(1,2,3),(4,5,6),(7,8,9);

利用不同欄位指定另一個欄位的值:

ex:
INSERT INTO tbl_name(a,b)
VALUES(1,a*0.5);

利用SELECT語法進行新增:

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ... [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

此語法使用SELECT查詢的資料,必須欄位與查詢值相對應,包含欄位的型態、值域、數量等

修改資料:

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]

ex:
UPDATE student
SET name='May',sex='F'
WHERE name='Mary';

  • 修改語法與INSERT很類似,但需要指定條件, 如果不指定條件代表全部資料都符合,這樣一個不小心全部資料都被改掉了 ,所以UPDATE語法如果沒看到WHERE出現就得特別注意了,語法中SET後方指定欄位與對應值,多個欄位對應使用逗號分開,如果是多筆資料進行更新,也可以限制筆數,利用LIMIT語法來控制
  • ORDER BY在這裡比較特別,通常具有兩種功能:
    1. 與LIMIT語法配合:例如,當我只需要更新前五筆或者後五筆資料時,先進行排序動作,然後限制取回前五筆或者後五筆進行更新
    2. 連續更新KEY值:例如,我需要將每筆KEY值欄位通通加1,如果有前方開始做必定會遇到重複的kEY值,此時資料庫會出現錯誤訊息而停止,如果將資料更新順序反過來就不會有這樣的問題
      ex:
      這樣會有問題:
      UPDATE t SET id = id + 1;
      這樣才能正確執行:
      UPDATE t SET id = id + 1
      ORDER BY id DESC;

資料刪除:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count]

ex:
DELETE student
WHERE name='Tom';

  • DELETE與UPDATE一樣必須指定條件, 如果不指定代表全部刪除 ,這樣一個不小心麻煩就大了,所以DELETE語法如沒有看到WHERE條件時,先想想這樣做會不會有問題,其餘部分與UPDATE相同
  • OUICK:這個選項可以忽略索引的更新,快速刪除資料,但這樣的動作會導致索引運作效能降低

使用者建立:

使用者建立方式有三種,第一種直接由mysql資料庫中user資料表來建立,但這樣的方式太麻煩了,所以底下列出的方式不包含此種方法

第一種:CREATE USER語法

CREATE USER user [IDENTIFIED BY [PASSWORD] 'password']
[, user [IDENTIFIED BY [PASSWORD] 'password']]

此語法適用於只有建立使用者及密碼部分,user代表使用者名稱,而IDENTIFIED BY後方指定密碼,此密碼會自動加密,另外使用者部分必須指定使用者與來源主機,並以@來分隔,此語法可以一次建立多個使用者,參考範例如下:

ex:


CREATE USER
'user1'@'host1' IDENTIFIED BY 'passwd1',
'user2'@'host2' IDENTIFIED BY 'passwd2';

第二種:利用GRANT產生使用者,並指定權限

此種方法原本是用於指定使用者資料庫的使用權限,但如果使用者不存在,則會自動建立,語法如下:

GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ...
ON [object_type] {tbl_name | * | *.* | db_name.*}
TO user [IDENTIFIED BY [PASSWORD] 'password']
[, user [IDENTIFIED BY [PASSWORD] 'password']] ...
[REQUIRE
NONE
| [{SSL| X509}]
[CIPHER 'cipher' [AND]]
[ISSUER 'issuer' [AND]]
[SUBJECT 'subject']]
[WITH with_option [with_option] ...]

實際上此語法大部分只會用到下面部分

GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ...
ON [object_type] {tbl_name | * | *.* | db_name.*}
TO user [IDENTIFIED BY [PASSWORD] 'password']
[, user [IDENTIFIED BY [PASSWORD] 'password']] ...
[WITH with_option [with_option] ...]

priv_type是指定授權種類,這個部分下面說明

column_list 可以指定授權給欄位,這表示只能使用控制欄位的語法,如:SELECT,INSERT,UPDATE,DELETE

ON object_type 可以指定三種,TABLE, FUNCTION,PROCEDURE,當object_type有使用時,後方必須指定object_type所要授權的物件,例如:指定 FUNCTION,則後方必須接著function的名稱,如果不指定,則後方可以是tbl_name,*,*.*或者db_name,也就是說可以指定資料表或者整個資料庫給使用者,指定時可以採用萬用字元*來代替全部,例如:指定test這個資料庫給使用者,則指定test給使用者即可,如果只需要 test之內的所有資料表,則指定test.*給使用者

TO user 這裡與 CREATE USER語法的user相同,必須指定使用者名稱與主機名稱,使用者名稱請不要給空字串,因為那代表匿名anonymous,而且使用者不可以使用 wildcard字元來取代,但host名稱可以使用wildcard,例如:'myname'@'192.168.100.%',這裡不是用*這個字元而是%這個字元,與SELECT時所使用的wildcard相同意義

IDENTIFIED BY password 指定使用者的密碼,這與CREATE USER語法相同,指定密碼,但如果只是授權給一個已經存在的使用者時,可以不需要指定密碼,也就是這個部分語法可以省略,因為使用者可能有自己的密碼,這樣會造成覆蓋原有密碼的情形,除非確定要更改他的密碼

WITH with_option 這個語法用以指定一些使用者的限制如下:
with_option =
GRANT OPTION
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count

GRANT OPTION:
指定此使用者可以具有授權給其他使用者的權限,通常這個權限只有最高管理者才會具有

MAX_QUERIES_PER_HOUR等後四個項目:
此四個項目分別限制使用者的每小時查詢次數、更新次數、連線數量以及最大同時在線數量

此語法的簡單範例:


GRANT ALL ON mydb.*
TO 'myusername'@'localhost'
IDENTIFIED BY 'mypwd';

建立管理者身份:


GRANT ALL ON *.*
TO 'admin_db'@'localhost'
IDENTIFIED BY 'admin_pw'
WITH GRANT OPTION;

REQUIRE這個選項比較特別,這裡可以指定連線加密方式,通常不指定除非真的有這樣的需求, 連線進行加密會導致系統負擔,增加CPU的工作量 ,除非有這樣的需求才進行設定,加密方式SSL對應CHIPHER語法,而X509對應ISSUER與SUBJECT,但這部分我不是很懂,無法加以說明,有機會深入研究再來補完

priv_type ,這部分包含很多項目,可以透過show privileges指令來列出相關訊息,因為篇幅過長底下列出項目與使用範圍部分:

priv_type 作用範圍
Alter Tables
Alter routine Functions,Procedures
Create Databases,Tables,Indexes
Create routine Functions,Procedures
Create temporary tables Databases
Create view Tables
Create user Server Admin
Delete Tables
Drop Databases,Tables
Execute Functions,Procedures
File File access on server
Grant option Databases,Tables,Functions,Procedures
Index Tables
Insert Tables
Lock tables Databases
Process Server Admin
References Databases,Tables
Reload Server Admin
Replication client Server Admin
Replication slave Server Admin
Select Tables
Show databases Server Admin
Show view Tables
Shutdown Server Admin
Super Server Admin
Update Tables
Usage Server Admin
這個部分實際上有很多地方都是很少用的,我只說明ALL與USAGE,其餘部分如果需要更清楚的說明,請查Doc或者使用show語法看相關訊息 ALL表示全部的權限,但不包含GRANT權限 ,必須另外指定 USAGE這表示no privilege,也就是什麼權限都沒有,使用者仍然可以進行連線的動作 ,但說明上有提醒一點,沒有權限不代表這個使用者什麼事情都不能做..@@"

解除授權:

GRANT可以對使用者授權,那麼送出的權限能不能收回,當然可以,使用REVOKE語法,將權限收回來,但請記住,解除授權不等於刪除使用者,也就是說當你解除授權後,使用者只是沒有權力進行解除權力部分的動作,但仍然可以登入資料庫,這點必須特別注意,語法如下:

REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
ON [object_type] {tbl_name | * | *.* | db_name.*}
FROM user [, user] ...

上面語法實際上與GRANT相同,只有少部分的差異,在priv_type指定上,是要解除的權限,ON則是由什麼地方解除,而FROM則是指定由誰身上解除,使用方法都與GRANT相同,所以不加以說明,但有一個地方需要注意,解除GRANT OPTION權限,實際上GRANT OPTION是屬於priv_type的一部份,但在GRANT時,習慣上會使用WITH來指定,但在解除的時候,必須將GRANT OPTION當成priv_type來看待,範例如下:

REVOKE GRANT OPTION
ON *.*
FROM 'admin_db'@'localhost';

全部解除:

REVOKE ALL
ON *.*
FROM 'admin_db'@'localhost';

更改使用者:

這個語法只有在5.0.2之後版本才有,可以更改使用者名稱,語法如下:

RENAME USER old_user TO new_user
[, old_user TO new_user] ...

這語法應該很容易理解才對,所以不加以說明了

ex:
RENAME USER myname TO new_myname;

刪除使用者:

在早期版本的MySQL中,刪除使用者必須透過mysql這個系統資料庫的user資料表來進行刪除, 如果沒有特別瞭解這個資料庫架構的人來說,是件很容易出錯的事情,在5.0.2之後提供了一個刪除使用者的語法:

DROP USER user[,user...]

這樣的語法簡單又好用,而且超容易瞭解他在幹嘛..^^ ,但因為有了這樣簡單的語法,所以使用前一定要三思,要知道自己到底在做啥,不然後果不堪設想

 

 

MySQL 筆記(四)

索引建立:

索引在MySQL中分為一般索引、唯一索引、主索引、全文索引四類,至於什麼是索引,索引就像是書本前方的目錄一樣,當你需要察看某個主題時,你只需要尋找索引列表的主題,然後直接翻開他所對應的頁數即可,而不需要一頁一頁的翻,索引就是這樣的東西。

目標是你要找的資料,但過程透過索引指向目標來取得,這樣的動作在查詢語法(SELECT),並不會有任何差異,因為索引是內部的動作,你只看到結果,那如何指定索引?該指定誰當索引?索引會指定給某個欄位或者某些欄位,這些欄位會具有相同的特質,就是這個欄位或這些欄位經常出現在WHERE語法後方,也就是經常當作條件來進行搜尋的欄位,就像書本的目錄一樣,你一定會先找"某個主題",這就是你要查詢的條件,在開始之前,必須先有個認知,索引可以加速搜尋速度,但相對的必須付出一定的代價,第一、索引會導致新增修改刪除時效率降低,第二、索引表會隨著資料而越來越大,除非資料真的很慢,而且資料筆數實在龐大,或者客戶要求,通常這樣的情況才會設定索引

實際上MySQL(二)、(三)這兩篇當中已經有提到索引相關的部分內容,例如在CREATE TABLE時建立索引,還有GRANT中指定建立索引的權限等,權限部分就不再提及了

一般索引:

一般索引針對一般欄位進行索引表的建立,這些欄位的值不需要特別限制,所已被稱為一般索引,建立的方法有兩種一種是在CREATE TABLE時:

CREATE TABLE tbl_name(
column_definition...
{INDEX|KEY} [index_name] (index_col_name,...));

index_col_name:

col_name [(length)] [ASC | DESC]

column_definition 是欄位的建立部分,請參考之前文章,一般索引可以使用INDEX這個關鍵字也可以使用KEY這個字,所代表的意義相同,後方接著索引的名稱,如果不指定則會以欄位名稱來指定索引名稱,這個有助於刪除索引時可以指定要刪除的索引名稱,接著小括弧內放入要進行索引的欄位,可以多個欄位進行索引,欄位以逗號分隔

但在索引欄位index_col_name後方又可指定length,這代表只使用最前面指定長度的內容來進行索引,被稱為partial index,這裡要特別注意欄位是文字型態時,指定的length是以字集的字來計算,也就是如果指定的字集為big5_chinese_ci,則一個中文字代表一個長度,如果欄位是是屬於二元型態,則以byte來計算,另外TEXT與BLOB以上的欄位一定要指定length才行,另外length最大可以到1000,而InnoDB則可以到767

ASC與DESC這是指定索引建立的順序,是要根據正向還是反向來建立,通常不指定,因為效果不大

唯一索引:

唯一索引顧名思義,要進行索引欄位的值只能唯一, 這與一般索引不同,因為唯一所以查詢時的動作會有不同,查詢速度也會比一般索引來的快,建立方式有三種,第一種是在column_definition中指定UNIQUE關鍵字:

CREATE TABLE tbl_name(
col_name data_type ... [UNIQUE],
...
);

第二種則是在table-wide部分建立:

CREATE TABLE tabl_name(
column_definition...
[CONSTRAINT [symbol]] UNIQUE [INDEX|KEY] [index_name] [USING {BTREE | HASH} ] (index_col_name,...) );

index_col_name:

col_name [(length)] [ASC | DESC]

CONSTRAINT symbol是指定限制名稱,因為索引只能進行刪除與新增無法進行修改,但透過CONSTRAINT的命名,則能夠以ALTER TABLE語法來進行修改的動作,但只有唯一索引可以這麼做,語法大部分都與一般索引相同,其中USING部分,這是指定索引的種類,BTREE是一種樹狀結構,他不是二元樹,原本以為B是Binary意思,但請教我的老師之後,發現並非如此,網路上查了一下發現B代表Bayer也就是這種結構的創建者名稱,需要瞭解更多請至Wikipedia查詢 BTREE ,BTREE是比BinaryTree來的更有效率的結構,而HASH是雜湊方式,這需要注意一下,MyISAM只支援BTREE,全部引擎當中只有MEMORY/HEAP支援HASH與BTREE兩種,所以通常USING不指定,第三種方法,後面一併介紹

全文索引:

全文索引通常針對大篇幅文章內容來進行索引,所以欄位型態上通常都是TEXT以上的型態,這裡需要特別留意,全文索引只能指定在文字型態欄位上,其他型態不支援,因為索引的內容較多,所耗損的空間量相對比較大,而且搜尋速度也相對慢很多,如果索引所提高的效益比這些不利因素來的大,建立索引是應該的,建立方法有兩種,第一種透過CREATE TABLE語法:

CREATE TABLE tbl_name(
column_definition...
{FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...));

其實上面這語法應該很容易就可以看得出來,因為他與一般索引相同,只是前方多了FULLTEXT關鍵字,但有個地方很怪異SPATIAL這是什麼?這是空間索引,這部分很少用到,因為他是針對地理資訊系統(GIS)所使用的欄位型態"Spatial Data"來進行索引,這通常只有研究GIS的人才會去使用,我沒研究過..^^,有興趣查DOC,另外全文索引不能指定索引長度,也就是上面一般索引中所提的length部分

第二種方式也是唯一索引、一般索引沒有講到的部分,利用CREATE INDEX語法來建立索引:

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_nameindex_type] ON tbl_name (index_col_name,...)

index_col_name:

col_name [(length)] [ASC | DESC]

index_type:

USING {BTREE | HASH}

上面語法應該很容易理解才對,一般索引則不需指定[UNIQUE|FULLTEXT|SPATIAL]這三者,就是一般索引,ON後方必須指定目前索引在那個資料表,由哪些欄位來建立索引,其餘部分與CREATE TABLE語法建立方式相同

實際上CREATE INDEX語法是對應到ALTER TABLE語法的ADD語法上,所以可以透過ALTER TABLE語法來建立索引也是其中一種方法,這部分請參考MySQL(二)

主索引:

所謂的主索引,就是指PRIMARY KEY,者部分應該不需要提了,這與CREATE TABLE及ALTER TABLE有關

索引表刪除:

建立後的索引要刪除方法有兩種,一種透過ALTER TABLE語法來刪除,另外可以透過DROP INDEX來刪除:

DROP INDEX index_name ON tbl_name

這個語法很簡單,但有個疑問,我該如何得知資料表有哪些索引,這些索引名稱是什麼?要得知索引名稱可以透過SHOW指令來查詢:

SHOW INDEX FROM tbl_name

此時會列出底下訊息

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
test_6 0 name 1 name A NULL NULL NULL YES BTREE

Table:資料表名稱
Non_unique:是否為不是unique,0代表是unique,1代表不是
Key_name:這是索引的名稱,刪除索引指定這裡的名稱即可
Seq_in_index:這是指順序,也可以說是序號,當同一個欄位被使用在兩個以上索引中,誰優先指定則在這個地方就會有大小的順序
Column_name:欄位名稱
Collation:這裡指定不是字集的校對,而是欄位在索引中的排序,A代表ASC的意思,也就是正向排序
Cardinality:這個部分我不是很瞭解,說明上說這是使用在分析資料表時,有興趣查DOC
Sub_part:就是length
Packed:索引表是否被塞滿,如果不是則為NULL(實際上這部分我也不是很瞭解,但說明上是這個寫的)
Null:是否允許Null
Index_type:這部分會出現三種BTREE、HASH、FULLTEXT還有一種RTREE,我查了一下wikipedia以及跟老師討論的結果,RTREE是一種空間向量的結構,所以我推測這樣的索引表結構是應用在GIS上的

上面Key_name就是索引的名稱,刪除時index_name就是指定這個名稱來進行刪除


全文索引的使用:

全文索引的使用(全文檢索),與其他的搜尋有點差異性,因為全文檢索採用的是權重,進行索引的欄位內容會被採用自然語言演算法進行拆解,然後依照出現的次數安排權重,出現次數越少權值越高,被搜尋到的時間越短,出現次數越多權值越低,搜尋的時間越長,甚至可能成為權值0,當權值為0,則有可能無法被搜尋出來,權值為0的可能性有兩種:

  • stopword:例如the、that、he、she...等,這些字眼屬於常用字眼,會被歸類為stopword,也就是不進行檢索,全文檢索具有stopword清單,將某些字眼歸類為stopword。
  • 出現次數過高的文字:例如:地址中的Taipei,地址欄位中可能出現次數過多,造成權值為0,將此字眼列為stopword,此時進行搜尋時,會被忽略不進行搜尋,而導致無法找到這樣的字眼。

檢索的方法:採用MATCH(...)AGAINST(...)來進行條件比對

SELECT *
FROM table_name
WHERE MATCH(欄位1,欄位2...) AGAINST('字串');

MATCH(...)指定要使用全文檢索的搜尋欄位,而AGAINT('字串')指定要搜尋的字串,搜尋出來的資料會依照權值排序,MATCH會傳回權值大小,當權值為0,條件接收之後,會不成立,則該資料不取,如具有權值,權值會以小數點方式呈現

IN BOOLEAN MODE:

IN BOOLEAN MODE有點類似正規表示式,採用一些特殊字元來進行搜尋

+:將權值提升至最大,也就是說,在+號後方的文字必須出現在搜尋出來的每筆資料中

-:將權值降為0,當權值為0,將無法被搜尋出來,-號後方的文字將不會出現在所有搜尋資料中

>與<:>增加權值,<減少權值

( ):利用子查詢查出之結果來進行檢索,也可以採用集合方式

~:類似-號,但是不會將指定字串排除在資料之外,而是將權值設為負值,此時同等於最低權值的資料,將會被列於資料的最後,通常使用於常出現但不須排除的字串

*:類似萬用字元,書上說這是截斷運算子,利用*來替代未知字串,例如以App開頭的字,此時搜尋採用App*,這樣Apple、Application、Apply、Appserv都會被搜尋到

":雙引號,用來指定片語,例如要搜尋一個句子,利用雙引號將某個句子包起來,這樣搜尋時必須完全符合雙引號的字串才能被搜尋出來

語法:

SELECT *
FROM table_name
WHERE MATCH(欄位1,欄位2...) AGAINST('字串' IN BOOLEAN MODE);

字串中採用上方字元來調整適用範圍

書上範例:

SELECT * FROM MemData
WHERE match(MemMemo)
against('+Taipei -golf' IN BOOLEAN MODE);

其餘索引檢索的注意事項:

檢索內容必須為進行索引內容才能進行索引,如採多欄位索引,此時要有效使用索引進行搜尋,必須注意一些事項,如索引建立時採用(col1,col2,col3)來進行索引,則MySQL會建立三份索引表col1一份,(col1,col2)一份,(col1, col3)一份,所以當進行檢索時,條件必須與此三份索引表進行AND的條件才能有效使用,此點必須特別注意

 

 

MySQL 筆記(五)

此篇屬雜項紀錄,一些零散指令的紀錄(不定時更新中)

結束符號定義
mysql>delimiter [符號]
說明: 此命令用於設定mysql client mode中語法的結束字符
ex:delimiter $$
將結束符號由;號變成$$符號

關於 Linux中的連線方法,client登入時,可以採用兩種方式進行登入
1.TCP/IP方式,也就是透過網路進行登入,一般採用此種,此種方式可以指定主機名稱、IP、網址、localhost等方式
2.Socket方式,透過Socket介面進行登入,此種方式只能用於Linux/Unix上
$mysql -u root -p --protocol=socket
將--protocol指定採用socket進行登入,預設為tcp

更新RAM中的授權資料
mysql>FLUSH PRIVILEGES;
說明: FLUSH語法很多,FLUSH的作用,用於刷新記憶體中的暫存資料,當剛設定某使用者的授權資料,或者更動使用者的資料時,記憶體中的資料可能不會馬上更動,此時可以使用此語法強制刷新

Group By [group_field] WITH ROLLUP
此語法在集總函式處理時,除了集總函式本身產生的集總結果外,會在每個群組下方多出群組小計,如果群組為多欄位時,除了每個群組進行小計外,另外會於查詢最後列出總計,此方法必須採用集總函式才會有對應的資料出現,另外總計與小計只會出現在集總函式結果欄位,其他欄位對於ROLLUP處理後,因為不知該放入什麼值,所以補上Null
ex:SELECT last_name,age,count(*)
FROM user
GROUP BY last_name,age WITH ROLLUP;
last_name
age count(*)

10 3

20 2

30 1

Null 6

10 10
20 2

30 4

Null 16
Null
Null 22

 

 

MySQL 筆記(六)

此篇記錄有關MySQL的一些外部命令(client端工具、server端工具),持續更新中

mysqladmin
此命令屬於client端工具,透過外部命令對mysql進行控制,與mysql互動模式(mysql命令)不同
$mysqladmin [options] command [command-options] [command [command-options]] ...

關於常用command

create db_name
建立資料庫,後方db_name為資料庫名稱

drop db_name
刪除資料庫,後方db_name為資料庫名稱

extended-status
顯示伺服器狀態、變數與變數值

flush-hosts
刷新所有主機快取

flush-logs
刷新log的紀錄

flush-privileges
刷新記憶體中的授權表 ,也可以採用reload

flush-status
清除所有狀態的變數

flush-tables
刷新所有資料表

flush-threads
刷新所有執行緒

kill id,id,...
踢除某些執行緒,id為執行緒的編號,執行緒所指的是,每個使用者在MySQL server中正在運行的程序,id可以透過processlist查得每個使用者執行狀態

old-password new-password
設定新密碼(採用舊版本4.01的雜湊進行加密)

password new-password
設定新密碼,採用目前版本的方式加密,下方是關於密碼的注意事項

If the new-password value contains spaces or other characters that are special
to your command interpreter, you need to enclose it within quotes. On Windows,
be sure to use double quotes rather than single quotes; single quotes are not
stripped from the password, but rather are interpreted as part of the
password. For example:

shell> mysqladmin password "my new password"

ping
檢查MySQL server是否運作中,如果正在運作中,則傳回0,反之傳回1,但如果伺服器拒絕檢查(權限不足),同樣會傳回0,但會出現錯誤訊息

processlist
列出所有正在運作中的執行緒,此命令與互動模式中的SHOW PROCESSLIST作用相同,也可以附加--verbose引數,列出詳細資訊,此時會與互動模式中的SHOW FULL PROCESSLIST相同


reload
更新授權表與flush-privileges相同作用

refresh
更新所有資料表與開啟、關閉的log檔

shutdown
停止server

start-slave
開始複製資料至附屬伺服器(多資料庫同步所採用的相關命令)

status
列出server的簡短狀態訊息

stop-slave
停止附屬伺服器(多資料庫同步所採用的相關命令)

variables
列出伺服器系統變數與值

以上為常用的command,大部分command都可以採用短語法(四個字)
ex:mysqladmin -u root -p proc

關於常用option

--help, -?
列出說明

--character-sets-dir=path
指定字集檔案位置

--compress, -C
壓縮client端與server端之間的資訊傳遞(必須雙方都可以支援壓縮才行)

--count=N, -c N
指定命令重複次數,需與--sleep一起使用

--default-character-set=charset_name
指定預設的字集

--force, -f
強制,當資料庫進行刪除時,不顯示任何提示

--host=host_name, -h host_name
指定連結的資料庫伺服器位置或者主機名稱

--password[=password (INSECURE)], -p[password (INSECURE)]
指定登入密碼,如過不給值則會提示輸入密碼,如果給值則會直接進行登入,但密碼會以明碼顯示

--port=port_num, -P port_num
指定port

--protocol={TCP|SOCKET|PIPE|MEMORY}
指定連接方式,採用TCP、SOCKET、PIPE等方式,預設為TCP

--relative, -r
當使用--sleep重複執行命令時,列出現在與之前一次的差異,只能與 extended-status 一起使用

--silent, -s
靜默模式,也就是當無法連線時,不顯示任何訊息

--sleep=delay, -i delay
重複執行命令時,指定每個命令間格多少秒執行一次

--socket=path, -S path
指定socket file路徑,如果在windows上則代表pipe line路徑

--ssl*
使用SSL進行連線

--user=user_name, -u user_name
指定登入帳號(使用者)

--verbose, -v
印出更多資訊(詳細資訊)

--version, -V
顯示版本

--vertical, -E
垂直輸出訊息

--wait[=count], -w[count]
當連線無法建立時,嘗試重複登入,後方count指定登入次數


指定變數:--variable_name=value

connect_timeout
指定連線的timeout時間(斷線時間),預設為43200(12小時)

shutdown_timeout
等待server關機的時間,預設3600秒(1小時)

不建議的變數指定方法:
--set-variable=variable_name=var_value