MariaDB 不会更改数据库的排序规则
MariaDB will not change the collation for a database
我已经在 Whosebug 上研究了这个问题超过 24 小时,并决定在其他地方没有涉及到这个问题,尽管有很多关于同一主题的问答。
我在 MariaDB 10.1 上使用 HeidiSQL 9.3,遇到一个奇怪的问题如下:我最初在创建数据库时接受默认排序规则,然后意识到这不是我想要的,并尝试用
ALTER DATABASE InternalFulfillment CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
这没有效果,数据库仍然报告为 ucs2_bin
,所有过程和函数也都是 ucs2_bin
。我尝试了在 Whosebug 上可以找到的所有问答中的所有建议,包括这些陈述:
SET collation_connection = 'utf8mb4_unicode_ci';
SET NAMES 'utf8mb4';
SET CHARACTER SET 'utf8mb4';
当我删除并重新创建过程时,它们仍然以 ucs2_bin
.
的形式返回
最奇怪的是,如果我删除并重新创建名称为 'InternalFulfilment' 的数据库,排序规则是错误的,但如果我创建一个具有不同名称的数据库,那么我会得到我想要的排序规则,并且 运行ning 创建存储过程的脚本使用 utf8mb4_unicode_ci
排序规则创建过程。
似乎 MariaDB and/or HeidiSQL 记住了我第一次创建 'InternalFulfillment' 数据库时使用的原始排序规则,并且每当我创建数据库时总是使用 ucs2_bin
排序规则这个名字。
有没有人知道这可能存储在哪里,以便我可以清除它。谢谢。
阅读以下答案后的补充评论
在一夜之间离开后,第二天早上我能够使用不同的排序规则删除并重新创建数据库,但现在它停留在新的排序规则上。
根据@Anse 的回答:
DROP DATABASE IF EXISTS `InternalFulfillment`;
CREATE DATABASE `InternalFulfillment` /*!40100 COLLATE 'ucs2_bin' */;
USE `InternalFulfillment`;
CREATE TABLE `table1` (
`column1` VARCHAR(50) NULL
)
COLLATE='ucs2_bin'
ENGINE=InnoDB;
DELIMITER //
CREATE DEFINER=`root`@`%` PROCEDURE `proc1`(IN `param1` VARCHAR(50))
DETERMINISTIC
BEGIN
SELECT
column1
FROM
table1 t
WHERE
t.column1 = param1;
END//
DELIMITER ;
CALL proc1('test');
产生:/* SQL Error (1267): Illegal mix of collations (ucs2_bin,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for operation '=' */
。如果我用 utf8mb4_general_ci
重新 运行 这个脚本然后它完成没有错误。
昨天我的数据库卡在了ucs2_bin
,今天卡在了utf8mb4_general_ci
,所以有一些东西被缓存了相当长的有效期。
MariaDB 中似乎有一些排序缓存。我是 HeidiSQL 的作者,我很确定 HeidiSQL 本身没有这样的排序缓存东西,所以它一定是 MySQL and/or MariaDB 问题。
但是,我只是试图在本地 Windows 的 MySQL v5.7.9 服务器上重现该问题,但没有成功:
CREATE DATABASE `InternalFulfillment` /*!40100 COLLATE 'ucs2_bin' */;
CREATE TABLE `table1` (
`Column 1` VARCHAR(50) NULL
)
COLLATE='ucs2_bin'
ENGINE=InnoDB;
数据库和表 1 都具有 ucs2_bin
排序规则,正如预期的那样。
ALTER DATABASE `internalfulfillment` COLLATE 'utf8mb4_general_ci';
CREATE TABLE `table2` (
`Column 1` VARCHAR(50) NULL
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB;
现在,数据库和新创建的 table2 报告更改的排序规则,如预期的那样:
SELECT `DEFAULT_COLLATION_NAME` FROM `information_schema`.`SCHEMATA`
WHERE `SCHEMA_NAME`='internalfulfillment';
>> utf8mb4_general_ci
SELECT TABLE_NAME, TABLE_COLLATION FROM `information_schema`.`TABLES`
WHERE TABLE_SCHEMA='internalfulfillment';
TABLE_NAME | TABLE_COLLATION
table1 | ucs2_bin
table2 | utf8mb4_general_ci
所以,我的猜测是您遇到了 MariaDB 中的错误。
检查这些:
SHOW VARIABLES LIKE 'char%'; -- If anything say 'ucs2...', you should change it
SHOW CREATE DATABASE ...; -- The /*!40100 */ 'comment' is for hiding the clause for old versions.
SHOW CREATE PROCEDURE ...\G
一些基础知识(您似乎已经了解):
数据库上的 CHARACTER SET
和 COLLATION
只是 默认值 用于当您 CREATE TABLE
没有指定它们时。
同样,为 table 指定的 CHARACTER SET
和 COLLATION
仅为列的 默认值 。
要更改给定列的 COLLATION
,您需要使用 ALTER TABLE ... MODIFY COLUMN ...
。
要更改默认值,可以在数据库上使用ALTER
或table;但这只会影响 未来 table 或列。
另一个问题...任何存储例程的 CHARACTER SET
和 COLLATION
都是在声明例程时定义的。要更改其中一个或两个,您必须 DROP
和 reCREATE
例程。
展望未来,utf8mb4
是主要 CHARACTER SET
使用。 ucs2
(以及大多数其他字符集)几乎不应该被使用。如果你能发现 "ucs2" 的起源,请将其铲除。
我已经在 Whosebug 上研究了这个问题超过 24 小时,并决定在其他地方没有涉及到这个问题,尽管有很多关于同一主题的问答。
我在 MariaDB 10.1 上使用 HeidiSQL 9.3,遇到一个奇怪的问题如下:我最初在创建数据库时接受默认排序规则,然后意识到这不是我想要的,并尝试用
ALTER DATABASE InternalFulfillment CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
这没有效果,数据库仍然报告为 ucs2_bin
,所有过程和函数也都是 ucs2_bin
。我尝试了在 Whosebug 上可以找到的所有问答中的所有建议,包括这些陈述:
SET collation_connection = 'utf8mb4_unicode_ci';
SET NAMES 'utf8mb4';
SET CHARACTER SET 'utf8mb4';
当我删除并重新创建过程时,它们仍然以 ucs2_bin
.
最奇怪的是,如果我删除并重新创建名称为 'InternalFulfilment' 的数据库,排序规则是错误的,但如果我创建一个具有不同名称的数据库,那么我会得到我想要的排序规则,并且 运行ning 创建存储过程的脚本使用 utf8mb4_unicode_ci
排序规则创建过程。
似乎 MariaDB and/or HeidiSQL 记住了我第一次创建 'InternalFulfillment' 数据库时使用的原始排序规则,并且每当我创建数据库时总是使用 ucs2_bin
排序规则这个名字。
有没有人知道这可能存储在哪里,以便我可以清除它。谢谢。
阅读以下答案后的补充评论
在一夜之间离开后,第二天早上我能够使用不同的排序规则删除并重新创建数据库,但现在它停留在新的排序规则上。
根据@Anse 的回答:
DROP DATABASE IF EXISTS `InternalFulfillment`;
CREATE DATABASE `InternalFulfillment` /*!40100 COLLATE 'ucs2_bin' */;
USE `InternalFulfillment`;
CREATE TABLE `table1` (
`column1` VARCHAR(50) NULL
)
COLLATE='ucs2_bin'
ENGINE=InnoDB;
DELIMITER //
CREATE DEFINER=`root`@`%` PROCEDURE `proc1`(IN `param1` VARCHAR(50))
DETERMINISTIC
BEGIN
SELECT
column1
FROM
table1 t
WHERE
t.column1 = param1;
END//
DELIMITER ;
CALL proc1('test');
产生:/* SQL Error (1267): Illegal mix of collations (ucs2_bin,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for operation '=' */
。如果我用 utf8mb4_general_ci
重新 运行 这个脚本然后它完成没有错误。
昨天我的数据库卡在了ucs2_bin
,今天卡在了utf8mb4_general_ci
,所以有一些东西被缓存了相当长的有效期。
MariaDB 中似乎有一些排序缓存。我是 HeidiSQL 的作者,我很确定 HeidiSQL 本身没有这样的排序缓存东西,所以它一定是 MySQL and/or MariaDB 问题。
但是,我只是试图在本地 Windows 的 MySQL v5.7.9 服务器上重现该问题,但没有成功:
CREATE DATABASE `InternalFulfillment` /*!40100 COLLATE 'ucs2_bin' */;
CREATE TABLE `table1` (
`Column 1` VARCHAR(50) NULL
)
COLLATE='ucs2_bin'
ENGINE=InnoDB;
数据库和表 1 都具有 ucs2_bin
排序规则,正如预期的那样。
ALTER DATABASE `internalfulfillment` COLLATE 'utf8mb4_general_ci';
CREATE TABLE `table2` (
`Column 1` VARCHAR(50) NULL
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB;
现在,数据库和新创建的 table2 报告更改的排序规则,如预期的那样:
SELECT `DEFAULT_COLLATION_NAME` FROM `information_schema`.`SCHEMATA`
WHERE `SCHEMA_NAME`='internalfulfillment';
>> utf8mb4_general_ci
SELECT TABLE_NAME, TABLE_COLLATION FROM `information_schema`.`TABLES`
WHERE TABLE_SCHEMA='internalfulfillment';
TABLE_NAME | TABLE_COLLATION
table1 | ucs2_bin
table2 | utf8mb4_general_ci
所以,我的猜测是您遇到了 MariaDB 中的错误。
检查这些:
SHOW VARIABLES LIKE 'char%'; -- If anything say 'ucs2...', you should change it
SHOW CREATE DATABASE ...; -- The /*!40100 */ 'comment' is for hiding the clause for old versions.
SHOW CREATE PROCEDURE ...\G
一些基础知识(您似乎已经了解):
数据库上的 CHARACTER SET
和 COLLATION
只是 默认值 用于当您 CREATE TABLE
没有指定它们时。
同样,为 table 指定的 CHARACTER SET
和 COLLATION
仅为列的 默认值 。
要更改给定列的 COLLATION
,您需要使用 ALTER TABLE ... MODIFY COLUMN ...
。
要更改默认值,可以在数据库上使用ALTER
或table;但这只会影响 未来 table 或列。
另一个问题...任何存储例程的 CHARACTER SET
和 COLLATION
都是在声明例程时定义的。要更改其中一个或两个,您必须 DROP
和 reCREATE
例程。
展望未来,utf8mb4
是主要 CHARACTER SET
使用。 ucs2
(以及大多数其他字符集)几乎不应该被使用。如果你能发现 "ucs2" 的起源,请将其铲除。