mysql溢位 MySQL數值型別溢位的處理方法

2021-10-22 09:24:50 字數 3153 閱讀 4862

來,考考大家乙個問題,在 mysql 中當某一列設定為 int(0) 時會發生什麼 ?

為了演示這個問題,我們先要建立乙個表

drop table if exists `na`;

create table `na` (

n1 int(0) not null default '0',

n2 int(11) not null default '0'

然後我們使用下面的語句往 na 表中插入一些資料

mysql> insert into `na` values(520,520),(5201314,5201314);

query ok, 2 rows affected (0.02 sec)

records: 2 duplicates: 0 warnings: 0

最後我們讀取出來看看

mysql> select * from na;

| n1 | n2 |

| 520 | 520 |

| 5201314 | 5201314 |

2 rows in set (0.00 sec)

對的,好像什麼都不會發生,沒什麼問題才是對的,我就怕有什麼問題…哈哈

我們這一章節來講講整型溢位問題。

mysql 數值型別溢位處理

當 mysql 在某個數值列上儲存超出列資料型別允許範圍的值時,結果取決於當時生效的 sql 模式

如果啟用了嚴格的 sql 模式,則 mysql 會根據 sql 標準拒絕帶有錯誤的超出範圍的值,並且插入失敗

如果沒有啟用任何限制模式,那麼 mysql 會將值裁剪到列資料型別範圍的上下限值並儲存

當超出範圍的值分配給整數列時,mysql 會儲存表示列資料型別範圍的相應端點的值

當為浮點或定點列分配的值超出指定(或缺省)精度和比例所隱含的範圍時,mysql 會儲存表示該範圍的相應端點的值

這個,應該很好理解吧?

我們舉乙個例子,假設 t1 表的結構如下

create table t1 (

i1 tinyint,

i2 tinyint unsigned

如果啟用了嚴格的 sql 模式,超出範圍會發生乙個錯誤

mysql> set sql_mode = 'traditional'; -- 首先設定嚴格模式

mysql> insert into t1 (i1, i2) values(256, 256);

error 1264 (22003): out of range value for column 'i1' at row 1

mysql> select * from t1;

empty set (0.00 sec)

當嚴格模式被禁用,值可以插入,但會被裁剪,並且引發乙個警告

mysql> set sql_mode = ''; -- 禁用所有模式

mysql> insert into t1 (i1, i2) values(256, 256);

mysql> show warnings;

| level | code | message |

| warning | 1264 | out of range value for column 'i1' at row 1 |

| warning | 1264 | out of range value for column 'i2' at row 1 |

mysql> select * from t1;

| i1 | i2 |

| 127 | 255 |

如果未啟用嚴格 sql 模式,對於 alter table,load data infile,update 和多行 insert等語句會由於裁剪而發生的列分配轉換並且引發乙個警告。

而如果啟用了嚴格模式,這些語句會直接失敗,並且未插入或更改部分或全部值,具體取決於表是否為事務表和其他因素。

數值表示式求值過程中的溢位會導致錯誤,例如,因為最大的有符號 bigint 值是 9223372036854775807,因此以下表示式會產生錯誤

mysql> select 9223372036854775807 + 1;

error 1690 (22003): bigint value is out of range in '(9223372036854775807 + 1)'

為了在這種情況下使操作成功,需要將值轉換為 unsigned

mysql> select cast(9223372036854775807 as unsigned) + 1;

| cast(9223372036854775807 as unsigned) + 1 |

| 9223372036854775808 |

從另一方面說,是否發生溢位取決於運算元的範圍,因此處理前乙個表示式的另一種方法是使用精確值算術,因為 decimal 值的範圍大於整數

mysql> select 9223372036854775807.0 + 1;

| 9223372036854775807.0 + 1 |

| 9223372036854775808.0 |

整數數值之間的減去,如果其中乙個型別為 unsigned ,預設情況下會生成無符號結果。如果為負,則會引發錯誤

mysql> set sql_mode = '';

query ok, 0 rows affected (0.00 sec)

mysql> select cast(0 as unsigned) - 1;

error 1690 (22003): bigint unsigned value is out of range in '(cast(0 as unsigned) - 1)'

這種情況下,如果啟用了 no_unsigned_subtraction sql 模式,則結果為負

mysql> set sql_mode = 'no_unsigned_subtraction';

mysql> select cast(0 as unsigned) - 1;

| cast(0 as unsigned) - 1 |

| -1 |

如果此類操作的結果用於更新 unsigned 整數列,則結果將裁剪為列型別的最大值,如果啟用了 no_unsigned_subtraction 則裁剪為 0。但如果啟用了嚴格的 sql 模式,則會發生錯誤並且列保持不變。

後記一切都是套路,套路….基本都和 sql 模式有關…

總結

mySQL什麼是數字數值 MySQL數值型別

mysql數值型別 mysql支援所有標準的sql數值資料型別。這些型別包括數值資料型別integer smallint decimal numeric和近似數值資料型別float real double precision。其中關鍵字int是integer的同義詞,關鍵字dec是decimal的同...

mysql溢位 MySQL 行溢位資料

mysql 行溢位資料 mysql 對一條記錄占用的最大儲存空間是有限制的,除了 blob 和 text 型別之外,其他所有列 不包括隱藏列和記錄頭資訊 占用的位元組長度不能超過 65535 個位元組,當記錄長度超過限制時,mysql 會建議使用 text 或 blob 型別 儲存資料 儲存上限 6...

mysql防止記憶體溢位 mysql記憶體溢位處理

主庫實列發生oom,例項程序由於占用記憶體達到linux系統的最大閾值,導致linux系統kill了mysql例項程序,可以通過如下方式檢視mysql使用了多少記憶體 檢視每個執行緒占用多少記憶體,然後乘以正在執行的執行緒 也就是排查sleep的 select read buffer size re...