首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PostgreSQL参数化查询

PostgreSQL参数化查询
EN

Stack Overflow用户
提问于 2016-05-19 10:28:12
回答 1查看 118关注 0票数 0

我经常需要提交几乎相同的查询,但使用不同的参数(单个参数,但在SELECT …子句中多次提交(不是WHERE(!))。

为了说明这一点,它位于duc.opt_level >= 5 /*v_min_level*/出现在下面的每一个地方:

代码语言:javascript
复制
SELECT duc.id_du, duc.du_type_cd, duc.du_name, duc.du_addr, duc.id_du_def, duc.def_repeat_flg, defc.allows_txt_flg
  ,r.lvl + CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN 0 ELSE 1 END ELSE 0 END lvl
  ,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.id_du ELSE duc.id_du END ELSE r.id_du END entid
  ,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.entraw ELSE duc.du_addr END ELSE r.entraw END entraw
  ,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.entnm ELSE duc.du_name END ELSE r.entnm END entnm
  ,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.pentid ELSE r.entid END ELSE r.pentid END pentid
  ,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.pentraw ELSE r.entraw END ELSE r.pentraw END pentraw
  ,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.pentnm ELSE r.entnm END ELSE r.pentnm END pentnm
  ,defc.def_type, defc.val_type
  ,defc.is_nillable
  ,defc.optional
FROM r
JOIN data_unit duc
  ON duc.id_parent_du = r.id_du
JOIN du_def defc
  ON defc.id_du_def = duc.id_du_def

波斯特格雷斯。9.5.1

有什么优雅的方法来参数化这个查询,所以我只需要通过重新定义这个参数就可以使用调用它?

我想到了一些类似于匿名PL/pgSQL块的东西,但我不知道具体是如何实现的。

EN

回答 1

Stack Overflow用户

发布于 2016-05-23 00:41:57

假设所有列都不能为空(问题中缺少信息)。

在解开CASE表达式后,您的任务变得简单得多:

代码语言:javascript
复制
 , CASE WHEN duc.du_type_cd = 'e' AND (duc.opt_level < 5 OR duc.max_occurs <> 1) THEN r.lvl + 1   ELSE r.lvl     END AS lvl
 , CASE WHEN duc.du_type_cd = 'e' AND (duc.opt_level < 5 OR duc.max_occurs <> 1) THEN duc.id_du   ELSE r.id_du   END AS entid
 , CASE WHEN duc.du_type_cd = 'e' AND (duc.opt_level < 5 OR duc.max_occurs <> 1) THEN duc.du_addr ELSE r.entraw  END AS entraw
  -- etc.

同样,重复的条件可以集中在单个LEFT JOIN中,到r (r1)在FROM列表中的另一个实例中。如果不满足条件,则默认为COALESCE的替代值:

代码语言:javascript
复制
SELECT duc.id_du, duc.du_type_cd, duc.du_name, duc.du_addr, duc.id_du_def, duc.def_repeat_flg
     , defc.allows_txt_flg, defc.def_type, defc.val_type, defc.is_nillable, defc.optional
     , COALESCE(r1.lvl    , r.lvl + 1)   AS lvl
     , COALESCE(r1.id_du  , duc.id_du)   AS entid
     , COALESCE(r1.entraw , duc.du_addr) AS entraw
     , COALESCE(r1.entnm  , duc.du_name) AS entnm
     , COALESCE(r1.pentid , r.entid)     AS pentid
     , COALESCE(r1.pentraw, r.entraw)    AS pentraw
     , COALESCE(r1.pentnm , r.entnm)     AS pentnm
FROM   duc
JOIN   defc ON ???  -- missing information
JOIN   r    ON ???  -- missing information
LEFT   JOIN r1 ON duc.du_type_cd <> 'e'
               OR (duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs = 1);

现在您只提供一次v_min_level。查询要短得多。可能也会更快一些。

千万不要忽略列别名的关键字AS手册:

AS 省略关键字 ..。 在FROM项中,标准和PostgreSQL都允许在别名(即非保留关键字)之前省略AS。但是对于输出列名来说,这是不切实际的,因为语法上有歧义。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37320506

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档