оператор if со строкой, содержащей условие - PullRequest
1 голос
/ 17 января 2012

Этот вопрос о Postgresql 8.3 .

У меня есть таблица с полем, содержащим такие условия, как «lastcontact is null». В коде я хочу пройтись по этой таблице и для каждой записи я хочу проверить «если условие тогда», как в этом примере:

FOR myrec IN
    SELECT * FROM tabel ORDER BY colorlevel, volgnummer
LOOP
    if (myrec.conditie) then
        raise notice 'Condition % is true', myrec.conditie;
    else
        raise notice 'Condition % is false', myrec.conditie;
    end if;
END LOOP;

Таблица, которую я назвал 'tabel' в этом примере:

ID | Conditie             | Colorlevel | Volgnummer | Code | Description
1  | lastcontact is null  | 1          | 1          | ...  | ...
2  | lastchanged is null  | 1          | 2          | ...  | ...
3  | lastmodified is null | 1          | 3          | ...  | ...

Можно ли сделать проверку, которую я желаю? Приведенный выше код приводит к следующей ошибке:

ERROR:  invalid input syntax for type boolean: "lastcontact is null"

Новый раздел, содержащий результат функции Эрвина

Я использовал эту функцию:

CREATE OR REPLACE FUNCTION foo(lastcontact timestamptz)
  RETURNS void AS
$BODY$
DECLARE
  myrec record;
  mycond boolean;
BEGIN

FOR myrec IN
    SELECT * FROM tabel ORDER BY colorlevel, volgnummer
LOOP
    EXECUTE 'SELECT ' || myrec.conditie || ' FROM tabel' INTO mycond;

    IF mycond then
        RAISE NOTICE 'Condition % is true', myrec.conditie;
    ELSE
        RAISE NOTICE 'Condition % is false', COALESCE(myrec.conditie, 'NULL');
    END IF;
END LOOP;

END;
$BODY$
language 'plpgsql' volatile
cost 100;

Я получаю эту ошибку:

ERROR:  column "lastcontact" does not exist
LINE 1: SELECT lastcontact is null FROM tabel
           ^
QUERY:  SELECT lastcontact is null FROM tabel
CONTEXT:  PL/pgSQL function "foo" line 9 at EXECUTE statement1

Я пытался найти объяснение самостоятельно, но безрезультатно. Очевидно, он пытается выполнить оператор для базы данных, но он должен понимать, что lastcontact - это переменная, заданная в качестве параметра функции.

1 Ответ

1 голос
/ 17 января 2012

Из комментариев я, наконец, думаю, что понимаю.Вам необходимо динамический SQL :

CREATE OR REPLACE FUNCTION foo(lastcontact timestamptz)
  RETURNS void AS
$func$
DECLARE
   myrec  record;
   mycond boolean;
BEGIN

FOR myrec IN
    SELECT * FROM tabel ORDER BY colorlevel, volgnummer
LOOP
    IF myrec.conditie ~~ '%lastcontact %' THEN   -- special case for input param
        myrec.conditie := replace (myrec.conditie
                        , 'lastcontact '
                        , CASE WHEN lastcontact IS NULL THEN 'NULL '
                          ELSE '''' || lastcontact::text || ''' ' END);
    END IF;

    EXECUTE 'SELECT ' || myrec.conditie || ' FROM tabel' INTO mycond;

    IF mycond then
        RAISE NOTICE 'Condition % is true', myrec.conditie;
    ELSE
        RAISE NOTICE 'Condition % is false', COALESCE(myrec.conditie, 'NULL');
    END IF;
END LOOP;

END
$func$  LANGUAGE plpgsql;

Однако имейте в виду, что эта установка широко открыта для SQL-инъекции .Используйте только проверенные данные.Функция работает и в PostgreSQL 8.3 (пока нет операторов DO).

Нельзя ссылаться на параметры внутри динамического SQL (оператор EXECUTE).Вы должны поместить значение в строку запроса.

В PostgreSQL 8.4 или более поздней версии у вас есть превосходящий элемент предложения USING .Увы, не в версии 8.3.Вы можете рассмотреть возможность обновления, если можете.

Я добавил обходной путь для вашей старой версии.Вы должны позаботиться о значении NULL.

...