Postgresql Postgres选择UUID或字符串所在的位置

Postgresql Postgres选择UUID或字符串所在的位置,postgresql,Postgresql,我在Postgres中有以下简化表格: 用户模型 id(UUID) uid(varchar) 名称(varchar) 我想要一个可以在UUIDid或文本uid上找到用户的查询 SELECT * FROM user WHERE id = 'jsdfhiureeirh' or uid = 'jsdfhiureeirh'; 我的查询为uuid生成了一个无效的输入语法,因为在这个实例中我显然没有使用uuid 如何完善此查询或检查该值是否为有效的UUID?我最初误解了这个问题。如果要“安全地”尝

我在Postgres中有以下简化表格:

  • 用户模型
    • id(UUID)
    • uid(varchar)
    • 名称(varchar)
我想要一个可以在UUID
id
或文本
uid
上找到用户的查询

SELECT * FROM user
WHERE id = 'jsdfhiureeirh' or uid = 'jsdfhiureeirh';
我的查询为uuid生成了一个无效的输入语法,因为在这个实例中我显然没有使用uuid


如何完善此查询或检查该值是否为有效的UUID?

我最初误解了这个问题。如果要“安全地”尝试将字符串强制转换为UUID,可以编写一个函数来捕获
无效的\u text_表示形式
异常,然后只返回
null
():

SELECT uuid\u或_null('INVALID')为null将导致
true

换句话说(假设
(true或null)=true


原始答案:

Postgres将为您自动将字符串转换为UUID,但您需要使用有效的UUID。 例如:

SELECT * FROM user
WHERE id = '5af75c52-cb8e-44fb-93c8-1d46da518ee6' or uid = 'jsdfhiureeirh';
您还可以使用
uuid\u generate\u v4()
函数的
DEFAULT
子句,通过使用
uuid ossp
扩展名,让Postgres为您生成uuid:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE user (  
   id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
   uid TEXT,
   name TEXT
);

您可以使用正则表达式进行检查:

SELECT *
FROM user
WHERE ('jsdfhiureeirh' ~ E'^[[:xdigit:]]{8}-([[:xdigit:]]{4}-){3}[[:xdigit:]]{12}$'
       AND id = 'jsdfhiureeirh')
      OR uid = 'jsdfhiureeirh';

找到了!将UUID列强制转换为
::text
将停止错误。不确定性能是否受到影响,但在大约5000行上,我获得了足够的性能

SELECT * FROM user
WHERE id::text = 'jsdfhiureeirh' OR uid = 'jsdfhiureeirh';

SELECT * FROM user
WHERE id::text = '33bb9554-c616-42e6-a9c6-88d3bba4221c' 
  OR uid = '33bb9554-c616-42e6-a9c6-88d3bba4221c';

我有未知的
进入(将传统系统与现代系统合并),因此我的查询形状(不确定ID可能来自哪里)。很明显,我可以在后端完成这项工作,但我希望有一个SQLsolution@Wainage感谢您的澄清,我已经更新了我的答案,可能是
SELECT*来自用户,其中id=uuid\u或空('FOOBARBAZ')或uid='FOOBARBAZ'
?。。id::uuidOn 200万行,将id转换为字符串进行查询需要600毫秒,而执行上述操作需要18秒。@red6我并不完全感到惊讶(因为在过去几年中,我学到了更多关于Postgres的知识),在每行上运行PL/pgSQL函数的开销将比Postgres内部转换为
text
慢得多。也许有人会发现这种模式对其他类型的应用很有用,但在这种情况下,我建议使用@Wainage answer来提高性能。这个答案肯定会被更多的人考虑。存储过程不是每个人都可以轻松使用的。在我的情况下,我强烈希望能够修改查询。我的问题是我有一个文本列,其中有时有UUID,但有时有其他数据格式。当我有UUID时,我知道连接应该工作。这个答案在我的情况下是完美的,因为它完全避免了铸造错误在我的情况下,这个解决方案快得多,谢谢你的帮助!
SELECT *
FROM user
WHERE ('jsdfhiureeirh' ~ E'^[[:xdigit:]]{8}-([[:xdigit:]]{4}-){3}[[:xdigit:]]{12}$'
       AND id = 'jsdfhiureeirh')
      OR uid = 'jsdfhiureeirh';
SELECT * FROM user
WHERE id::text = 'jsdfhiureeirh' OR uid = 'jsdfhiureeirh';

SELECT * FROM user
WHERE id::text = '33bb9554-c616-42e6-a9c6-88d3bba4221c' 
  OR uid = '33bb9554-c616-42e6-a9c6-88d3bba4221c';