Объявите переменную составного типа в PostgreSQL, используя% TYPE - PullRequest
2 голосов
/ 03 октября 2011

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

Простой ответ - использовать %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 Ответ

5 голосов
/ 03 октября 2011

Используйте %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;

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

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

Dynamic Filed names

...