作者 主題: MySQL超出欄位長度後仍能儲存  (閱讀 15889 次)

0 會員 與 1 訪客 正在閱讀本文。

yes298

  • 活潑的大學生
  • ***
  • 文章數: 380
    • 檢視個人資料
MySQL超出欄位長度後仍能儲存
« 於: 2006-07-08 16:33 »
我在FC5下的MySQL有個database, 其中一欄位的定義如下:

`subject` varchar(20) collate utf8_unicode_ci default NULL,

奇怪的是, 我在subject欄位輸入80個中文字,很明顯已超出以上的定義,但它仍能儲存入DB中而無任何警告! 這是為何呢?

asako

  • 活潑的大學生
  • ***
  • 文章數: 227
    • 檢視個人資料
MySQL超出欄位長度後仍能儲存
« 回覆 #1 於: 2006-07-09 12:21 »
超出的會截掉,很多的 db 都是這樣的,也不會警告。

Yamaka

  • 俺是博士!
  • *****
  • 文章數: 4913
    • 檢視個人資料
    • http://www.ecmagic.com
MySQL超出欄位長度後仍能儲存
« 回覆 #2 於: 2006-07-10 16:53 »
引述: "asako"
超出的會截掉,很多的 db 都是這樣的,也不會警告。


而且....

如果中文字碼後面被切掉,
然後顯示在網頁上的話,
會影響到版面的顯示,

例如,
一些 TAG 可能就無法正常處理~~

asako

  • 活潑的大學生
  • ***
  • 文章數: 227
    • 檢視個人資料
MySQL超出欄位長度後仍能儲存
« 回覆 #3 於: 2006-07-11 07:24 »
剛我自已試了一下,
把table 設成 utf8
然後隨便開個欄位 id varchar 10
存進 中文1許功一二三
結果mysql 會存 『中文1許功』 沒有字被切掉的問題

我用的是mysql 4.1.20 win32


至於 TAG 的話,那就只能放大欄位了。不然就在網頁上設限。

yes298

  • 活潑的大學生
  • ***
  • 文章數: 380
    • 檢視個人資料
MySQL超出欄位長度後仍能儲存
« 回覆 #4 於: 2006-07-12 08:39 »
對呀, 我奇怪的就是沒有任何字被截斷了,而是完完整地儲存入DB, 取出來亦沒有少任何一個字.

誰知道為何會如此呢?

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5384
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
MySQL超出欄位長度後仍能儲存
« 回覆 #5 於: 2006-07-12 10:43 »
http://dev.mysql.com/doc/refman/5.0/en/charset-unicode.html
因為你的 table 用的是 utf-8, 那個字串只有 5 個 utf-8 字元.

varchar 或 char 對於 utf-8 是一個字元用三個 byte 來存.

yes298

  • 活潑的大學生
  • ***
  • 文章數: 380
    • 檢視個人資料
MySQL超出欄位長度後仍能儲存
« 回覆 #6 於: 2006-07-13 19:27 »
這樣看來,只要將欄位定義為UTF8, MySQL會自動增大欄位長度,存放所有字串, 即是說此時不會去理該欄位所定義的長度了, 只要不超過該Field type的最大限制就可以了, 比如: MySQL的varchar,最大允許255個字元,只要輸入的中文字不超過85(255除3),不用理定義該欄位的長度,即不會出現警告信息吧~

Darkhero

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 3728
  • 性別: 男
    • 檢視個人資料
    • ㄚ凱隨手紀
MySQL超出欄位長度後仍能儲存
« 回覆 #7 於: 2006-07-13 20:03 »
引述: "yes298"
這樣看來,只要將欄位定義為UTF8, MySQL會自動增大欄位長度,存放所有字串, 即是說此時不會去理該欄位所定義的長度了, 只要不超過該Field type的最大限制就可以了, 比如: MySQL的varchar,最大允許255個字元,只要輸入的中文字不超過85(255除3),不用理定義該欄位的長度,即不會出現警告信息吧~


似乎不是這樣?...

你試試看塞資料進去看看,我測試的話, mysql 5.0 , varchar 255 , 可以塞入 255 個中文字, 或是 255 個英文字母...

或許應該是說 varchar or char 都是以字為單為,一個字母或是一個中文字。
在 utf8 中 一個 "1"  跟 一個"一" ,同樣都代表一個字,只是所用來對應用的 byte 長度是不一樣的...一個是 1 byte 一個是用 3 byte 去對應.

你可以在 test 資料庫中測試下面的資料..
代碼: [選擇]

CREATE TABLE `test` (
  `test` varchar(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

--
-- 列出以下資料庫的數據: `test`
--

INSERT INTO `test` (`test`) VALUES ('123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345');
INSERT INTO `test` (`test`) VALUES ('一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五六七八九零一二三四五');
INSERT INTO `test` (`test`) VALUES ('1234567890');
INSERT INTO `test` (`test`) VALUES ('一二三四五六七八九零');
INSERT INTO `test` (`test`) VALUES ('1二3四5六7八9零');



然後執行語法:
代碼: [選擇]
SELECT test,length(test),CHAR_LENGTH(test) FROM `test`

你就會發現,MySQL除了字元長度以外,也算字數,而 varchar , char 算的是字數,不是佔用的byte數
希望我們的討論是為了把問題解決,而不是爭論誰對誰錯.
『灌水才是重點,發文只是順便』
『我寧可讓不會釣魚的工程師餓死,也不想讓會餓死的工程師去攪沉公司....』
Blog: http://blog.darkhero.net/
秘密基地: http://www.darkhero.net/comic/
目前服務的網站: http://www.libook.com.tw/

Darkhero

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 3728
  • 性別: 男
    • 檢視個人資料
    • ㄚ凱隨手紀
MySQL超出欄位長度後仍能儲存
« 回覆 #8 於: 2006-07-13 20:14 »
更重要的是...
當你使用 mysql 4.1 以上的時候,若是使用了 string 類的函式,要注意用的是字數不是byte...

例如 LEFT , MID 等....
以前可能會有為了取出姓的時候用 left(name,2); 取出最左邊兩個byte ,這是因為mysql 4.0 之前都是用英文再看所有的編碼語系。

但在 4.1 以上應該改成 left(name,1), 也就是取出最左邊第一個"字".
希望我們的討論是為了把問題解決,而不是爭論誰對誰錯.
『灌水才是重點,發文只是順便』
『我寧可讓不會釣魚的工程師餓死,也不想讓會餓死的工程師去攪沉公司....』
Blog: http://blog.darkhero.net/
秘密基地: http://www.darkhero.net/comic/
目前服務的網站: http://www.libook.com.tw/