sql - 来自 Postgres 存储过程的意外 OUT 值

标签 sql database postgresql stored-procedures plpgsql

使用 Postgres10。

我遇到一个问题,我正在调用一个存储过程并期望我的 OUT 参数有一个特定值,但我没有得到它。我正在使用下面的调用代码调用 Items 存储过程。

问题 我希望我第一次调用 Item 存储过程来获取 rtn 值为 1 的插入,但我得到的是 4...这意味着 IF EXISTS 在表中找到同名的行,但我的表是空的.

我期望在 INSERT 语句之后重新评估 IF EXISTS 语句并进入 rtn 设置为 4 的 block 时会发生一些奇怪的事情。这与 plpgsql 有关吗?当我放入 Raise 命令以测试某些点的值时,就好像存储过程的顺序并不总是从上到下。

架构/表

CREATE TABLE aips.Item (
 ItemPk SERIAL PRIMARY KEY,
 Name VARCHAR(100) NOT NULL,
 CONSTRAINT UNI_Item_Name UNIQUE(Name)
);

存储过程

CREATE OR REPLACE FUNCTION aips.Item(
    INOUT p_ItemPk INT,
    INOUT p_Name VARCHAR(100),
    OUT rtn INT
) AS
$$
DECLARE rowcnt INT;
BEGIN
  -- Insert or Find Path
  IF p_ItemPk IS NULL THEN

    -- Check for Find
    IF EXISTS (SELECT * FROM aips.Item where Name = p_Name) THEN
        SELECT ItemPk, Name
        INTO p_ItemPk, p_Name
        FROM aips.Item
        WHERE Name = p_Name;

        rtn := 4;
        RETURN;
    END IF;

    -- Perform insert
    INSERT INTO aips.Item (Name)
    VALUES (p_Name)
    RETURNING ItemPk INTO p_ItemPk;
    GET DIAGNOSTICS rowcnt = ROW_COUNT;

    IF rowcnt = 1 THEN
      rtn := 1;
    ELSE
      rtn := 0;
      RAISE EXCEPTION 'Expecting to insert a single row and rows returned --> %', rowcnt;
    END IF;

  ELSE -- Update or No Operation Path

    -- Check for no changes
    IF EXISTS (SELECT ItemPk 
               FROM aips.Item 
               WHERE ItemPk = p_ItemPk
               AND Name = p_Name) THEN
        rtn := 5;
        RETURN;
    END IF;

    -- Perform Update
    UPDATE aips.Item 
    SET Name = p_Name
    WHERE ItemPk = p_ItemPk;
    GET DIAGNOSTICS rowcnt = ROW_COUNT;

    IF rowcnt = 1 THEN
      rtn := 2;
    ELSE
      rtn := 0;
      RAISE EXCEPTION 'Expecting to update a single row and rows returned --> %', rowcnt;
    END IF;
  END IF;

  RETURN;
END;
$$ LANGUAGE plpgsql;

调用

select (aips.Item(NULL, 'Test 1')).*;

最佳答案

问题是你调用函数的方式:

select (aips.Item(NULL, 'Test 1')).*; -- WRONG!

因为执行了三次,每个输出列一次。该函数应在 FROM 子句中调用:

select * from aips.Item(NULL, 'Test 1');

关于sql - 来自 Postgres 存储过程的意外 OUT 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54064438/

相关文章:

database - 使用 Amazon SimpleDB 有什么意义?

SQLite/Postgres SQL 查询不同列

ruby-on-rails - PostgreSQL LIKE 中的特殊字符

sql - 如何查询坐标 5 英里半径范围内的所有行?

php - 获取行号

java - 具有本地数据库的小型 Java 应用程序?使用哪个数据库?

MySql - 使用 1 列中的 2 个值计算时间距离(糟糕的设计解决方法)

mysql - 在另一个表中复制数据以提高性能

java - DB2 和 Jasper 报告中的 COALESCE 问题

mysql - 如何在MySQL中获取每月的数据