配置sql-mode
在oracle或sqlserver中,如果某个表的字段设置成not null,insert或update时不给这个字段赋值。必然报错,这是天经地义的事情,但是在mysql中这是有可能成功。再比如表中设置了declare类型,但如果你插入了字符串'abc',不但不会报错并且会自动变成0...
其实具体取决于sql_mode的设置:
SELECT @@sql_mode
大概上讲,sql_mode可以分为二大类:
一类是所谓的宽松无敌模式(my.ini中sql_mode设置为空或仅NO_ENGINE_SUBSTITUTION), 这种模式下,not null 的字段,在insert或update时不设置值也能成功,db在插入时,会自动给默认值,比如int会给0值,甚至可以把abc赋值给int型的字段(当然,db会自动忽略该值,变成默认值0)
另一类的是所谓的严格模式(具体有很多可选值),设置成严格模式后,mysql就跟传统的oracle、sqlserver表现一致了,这也是我个人强烈推荐的模式。
最后,无耻的从网上抄一段贴在这里备份:
如果使用mysql,为了继续保留大家使用oracle的习惯,可以对mysql的sql_mode设置如下:
在my.cnf添加如下配置
[mysqld]
sql_mode='ONLY_FULL_GROUP_BY,NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE, RROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PIPES_AS_CONCAT,ANSI_QUOTES'
如果是window下phpstudy为例,找到/phpstudy/mysql/my.ini,找打sql-mode
sql-mode="ONLY_FULL_GROUP_BY,NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PIPES_AS_CONCAT,ANSI_QUOTES"
配置成功后记得重启mysql服务。
异常捕获处理与事务回滚
DROP PROCEDURE IF EXISTS `sp_sql_error`;
CREATE DEFINER = `root`@`localhost` PROCEDURE `sp_sql_error`()
BEGIN
DECLARE err INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET err = 1;
# 开启事务
START TRANSACTION;
# 类型错误
INSERT INTO user_balance(user_id, user_money) VALUES (4, 'abc');
# 正确执行
INSERT INTO user_balance(user_id, user_money) VALUES (3, 10);
# 如果发生了错误,那么就回滚,否则提交。
IF err = 1 THEN
SELECT '报错了' AS result;
ROLLBACK;
ELSE
COMMIT;
END IF;
END;