为什么我的排序不区分大小写而不区分大小写?

时间:2018-11-29 23:17:14

标签: mysql sql sql-order-by innodb

我在Amazon Linux上使用MySql 5.6.15。我正在尝试编写一个简单的查询,以按表NAME列的小写版本(其类型为VARCHAR(100))对结果进行排序。该表具有属性

ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

但是请注意,我得到的结果是不同的,唯一不同的是在下面的错误结果中,我得到了另外一列...

mysql> select NAME, ACTIVE, ADDRESS_ID, COUNTRY_ID, CREATED_ON, ORGANIZATION_ID, IMPORT_ADMIN_DATA_FROM_SIS, IMPORT_DATA_FROM_SIS, MDR_NUMBER from organization order by lower(NAME);
+--------------------------------------+--------+------------+------------+---------------------+-----------------+----------------------------+----------------------+------------+
| NAME                                 | ACTIVE | ADDRESS_ID | COUNTRY_ID | CREATED_ON          | ORGANIZATION_ID | IMPORT_ADMIN_DATA_FROM_SIS | IMPORT_DATA_FROM_SIS | MDR_NUMBER |
+--------------------------------------+--------+------------+------------+---------------------+-----------------+----------------------------+----------------------+------------+
| Billy Madison Elementary             |       | NULL       | US         | 2018-11-29 22:35:57 | 7788            |                            |                    0 | NULL       |
| Bradley County Schools               |       | NULL       | US         | 2018-11-29 22:35:57 | 8888            |                            |                    0 | NULL       |
| Billy Madison Elementary             |       | NULL       | US         | 2018-11-29 22:35:57 | 9998            |                            |                    0 | NULL       |

当我不要求额外的列时,我得到正确的结果...

mysql> select NAME, ACTIVE, ADDRESS_ID, COUNTRY_ID, CREATED_ON, ORGANIZATION_ID, IMPORT_ADMIN_DATA_FROM_SIS, IMPORT_DATA_FROM_SIS from organization order by lower(NAME);
+--------------------------------------+--------+------------+------------+---------------------+-----------------+----------------------------+----------------------+
| NAME                                 | ACTIVE | ADDRESS_ID | COUNTRY_ID | CREATED_ON          | ORGANIZATION_ID | IMPORT_ADMIN_DATA_FROM_SIS | IMPORT_DATA_FROM_SIS |
+--------------------------------------+--------+------------+------------+---------------------+-----------------+----------------------------+----------------------+
| Billy Madison Elementary             |       | NULL       | US         | 2018-11-29 22:35:57 | 9998            |                            |                    0 |
| Billy Madison Elementary             |       | NULL       | US         | 2018-11-29 22:35:57 | 7788            |                            |                    0 |
| Bradley County Schools               |       | NULL       | US         | 2018-11-29 22:35:57 | 8888            |                            |                    0 |

这到底是怎么回事?如何返回按小写名称排序的结果?

编辑:通过运行“ SHOW CREATE TABLE”来创建表语句...

| organization | CREATE TABLE `organization` (
  `ID` varchar(32) COLLATE utf8_bin NOT NULL,
  `STATE_ID` varchar(10) COLLATE utf8_bin DEFAULT NULL,
  `ORGANIZATION_ID` varchar(32) COLLATE utf8_bin NOT NULL,
  `COUNTRY_ID` varchar(10) COLLATE utf8_bin NOT NULL,
  `NAME` varchar(100) COLLATE utf8_bin NOT NULL,
  `ORGANIZATION_TYPE_ID` varchar(2) COLLATE utf8_bin NOT NULL,
  `PARENT_ORGANIZATION_ID` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  `USER_ENTERED` tinyint(4) DEFAULT '0',
  `SAMPLE_ORGANIZATION` tinyint(4) DEFAULT '0',
  `IMPORT_DATA_FROM_SIS` tinyint(1) NOT NULL DEFAULT '0',
  `USE_EXTERNAL_AUTHENTICATION` tinyint(1) NOT NULL DEFAULT '0',
  `ADDRESS_ID` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  `LTI_REFERER_DOMAIN` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  `URL_ID` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  `CREATED_ON` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `MDR_NUMBER` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  `ACTIVE` bit(1) DEFAULT b'1',
  `IMPORT_ADMIN_DATA_FROM_SIS` bit(1) DEFAULT b'0',
  `USE_EXTERNAL_AUTH_FOR_ADMINS` bit(1) DEFAULT b'0',
  PRIMARY KEY (`ID`),
  UNIQUE KEY `UK_ORGANIZATION` (`ORGANIZATION_ID`),
  KEY `FK1_ORGANIZATION` (`COUNTRY_ID`),
  KEY `FK3_ORGANIZATION` (`ORGANIZATION_TYPE_ID`),
  KEY `FK2_ORGANIZATION` (`PARENT_ORGANIZATION_ID`),
  KEY `FK_ORGANIZATION` (`ADDRESS_ID`),
  KEY `FK5_ORGANIZATION` (`URL_ID`),
  CONSTRAINT `FK1_ORGANIZATION` FOREIGN KEY (`COUNTRY_ID`) REFERENCES `cb_country` (`ID`) ON DELETE CASCADE ON UPDATE NO ACTION,
  CONSTRAINT `FK2_ORGANIZATION` FOREIGN KEY (`PARENT_ORGANIZATION_ID`) REFERENCES `organization` (`ID`) ON DELETE CASCADE ON UPDATE NO ACTION,
  CONSTRAINT `FK3_ORGANIZATION` FOREIGN KEY (`ORGANIZATION_TYPE_ID`) REFERENCES `cb_org_type` (`ID`) ON DELETE CASCADE ON UPDATE NO ACTION,
  CONSTRAINT `FK5_ORGANIZATION` FOREIGN KEY (`URL_ID`) REFERENCES `sb_url` (`ID`) ON UPDATE NO ACTION,
  CONSTRAINT `FK_ORGANIZATION` FOREIGN KEY (`ADDRESS_ID`) REFERENCES `cb_address` (`ID`) ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin |

3 个答案:

答案 0 :(得分:0)

您实际上并不需要在order by语句中使用较低的值,这是MySQL的默认设置。除此之外,我从未见过这样的错误...也许是要删除订单中的较低功能,看看是否能解决问题...

从MySQL文档开始: 与所有其他比较操作一样,在字符类型列上的排序通常以不区分大小写的方式执行。这意味着除了大小写相同之外,其他列均未定义顺序。您可以像这样使用BINARY强制对列进行区分大小写的排序:ORDER BY BINARY col_name。

答案 1 :(得分:0)

您发布的SQL是正确的。我创建了一个SQL fiddle来尝试使用问题中的数据来重现您的问题,但是效果很好。 Comment out the order by clause,您会在问题中看到不好的结果。

有时UTF8字符串看起来相同,但是却不相同。您是否已验证

select * from organization where name = "Billy Madison Elementary"

返回您期望的2行?

如果NAME是相同的,则没有一种排序不会使它们彼此相邻。 NAME上唯一与您看到的结果一致的排序是,所有3行都具有相同的NAME值。在某些情况下,您可能会遇到这种情况,其中字符串全部都转换为整数值,所有名称都转换为零,但是即使那样,我仍希望结果的顺序在您的问题的两个查询之间保持一致。

有很多晦涩的查询可以被截断的方式,我想您最可能看到的解释是,第一个查询中的order by子句没有到达服务器。您如何发出查询?您是否尝试过使用(不同的)交互方式来运行查询?如果您保留MDR_NUMBER列但在查询中忽略了IMPORT_ADMIN_DATA_FROM_SIS列怎么办?

您可以使用sqlfiddle.com重现该问题吗?如果是这样,请将链接添加到您的问题。

答案 2 :(得分:0)

在这里列选择不应该成为问题。我不确定“布拉德利县学校”是如何出现的。但是,如果大小写敏感是问题,则可以使用BINARY运算符。它强制字符串比较是逐字节而不是逐字符。查找更多详细信息here