【问题标题】:How do I specify collation when creating a table from select in mysql?从mysql中的select创建表时如何指定排序规则?
【发布时间】:2018-02-21 13:47:11
【问题描述】:

当使用从选择结果中动态创建和定义的列创建表时,如何像创建具有列定义的表时那样指定排序规则?

CREATE TABLE IF NOT EXISTS my_table (
  SELECT * FROM (
    SELECT ....
  ) )

上面创建的动态列很好,但它没有使用我想要的排序规则。它使用的是 utf8_general_ci,我希望它是 utf8_unicode_ci。

下面这个不行

CREATE TABLE IF NOT EXISTS my_table (
  SELECT * FROM (
    SELECT ....
  ) ) DEFAULT CHARSET=utf8 DEFAULT COLLATE utf8_unicode_ci;

它给出的错误信息表明命令在这个位置是无效的。

我意识到上述建议是无效的,那么实现这一点的方法是什么?我尝试设置数据库排序规则,认为这是为所有创建的表设置数据库的默认值,但它的行为似乎不像那样 - 或 当我ALTER 数据库排序规则时,也许我实际上并没有为数据库设置默认值。有没有办法为表设置默认值,以便上面的第一个代码块使用所需的排序规则创建表?

上述代码块中的SELECT...结果指的是使用case/when语句、字符串解析和函数结果的各种条件/逻辑值设置——它不仅仅是从另一个表中一对一地选择列已经定义了列,所以它不像定义其他表的列那么简单。

我已经尝试使用ALTER DATABASE my_db DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci 提前设置数据库排序规则,但这不会改变结果。从选择创建表(从选择结果动态定义的列)时,仍然使用utf8_general_ci 创建表(以及表中的列)

【问题讨论】:

  • CREATE TABLE 上的文档概述了执行此类操作的几种方法,但在第二种情况下,它们都不符合您的期望。
  • 对,这就是为什么我在这里问这个问题(?)我提供上面的第二个代码块只是作为我想要工作的建议,但我意识到它不正确。我正在寻找正确的解决方案。该文档提到了您可以从选择创建表以及存在排序规则的表选项这一事实,但我找不到将这两者一起显示的示例。上面的SELECT .... 是创建各种逻辑的结果集合,如case when 表达式、其他表和函数结果。

标签: mysql collation


【解决方案1】:
CREATE TABLE my_table (
    ... none, some, or all columns ...
) ... none, some, or all specifications ...  -- Here
    SELECT ...;

如果失败了,那么

CREATE TABLE my_table ( all columns ) all specs;
INSERT INTO my_table
    SELECT ...;

或者……

CREATE ... SELECT ...;
ALTER TABLE my_table ...;  -- any fixes needed

另一种方法是确保DATABASECREATE TABLE ... 之前具有所需的DEFAULT CHARACTER SET 和/或DEFAULT COLLATION

不管你做什么,跟着它做

SHOW CREATE TABLE my_table;

验证每列是否具有所需的CHARACTER SETCOLLATION。如果 中缺失,请查看表格的DEFAULTs

示例

CREATE TABLE `us` (
  `id` int(10) unsigned NOT NULL DEFAULT '0',
  `country` char(2) CHARACTER SET ascii NOT NULL COMMENT 'ISO 3166 Country Code',
  `ascii_city` varchar(100) CHARACTER SET ascii NOT NULL COMMENT 'Name of city or town in ASCII encoding',
  `city` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `state` char(2) CHARACTER SET ascii NOT NULL COMMENT 'For US, ISO-3166-2 code for the state/province name.',
  `population` int(10) unsigned NOT NULL DEFAULT '0',
  `lat` float NOT NULL,
  `lng` float NOT NULL,
  PRIMARY KEY (`id`),
  KEY `state` (`state`,`city`),
  KEY `state_2` (`state`,`population`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

注意某些列上的显式CHARACTER SETCOLLATE,从而覆盖表的DEFAULT CHARSET

当没有排序规则时,CHARSET utf8 默认为COLLATE utf8_general_ci

示例 2

在此,我将从该表创建一个新表us2,但更改city 的排序规则:

CREATE TABLE us2 (
  `city` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
)
    SELECT * from us;

关于us2 的所有内容都将与us 相同,除了那一列的排序规则。

【讨论】:

  • 当您说确保数据库 default 字符集/排序规则符合要求时,检查变量是否相同?即,如果我在使用相关数据库时检查 mysql 客户端中的系统变量collation_database,它会告诉我utf8_unicode_ci,但是当按照我帖子中的第一个示例创建表时,它会创建为utf8_general_ci。除了ALTER DATABASE db_name CHARACTER SET charset COLLATE collation;,还有其他方法可以检查/设置数据库的默认吗?数据库的选项与数据库的默认选项不同吗?
  • 按照我的最后一条评论,我确实尝试在使用 alter database 命令时添加单词 DEFAULTALTER DATABASE my_db DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci,但它仍然没有改变我看到的结果。我仍然得到使用 utf8_general_ci 从选择中创建的表
  • 要检查数据库的默认值,请使用SHOW CREATE DATABASE dbname;
  • 在不指定排序规则的情况下指定 CHARACTER SET utf8 会为您提供默认的 utf8_general_ci
  • 谢谢,但您的示例展示了如何在定义列的同时创建表。我熟悉如何以这种方式定义表和列的排序规则。我的场景是创建一个表,同时让选择的结果动态定义新表的列,这就是为什么我不清楚如何强制对新表进行排序。
【解决方案2】:

以下在 MariaDB 版本 10 上确实对我有用:

CREATE TABLE my_table ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SELECT *
FROM other_table
;

【讨论】:

    猜你喜欢
    • 2011-05-17
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 2011-12-02
    • 2012-12-23
    • 2018-05-05
    • 2011-08-18
    相关资源
    最近更新 更多