Объявите переменную составного типа в PostgreSQL, используя%TYPE

Вопрос: Как я могу объявить переменную того же типа параметром в хранимой функции?

Простой ответ - использование %TYPE, это работает:

CREATE OR REPLACE FUNCTION test_function_1(param1 text)
  RETURNS integer AS
$BODY$ 
DECLARE
    myVariable param1%TYPE;
BEGIN
    return 1;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

Но проблема в том, когда param1 это составной тип:

CREATE TYPE comp_type as
(
    field1 text
)

CREATE OR REPLACE FUNCTION test_function_2(param1 comp_type)
  RETURNS integer AS
$BODY$ 
DECLARE
    myVariable param1%TYPE;
BEGIN
    return 1;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

Это не работает:

ERROR: type comp_type does not exist [SQL State=42704]

Так как я могу сделать, когда param1 такое составной тип?

(Примечание: просто myVariable comp_type это не хороший вариант, потому что моя функция немного сложнее.)


Отредактировано: у меня была ошибка при копировании и вставке, настоящая ошибка:

ERROR: invalid type name "param1%TYPE"
  Position: 130 [SQL State=42601] 

И используя param1%ROWTYPE ошибка:

ERROR: relation "param1" does not exist
  Where: compilation of PL/pgSQL function "test_function_2" near line 3 [SQL State=42P01] 

1 ответ

Решение

использование %ROWTYPE в таком случае.

Редактировать - простой случай

Тесты AH и DavidEG показали, что это не сработает. Интересная проблема!
Вы можете попробовать обходной путь. Пока ваше определение похоже на пример, вы можете просто прибегнуть к

CREATE FUNCTION test(param1 comp_type)
  RETURNS integer AS
$BODY$ 
DECLARE
    myvar comp_type;
BEGIN
    return 1;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

Но ваша настоящая проблема, вероятно, не так просто?

Edit 2 - настоящая проблема

Как и ожидалось, реальная проблема более сложна: полиморфный тип ввода.
Обойти этот сценарий было сложнее, но он должен работать без нареканий:

CREATE FUNCTION test(param1 anyelement, OUT a integer, OUT myvar anyelement)
  RETURNS record AS
$BODY$
BEGIN
    myvar := $1;  -- myvar has now the required type.

    --- do stuff with myvar.

    myvar := NULL;  -- reset if you don't want to output ..
    a := 1;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

Вызов:

SELECT a FROM test('("foo")'::comp_type); -- just retrieve a, ignore myvar

Смотрите полный вывод:

SELECT * FROM test('("foo")'::comp_type);

Примечание для PostgreSQL 9.0+

В версии 9.0 произошло критическое обновление. Я цитирую примечания к выпуску:

  • Разрешить входным параметрам присваивать значения в функциях PL/pgSQL (Стив Прентис)

Раньше входные параметры обрабатывались как объявленные как CONST, поэтому код функции не мог изменить их значения. Это ограничение было снято, чтобы упростить перенос функций из других СУБД, которые не налагают эквивалентное ограничение. Входной параметр теперь действует как локальная переменная, инициализированная переданным значением.

Ergo, в дополнение к моему обходному пути, вы можете использовать входные переменные напрямую.

Динамические поданные имена

Другие вопросы по тегам