Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 为了避免重复的绑定变量,针对这样的子选择进行连接是一种糟糕的形式吗?_Sql_Join_Subquery_Bind Variables - Fatal编程技术网

Sql 为了避免重复的绑定变量,针对这样的子选择进行连接是一种糟糕的形式吗?

Sql 为了避免重复的绑定变量,针对这样的子选择进行连接是一种糟糕的形式吗?,sql,join,subquery,bind-variables,Sql,Join,Subquery,Bind Variables,下面是一个简化的示例查询,使用“传统”方式完成(在PostgreSQL 8.3中测试的示例查询): 问题是,将同一个bind变量传递两次是很麻烦的(对于更复杂的查询,当需要六次或更多次时,更是如此) 当然,SQL允许在同一查询中多次使用同一绑定变量: PREPARE b AS SELECT * FROM users WHERE uid=$1 OR parent=$1; EXECUTE b(0); 但是许多DB API层不支持(或者不容易),因此使用这种方法更加麻烦 我可以通过针对子选择

下面是一个简化的示例查询,使用“传统”方式完成(在PostgreSQL 8.3中测试的示例查询):

问题是,将同一个bind变量传递两次是很麻烦的(对于更复杂的查询,当需要六次或更多次时,更是如此)

当然,SQL允许在同一查询中多次使用同一绑定变量:

PREPARE b AS SELECT *
FROM users
WHERE uid=$1
    OR parent=$1;
EXECUTE b(0);
但是许多DB API层不支持(或者不容易),因此使用这种方法更加麻烦

我可以通过针对子选择添加连接来解决此问题,例如:

PREPARE c AS SELECT uids.*
FROM users
JOIN (SELECT $1::INT AS uid) AS x ON true
WHERE uids.uid=x.uid 
    OR uids.parent=x.uid;
EXECUTE c(0);
Explain表明,后一个选项具有最复杂的执行计划,但是,至少在本例中,它的执行速度始终比a快,而几乎不比b慢(尽管准备查询比其他两个选项中的任何一个都要长)

所以我的问题是:


对于更复杂的查询,这种连接/子选择构造被认为是好的还是坏的形式,以避免重复绑定变量?

不是对您的问题的直接回答,但在这种特殊情况下,您应该能够像这样重写查询:

PREPARE b AS SELECT *
FROM users
WHERE $1 IN (uid, parent);

EXECUTE b(0);

事实上,这在这种情况下是可行的(在我真正关心的更复杂的情况下是行不通的:),但即使如此,如果我没有弄错的话(如果我的基本测试是准确的话),它也不会在
uid
parent
列上使用索引。@Flimzy从逻辑上讲,它应该与
uid=$1或parent=$1
相同,因此,它应该以同样的方式执行。话虽如此,也许您已经发现了ProsGreSQL查询优化器的一些特性?在任何情况下,我都建议测量真实的数据量——我不是PostgreSQL优化器方面的专家,但许多DBMS甚至在索引可用的情况下也会在小表上进行表扫描。事实上。。。我在一张大桌子上做了测试。但是,不幸的是,这不是唯一改变的变量,所以我不能确定我的测试是否有效。这是一个很好的策略来保持我的秘密。
PREPARE b AS SELECT *
FROM users
WHERE $1 IN (uid, parent);

EXECUTE b(0);