MySQL 的大小写在 drop 或 create 触发器时的不同影响
一, 问题
今天用脚本更新 MySQL 的一个触发器时, 出现了极为奇怪的现象:MySQL>source crt_xxx_trigger.sql
ERROR1360(HY000):Triggerdoesnotexist
ERROR1359(HY000):Triggeralready exists
检查脚本, 确认触发器名完全一样(包括大小写):DROP TRIGGER IF EXISTS tr_yyy_ains//
CREATE TRIGGER tr_yyy_ains AFTER INSERT
ON zzz FOR EACH ROW
BEGIN
...
END;
当然了, 如果触发器名不一样, 执行时只会报一个错, 或者 drop 时报 not exists 或者 create 时报 already exists, 但现在两个错误同时出现, 问题出在哪里?
二, 解决
在排除其它原因后, 联想到是否因为大小写的原因. 检查 triggers 系统表:MySQL>selecttrigger_namefrominfoemation_schema.triggerswhereevent_object_table='zzz';
+--------------------------------+
|TRIGGER_NAME|
+--------------------------------+
|TR_YYY_INS|
|...|
修改脚本, 将 drop 语句的触发器名改为全大写的 TR_YYY_INS, 再次执行脚本, OK!
回想起来, 脚本在从 Oracle 移植到 MySQL 的过程中, 由最初的全大写 (初次创建时) 改成了后来的全小写, 因而出现了这个问题.
三, 讨论
问题虽然得以解决, 但觉得其中有问题: 为什么 drop trigger 时大小写敏感, 但 create 时又不再区分大小写. 区别对待的原因究竟是什么?
MySQL 运行在 Windows, 按官方说法已经是大小写不敏感, 而在 my.INI 中也设置了大小写不敏感的 lower_case_table_names = 1, 但从结果看只对表名有效, 而对触发器只是部分有效.
也许这可以算作 MySQL 的一个 bug?
关于 MySQL 的大小写敏感
由于 MySQL 的数据库直接对应着数据目录, 而表, 触发器则对应着目录下的文件, 因此 MySQL 的标识符是否大小写敏感不仅与所在操作系统相关, 也与是哪种对象相关.
缺省情况下, MySQL 的大小写敏感是这样的:
字段名, 字段别名, 索引名, 存储过程名......, 只要不涉及目录和文件, 任何平台都不分大小写;
Windows 平台, 数据库名, 表名, 表别名, 触发器名等, 也不分大小写;
Unix, Linux 平台, 数据库名, 表名, 表别名, 触发器名等, 就要区分大小写了;
日志文件组名, 又是区分大小写的, 这个一般情况下没多少人关注;
变量名严格区分大小写.
为了防止出现相同的代码在不同平台出现异常的情况, 通常有两种方法:
涉及到数据库, 表, 触发器的语句, 一律用小写;
在 my.INI 的 [mysqld] 段, 加上 "lower_case_table_names=1".
一旦这样做后, 在使用 JDBC 的接口 (比如 ResultSetMetaData.getColumnName()) 时, 返回结果也均为小写.
顺便说说其他数据库的情况:
Oracle: 默认是大小写不敏感, 表名, 字段名等不区分大小写, 小写字母会自动转换为大写字母, 需要用小写字母时需要使用双引号.
PostgreSQL: 默认是大小写不敏感, 表名, 字段名等不区分大小写, 大写字母会自动转换为小写字母(正好与 Oracle 相反), 需要用大写字母时需要使用双引号.
SQLServer: 默认是大小写不敏感; 可以通过修改排序规则改变.
来源: http://www.linuxidc.com/Linux/2019-07/159604.htm