如何在postgres的where子句中调用声明的数组变量?

时间:2017-11-28 21:56:08

标签: arrays postgresql plpgsql

我正在尝试从共享相同family_id的所有狗构建一个声明的数组,并使用该数组查询dog_characteristics表。

CREATE OR REPLACE FUNCTION update_dog_characteristics_guarantor_id()
  RETURNS trigger AS $$
  DECLARE dog_ids INT[];

  BEGIN
    SELECT id into dog_ids FROM dogs WHERE dogs.family_id = OLD.id;
    IF ((OLD.family_id IS NOT NULL) && ((SELECT COUNT(*) FROM dog_ids) > 0)) THEN
      UPDATE
        dog_characteristics
      SET
        guarantor_id = NEW.guarantor_id
      WHERE
        dog_characteristics.account_id = OLD.account_id
        AND dog_characteristics.dog_id IN ANY(dog_ids);
      RETURN NULL;
    END IF;
    RETURN NULL;
  END;
$$ LANGUAGE plpgsql;

我尝试了什么

 AND dog_characteristics.dog_id = ANY(dog_ids);
 AND dog_characteristics.dog_id = ANY(dog_ids::int[]);
 AND dog_characteristics.dog_id IN (dog_ids::int[]);
 AND dog_characteristics.dog_id IN (dog_ids);
 AND dog_characteristics.dog_id IN (ARRAY(dog_ids));
 AND dog_characteristics.dog_id IN ARRAY(dog_ids);
 AND dog_characteristics.dog_id IN implode( ',', dog_ids);

最常见的错误

  ERROR:  malformed array literal: "672"
  DETAIL:  Array value must start with "{" or dimension information.
  CONTEXT:  PL/pgSQL function update_dog_characteristics_guarantor_id() line 5 at SQL statement

1 个答案:

答案 0 :(得分:1)

您的触发功能有多处错误。

dog_ids被声明为数组时,第一个select的结果也必须是数组。为此,您需要聚合从查询返回的所有ID。

所以第一个select语句应该是

 select array_agg(id) --<< aggregate all IDs into an array
   into dog_ids 
 FROM dogs 
 WHERE dogs.family_id = OLD.id;

要检查数组是否包含元素,您无法使用select count(*),您需要使用array_length()cardinality()

&&不是&#34; AND&#34; SQL中的运算符 - AND - 所以if应该是:

IF OLD.family_id IS NOT NULL AND cardinality(dog_ids) > 0 THEN
  ... 
END IF;

数组的where条件应为:

AND dog_characteristics.dog_id = ANY(dog_ids);