postgresql 如何测试int2vector是否只包含一个特定值?

rdrgkggo  于 2023-05-28  发布在  PostgreSQL
关注(0)|答案(2)|浏览(242)

我现在的代码看起来像这样:

SELECT
  1
FROM pg_namespace   sch
JOIN pg_class       tab ON tab.relnamespace = sch.oid
JOIN pg_index       idx ON idx.indrelid     = tab.oid
JOIN pg_class       icl ON icl.oid          = idx.indexrelid
JOIN pg_attribute   col ON col.attrelid     = tab.oid
WHERE
      sch.nspname      = 'my_schema'
  AND tab.relkind      = 'r'
  AND idx.indisprimary
  AND icl.relname      = 'pk_my_table'
  AND col.attname      = 'my_table_id'
  AND idx.indkey       = ARRAY[col.attnum] -- <-- The problematic comparison
;

这不起作用,因为:ERROR: operator does not exist: int2vector = smallint[]
我尝试了各种组合:

  • indkey转换为类似idx.indkey::smallint[]的数组
  • ARRAY[col.attnum]转换为int2vector
  • 使用ALL运算符
  • 使用@>运算符

如何检查indkey是否只包含一个col.attnum条目?

r8xiu3jd

r8xiu3jd1#

您可以强制转换为text并转换为integer数组:

AND string_to_array(idx.indkey::text, ' ')::int2[] = ARRAY[col.attnum]

实际上,由于pg_attribute.attnumsmallintint2),因此使用int2[]
由于您只对***单个***列感兴趣,因此可以简化:

AND idx.indkey::text = col.attnum::text

SQL Fiddle。

在索引中处理多列时要小心。考虑这个相关的答案:

  • 如何查找给定列是否存在唯一键约束
hvvq6cgz

hvvq6cgz2#

看起来你可以解开它。

select unnest('1 2'::int2vector);

完整演示:

begin;
CREATE TABLE multi (my_table_id serial
, name text
, rs int
, CONSTRAINT pk_my_table 
PRIMARY KEY(my_table_id,name)); 

INSERT INTO multi (name, rs) 
VALUES('A', 10),('A', 20),('A', 30),('B', 15),('C', 70),('C', 30);
commit;

SELECT  sub.key, col.attnum
FROM    pg_namespace   sch
JOIN    pg_class       tab ON tab.relnamespace = sch.oid
JOIN    pg_index       idx ON idx.indrelid     = tab.oid
JOIN    pg_class       icl ON icl.oid          = idx.indexrelid
JOIN    pg_attribute   col ON col.attrelid     = tab.oid
CROSS   JOIN    LATERAL  unnest(idx.indkey) sub(key)
WHERE   sch.nspname      = 'public'
AND     idx.indisprimary
AND     icl.relname      = 'pk_my_table'
AND     col.attnum > 0
AND     attisdropped is false
AND     sub.key = attnum

相关问题