Использование Postgres10.
У меня проблема, когда я вызываю хранимую процедуру и ожидаю определенного значения для моего параметра OUT, но не получаю его. Я вызываю хранимую процедуру Items с приведенным ниже кодом вызова.
ПРОБЛЕМА Я ожидаю, что в первый раз, когда я вызову хранимую процедуру Item, я получу вставку со значением rtn, равным 1, но я получаю 4 ... Это означает, что IF EXISTS находит строку в таблице с тем же именем, но моя таблица пуста .
Я ожидаю, что происходит что-то странное, когда оператор IF EXISTS переоценивается после оператора INSERT и входит в блок, где rtn получает значение 4. Это как-то связано с 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');
x.*похож на макрос - он распакован вx.c1, x.c2, ..., и когда x является функцией, функция вычисляется несколько раз.