FOR循环PLpgSQL函数结果

时间:2015-04-26 16:45:00

标签: sql postgresql plpgsql postgresql-9.3

我写了一个PLpgSQL函数,它应该返回SETOF products table:

CREATE OR REPLACE FUNCTION get_products_by_category
(selected_category_id smallint DEFAULT 1) RETURNS SETOF products AS
$BODY

$BEGIN
RETURN QUERY  (SELECT * FROM products WHERE CategoryID = selected_category_id);
END;

$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF
COST 100
ROWS 1000;

接下来我想在另一个函数中迭代结果(未完成的视图,因为我尝试添加PgAdmin III并且我有错误):

DECLARE
    R RECORD;
BEGIN
IF TG_TABLE_NAME != 'Categories' THEN
    RAISE 'This trigger function is for Categories, but was called for %', TG_TABLE_NAME;
FOR R IN get_products_by_category(1) LOOP
    UPDATE products SET CategoryID = NEW.id WHERE id = R.id;
RETURN NEW;

我的想法是我在数据库中有一些产品,其默认类别ID为1.然后,当添加新类别时,会触发触发器,更新CategoryID(来自新添加的对象)默认CategoryID - 也许这听起来很愚蠢,但我正在学习Northwind数据库的触发器,我不得不为自己创建任务。 :)

但由于错误near get_products_by_category(1),我无法保存。 在PLpgSQL(我使用的是9.3版本)中,有可能编写类似Java的东西:

for (Product product: dao.getProductsByCategory(categoryId))

更新的代码:

DECLARE
    selected_products products[];
    product products;
BEGIN
IF TG_TABLE_NAME != 'categories' THEN
    RAISE 'This trigger function is for Categories, but was called for %', TG_TABLE_NAME;
END IF;
selected_products := get_products_by_category(1);
FOR product IN selected_products LOOP
    UPDATE products SET CategoryID = NEW.id
        WHERE id = R.id;
END LOOP;
RETURN NEW;
END;

1 个答案:

答案 0 :(得分:2)

基本上,您需要阅读手册中的这一章:Looping Through Query Results 关于plpgsql trigger functions

CREATE OR REPLACE FUNCTION my_trigger_func()
   RETURNS trigger AS
$func$
DECLARE
    _prod products;
BEGIN
   IF TG_TABLE_NAME <> 'categories' THEN
      RAISE EXCEPTION 'Trigger func for "categories", not for %', TG_TABLE_NAME;
   END IF;

   FOR _prod IN 
      SELECT * FROM get_products_by_category(1)
   LOOP
      UPDATE products p
      SET    categoryid = NEW.id
      WHERE  p.id = _prod.id;
   END LOOP;
   RETURN NEW;
END
$func$  LANGUAGE plpgsql

或者:

...
DECLARE
    _id int;
BEGIN
   ...
   FOR _id IN 
      SELECT id FROM get_products_by_category(1)
   LOOP
      ...
      WHERE  p.id = _id;
...

两者都只是作为概念的证明。大多数时候,基于集合的解决方案即将推出。像这里:

UPDATE products p
SET    categoryid = NEW.id
FROM   get_products_by_category(1) x
WHERE  p.id = x.id;

您可以使用像get_products_by_category(1)这样的集合返回函数,就像在大多数情况下使用表格一样。

注释