与 Unicode 字素匹配的 PostgreSQL 模式

PostgreSQL pattern matching with Unicode graphemes

有什么方法可以与 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',因为 是不同的字素。

这可能吗?

这个问题很有意思!

我不太确定是否可行:

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

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

当您查询任何以 开头的字符串时,它将 return:

  1. Two(琐碎)
  2. _ One(忽略下划线,我试图用这个来抑制自动连字)

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

Workarounds/Solutions:

  1. 您可以在查询中添加 space。这确保了您的角色之后没有皮肤修改器。当然,这只适用于你的情况,所有数据集的手后都有一个 space:

    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 似乎不提供自动连字,因此两个字符在那里分开显示)