<转>postgresql

huojiahui 2010-10-20

一、如何判断一个表是否已经存在

Sybase中可以使用如下语句来判断

selectcount(*)fromsystablewheretable_type='BASE'andtable_name='tablename';

也可以再加上creator=1来限定在用户创建的表而非系统的表。

在从Sybase移植到PostgreSQL过程中,不得不考虑的就是这个问题。最初不知道用什么办法,所以简单的用一句

select*fromtablename;

然后加上Exception处理来判断表是否存在。

后来去google了一下,原来有更多更简单的办法。

一种:

selectcount(*)frompg_classwhererelname='tablename';

另一种:

selectcount(*)frominformation_schema.tableswheretable_schema='public'andtable_type='BASETABLE'andtable_name='tablename';

最后一种,适用于检查那些临时的,虽然存在但却不可见的表的存在与否:

selectcount(*)frompg_catalog.pg_classwhererelkind='r'andrelname='tablename'andpg_catalog.pg_table_is_visible(oid);

二、如何返回result和resultset

例如有表test_table的定义如下:

createtabletest_table(col_idxinteger,

col_avarchar,

col_btext);

首先,返回result,我更愿意说是返回record。一条记录。有两种办法。

一种就是利用out参数返回,好处是不需要使用record类型,返回的数据结构清楚,便于使用。缺点是如果返回的列数目比较大,参数列表变长,不美观,不易于编写,有可能超过参数个数上限。以及,目前,我没办法用这种方式返回结果集。

createorreplacefunctiontest(inidxinteger,outcol_avarchar,outcol_btext)AS$$

begin

selectcol_a,col_bintocol_a,col_bfromtest_tablewherecol_idx=idx;

end;

$$LANGUAGE'plpgsql';

使用的时候,是这样的:

select*fromtest(1);

值得注意的是,在Sybase的存储过程中使用out参数,在调用存储过程的时候,是:(假如a和b分别是目标变量,用于存储out参数返回的值)

calltest(1,a,b);

而同样的在PostgreSQL中,却是

select*fromtest(1)intoa,b;

另一种方法就是使用record类型作为存储过程的返回值类型。例如:

createorreplacefunctiontest(inidxinteger)returnsrecordAS$$

declare

recrecord;

begin

selectcol_a,col_bintorecordfromtest_tablewherecol_idx=idx;

returnrec;

end;

$$LANGUAGE'plpgsql';

那么使用这个存储过程的时候,大致如下:

select*fromtest(1)a(avarchar,btext);

其中a(avarchar,btext)就是为了给返回的record一个明确的结构定义。

返回结果集使用的方法和上述的第二种方法类似。

createorreplacefunctiontest(inidxinteger)returnssetofrecordAS$$

declare

recrecord;

begin

forrecinselectcol_a,col_bfromtest_tablewherecol_idx=idxloop

returnnextrec;

endloop;

end;

$$LANGUAGE'plpgsql';

使用时候也是一样的。

select*fromtest(1)a(avarchar,btext);

同样,如果结果集中只有一条记录呢?那么就同样实现了返回单条记录的功能。

三、如何实现Sybase的执行动态SQL查询并返回结果集

Sybase中,使用如下的一行即可:

executeimmediatewithresultseton'SQLCommand';

而对应的PostgreSQL中要实现这个功能,可以这样:

forrecinexecute'SQLCommand'loop

returnnextrec;

endloop;

过程返回值类型是setofrecord。

不过让我不确定的是,似乎以前的PostgreSQL版本的excute并不返回数据。而我在8.1上测试,没有问题。

相关推荐