MySQL - 选择第一个字符是小写还是大写

Posted

技术标签:

【中文标题】MySQL - 选择第一个字符是小写还是大写【英文标题】:MySQL - Select where first character is lowercase or uppercase 【发布时间】:2019-04-03 10:47:01 【问题描述】:

对不起,如果这是之前提出的问题,但我无法找到答案。 如何创建 mysql 选择语句以从数据库中选择第一个字符为小写或大写的所有字符串。

我通常会使用这样的方法从英文单词数据库中随机选择 10 个长度超过 8 个字符的单词:

SELECT word FROM en_dictionary WHERE CHAR_LENGTH(word)>8 ORDER BY RAND() LIMIT 10

不幸的是,这也会选择我不希望在结果中出现的大写字母单词,因为它们通常是城市名称、物种名称等术语:

所以,我的问题是:有没有办法只选择以小写字母字符(或大写字母)开头的单词?

我可以做这样的事情并且它会起作用,但这是一个非常丑陋的陈述:

AND word LIKE BINARY 'a%' AND word LIKE BINARY 'b%' AND word LIKE BINARY 'c%'...

【问题讨论】:

word 列定义的字符集和排序规则是什么? 我的设置:COLLATE='utf8_general_ci' 【参考方案1】:

您可以使用Ascii() 函数。它返回输入字符串最左边字符的数值。

对于第一个小写字符a 的 ASCII 码是 97z122。所以,第一个字符的 ASCII 码应该在 97 到 122 之间。

SELECT word 
FROM en_dictionary 
WHERE CHAR_LENGTH(word) > 8 
  AND ASCII(word) BETWEEN 97 AND 122
ORDER BY RAND() LIMIT 10

对于第一个大写字符A 的 ASCII 码是 65Z90。所以,第一个字符的 ASCII 码应该在 65 到 90 之间。

SELECT word 
FROM en_dictionary 
WHERE CHAR_LENGTH(word) > 8 
  AND ASCII(word) BETWEEN 65 AND 90
ORDER BY RAND() LIMIT 10

【讨论】:

【参考方案2】:

不是一个完整的答案,但是对于一个评论来说太大了,所以我做了一个答案。

我建议您使用区分大小写的 utf8 排序规则,例如 utf8_bin。 然后你不需要使用 BINARY 或其他 MySQL “hacks”来获得你需要的结果,你可以简单地使用 LIKE/BETWEEN 并区分大小写。

创建表

CREATE TABLE test (

    utf8_general_ci_word VARCHAR(255) COLLATE utf8_general_ci
  , utf8_bin_word VARCHAR(255) COLLATE utf8_bin
);

INSERT INTO test (utf8_general_ci_word, utf8_bin_word) VALUES('a', 'a');
INSERT INTO test (utf8_general_ci_word, utf8_bin_word) VALUES('A', 'A');

INSERT INTO test (utf8_general_ci_word, utf8_bin_word) VALUES('b', 'b');
INSERT INTO test (utf8_general_ci_word, utf8_bin_word) VALUES('B', 'B');

结果

查询 #1

    SELECT 
     utf8_general_ci_word
    FROM
     test 
    WHERE
     utf8_general_ci_word LIKE 'a%'

    ;

| utf8_general_ci_word |
| -------------------- |
| a                    |
| A                    |

查询 #2

    SELECT 
     utf8_general_ci_word
    FROM
     test 
    WHERE
     utf8_general_ci_word LIKE BINARY 'a%'

    ;

| utf8_general_ci_word |
| -------------------- |
| a                    |

查询 #3

    SELECT 
     utf8_bin_word
    FROM
     test 
    WHERE
     utf8_bin_word LIKE 'a%';

| utf8_bin_word |
| ------------- |
| a             |

demo

所以您的查询将类似于

查询

SELECT
  word
FROM
  en_dictionary
WHERE
    CHAR_LENGTH(word) > 8
  AND
    word BETWEEN 'a' AND 'z'
ORDER BY
 RAND()
LIMIT 10

demo on the test data

于 2019 年 8 月 11 日编辑

这会漏掉像“zahn”这样的词,因为它不是

感谢 dnoeth 的评论和 2019 年 7 月 11 日晚些时候的一次较晚的陪练会议,在某些情况下,上面的 SQL 确实存在错误..

由于word BETWEEN 'a' AND 'z'word >= 'a' AND word <= 'z' 的语法糖,这确实不会匹配大于z 的单词,例如zahnzzzzzzzzz。 上述查询的有效补丁是使用 REPEAT('<char>', <number_of_size_of_table_column_datatype>) 作为本例中的最大范围含义 word BETWEEN 'a' AND REPEAT('z', 255)

补丁的demo..

【讨论】:

不应该是LEFT(word,1) Between 'a' and 'z' "不应该是 LEFT(word,1) 在 'a' 和 'z' 之间吗" 不,我使用 MySQL 的字符串转换来发挥我的优势 @MadhurBhaiya 检查这个 db-fiddle.com/f/tCUgdpcwH7E78gviia6yqv/4 .. 除了 if word被索引我会失去最好的索引使用LEFT(word,1)db-fiddle.com/f/tCUgdpcwH7E78gviia6yqv/6 有趣的+1;做了更多的实验:db-fiddle.com/f/tCUgdpcwH7E78gviia6yqv/7 感谢@dnoeth 的这次较晚的陪练会议,它用补丁更新了答案,现在确实可以正确返回.. “不应该是 LEFT(word,1) between 'a' and 'z'” @MadhurBhaiya 查看更新后的答案,确实需要一个补丁才能让这适用于很久以前被忽视的所有情况:-) ...加上索引使用仍然是good【参考方案3】:

您可以使用 SUBSTRING 和 REGEXP BINARY

SELECT word 
FROM en_dictionary 
WHERE CHAR_LENGTH(word)>8 
AND SUBSTRING(word, 1, 1) REGEXP BINARY '[A-Z]'
ORDER BY RAND() LIMIT 10

使用 REGEXP BINARY 您可以根据需要使用任何正则表达式,请参阅文档:https://dev.mysql.com/doc/refman/8.0/en/regexp.html

SUBSTRING 只是为了获取第一个字母。

How to check for uppercase letters in MySQL?

MySQL Select Query - Get only first 10 characters of a value

【讨论】:

以上是关于MySQL - 选择第一个字符是小写还是大写的主要内容,如果未能解决你的问题,请参考以下文章

javajava 实现 将 字符串 第一个字符 大写 或者 小写

如何通过 js 仅将第一个字符小写所有字符和大写? [复制]

如何检查PHP中的字母是大写还是小写?

mysql 为啥有些字段首字母是大写的在插入时会变成小写?

java 如何判断字符串开头首字为字母且若大写自动更改为小写

请问SQL数据库设计时字段名头一个字母是大写还是小写?