模拟 iif 函数

来自 PostgreSQL wiki
跳转到导航跳转到搜索

兼容性代码片段

规范化空格

适用于 PostgreSQL

任何版本

SQL

依赖于

作者:Emanuel Calvo Franco 和 Hector de los Santos


一些开发者习惯使用某些“Access”(以及其他数据库)函数。其中之一是“iif”函数,它工作起来非常简单,有时可以为查询添加更多智能。

你会惊讶地发现,在 Postgresql 中可以很容易地添加此函数。

在纯 SQL 中

CREATE OR REPLACE FUNCTION iif_sql(boolean, anyelement, anyelement) returns anyelement as
$body$ select case $1 when true then $2 else $3 end $body$
LANGUAGE sql IMMUTABLE;

虽然你可以使用此多态函数一次覆盖所有数据类型,但需要使用强制转换定义或指定类型。一个简单的 iif_sql(8<9,'yes','no') 会失败。为了解决这个问题,你可以添加一个重载方法来覆盖这种情况。

CREATE OR REPLACE FUNCTION iif_sql(boolean, unknown, unknown) returns text as
$body$ select case $1 when true then textin(unknownout($2)) else textin(unknownout($3)) end $body$
LANGUAGE sql IMMUTABLE;


在 PL/Pgsql 中

CREATE OR REPLACE FUNCTION iif_(boolean, double precision, double precision) RETURNS double precision AS
$body$
DECLARE
	rtVal double precision;
BEGIN
	rtVal := (select case $1 when true then $2 else $3 end);
	return rtVal;
END;
$body$
LANGUAGE 'plpgsql' IMMUTABLE CALLED ON NULL INPUT SECURITY INVOKER;


在 PL/Perl 中(警告 - 我们正在用不同的方式解决同一个问题,如果你想像 plpglsql 一样执行,你必须使用 spi_query_exec() 函数)

CREATE OR REPLACE FUNCTION iif_perl(boolean, double precision, double precision) RETURNS double precision AS
$body$
if($_[0] =~ /t/){
	return $_[1];
}else{
	return $_[2];
}
$body$
LANGUAGE 'plperl' IMMUTABLE RETURNS NULL ON NULL INPUT SECURITY INVOKER;

像一个 C 共享对象

#include <stdio.h>
#include "postgres.h"
#include "executor/executor.h"

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

PG_FUNCTION_INFO_V1(iif_c);

Datum
iif_c (PG_FUNCTION_ARGS){
   bool message = PG_GETARG_BOOL(0);
   float8 first = PG_GETARG_FLOAT8(1);
   float8 second = PG_GETARG_FLOAT8(2);

   if(message == 1){
      PG_RETURN_FLOAT8(first);
   }else{
      PG_RETURN_FLOAT8(second);
   }
}

但用这种方式,你必须执行编译和语句“CREATE FUNCTION”。

postgres@pgsql:/usr/local/pgsql84/$ gcc -I include/server/ --shared iif_c.c

...然后

CREATE OR REPLACE FUNCTION iif_c(boolean, double precision, double precision) RETURNS double precision
     AS '/usr/local/pgsql84/compiled/a.out', 'iif_c'
     LANGUAGE C STRICT;

-- test it? go!
SELECT iif_c(9<8,0,9);


请注意,你必须修改参数的类型以接受其他类型的值! (除了第一个)。

在这些函数中,我们有不同的“总运行时间”。

plpgsql: Total runtime: 0.091 ms
plperl: Total runtime: 0.116 ms
C: Total runtime: 0.034 ms

真快啊!:D