程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> [MySQL Reference Manual] 10 全球化,referencemanual

[MySQL Reference Manual] 10 全球化,referencemanual

編輯:MySQL綜合教程

[MySQL Reference Manual] 10 全球化,referencemanual


10.全球化

本章主要介紹全球化,包含國際化和本地化,的一些問題:

·         MySQL在語句中支持的字符集

·         如何為服務配置不同的字符集

·         選擇錯誤信息的語言

·         如何設置服務的時區和每個連接的時區

·         選擇本土化的日期和月份名

10.全球化... 1

10.1 字符集的支持... 2

10.1.1 字符集和排序規則... 2

10.1.2 mysql中的字符集和排序規則... 3

10.1.3 制定字符集和排序規則... 3

10.1.3.1 服務字符集和排序規則... 3

10.1.3.2 數據庫級字符集和排序規則... 3

10.1.3.3 表的字符集和排序規則... 4

10.1.3.4 列的字符集和排序規則... 4

10.1.3.5 字符串常量的字符集和排序規則... 5

10.1.3.6 National Character Set6

10.1.3.7 字符集和排序規則設置的例子... 6

10.1.3.8 和其他數據的兼容... 6

10.1.4 連接的字符集和排序規則... 7

10.1.5 為應用程序配置字符集和排序規則... 8

10.1.5.1 為每個數據指定字符集和排序規則... 8

10.1.5.2 在服務啟動是配置字符集... 8

10.1.5.3 在Mysql配置的時候設置字符集和排序規則... 8

10.1.6 錯誤信息的字符集... 9

10.1.7 排序規則... 9

10.1.7.1 排序規則名... 9

10.1.7.2 在語句中使用排序規則... 9

10.1.7.3 COLLATE子句... 10

10.1.7.4 排序規則必須要一個正確的字符集... 10

10.1.7.5 表達式中的排序規則... 10

10.1.7.6 _bin和binary. 11

10.1.7.7 BINARY操作... 13

10.1.7.8 Collation的影響例子... 13

10.1.7.9 排序規則和INFORMATION_SCHEMA查找... 13

10.1.8 字符目錄(String Repertoire)15

10.1.9 受字符集影響的操作... 16

10.1.9.1 結果字符串... 16

10.1.9.2 CONVERT()和CAST()16

10.1.9.3 SHOW語句和INFORMATION_SCHEMA.. 16

10.1.10 Unicode支持... 16

10.1.10.1 ucs2字符集... 17

10.1.10.2 utf16字符集... 17

10.1.10.3 utf16le字符集... 17

10.1.10.4 utf32字符集... 17

10.1.10.5 utf8字符集... 17

10.1.10.6 utf8mb3字符集... 18

10.1.10.7 utf8mb4字符集... 18

10.1.11 更新unicode的支持... 18

10.1.12 元數據為utf8. 19

10.1.13 列字符集轉化... 19

10.1.14 MySQL支持的字符集和排序規則... 20

10.2 設置錯誤信息語言... 20

10.3 增加一個字符集... 20

10.4 為字符集增加一個排序規則... 20

10.5 配置字符集... 20

10.6 MySQL時區的支持... 20

10.6.1 跟上時區修改... 21

10.6.2 時區閏秒支持(Time Zone Leap Seconad Support)22

10.7 MySQL Server本地化支持... 23

 

10.1 字符集的支持

Mysql可以讓你使用不同的字符集來保存數據,可以再多個排序規則下比較數據。可以再服務,數據庫,表和列級別設置字符集。本章回答以下幾個問題:

·         使用什麼字符集和排序規則

·         多個級別的系統默認字符集的分配

·         設置字符集和排序規則的設置語法

·         會收到影響的函數和操作

·         Unicode 的支持

·         可用的字符集和排序規則

字符集不單單影響數據存儲,也會影響client和server之間的交互。可以使用set names來設置client和server之間交互使用的字符集。

10.1.1 字符集和排序規則

字符集是一堆符號和編碼,排序規則是字符集的比較規則。比如比較“A”和“B”最簡單的方法是比較編碼,這種排序規則也是最簡單的排序規則,成為binary排序規則。

對於a=A,b=B我們成為大小寫不敏感的排序規則。每個字符集有很多個排序規則。

mysql可以做到以下一些:

1.可以以多個字符集保存字符串

2.比較字符串可以使用不同的排序規則

3.在同一個服務中可以混合多個字符集和排序規則

4.字符集和排序規則有很多級別(server,db,tb.column)

10.1.2 mysql中的字符集和排序規則

Mysql可以支持多個字符集,可以使用SHOW CHARACTER SET來顯示。一個字符集有多個排序規則,至少一個,可以使用SHOW COLLATION,查看。

排序規則有以下一些特性:

·         2個不同的字符集不可能擁有同一個排序規則

·         每個字符集都有一個默認排序規則

·         排序規則命名,一般是字符集名,語言名,後綴。後綴有_ci(大小寫不明感),_cs(大小寫敏感),_bin(binary)

避免使用錯的排序規則,保證制定的排序規則給出的順序是你要的。

10.1.3 制定字符集和排序規則

在4個級別上會設置默認的字符集和排序規則,CHARACTER SET可以用來設置指定字符集。CHARSET是CHARACTER SET的另外一種寫法。

字符集不單單影響數據存儲,也會影響客戶端和服務器之間的交互。

10.1.3.1 服務字符集和排序規則

服務級別的字符集和排序規則可以在命令行和配置文件中設置。使用—character-set-server設置字符集,--collation-server設置排序規則。

shell> mysqld

shell> mysqld --character-set-server=latin1

shell> mysqld --character-set-server=latin1 \

           --collation-server=latin1_swedish_ci

如果要修改默認的服務級的字符集和排序規則,可以通過重編譯源代碼進行。

shell> cmake . -DDEFAULT_CHARSET=latin1

shell> cmake . -DDEFAULT_CHARSET=latin1 \

           -DDEFAULT_COLLATION=latin1_german1_ci

Mysqld和CMake都會驗證字符集和排序規則是否可用,如果不可用每個程序都會顯示錯誤信息和中斷。

當create database沒有指定,會使用服務的字符集和排序規則。Character_set_server和collation_server指定了服務的字符集和排序規則。這些變量可以再運行時被修改。

10.1.3.2 數據庫級字符集和排序規則

數據庫級的排序規則可以使用create database和alterdatabase來指定。

CREATE DATABASE db_name

    [[DEFAULT] CHARACTER SET charset_name]

    [[DEFAULT] COLLATE collation_name]

 

ALTER DATABASE db_name

    [[DEFAULT] CHARACTER SET charset_name]

    [[DEFAULT] COLLATE collation_name]

CHARACTER_SET,COLLATE子句可以指定不同於服務的字符集和排序規則。

CREATE DATABASE db_name CHARACTER SET latin1 COLLATE latin1_swedish_ci;

Mysql以以下方式來獲取字符集和排序規則:

·         如果指定了CHARACTER SET X和COLLATE Y,那麼會使用字符集x,排序規則y

·         如果指定了字符集x沒有指定排序規則,那麼使用默認的排序規則。

·         如果指定了排序規則沒有指定字符集,那麼使用和排序規則相關的字符集。

·         否則使用服務的字符集和排序規則。

和創建數據庫一樣,創建表的時候沒有指定就使用數據庫級的字符集和排序規則。Character_set_database和collation_database系統變量,當有數據庫時,為數據庫的字符集和排序規則,如果沒有數據庫時是server的字符集和排序規則。

10.1.3.3 表的字符集和排序規則

表的排序規則可以通過create table和alter table來修改。

CREATE TABLE tbl_name (column_list)

    [[DEFAULT] CHARACTER SET charset_name]

    [COLLATE collation_name]]

 

ALTER TABLE tbl_name

    [[DEFAULT] CHARACTER SET charset_name]

    [COLLATE collation_name]

表選擇字符集和排序規則和數據庫一致。

如果創建表時,表沒有指定列的字符集和排序規則,那麼就用表的字符集和排序規則。

10.1.3.4 列的字符集和排序規則

列的字符集和排序規則通過create table和alter table來指定。

col_name {CHAR | VARCHAR | TEXT} (col_length)

    [CHARACTER SET charset_name]

    [COLLATE collation_name]

col_name {ENUM | SET} (val_list)

    [CHARACTER SET charset_name]

    [COLLATE collation_name]

如:

CREATE TABLE t1

(

    col1 VARCHAR(5)

      CHARACTER SET latin1

      COLLATE latin1_german1_ci

);

 

ALTER TABLE t1 MODIFY

    col1 VARCHAR(5)

      CHARACTER SET latin1

      COLLATE latin1_swedish_ci;

Mysql為列選擇字符集和排序規則的方法和表一樣。

如果alter table從一個字符集轉為另外一個字符集的時候,如果字符集不兼容那麼就有可能丟失數據。

10.1.3.5 字符串常量的字符集和排序規則

每個字符串都有一個字符集和排序規則。指定字符串常量字符集的方法:

[_charset_name]'string' [COLLATE collation_name]

例如:

SELECT 'string';

SELECT _latin1'string';

SELECT _latin1'string' COLLATE latin1_danish_ci;

如果什麼都沒有指定,那麼使用連接的字符集和排序規則,character_set_connection和collation_connection決定。

Mysql選擇字符集和排序規則的方式如下:

·         如果指定了字符集x和排序規則y,那麼就是用x,y

·         如果指定了字符集沒有指定排序規則,那麼使用x和x的默認排序規則

·         否則使用變量character_set_connection和collation_connection

前面指定的字符集並不影響轉移字符,轉移字符是受character_set_connection影響。

mysql> SET NAMES latin1;

Query OK, 0 rows affected (0.01 sec)

 

mysql> SELECT HEX('à\n'), HEX(_sjis'à\n');

+------------+-----------------+

| HEX('à\n') | HEX(_sjis'à\n') |

+------------+-----------------+

| E00A       | E00A            |

+------------+-----------------+

1 row in set (0.00 sec)

mysql> SET NAMES sjis;

Query OK, 0 rows affected (0.00 sec)

 

mysql> SELECT HEX('à\n'), HEX(_latin1'à\n');

+------------+-------------------+

| HEX('à\n') | HEX(_latin1'à\n') |

+------------+-------------------+

| E05C6E     | E05C6E            |

+------------+-------------------+

1 row in set (0.04 sec)

在字符集sjis中“\”並不認為是轉移“\”=5C,“n”=6E。

10.1.3.6 National Character Set

標准SQL定義NCHAR或者 NATIONAL CHAR來說明這個char列要使用預定於的字符集。Mysql 5.6使用utf8作為預定義的字符集。可以通過N’some text’來創建national 字符集內的字符串。

10.1.3.7 字符集和排序規則設置的例子

1.設置列和表的字符集和排序規則

CREATE TABLE t1

(

    c1 CHAR(10) CHARACTER SET latin1 COLLATE latin1_german1_ci

) DEFAULT CHARACTER SET latin2 COLLATE latin2_bin;

2.列不帶排序規則

CREATE TABLE t1

(

    c1 CHAR(10) CHARACTER SET latin1

) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

3.列不帶字符集和排序規則

CREATE TABLE t1

(

    c1 CHAR(10)

) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

4.數據庫設置排序規則和字符集,表和列不設置

CREATE DATABASE d1

    DEFAULT CHARACTER SET latin2 COLLATE latin2_czech_ci;

USE d1;

CREATE TABLE t1

(

    c1 CHAR(10)

);

10.1.3.8 和其他數據的兼容

10.1.4 連接的字符集和排序規則

連接的字符集和排序規則主要說明一下一些問題:

·         當客戶端發送前語句的時候使用什麼字符集,character_set_client

·         語句在傳輸過程中是什麼字符集,character_set_connection,和排序規則collation_connection,然後會從character_set_client轉化為character_set_connection。

·         在傳輸錯誤或者結果到客戶端前字符集是什麼,character_set_results指定了返回前的字符集。

有2個語句會影響和連接相關的字符集變量

·         SET NAMES ‘charset_name’[COLLATE ‘collation_name’]

SET NAMES相當於以下3個語句

SET character_set_client = charset_name;

SET character_set_results = charset_name;

SET character_set_connection = charset_name;

·         使用SET語句設置,如:

SET character_set_client = charset_name;

SET character_set_results = charset_name;

SET collation_connection = @@collation_database;

Mysql的一些客戶端程序如mysql,MySQLadmin,mysqlcheck,mysqlimport,mysqlshow決定默認字符集規則如下:

·         在沒有信息的情況下使用Latin1字符集

·         程序可以自動識別OS上使用的字符集,如LANG或者LC_ALL。或者windows上的codepage來判斷

·         程序也支持使用—default-character-set選項,顯示的設置字符集。

在程序連接服務的時候,使用程序要的字符集發送給服務,然後何止,character_set_client,character_set_results和character_set_connection系統變量。事實上可以使用set names來設置。

如果默認的和你想要的不一樣可以使用set names來設置或者加上參數—default-caracter-set,或者加在配置文件中。

[mysql]

default-character-set=koi8r

如果可以自動重連,可以使用charset命令:

mysql> charset utf8

Charset changed

Charset命令使用set names,然後修改mysql的默認字符集,然後重連。

假設列column1定義為char(5) CHARACTER SET latin2。如果沒有設置set names和set character set。那麼mysql會以column1的字符集和排序規則來發送數據,如果設置了set names latin1,那麼會把latin2轉化為latin1然後再發送。

如果要嘗試直接發送:

SET character_set_results = NULL;

10.1.5 為應用程序配置字符集和排序規則

應用程序存數據使用默認的字符集和排序規則。如果應用程序要不同的排序規則和字符集,可以通過幾個方式來配置:

·         為每個數據庫指定一個字符集

·         在服務啟動的時候指定一個字符集

·         在mysql編譯的時候配置字符集

如果所有的或者大多數的應用程序使用相同的字符集,可以再服務啟動的時候或者配置mysql的時候設置。

10.1.5.1 為每個數據指定字符集和排序規則

在create database中設置如:

CREATE DATABASE mydb

  DEFAULT CHARACTER SET utf8

  DEFAULT COLLATE utf8_general_ci;

應用程序在使用這個數據庫的時候,每次連接都要配置可以指定—default-character-set=utf8或者set names=‘utf8’。

如果修改了數據庫的字符集和排序規則,那麼所有的過程都要被重建。

10.1.5.2 在服務啟動是配置字符集

在服務啟動的時候,使用命令行—character-set-server和—collation-server,或者設置配置文件:

[mysqld]

character-set-server=utf8

collation-server=utf8_general_ci

這些配置是服務級別的,所以在創建數據庫的時候會以這個為默認的字符集和排序規則。一旦設置了之後,每個連接可能都要設置一下排序規則,那麼可以再系統啟動的時候設置—init_connect=”SET NAMES ‘utf8’”,這樣每次連接的時候都會運行一下set names命令。

10.1.5.3 在Mysql配置的時候設置字符集和排序規則

設置方法:

shell> cmake . -DDEFAULT_CHARSET=utf8 \

           -DDEFAULT_COLLATION=utf8_general_ci

10.1.6 錯誤信息的字符集

在mysql 5.6,服務使用utf8構建消息,並且通過character_set_results系統變量來返回。

服務構建錯誤消息的過程:

·         消息模板使用utf8

·         然後消息中的參數被替換

o    如表名,列名會被原樣復制

o    如果是字符串那麼會被轉化成utf8

o    如果是二進制串恢復0x20到0x7e之間的值,其他的會被加上前綴\x

o    Duplicate entry 'A\xC3\x9F' for key 1

如果構建完就會發送給client,字符集會從utf8轉化為character_set_results系統變量。如果變量為null或者binary不會發送轉化。

如果字符在character_set_results上沒辦法體現,某些字符可能發生某些編碼。編碼使用unicode指針值:

·         如果字符在BMP(Basic Multilingual Plane)范圍內(0x0000-0xffff)寫成\nnnn

·         如果再范圍之外室友\+nnnnnn

客戶端可以控制character_set_results來控制接受的字符串的字符集。

10.1.7 排序規則

10.1.7.1 排序規則名

排序規則名一般以_ci,_cs,_bin結尾

10.1.7.2 在語句中使用排序規則

·  With ORDER BY:

SELECT k

FROM t1

ORDER BY k COLLATE latin1_german2_ci;

·  With AS:

SELECT k COLLATE latin1_german2_ci AS k1

FROM t1

ORDER BY k1;

·  With GROUP BY:

SELECT k

FROM t1

GROUP BY k COLLATE latin1_german2_ci;

·  With aggregate functions:

SELECT MAX(k COLLATE latin1_german2_ci)

FROM t1;

·  With DISTINCT:

SELECT DISTINCT k COLLATE latin1_german2_ci

FROM t1;

·  With WHERE:

     SELECT *

     FROM t1

     WHERE _latin1 'Müller' COLLATE latin1_german2_ci = k;

     SELECT *

     FROM t1

     WHERE k LIKE _latin1 'Müller' COLLATE latin1_german2_ci;

·  With HAVING:

SELECT k

FROM t1

GROUP BY k

HAVING k = _latin1 'Müller' COLLATE latin1_german2_ci;

 

10.1.7.3 COLLATE子句

COLLATE比||優先級要高,所以下面語句是等價的:

x || y COLLATE z

x || (y COLLATE z)

10.1.7.4 排序規則必須要一個正確的字符集

一個字符集有多個排序規則,但是一個排序規則只能對應到一個字符集,因此如果出現以下情況那麼就會報錯:

mysql> SELECT _latin1 'x' COLLATE latin2_bin;

ERROR 1253 (42000): COLLATION 'latin2_bin' is not valid

for CHARACTER SET 'latin1'

10.1.7.5 表達式中的排序規則

排序規則的主要用處是用來比較,如:

SELECT x FROM T ORDER BY x;

SELECT x FROM T WHERE x = x;

SELECT DISTINCT x FROM T;

如果是2個不同的操作數,可能排序規則會歧義如:

SELECT x FROM T WHERE x = 'Y';

出現這種情況標准的sql使用可壓縮性規則來確定使用什麼字符集。可壓縮性值有以下決定:

·         一個現實的COLLATE子句的可壓縮性值為0

·         並列的2個字符串有2個不同的排序規則,那麼可壓縮性為1

·         列或者存儲的參數的排序規則可壓縮性為2

·         系統常量,或者USER(),VERSION()的可壓縮性為3

·         字符串常量的可壓縮性值為4

·         Null的可壓縮性值為5

Mysql使用可壓縮性值來解決這個問題:

·         使用可壓縮值最低的

·         如果吹按可壓縮值相同

o    如果2邊都是unicode或者都不是那麼就報錯

o    如果一邊是unicode,一邊不是那麼傳為非unicode

o    如果操作字符集相同,但是排序規則不同,比如_bin混合了_ci,_cs那麼使用_bin。

可壓縮性值,可以通過coercibility查看

對於使用concat隱式轉化的字符集和排序規則有連接的字符集和排序規則決定。

10.1.7.6 _bin和binary

串有2中,一種是字符串(Nonbinary string),一種是二進制串(binary string)。

Nonbinary string以數據類型char,varchar,text保存,有字符集和排序規則。

Binary string以binary,varbinary,blob類型保存,無字符集和排序規則。

在很多方面_bin排序規則和binary排序規則不同。

10.1.7.6.1 比較單位

Binary string是字節流。比較是根據字節的值來比較。Nonbinary string是字符流,所以比較是以一個字符來進行比較。Nonbinary strings的排序規則定義了字符的順序和比較。對於_bin排序規則就是以字符的二進制的值進行排序。

10.1.7.6.2 字符集轉化

Nonbinary strings可以轉化為其他字符集的字符串,就算是_bin排序規則的。但是對於binary strings就不會發生轉化。

10.1.7.6.3 大小寫轉化

Nonbinary strings可以大小寫轉化:

mysql> SET NAMES latin1 COLLATE latin1_bin;

Query OK, 0 rows affected (0.02 sec)

 

mysql> SELECT LOWER('aA'), UPPER('zZ');

+-------------+-------------+

| LOWER('aA') | UPPER('zZ') |

+-------------+-------------+

| aa          | ZZ          |

+-------------+-------------+

1 row in set (0.13 sec)

在binary strings中是不能轉化的:

mysql> SET NAMES binary;

Query OK, 0 rows affected (0.00 sec)

 

mysql> SELECT LOWER('aA'), LOWER(CONVERT('aA' USING latin1));

+-------------+-----------------------------------+

| LOWER('aA') | LOWER(CONVERT('aA' USING latin1)) |

+-------------+-----------------------------------+

| aA          | aa                                |

+-------------+-----------------------------------+

1 row in set (0.00 sec)

10.1.7.6.4 比較時尾隨的空格處理

Nonbinary strings所有的排序規則有PADSPACE行為。

mysql> SET NAMES utf8 COLLATE utf8_bin;

Query OK, 0 rows affected (0.00 sec)

 

mysql> SELECT 'a ' = 'a';

+------------+

| 'a ' = 'a' |

+------------+

|          1 |

+------------+

1 row in set (0.00 sec)

但是binary string不行

mysql> SET NAMES binary;

Query OK, 0 rows affected (0.00 sec)

 

mysql> SELECT 'a ' = 'a';

+------------+

| 'a ' = 'a' |

+------------+

|          0 |

+------------+

1 row in set (0.00 sec)

10.1.7.6.5 插入和獲取時的空格處理

CHAR(N)保存nonbinary strings數據,當插入長度不足N會以空格插入。

binary(N)保存binary string數據,會以0x00填充。

mysql> CREATE TABLE t1 (

    ->   a CHAR(10) CHARACTER SET utf8 COLLATE utf8_bin,

    ->   b BINARY(10)

    -> );

Query OK, 0 rows affected (0.09 sec)

 

mysql> INSERT INTO t1 VALUES ('a','a');

Query OK, 1 row affected (0.01 sec)

 

mysql> SELECT HEX(a), HEX(b) FROM t1;

+--------+----------------------+

| HEX(a) | HEX(b)               |

+--------+----------------------+

| 61     | 61000000000000000000 |

+--------+----------------------+

1 row in set (0.04 sec)

10.1.7.7 BINARY操作

Binary操作是把它之後的字符串變為binary string。BINARY str是cast(str as BINARY)的縮寫。

10.1.7.8 Collation的影響例子

10.1.7.9 排序規則和INFORMATION_SCHEMA查找

INFORMATION_SCHEMA表的字符串列的排序規則是uft8_genernal_ci,大小寫不敏感。但是文件系統的是否大小寫敏感也會影響INFORMATION_SCHEMA的字符串列。如linux系統上大小寫是敏感的。

在linux 下:

mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA

    -> WHERE SCHEMA_NAME = 'test';

+-------------+

| SCHEMA_NAME |

+-------------+

| test        |

+-------------+

1 row in set (0.01 sec)

 

mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA

    -> WHERE SCHEMA_NAME = 'TEST';

Empty set (0.00 sec)

在windows下:

mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA

    -> WHERE SCHEMA_NAME = 'test';

+-------------+

| SCHEMA_NAME |

+-------------+

| test        |

+-------------+

1 row in set (0.00 sec)

 

mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA

    -> WHERE SCHEMA_NAME = 'TEST';

+-------------+

| SCHEMA_NAME |

+-------------+

| TEST        |

+-------------+

1 row in set (0.00 sec)

如果列的排序規則和想到的不同,可以使用COLLATE語句顯示指定一個排序規則:

mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA

    -> WHERE SCHEMA_NAME COLLATE utf8_general_ci = 'test';

+-------------+

| SCHEMA_NAME |

+-------------+

| test        |

+-------------+

1 row in set (0.00 sec)

 

mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA

    -> WHERE SCHEMA_NAME COLLATE utf8_general_ci = 'TEST';

| SCHEMA_NAME |

+-------------+

| test        |

+-------------+

1 row in set (0.00 sec)

當然也可以使用UPPER(),LOWER()。

10.1.8 字符目錄(String Repertoire)

字符集目錄是字符集合。

字符串表達式有2種目錄屬性:

ASCII:只能包含unicode范圍中U+0000到U+007U。

UNICODE:包含unicode范圍從U+0000到U+FFFF。

ASCII是UNICODE的子集。

使用以下例子來說明目錄:

·         字符串的內容限制了目錄

SET NAMES utf8; SELECT 'abc';

SELECT _utf8'def';

SELECT N'MySQL';

盡管是使用了utf8字符集,但是只使用了ASCII范圍的所以目錄是ASCII。不是unicode。

·         有ascii字符集的列有ASCII目錄。2個列concat的時候只能是子集連接超集,如:

CREATE TABLE t1 (

  c1 CHAR(1) CHARACTER SET latin1,

  c2 CHAR(1) CHARACTER SET ascii

);

INSERT INTO t1 VALUES ('a','b');

SELECT CONCAT(c1,c2) FROM t1;

ERROR 1267 (HY000): Illegal mix of collations (latin1_swedish_ci,IMPLICIT)

and (ascii_general_ci,IMPLICIT) for operation 'concat'

如果是子集連接超集。

+---------------+

| CONCAT(c1,c2) |

+---------------+

| ab            |

+---------------+

·         有一個字符串參數的函數,會集成參數的目錄,如UPPER(_utf8’abc’)是ASCII目錄。

·         如果函數返回字符串,但是沒有字符串參數,那麼字符集使用chararter_set_connection作為結果,如果字符集是ascii那麼目錄使用ascii,否則使用unicode。

·         當函數有2個或者2個以上字符參數時,使用最寬的目錄,如unicode比ascii寬,

CONCAT(_ucs2 0x0041, _ucs2 0x0042)

CONCAT(_ucs2 0x0041, _ucs2 0x00C2)

第一個函數都沒超過ascii range,那麼就是ascii,第二個超過了ascii,那麼就是unicode。

·         函數的返回字符串的目錄由參數的目錄決定

10.1.9 受字符集影響的操作

 

10.1.9.1 結果字符串

Mysql有很多操作和函數返回字符串。那麼本節介紹結果字符串的排序規則和字符集。

對於簡單的函數,輸入字符串的,那麼輸出的字符串和輸入的字符串的排序規則和字符集一樣。

如果輸入或者輸出的字符串是binary串,那麼是沒有字符集和排序規則的,charset()和collation()都是返回binary。

如果有對個數據字符串,一個輸出,那麼有以下規則決定輸出的排序規則:

·         如果現實的指定了collate x那麼使用x

·         如果指定了collate x,collate y,報錯

·         如果所有的排序規則是x,那麼使用x

·         否則結果沒有排序規則

10.1.9.2 CONVERT()和CAST()

Convert提供了字符串在不同字符集上轉化的功能

CONVERT(expr USING transcoding_name)

如:

SELECT CONVERT(_latin1'Müller' USING utf8);

INSERT INTO utf8table (utf8column)

    SELECT CONVERT(latin1field USING utf8) FROM latin1table;

也可以使用cast,

CAST(character_string AS character_data_type CHARACTER SET charset_name)

如:

SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8);

Convert和cast上不能使用字符集,可以再函數外面使用:

SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin;

10.1.9.3 SHOW語句和INFORMATION_SCHEMA

show命令的結果會提供一些字符集合排序規則信息,INFORMATION_SCHEMA和show命令類似。

10.1.10 Unicode支持

起初,mysql 4.1中就支持2中保存unicode的方式:

·         Ucs2:每個字節使用2個字節來編碼。

·         Utf8:每個字節1-3個字節。

這2個字符集支持來自unicode 3.0 BMP的字符。

如果超出BMP的字符會被替換為‘?’

在mysql 5.6,為了要支持新的unicode的字符,所以增加了新的字符集。

Mysql 5.6支持的字符集:

Ucs2:有2個字節來編碼

Utf16:和ucs2類似,但是多了新增的字符

Utf16le:utf16是大端的,utf16le是小端的

Utf32:每個字符3個字節

Utf8:每個字符1-3個字節

Utf8mb4:1-4個字節編碼

Ucs2,utf8支持BMP字符,utf8mb4,utf16,utf16le和utf32支持BMP字符和額外字符。

10.1.10.1 ucs2字符集

在ucs2字符集中,每個字符占2個字節。

10.1.10.2 utf16字符集

Utf16是ucs2加上一些新增的字符,有以下 特性:

·         對於BMP字符,utf16個ucs2編發都是一樣的

·         對於增益的字符,如果大於0xffff,加上0xd800,放到前16bit,然後去之後的10bit加上0xdc00放到後16bit。

10.1.10.3 utf16le字符集

和utf16一樣,只是是小端的。

10.1.10.4 utf32字符集

Utf32的字符長度是固定的,4個字節。在使用的時候要注意,定義的長度必須是4字節的倍數。

10.1.10.5 utf8字符集

Uft8是一種保存unicode的替代方案。

Utf8把字符以不同的字節長度進行編碼:

·         基本的Latin字母,數字和標點符號使用一個字節。

·         大多數歐洲,中東字符使用2個字節。

·         韓文,中文,日文在3個或者4個字節中。

Utf8在mysql5.6還是之前的版本都有2個特點:

·         不支持新增字符。

·         最多每個字符3個字節。

Uft8和ucs2有相同的目錄

10.1.10.6 utf8mb3字符集

在未來utf8會變成4字節的utf8,之前的3字節的utf8要被稱為utf8mb8。為了避免將來復制之間的版本不同導致字符集問題,可以讓用戶指定utf8mb3字符集和排序規則。如:

CREATE TABLE t (s1 CHAR(1) CHARACTER SET utf8mb3;

SELECT * FROM t WHERE s1 COLLATE utf8mb3_general_ci = 'x';

DECLARE x VARCHAR(5) CHARACTER SET utf8mb3 COLLATE utf8mb3_danish_ci;

SELECT CAST('a' AS CHAR CHARACTER SET utf8) COLLATE utf8_czech_ci;

這時,mysql會吧utf8mb3轉化為utf8.目前utf8mb3只能用在CHARACTER SET子句上。

10.1.10.7 utf8mb4字符集

Utf8字符集一個字符最多3個字節,並且只包含BMP字符。Utf8mb4是最多使用每個字符4個字節:

·         對於BMP,utf8和utf8mb4都是一樣的存儲特性,同樣的code值,同樣的編碼,同樣的長度。

·         對於新增的字符,utf8buneng baocun ,utf8mb4需要4個字節來保存。

Utf8mb4是utf8的超集。

10.1.11 更新unicode的支持

對於utf8mb4個utf8比,在相同的長度下utf8能夠存更多的字符。可以使用alter table把utf8轉成utf8mb4:

CREATE TABLE t1 (

  col1 CHAR(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,

  col2 CHAR(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL

) CHARACTER SET utf8;

ALTER TABLE t1

  DEFAULT CHARACTER SET utf8mb4,

  MODIFY col1 CHAR(10)

    CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,

  MODIFY col2 CHAR(10)

    CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;

對於BMP字符來說,utf8和utf8mb4沒有什麼差別,但是utf8不支持新增字符。

對於所有的char,varchar,text需要注意:

·         檢查所有的utf8定義的列,不會超過引擎的最大值

·         檢查utf8的索引,不會超過引擎的最大值。

如果上面條件不滿足,那麼只能使用utf8.還有一些例子修改字符集可能要修改表結構:

·         Tinytext類型,只有255個字節,如果使用3個字節一個字符最多可以存85個,如果4字節那麼最多63個。如果要使用utf8mb4又要超過63個字符,那麼需要修改表結構。

·         Innodb索引,如果使用COMPACT或REDUNDANT行格式,最長767個字節。對於utf8和utf8mb4來說,最多可以保存255和191個字符。也就是說,如果utf8長度超過191個字符,要轉化為utf8mb4那麼是不夠的。

還有一些utf8和utf8mb4的比較:

·         4字節的utf8比3字節的utf8性能差

·         Set names ‘utf8mb4’連接字符集會是4字節字符集,如果沒有4個字節字符發送就沒有問題。否則應用程序視圖以最大3個字節獲取信息可能會出問題。

·         應用不能發utf16,utf16le,utf32發送數據到老的服務

·         對於復制,如果master支持新增的字符集,那麼slave必須也支持。

如果要從新系統換成老系統:

·         Ucs2和utf8是沒問題的

·         老系統不支持utf8mb4,utf16,utf16le,utf32

·         對於使用了utf8mb4的對象定義,可以先dump,然後把utf8mb4轉為utf8。

10.1.12 元數據為utf8

元數據需要滿足以下特點:

·         所有的元數據要使用同一個字符集。

·         元數據必須包含所有語言的字符。

為了滿足這個條件,mysql使用utf8字符集來存元數據。比如函數USER(),CURRENT_USER(),SESSION_USER(),SYSTEM_USER(),DATEBASE()和VERSION(),默認都是使用utf8。

使用character_set_system系統變量來控制元數據的字符集。

元數據是以character_set_system保存的,並不意味著DESCRIBE函數返回的字符集也是默認character_set_system字符集。如select column1 from t,從服務器返回給client,column1的字符集是由character_set_results決定的,默認為latin1。如果想要把元數據的結果以其他字符集傳輸,可以使用set name 來設置。如果character_set_results為null,那麼就不會發出轉化,如果是元數據,那麼會以character_Set_system字符集傳輸。

如果在表達式中使用user()那麼mysql會自動進行傳化。

SELECT * FROM t1 WHERE USER() = latin1_column;

INSERT INTO t1 (latin1_column) SELECT USER();

10.1.13 列字符集轉化

使用alter table把binary string或者nonbinary string 指定特定字符集。

·         如果列是bianry數據類型(BINARY,VARBINARY,BLOB)那麼所有的值只能是一個字符集。

·         如果是nonbinary數據類型(char,varchar,text)包含的值,只能變編碼為列自定的字符集。

假設表t是有一個col1定義為varbinary,使用一個字符集編碼,並且為greek,那麼可以通過以下語句去轉化:

ALTER TABLE t MODIFY col1 VARCHAR(50) CHARACTER SET greek;

如果類型是binary(50),那麼可以轉化為char(50)但是,可能會出現0x00在末尾可能無法描述,需要使用trim();

UPDATE t SET col1 = TRIM(TRAILING 0x00 FROM col1);

如果表t有col1 char(50) character set latin1,要轉化為utf8,可以直接:

ALTER TABLE t MODIFY col1 CHAR(50) CHARACTER SET utf8;

10.1.14 MySQL支持的字符集和排序規則

10.2 設置錯誤信息語言

默認mysql的錯誤信息是英語,但是可以指定其他語言。

在mysql 5.6中錯誤信息在以下2個目錄下去查找:

·         會從lc_messages_dir和lc_messages 2個系統變量上去查找,使用如下:

shell> mysqld --lc_messages_dir=/usr/share/mysql --lc_messages=fr_FR

·         如果找不到,那麼會放棄lc_messages,直接通過lc_messages_dir來查找。

lc_messages_dir是全局只讀變量,lc_messages是全局和會話變量,可以運行時修改。默認語言文件在share/mysql/LANGUAGE目錄下。

10.3 增加一個字符集

10.4 為字符集增加一個排序規則

10.5 配置字符集

10.6 MySQL時區的支持

mysql時區有好幾個維護時區的設置:

·         系統級別的時區,當服務啟動的時候,把系統使用的時區賦值給system_time_zone系統變量

·         服務當前時區,全局time_zone,表明當前所在的時區,初始值是’SYSTEM’表示和服務時區一樣。全局服務時間可以在啟動時設置,可以使用--default-time-zone。

·         每個連接的時區,當連接的時候會話變量time_zone和全局time_zone一樣,但是可以自己修改。

當前的時區,不會對UTC_TIMESTAMP()和date,time,datetime列的值進行影響。當前的時區可以通過以下方式獲取:

mysql> SELECT @@global.time_zone, @@session.time_zone;

時區的值可以是以下幾種:

·           ‘SYSTEM’表示和服務的時區一樣

·           ‘+10:00’,’-6:00’直接設置時區

·           使用命名的時區,如 ‘Europe/Helsinki’

mysql安裝的時候會生成時區表在mysql數據庫內,但是不會被load需要手動load。

如果系統有自己的時區信息,那麼可以使用mysql_tzinfo_to_sql程序來填充時區表,如linux,時區信息在/usr/shar/zoneinfo目錄下。如果沒有時區庫,那麼可以自己去下載。

mysql_tzinfo_to_sql用來把時區信息導入到時區表中:

shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

10.6.1 跟上時區修改

當時區被修改的時候,應用程序還是使用老的時區,為了跟上,確定系統使用的時區信息是很有必要的。對於mysql有2個方式可以用於跟上時區:

·           如果時區設置為‘system’那麼操作系統的時區會影響mysql服務的事務。

·           如果實在/ect/localtime時區文件中替換,你就應該重啟mysqld才能更新修改後的時區。

如果使用命名時區,那麼要保證時區表中的數據時最新的。若系統有自己的時區信息,那麼系統的時區信息被更新的時候,要保證mysql內的時區信息也要被更新。mysqld會cache時區信息因此更新後需要重啟服務。如果你要使用命名時區但是不確定有沒有,那麼先查看時區表。

mysql> SELECT COUNT(*) FROM mysql.time_zone_name;

+----------+

| COUNT(*) |

+----------+

|        0 |

+----------+

若不為空那麼說明可以使用命名時區。

檢查是否有夏令時規則:

SELECT CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central');

SELECT CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central');

更新前:

mysql> SELECT CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central');

+------------------------------------------------------------+

| CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central') |

+------------------------------------------------------------+

| 2007-03-11 01:00:00                                        |

+------------------------------------------------------------+

 

mysql> SELECT CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central');

+------------------------------------------------------------+

| CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central') |

+------------------------------------------------------------+

| 2007-03-11 02:00:00                                        |

+------------------------------------------------------------+

更新後:

mysql> SELECT CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central');

+------------------------------------------------------------+

| CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central') |

+------------------------------------------------------------+

| 2007-03-11 01:00:00                                        |

+------------------------------------------------------------+

 

mysql> SELECT CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central');

+------------------------------------------------------------+

| CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central') |

+------------------------------------------------------------+

| 2007-03-11 01:00:00                                        |

+------------------------------------------------------------+

 

10.6.2 時區閏秒支持(Time Zone Leap Seconad Support)

如果出現閏秒(23:59:60)情況會使用59:59。

mysql> CREATE TABLE t1 (

    ->   a INT,

    ->   ts TIMESTAMP DEFAULT NOW(),

    ->   PRIMARY KEY (ts)

    -> );

Query OK, 0 rows affected (0.01 sec)

 

mysql> -- change to UTC

mysql> SET time_zone = '+00:00';

Query OK, 0 rows affected (0.00 sec)

 

mysql> -- Simulate NOW() = '2008-12-31 23:59:59'

mysql> SET timestamp = 1230767999;

Query OK, 0 rows affected (0.00 sec)

 

mysql> INSERT INTO t1 (a) VALUES (1);

Query OK, 1 row affected (0.00 sec)

 

mysql> -- Simulate NOW() = '2008-12-31 23:59:60'

mysql> SET timestamp = 1230768000;

Query OK, 0 rows affected (0.00 sec)

 

mysql> INSERT INTO t1 (a) VALUES (2);

Query OK, 1 row affected (0.00 sec)

 

mysql> -- values differ internally but display the same

mysql> SELECT a, ts, UNIX_TIMESTAMP(ts) FROM t1;

+------+---------------------+--------------------+

| a    | ts                  | UNIX_TIMESTAMP(ts) |

+------+---------------------+--------------------+

|    1 | 2008-12-31 23:59:59 |         1230767999 |

|    2 | 2008-12-31 23:59:59 |         1230768000 |

+------+---------------------+--------------------+

2 rows in set (0.00 sec)

 

mysql> -- only the non-leap value matches

mysql> SELECT * FROM t1 WHERE ts = '2008-12-31 23:59:59';

+------+---------------------+

| a    | ts                  

+------+---------------------+

|    1 | 2008-12-31 23:59:59 |

+------+---------------------+

1 row in set (0.00 sec)

 

mysql> -- the leap value with seconds=60 is invalid

mysql> SELECT * FROM t1 WHERE ts = '2008-12-31 23:59:60';

Empty set, 2 warnings (0.00 sec)

10.7 MySQL Server本地化支持

lc_time_names控制了日期,月份星期的顯示語言,會影響DATA_FORMAT(),DAYNAME(),MONTHNAME()的輸出。但是lc_time_names不影響STR_TO_DATE(),GET_FORMAT()。format雖然不受lc_time_names影響,但是通過傳入參數可以影響結果。

mysql> SET NAMES 'utf8';

Query OK, 0 rows affected (0.09 sec)

 

mysql> SELECT @@lc_time_names;

+-----------------+

| @@lc_time_names |

+-----------------+

| en_US           |

+-----------------+

1 row in set (0.00 sec)

 

mysql> SELECT DAYNAME('2010-01-01'), MONTHNAME('2010-01-01');

+-----------------------+-------------------------+

| DAYNAME('2010-01-01') | MONTHNAME('2010-01-01') |

+-----------------------+-------------------------+

| Friday                | January                 |

+-----------------------+-------------------------+

1 row in set (0.00 sec)

 

mysql> SELECT DATE_FORMAT('2010-01-01','%W %a %M %b');

+-----------------------------------------+

| DATE_FORMAT('2010-01-01','%W %a %M %b') |

+-----------------------------------------+

| Friday Fri January Jan                  |

+-----------------------------------------+

1 row in set (0.00 sec)

 

mysql> SET lc_time_names = 'es_MX';

Query OK, 0 rows affected (0.00 sec)

 

mysql> SELECT @@lc_time_names;

+-----------------+

| @@lc_time_names |

+-----------------+

| es_MX           |

+-----------------+

1 row in set (0.00 sec)

 

mysql>

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved