SELECT 查询 PostgreSQL 中的西里尔符号
Cyrillic symbols in SELECT query PostgreSQL
我有一个电报机器人(Aiogram,Python),它连接到 PostgreSQL 数据库。
如果用户输入某个用户名(西里尔文、俄文或乌克兰文),bot 应该 return 关于此用户的完整信息,存储在数据库中。
问题是:当机器人查询数据库时,使用用户名例如“Сергій”,它return什么都没有,尽管数据库中存在信息。
SELECT *
FROM users
WHERE username = 'Сергій';
我发现问题出在像 'c' 或 'i' 这样的符号中,它们看起来很相似,但在 UTF-8 中有不同的十六进制代码。如果我们以这种方式更改查询,一切正常
SELECT *
FROM users
WHERE username LIKE '_ерг_й';
我已经将数据库编码更改为UTF-8,但仍然有这个问题。
如果我直接从数据库复制用户名并将其粘贴到 bot 的输入字段中 - 它有效。
这是我的代码的主要片段:
@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 "
user = await self.pool.execute(query, username)
return user
...
更新:
只有在查询 'users' table 时才会出现问题。 table 的数据是从 .txt
文件导入的。
运行 对另一个 table 的相同查询工作正常。
如果用户输入的字符与数据库中的字符完全相同,则查询将起作用,但显然它们不是。您可能需要相似性搜索:
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 (, 'Ci', 'Сі')$$;
其中第一个字符串包含拉丁字母,第二个字符串包含相应的西里尔字母。
然后将您的查询更改为
WHERE cyrillic_normalize(username) = cyrillic_normalize('Сергій')
我有一个电报机器人(Aiogram,Python),它连接到 PostgreSQL 数据库。
如果用户输入某个用户名(西里尔文、俄文或乌克兰文),bot 应该 return 关于此用户的完整信息,存储在数据库中。
问题是:当机器人查询数据库时,使用用户名例如“Сергій”,它return什么都没有,尽管数据库中存在信息。
SELECT *
FROM users
WHERE username = 'Сергій';
我发现问题出在像 'c' 或 'i' 这样的符号中,它们看起来很相似,但在 UTF-8 中有不同的十六进制代码。如果我们以这种方式更改查询,一切正常
SELECT *
FROM users
WHERE username LIKE '_ерг_й';
我已经将数据库编码更改为UTF-8,但仍然有这个问题。 如果我直接从数据库复制用户名并将其粘贴到 bot 的输入字段中 - 它有效。
这是我的代码的主要片段:
@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 "
user = await self.pool.execute(query, username)
return user
...
更新:
只有在查询 'users' table 时才会出现问题。 table 的数据是从 .txt
文件导入的。
运行 对另一个 table 的相同查询工作正常。
如果用户输入的字符与数据库中的字符完全相同,则查询将起作用,但显然它们不是。您可能需要相似性搜索:
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 (, 'Ci', 'Сі')$$;
其中第一个字符串包含拉丁字母,第二个字符串包含相应的西里尔字母。
然后将您的查询更改为
WHERE cyrillic_normalize(username) = cyrillic_normalize('Сергій')