Объявите переменную составного типа в 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, в дополнение к моему обходному пути, вы можете использовать входные переменные напрямую.