【问题标题】:Cyrillic symbols in SELECT query PostgreSQLSELECT 查询 PostgreSQL 中的西里尔符号
【发布时间】:2020-11-17 21:14:06
【问题描述】:

我有一个电报机器人(Aiogram,Python),它连接到 PostgreSQL 数据库。

如果用户输入了某个用户名(西里尔文、俄文或乌克兰文),机器人应返回有关该用户的完整信息,并存储在数据库中。

问题是:当机器人查询数据库时,用户名例如“Сергій”,它什么也不返回,尽管数据库中存在信息。

SELECT * 
FROM users 
WHERE username = 'Сергій';

我发现问题出在“c”或“i”之类的符号中,它们看起来很相似,但在 UTF-8 中具有不同的十六进制代码。如果我们以这种方式更改查询,一切正常

SELECT * 
FROM users 
WHERE username LIKE '_ерг_й';

我已经将数据库编码更改为 UTF-8,但还是有这个问题。 如果我直接从数据库中复制用户名并将其粘贴到机器人的输入字段中 - 它可以工作。

这是我的代码的主要片段:

@dp.message_handler()
async def username_input_handler(message: Message):
    username = message.text

    answer_text = await db.search_by_username(username)
    await message.answer(text=answer_text)

# database class
class Database():
    ...
    async def search_by_username(username):
        query = "SELECT * FROM users WHERE username LIKE $1"
        user = await self.pool.execute(query, username)
        return user
    ...

更新:

仅当我查询“用户”表时才会出现问题。此表的数据是从 .txt 文件导入的。

对另一个表运行相同的查询可以正常工作。

【问题讨论】:

  • 尝试一个国家字符文字,N'Сергій'
  • @jarlh,它没有效果。我试图通过控制台直接查询数据库,添加了 N 前缀。我想,这可能是我的数据库文件如何填充的问题。例如,在格式化源用户文件的过程中可能发生错误,并且诸如“c”或“i”之类的字母(在英语和乌克兰语中相似)被编码错误。有可能吗?

标签: python sql postgresql python-telegram-bot


【解决方案1】:

如果用户输入的字符与数据库中的字符完全相同,则查询将起作用,但显然不是。您可能需要相似性搜索:

CREATE EXTENSION pg_trgm;

CREATE INDEX ON users USING gist (username gist_trgm_ops);

SELECT *
FROM users
ORDER BY username <-> 'Сергій'
LIMIT 1;

这对于像Сергій 这样的短名称可能并不令人满意。如果Сі 都是错误字符,则只剩下一个三元组可以匹配:ерг。这可能找不到您正在寻找的最接近的匹配项。

您可能需要编写一个函数cyrillic_normalize,将每个非西里尔字母替换为“最接近”的西里尔字母,例如

CREATE FUNCTION cyrillic_normalize(text) RETURNS text
   LANGUAGE sql AS
$$SELECT translate ($1, 'Ci', 'Сі')$$;

第一个字符串包含拉丁字母,第二个字符串包含相应的西里尔字母。

然后将您的查询更改为

WHERE cyrillic_normalize(username) = cyrillic_normalize('Сергій')

【讨论】:

  • 感谢您的回答,但我需要一些不同的东西。我需要通过用户名返回有关用户的所有信息:年龄、职位等。所以 WHERE 语句是必要的。即使我在数据库“用户名='Іван'”中过滤记录,它也找不到这一行。但是,如果我将“I”字母(乌克兰语)更改为“I”(拉丁语),瞧,数据库会返回我所需的行 :) 'C' 也会发生同样的情况。
  • 但是我的查询将只返回一行。写SELECT *,你会得到整行。但它不适用于短名称,请参阅我的扩展答案。
猜你喜欢
  • 2011-09-08
  • 2018-02-19
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
  • 2011-12-17
  • 2014-06-01
  • 1970-01-01
相关资源
最近更新 更多