为什么我的订单不区分大小写,因为未能正确排序结果?
Why is my case-insensitive order by failing to sort results properly?
我在亚马逊 Linux 上使用 MySql 5.6.15。我正在尝试编写一个简单的查询来获取按我的 table 的 NAME 列的小写版本排序的结果,该列的类型为 VARCHAR(100)。 table 有属性
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 |
这到底是怎么回事?如何 return 结果按小写名称排序?
编辑: 从 运行 "SHOW CREATE TABLE" ...
创建 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 |
您真的不需要在 order by 语句中使用 lower,这是 MySQL 的默认设置。除此之外,我从未见过这样的错误...也许从 order by 中删除较低的功能,看看它是否修复了它...
来自 MySQL 文档:
在字符类型列上,排序(与所有其他比较操作一样)通常以不区分大小写的方式执行。这意味着对于除了它们的大小写之外相同的列,顺序是未定义的。您可以像这样使用 BINARY 强制对列进行区分大小写的排序:ORDER BY BINARY col_name.
您发布的 SQL 是正确的。我创建了一个 SQL fiddle to try to reproduce your problem using the data in your question, but it works fine. Comment out the order by
clause,你得到了你在问题中显示的错误结果。
有时 UTF8 字符串看起来完全相同,但实际上并非如此。你确认过
select * from organization where name = "Billy Madison Elementary"
returns 您期望的 2 行?
如果 NAME
相同,则没有一种排序不会将它们并排放置。 NAME
上唯一与您看到的结果一致的排序是所有 3 行都具有相同的 NAME
值。在某些情况下,您可能 运行 遇到这种情况,其中字符串全部转换为整数值并且所有名称都转换为零,但即便如此,我仍希望结果的顺序在 2 个查询之间保持一致你的问题。
有许多模糊的方式可以对查询进行 运行 分类,我猜想您所看到的最可能的解释是第一个查询中的 order by
子句没有进入服务器。您如何发出查询?您是否尝试过使用(不同的)交互方式来 运行 查询?如果在查询中保留 MDR_NUMBER
列但省略 IMPORT_ADMIN_DATA_FROM_SIS
列怎么办?
您可以使用 sqlfiddle.com 重现该问题吗?如果是这样,请将 link 添加到您的问题中。
列选择不应该是这里的问题。我不确定 'Bradley County Schools' 是如何介于两者之间的。但是,如果区分大小写是个问题,那么您可以使用 BINARY 运算符。它强制字符串比较是逐字节而不是逐字符进行的。查找更多详细信息here
我在亚马逊 Linux 上使用 MySql 5.6.15。我正在尝试编写一个简单的查询来获取按我的 table 的 NAME 列的小写版本排序的结果,该列的类型为 VARCHAR(100)。 table 有属性
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 |
这到底是怎么回事?如何 return 结果按小写名称排序?
编辑: 从 运行 "SHOW CREATE TABLE" ...
创建 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 |
您真的不需要在 order by 语句中使用 lower,这是 MySQL 的默认设置。除此之外,我从未见过这样的错误...也许从 order by 中删除较低的功能,看看它是否修复了它...
来自 MySQL 文档: 在字符类型列上,排序(与所有其他比较操作一样)通常以不区分大小写的方式执行。这意味着对于除了它们的大小写之外相同的列,顺序是未定义的。您可以像这样使用 BINARY 强制对列进行区分大小写的排序:ORDER BY BINARY col_name.
您发布的 SQL 是正确的。我创建了一个 SQL fiddle to try to reproduce your problem using the data in your question, but it works fine. Comment out the order by
clause,你得到了你在问题中显示的错误结果。
有时 UTF8 字符串看起来完全相同,但实际上并非如此。你确认过
select * from organization where name = "Billy Madison Elementary"
returns 您期望的 2 行?
如果 NAME
相同,则没有一种排序不会将它们并排放置。 NAME
上唯一与您看到的结果一致的排序是所有 3 行都具有相同的 NAME
值。在某些情况下,您可能 运行 遇到这种情况,其中字符串全部转换为整数值并且所有名称都转换为零,但即便如此,我仍希望结果的顺序在 2 个查询之间保持一致你的问题。
有许多模糊的方式可以对查询进行 运行 分类,我猜想您所看到的最可能的解释是第一个查询中的 order by
子句没有进入服务器。您如何发出查询?您是否尝试过使用(不同的)交互方式来 运行 查询?如果在查询中保留 MDR_NUMBER
列但省略 IMPORT_ADMIN_DATA_FROM_SIS
列怎么办?
您可以使用 sqlfiddle.com 重现该问题吗?如果是这样,请将 link 添加到您的问题中。
列选择不应该是这里的问题。我不确定 'Bradley County Schools' 是如何介于两者之间的。但是,如果区分大小写是个问题,那么您可以使用 BINARY 运算符。它强制字符串比较是逐字节而不是逐字符进行的。查找更多详细信息here