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 SETCOLLATION 只是 默认值 用于当您 CREATE TABLE 没有指定它们时。

同样,为 table 指定的 CHARACTER SETCOLLATION 仅为列的 默认值

要更改给定列的 COLLATION,您需要使用 ALTER TABLE ... MODIFY COLUMN ...

要更改默认值,可以在数据库上使用ALTER或table;但这只会影响 未来 table 或列。

另一个问题...任何存储例程的 CHARACTER SETCOLLATION 都是在声明例程时定义的。要更改其中一个或两个,您必须 DROPreCREATE 例程。

展望未来,utf8mb4 是主要 CHARACTER SET 使用。 ucs2(以及大多数其他字符集)几乎不应该被使用。如果你能发现 "ucs2" 的起源,请将其铲除。