1、PostgreSQL数据转换

字符串转double类型        
    to_number(#{lat},9999.99)

数字转字符
    to_char(#{state},'fm9')
    备注:to_char函数会在前面多一个空格,解决方法可以是在第二个格式参数前加fm

2、PostgreSQL 取查询结果的第一行(分页方式)

pg
    select ... from ... where ...  limit 1

oracle
    select ... from ... where ... and rownum=1

3、PostgreSQL中类似oracle的nvl()函数

SELECT coalesce(column,0) as alias  FROM table

4、PostgreSQL支持sys_guid()
        Oracle 使用sys_guid()用来产生UUID值。
        在PostgreSQL中有类似的函数,需要安装uuid-ossp插件。
        如果用户不想修改代码,还是需要使用sys_guid()函数的话,可以自己写一个

DECLARE
    v_seed_value varchar(32);
BEGIN
    select
    md5(
        inet_client_addr()::varchar ||
        timeofday() ||
        inet_server_addr()::varchar ||
        to_hex(inet_client_port())
    )
    into v_seed_value;

    return (substr(v_seed_value,1,8) ||
        substr(v_seed_value,9,4) ||
        substr(v_seed_value,13,4) ||
        substr(v_seed_value,17,4) ||
        substr(v_seed_value,21,12));
END;

5、PostgreSQL对add_months()函数的支持
        Oracle中add_months()函数如果当前日期是月末,或者目标月没有当前日期的,取最后一天。

CREATE FUNCTION agcloud.add_months()
    RETURNS timestamp with time zone
    LANGUAGE 'plpgsql'
    
AS $BODY$declare
  i interval := ($2 || 'month');
  d1 date := date(to_timestamp($1::text,'yyyy-mm') + interval '1 month' - interval '1 day');
  d2 date := date($1);
  res timestamp;
begin
  select case when d1=d2 then ((to_char($1+i+interval '1 month', 'yyyy-mm')||'-01')::date - 1) + $1::time else $1+i end into res;
  return res;
end;
$BODY$;

ALTER FUNCTION agcloud.add_months()
    OWNER TO postgres;

6、PostgreSQL的update语句起别名报错

--错误写法
 UPDATE [TABLE] AS T SET T.TID=1,T.TNAME='Name',T.TClass=1 WHERE T.ID=10

--规范写法
 UPDATE TABLE SET TID=1,TNAME='Name',TClass=1 WHERE ID=10;
 UPDATE SWG_DRI_TRACK_PROBLEM t SET SZWZ = ?, jdmc = ?, jjcd = ?, wtms = ?, x = ?, y = ?, FILE_GROUP_IDS = ? WHERE t.id = ?

7、PostgreSQL的序列生成方式不同
        注意:使用nextval()函数时,可能会识别不了序列,需要加模式和单引号

<insert id="addUnitWell" parameterType="map">
    <selectKey keyProperty="id" resultType="int" order="BEFORE" databaseId="oracle">
        select SEQ_SWG_DRI_UNIT_WELL.Nextval from dual
    </selectKey>
    <selectKey keyProperty="id" resultType="int" order="BEFORE" databaseId="pg">
        select nextval('SEQ_SWG_DRI_UNIT_WELL')
    </selectKey>
    ...
</insert>

8、递归函数查找:
        oracle:start with … connect by prior 递归算法
        postgresql: with recursive 递归函数


管线表中设计的时候用两个字段来标识起始点和终止点,形成了类似树状的结构

使用oracle的递归函数查找

start with … connect by prior 递归算法

语法:
    select * from table
    where 条件3
    start with 条件1
    connect by 条件2

    条件1:是根节点的限定语句,若不写start with 指定根节点查询时,是以每条记录的connect by的字段当根全查一遍
    条件2:是连接条件,当中用prior表示上一条记录的字段
    条件3:是过滤条件,用于对返回结果集的过滤
SELECT t.*, substr(sys_connect_by_path(t.objectid, '->'), 3) chainsNode
FROM swg_sma_pipe t
START WITH t.end_usid = '060208-28420315-000001'
CONNECT BY PRIOR t.start_usid = t.end_usid and t.sort != '雨水'--遇到雨水就不继续递归

ORA-01436: 用户数据中的 CONNECT BY 循环,死循环导致,解决方法:使用nocycle剔除导致死循环的记录

SELECT t.*, substr(sys_connect_by_path(t.objectid, '->'), 3) chainsNode
FROM swg_sma_pipe t
START WITH t.end_usid = '060208-28420315-000001'
CONNECT BY nocycle PRIOR t.start_usid = t.end_usid and t.sort != '雨水'--遇到雨水就不继续递归

PostgreSQL的with语句的用法:
详细内容:http://www.jasongj.com/sql/cte/ WITH RECURSIVE 执行过程:

WITH RECURSIVE语句包含了两个部分
* non-recursive term(非递归部分),即上例中的union all前面部分
* recursive term(递归部分),即上例中union all后面部分
执行步骤如下:
1. 执行non-recursive term。(如果使用的是union而非union all,则需对结果去重)其结果作为recursive term中对result的引用,
   同时将这部分结果放入临时的working table中
2. 重复执行如下步骤,直到working table为空:用working table的内容替换递归的自引用,执行recursive term,
  (如果使用union而非union all,去除重复数据),并用该结果(如果使用union而非union all,则是去重后的结果)替换working table
--添加层级level,在根节点定义一个level,再union all递归子节点时,使用rec上一条记录进行计算
WITH RECURSIVE rec AS
(
    SELECT p.gid OBJECTID,1 as level,p.USID,p.SORT,p.end_usid,p.start_usid,p.DISTRICT,sde.st_astext(p.shape) PATHS,
        p.LENGTH,p.D_S D_SIZE, cast(p.gid as varchar(20480)) chain_node FROM sde.ps_pipe_zy_new p  WHERE p.start_usid = '060209-32302010-000014'
    union   ALL
    SELECT t.gid OBJECTID,r.level+1,t.USID,t.SORT,t.end_usid,t.start_usid,t.DISTRICT,sde.st_astext(t.shape) PATHS,
        t.LENGTH,t.D_S D_SIZE, cast(r. chain_node||'>'||t.gid as varchar(20480)) chain_node FROM sde.ps_pipe_zy_new t , rec r where  r.start_usid = t.end_usid
)
SELECT * FROM rec;