mysql里面integer默认宽度_MySQL中关于数据类型指定宽度之后的情况
概述
MySQL有很多種數(shù)據(jù)類型,最常用的就是int,char,varchar,這些類型在創(chuàng)建表的時(shí)候都可以指定該字段的寬度,方法是在類型后面加一個(gè)括號(hào),括號(hào)中寫寬度就可以了。
但是,在指定寬度之后,有時(shí)候,我們可以看到插入的數(shù)據(jù)有一些被截?cái)嗔?#xff1b;有一些并沒有截?cái)?#xff0c;而是四舍五入了,甚至什么操作都沒有,原樣插入了。
下面對(duì)于每一種數(shù)據(jù)類型單獨(dú)測(cè)試:
數(shù)字型(int、tinyint...)
mysql> create table t (id int(5));
mysql> insert into t values(1234567),(123),(12345);
mysql> select * from t;
+---------+
| id |
+---------+
| 1234567 |
| 123 |
| 12345 |
+---------+
從上面的例子中可以看到,對(duì)于int而言,雖然指定了寬度,但是當(dāng)插入的數(shù)據(jù)寬度大于指定的寬度時(shí),并不會(huì)截?cái)唷?/p>
其實(shí)對(duì)于int而言,要指定寬度,那么就必定要指定zerofill,但同樣,zerofill只是在寬度不夠的時(shí)候用0填充,但是寬度大于指定寬度時(shí),數(shù)據(jù)仍然不會(huì)被截取。
mysql> create table t (id int(5) zerofill);
mysql> insert into t values(1234567),(123),(12345);
mysql> select * from t;
+---------+
| id |
+---------+
| 1234567 |
| 00123 |
| 12345 |
+---------+
字符串型(char、varchar)
mysql> create table t (fields_1 char(5),fields_2 varchar(5));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into t values("123","123"),("12345","12345"),("1234567","1234567");
Query OK, 3 rows affected, 2 warnings (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 2
mysql> show Warnings;
+---------+------+-----------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------+
| Warning | 1265 | Data truncated for column 'fields_1' at row 3 |
| Warning | 1265 | Data truncated for column 'fields_2' at row 3 |
+---------+------+-----------------------------------------------+
2 rows in set (0.00 sec)
mysql> select fields_1,length(fields_1),fields_2,length(fields_2) from t;
+----------+------------------+----------+------------------+
| fields_1 | length(fields_1) | fields_2 | length(fields_2) |
+----------+------------------+----------+------------------+
| 123 | 3 | 123 | 3 |
| 12345 | 5 | 12345 | 5 |
| 12345 | 5 | 12345 | 5 |
+----------+------------------+----------+------------------+
可以看到,對(duì)于char和varchar,如果制定了寬度,如果要插入的字符串的寬度超過了指定的寬度,則會(huì)截取掉超出的部分。
簡單來說,varchar的可變長度,這個(gè)可變,前提是存入的字符串長度不超過定義該字段時(shí)指定的長度,如果長度超過了指定長度,即使是可變長度字符串類型,數(shù)據(jù)仍會(huì)出現(xiàn)截?cái)唷?/p>
可以簡單記為:可縮不可擴(kuò)。
而固定長度的char類型,在存儲(chǔ)效率比varchar高,但是,會(huì)存在空間浪費(fèi)的情況,所以空間利用率沒有varchar高,而varchar是可變長度的,就意味著,在讀數(shù)據(jù)的時(shí)候,效率沒有char類型高,因?yàn)樵谧x數(shù)據(jù)的時(shí)候要判斷是否讀到結(jié)尾。
拓展1
前面已經(jīng)提到,對(duì)于數(shù)值類型的字段后面的寬度來說,只有在指定zerofill的時(shí)候,后面指定的寬度才有意義,否則,既不會(huì)出現(xiàn)截?cái)?#xff0c;也不會(huì)出現(xiàn)0填充。那么,不會(huì)出現(xiàn)截?cái)?#xff0c;是不是說,向一個(gè)int(5)字段的插入一個(gè)值,這個(gè)值是12345678912345678912345678...(由100位數(shù)字長度),那么還能存進(jìn)去嗎?
看下面示例:
mysql> create table t (id int(5) zerofill);
Query OK, 0 rows affected (0.10 sec)
mysql> insert into t values (9999999999999999999999999999999999999999999);
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> show warnings;
+---------+------+---------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------+
| Warning | 1264 | Out of range value for column 'id' at row 1 |
| Warning | 1264 | Out of range value for column 'id' at row 1 |
+---------+------+---------------------------------------------+
2 rows in set (0.00 sec)
mysql> select * from t;
+------------+
| id |
+------------+
| 4294967295 |
+------------+
1 row in set (0.00 sec)
可以從警告信息和執(zhí)行結(jié)果中看出,當(dāng)嘗試向指定寬度字段插入一個(gè)很大的數(shù)據(jù),大到遠(yuǎn)超該數(shù)據(jù)類型的上限,執(zhí)行雖然會(huì)出現(xiàn)警告,但是,數(shù)據(jù)確實(shí)插入了,只不過存儲(chǔ)的數(shù)據(jù)不是插入的數(shù)據(jù),而是存了一個(gè)該類型的最大值。
所以可以得出結(jié)論:對(duì)一個(gè)數(shù)字類型的字段而言,其數(shù)據(jù)類型已經(jīng)限定了它的數(shù)據(jù)范圍,當(dāng)嘗試插入一個(gè)超過數(shù)據(jù)范圍的值時(shí),會(huì)觸發(fā)警告,同時(shí),存入該數(shù)據(jù)類型的最大值。
拓展2
前面也提到了字符串(char和varchar)后面指定的寬度,這個(gè)寬度就不像數(shù)字類型的寬度了,因?yàn)?#xff0c;如果是字符串類型,那么,一旦超過字符串后面指定的寬度,那么一定會(huì)出現(xiàn)截?cái)唷?/p>
這里有個(gè)問題,字符串后面指定的寬度,比如char(5),varchar(5),這個(gè)5是指5個(gè)字符,還是指5個(gè)字節(jié)呢,或者說是5個(gè)bit(位)呢?
前面的示例中,很顯然看出,這個(gè)5不可能是bit(位),畢竟一個(gè)字節(jié)就有8位,在測(cè)試中,一個(gè)字符都插不進(jìn)去。
那么,要么是5個(gè)字符,或者5個(gè)字節(jié)。可能你會(huì)疑惑,5個(gè)字符和5個(gè)字節(jié)有什么區(qū)別嗎?abc,是3個(gè)字符,同時(shí)也是3個(gè)字節(jié),何必去區(qū)分呢?
那你想一下,咱們的漢字,一個(gè)漢字,經(jīng)過不同的編碼(GBK,GB2312,lantin1,UTF-8,UTF-8mb4)之后,所占的字節(jié)數(shù)是不一定相同的呀。
mysql> create table t (field char(5));
Query OK, 0 rows affected (0.40 sec)
mysql> show create table t\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t` (
`field` char(5) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> insert into t values ('abcde');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values ('中國你好啊');
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> show warnings;
+---------+------+-----------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------------------------------------+
| Warning | 1300 | Invalid utf8 character string: 'D6D0B9' |
| Warning | 1366 | Incorrect string value: '\xD6\xD0\xB9\xFA\xC4\xE3...' for column 'field' at row 1 |
+---------+------+-----------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
從上面的實(shí)例,很明顯可以看出答案,char(5)后面的5,是指的5字節(jié),而不是5個(gè)字符。
可以查看一下,存入的內(nèi)容是什么:
mysql> select * from t;
+-------+
| field |
+-------+
| abcde |
| ????? |
+-------+
2 rows in set (0.03 sec)
mysql> set names utf8;
Query OK, 0 rows affected (0.02 sec)
mysql> select * from t;
+-------+
| field |
+-------+
| abcde |
| ????? |
+-------+
2 rows in set (0.00 sec)
可以看出,后面雖然插入的“中國你好啊”,但是存的時(shí)候,已經(jīng)出現(xiàn)亂碼了,即使強(qiáng)制指定字符集,也是顯示亂碼。
咱們一般使用的都會(huì)utf8或者utf8mb4,可以在創(chuàng)建表格的時(shí)候,指定default charset=utf8。
拓展3
如果一個(gè)漢字使用某種編碼方式(比如utf8),在存儲(chǔ)的時(shí)候占3字節(jié),那么兩個(gè)漢字,就需要6個(gè)字節(jié)來存。
那么,如果char(5)類型的字段,能存入“中國”兩個(gè)字嗎?中國兩個(gè)字編碼之后是6字節(jié)。
首先解決一個(gè)問題:
mysql> create table t ( field char(5)) default charset=utf8;
Query OK, 0 rows affected (0.11 sec)
mysql> insert into t values ('abcde');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values ('中');
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> show warnings;
+---------+------+----------------------------------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------------------------------+
| Warning | 1300 | Invalid utf8 character string: 'D6D0' |
| Warning | 1366 | Incorrect string value: '\xD6\xD0' for column 'field' at row 1 |
+---------+------+----------------------------------------------------------------+
2 rows in set (0.00 sec)
mysql> select * from t;
+-------+
| field |
+-------+
| abcde |
| |
+-------+
2 rows in set (0.00 sec)
mysql> set names utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t;
+-------+
| field |
+-------+
| abcde |
| |
+-------+
2 rows in set (0.00 sec)
可以看到,即使單個(gè)漢字“中”編碼之后3字節(jié)(未超過5字節(jié)范圍,仍舊未存入),這時(shí)可以看一下數(shù)據(jù)庫的字符集:
mysql> show variables like '%char%';
+--------------------------+-----------------------------------+
| Variable_name | Value |
+--------------------------+-----------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | E:\phpStudy\MySQL\share\charsets\ |
+--------------------------+-----------------------------------+
8 rows in set (0.00 sec)
可以看到,character_set_database設(shè)定的還是latin1字符集編碼,可以使用下面的命令修改:
set character_set_database='utf8';
接下來,測(cè)試過程中,即使插入單獨(dú)的一個(gè)漢字,也會(huì)出現(xiàn)警告,并且查看插入的值,只出現(xiàn)一個(gè)?或者一些亂碼,甚至沒有值(空的)。
我嘗試在php中執(zhí)行插入和查看操作:
$mysqli = new Mysqli();
$mysqli->connect("localhost","root","root","test");
$mysqli->set_charset("utf8");
$mysqli->query("truncate table t");
$mysqli->query("insert into t values ('abcde')");
$mysqli->query("insert into t values ('你')");
$mysqli->query("insert into t values ('你好')");
$sql = "select * from t";
$mysqli_result = $mysqli->query($sql);
$res = $mysqli_result->fetch_all();//一次性去的所有數(shù)據(jù)
print_r($res);
執(zhí)行之后,結(jié)果如下:
λ php index.php
Array
(
[0] => Array
(
[0] => abcde
)
[1] => Array
(
[0] => ?
)
[2] => Array
(
[0] => ???
)
)
至于為什么會(huì)這樣,現(xiàn)在還沒找到問題根源。之前好像也沒遇到過這種情況呀,等有時(shí)間在其他機(jī)器上試一下。
總結(jié)
以上是生活随笔為你收集整理的mysql里面integer默认宽度_MySQL中关于数据类型指定宽度之后的情况的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 幽灵交易策略_源码 | 幽灵交易者策略
- 下一篇: java编写流星_纯Java代码实现流星