MySQLdecimalunsigned更新负数不报错却为0今天在验证接⼝的并发问题时,把之前通过 redis 解决的并发压⼒转移到 mysql 上(redis 在 set 保存数据和数据过期需要去向数据库获
取时存在时延,会存在空挡造成⼤并发多插⼊数据的风险;由于有负载均衡,PHP 的信号量也⽆法⽤上,只好利⽤ mysql 的update 来解决并发,设置索引后速度也不慢,只是会承受压⼒)。发现在 update ⼀个字段(属性为 decimal unsigned),填⼊负值不会报错,会⾃动转化为 0。搜索了很久,是 myf 中 STRICT_TRANS_TABLES 搞的⿁。
这时需要先了解 sql_mode 。
MySQL服务器可以以不同的SQL模式来操作,并且可以为不同客户端应⽤不同模式。这样每个应⽤程序可以根据⾃⼰的需求来定制服务器的操作模式。模式定义MySQL应⽀持哪些SQL语法,以及应执⾏哪种数据验证检查。这样可以更容易地在不同的环境中使⽤MySQL,并结合其它数据库服务器使⽤MySQL。你可以⽤--sql-mode="modes"选项启动 mysqld 来设置默认SQL模式。如果你想要重设,该值还可以为空(--sql-mode ="")。你还可以在启动后⽤SET [SESSION|GLOBAL] sql_mode='modes' 语句设置sql_mode变量来更改SQL模式。设
置 GLOBAL变量时需要拥有SUPER权限,并且会影响从那时起连接的所有客户端的操作。设置SESSION变量只影响当前的客户端。任何客户端可以随时更改⾃⼰的会话 sql_mode值。
sql_mode 是⽤逗号(',')间隔开的⼀系列不同的模式。你可以⽤SELECT @@sql_mode语句查询当前的模式。默认值是空(没有设置任何模式)。
主要重要sql_mode值为:
  ANSI
  更改语法和⾏为,使其更符合标准SQL。
  STRICT_TRANS_TABLES
  如果不能将给定的值插⼊到事务表中,则放弃该语句。对于⾮事务表,如果值出现在单⾏语句或多⾏语句的第1⾏,则放弃该语句。
  TRADITIONAL
  Make MySQL的⾏为象“传统”SQL数据库系统。该模式的简单描述是当在列中插⼊不正确的值时“给出错误⽽不是警告”。注释:⼀旦发现错误⽴即放弃INSERT/UPDATE。如果你使⽤⾮事务存储引擎,这种⽅式不是你想要的,因为出现错误前进⾏的数据更改不会“滚动”,结果是更新“只进⾏了⼀部分”。
  本⼿册指“严格模式”,表⽰⾄少STRICT _TRANS_TABLES或STRICT _ALL_TABLES被启⽤的模式。
  以下是 STRICT_TRANS_TABLES 和 STRICT_ALL_TABLES 两种模式的区别:
  对于事务表,当启⽤STRICT_ALL_TABLES或STRICT_TRANS_TABLES模式时,如果语句中有⾮法或丢失值,则会出现错误。语句被放弃并滚动。
  对于⾮事务表,如果插⼊或更新的第1⾏出现坏值,两种模式的⾏为相同。语句被放弃,表保持不变。如果语句插⼊或修改多⾏,并且坏值出现在第2或后⾯的⾏,结果取决于启⽤了哪个严格选项:
  对于STRICT_ALL_TABLES,MySQL返回错误并忽视剩余的⾏。但是,在这种情况下,前⾯的⾏已经被插⼊或更新。这说明你可以部分更新,这可能不是你想要的。要避免这点,最好使⽤单⾏语句,因为这样可以不更改表即可以放弃。对于
STRICT_TRANS_TABLES,MySQL将⾮法值转换为最接近该列的合法值并插⼊调整后的值。如果值丢失,MySQL在列中插⼊隐式默认值。在任何情况下,MySQL都会⽣成警告⽽不是给出错误并继续执⾏语句。
  其他模式还有:
  ALLOW_INVALID_DATES:不完全对⽇期合法性作检查,只检查⽉份是否在1~12,⽇期是否在1~31之间;仅对DATE和DATETIME 有效,⽽对TIMESTAMP⽆效,因为TIMESTAMP总要求⼀个合法的输⼊。
  ANSI_QUOTES:启⽤后,不能⽤双引号来引⽤字符串,因为"(双引号)将被解释为标识符
  ERROR_FOR_DIVISION_BY_ZERO:启⽤后,在insert或update过程中,若数据被零除(或MOD(x,0),则产⽣错误,若未启⽤,则产⽣警告,数据被零除时系统返回NULL。
  HIGH_NOT_PRECEDENCE:启⽤后,可获得以前旧版本的优先级:
  NO_AUTO_CREATE_USER:禁⽌GRANT创建密码为空的⽤户。
  NO_AUTO_VALUE_ON_ZERO:在⾃增长的列中插⼊0或NULL将不会是下⼀个⾃增长值。
  NO_BACKSLASH_ESCAPES:反斜杠"\"作为普通字符⽽⾮转义字符
  NO_DIR_IN_CREATE:在创建表时忽略所有index directory和data directory的选项。
  NO_ENGINE_SUBSTITUTION:启⽤后,若需要的存储引擎被禁⽤或未编译,则抛出错误;未启⽤时将⽤默认的存储引擎代替,并抛出⼀个异常。
  NO_UNSIGNED_SUBSTRACTION:启⽤后,两个UNSIGNED类型相减返回SIGNED类型。
  NO_ZERO_DATE:启⽤后,不允许插⼊“0000-00-00 00:00:00”形如此类的零⽇期,这将抛出⼀个错误,若未启⽤,则可插⼊但仅会抛出⼀个警告。
  NO_ZERO_IN_DATE:启⽤后,不允许⽉份和⽇期为零,和 NO_ZERO_DATE⼀起启⽤,如“1999-01-00”将抛出错误⽽⾮警告。若单独启⽤本项,则会抛出warning,然后插⼊如“0000-00-00 00:00:00”。
  ONLY_FULL_GROUP_BY:对于GROUP BY聚合操作,若select中的列没有在group by中出现,那么这句SQL是不合法的。
  PAD_CHAR_TO_FULL_LENGTH:启⽤后,对于CHAR类型将不会截断空洞数据;
oracle decimal类型
  PIPES_AS_CONCAT:将"||"视为连接操作符⽽⾮“或运算符”。
  REAL_AS_FLOAT:将REAL视为FLOAT的同义词⽽⾮DOUBLE的同义词。
  组合选项:
  ·ANSI:
  REAL_AS_FLOAT、PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、ANSI
  ·ORACLE:
  PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、
NO_FIELD_OPTIONS、NO_AUTO_CREATE_USER、ORACLE
  ·TRADITIONAL:
  STRICT_TRANS_TABLES、STRICT_ALL_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、
ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER、NO_ENGINE_SUBSTITUTION、TRADITIONAL
  ·MSSQL:
  PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、MSSQL、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、
NO_FIELD_OPTIONS、MSSQL
  ·DB2:
  PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、
NO_FIELD_OPTIONS、DB2
  ·MYSQL323:
  HIGH_NOT_PRECEDENCE、MYSQL323
  ·MYSQL40:
  HIGH_NOT_PRECEDENCE、MYSQL40
  ·MAXDB:
  PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、
NO_FIELD_OPTIONS、NO_AUTO_CREATE_USER、MAXDB

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。