健壮的方法以编程方式构建SQL查询 [英] Robust approach for building SQL queries programmatically

查看:80
本文介绍了健壮的方法以编程方式构建SQL查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不得不求助于ORM不足的原始SQL(使用Django 1.7).问题在于大多数查询最终都具有80-90%的相似性.我想不出一个强大的&建立查询而又不违反可重用性的安全方法.

I have to resort to raw SQL where the ORM is falling short (using Django 1.7). The problem is that most of the queries end up being 80-90% similar. I cannot figure out a robust & secure way to build queries without violating re-usability.

字符串连接是唯一的出路,即使用if-else条件构建无参数查询字符串,然后使用准备好的语句安全地包含参数(以避免SQL注入).我想采用一种简单的方法来为我的项目模板SQL,而不是重新发明一个小型ORM.

Is string concatenation the only way out, i.e. build parameter-less query strings using if-else conditions, then safely include the parameters using prepared statements (to avoid SQL injection). I want to follow a simple approach for templating SQL for my project instead of re-inventing a mini ORM.

例如,考虑以下查询:

SELECT id, name, team, rank_score
FROM
  ( SELECT id, name, team
    ROW_NUMBER() OVER (PARTITION BY team
                       ORDER BY count_score DESC) AS rank_score
    FROM 
      (SELECT id, name, team
       COUNT(score) AS count_score
       FROM people
       INNER JOIN scores on (scores.people_id = people.id)
       GROUP BY id, name, team
      ) AS count_table
  ) AS rank_table
WHERE rank_score < 3

我该怎么办

a)在people
上添加可选的WHERE约束 b)将INNER JOIN更改为LEFT OUTER
c)将COUNT更改为SUM
d)完全跳过OVER / PARTITION子句?

a) add optional WHERE constraint on people or
b) change INNER JOIN to LEFT OUTER or
c) change COUNT to SUM or
d) completely skip the OVER / PARTITION clause?

推荐答案

更好的查询

对于初学者来说,您可以修复语法,简化和澄清很多事情:

Better query

For starters you can fix the syntax, simplify and clarify quite a bit:

SELECT *
FROM  (
   SELECT p.person_id, p.name, p.team, sum(s.score)::int AS score
         ,rank() OVER (PARTITION BY p.team
                       ORDER BY sum(s.score) DESC)::int AS rnk
    FROM  person p
    JOIN  score  s USING (person_id)
    GROUP BY 1
   ) sub
WHERE  rnk < 3;

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆