if-statement包含包含条件的字符串

时间:2012-01-17 10:37:33

标签: sql postgresql null dynamic-sql plpgsql

这个问题是关于 Postgresql 8.3

我有一个表格,其中的字段包含'lastcontact is null'等条件。在代码中,我想循环遍历这个表,对于每个记录,我想检查'if condition then',就像在这个例子中一样:

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"

包含Erwin功能结果的新栏目

我使用过这个功能:

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 个答案:

答案 0 :(得分:1)

从评论中我终于认为我明白了。您需要dynamic 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 clause的优质商品。唉,不是8.3版本。如果可以的话,你应该考虑升级。

我为您的旧版本提供了解决方法。您必须特别注意NULL值。