与 Unicode 字素匹配的 PostgreSQL 模式

标签 postgresql unicode grapheme

有什么方法可以与 Unicode 字素进行模式匹配吗?

举个简单的例子,当我运行这个查询时:

CREATE TABLE test (
    id SERIAL NOT NULL, 
    name VARCHAR NOT NULL,
    PRIMARY KEY (id), 
    UNIQUE (name)
);
INSERT INTO test (name) VALUES ('👍🏻 One');
INSERT INTO test (name) VALUES ('👍 Two');

SELECT * FROM public.test WHERE test.name LIKE '👍%';

我返回了两行,而不仅仅是 '👍 Two'。 Postgres 似乎只是比较代码点,但我希望它比较完整的字素,所以它应该只匹配 '👍 Two',因为 👍🏻 是不同的字素。

这可能吗?

最佳答案

这是一个非常有趣的问题!

我不太确定这是否可能:

皮肤表情符号实际上是两个连接的字符(如连字)。第一个字符是黄色的手 👍,后面是表情符号皮肤修饰符 🏻

这就是浅肤色手的内部存储方式。所以,对我来说,你的结果是有道理的:

当你查询任何以👍开头的字符串时,它会返回:

  1. 👍 两个(琐碎的)
  2. 👍_🏻一个(忽略下划线,我试图用这个来抑制自动连字)

所以,你可以看到,内部的浅肤色表情符号也是以👍开头的。这就是为什么我相信,您的查询没有按照您喜欢的方式工作。

解决方法/解决方案:

  1. 您可以在查询中添加空格。这可以确保您的 👍 角色后没有皮肤修饰符。当然,这只适用于您的情况,所有数据集在手后都有一个空格:

    SELECT * FROM test WHERE name LIKE '👍 %';
    
  2. 您可以像这样简单地扩展 WHERE 子句:

    SELECT * FROM test 
    WHERE name LIKE '👍%'
        AND name NOT LIKE '👍🏻%'
        AND name NOT LIKE '👍🏼%'
        AND name NOT LIKE '👍🏽%'
        AND name NOT LIKE '👍🏾%'
        AND name NOT LIKE '👍🏿%'
    
  3. 您可以使用正则表达式模式匹配来排除皮肤:

    SELECT * FROM test 
    WHERE name  ~ '^👍[^🏻🏼🏽🏾🏿]*$'
    

参见 demo:db<>fiddle (请注意, fiddle 似乎不提供自动连字,因此两个字符都分开显示在那里)

关于与 Unicode 字素匹配的 PostgreSQL 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64886585/

相关文章:

python - suds 请求中的嵌套文本编码

java - 如何计算 Java 中的字素簇或 "perceived"表情符号字符

ruby - 按字素拆分 Unicode 实体

sql - 如何使用 SQL 查找用户 session 事件之间的时间

php utf8_encode - 字符前面加上\u

sql - Postgres 正则表达式 ^ 以 $ 结尾

c++ - Boost.format 和宽字符

python - python 正则表达式中的字素支持

sql - 更新事务内的外键失败

postgresql - 仅将 4D 用作前端应用程序