是否可以在 JOIN 中使用占位符?

Is it possible to use placeholders in JOIN?

我有以下 SQL 查询,用于输出论坛 posts 与 posts 的关系 tables 中的相关数据(用户 post编辑它,forum/thread 它是 etc 的子项)。

我正在使用 PDO 位置占位符(因此是 ?)

SELECT {Lots of select stuff here}
FROM tab_posts tposts
INNER JOIN tab_users tuser ON tuser.id=?
INNER JOIN tab_users tusers ON tposts.user_id=tusers.id
INNER JOIN tab_ranks tranks ON tusers.rank_id=tranks.id
INNER JOIN tab_avatars tavatars ON tusers.avatar_id=tavatars.id
INNER JOIN tab_threads tthreads ON tposts.thread_id=tthreads.id
INNER JOIN tab_forums tforums ON tthreads.forum_id=tforums.id
WHERE tposts.thread_id=? AND tforums.rank_id <= tuser.rank_id

所以在这个查询中我使用了 2 个占位符,第一个是从会话中检索到的用户 ID,另一个是从请求中检索到的线程 ID(以确保我们只列出 posts 属于该线程)。

tuser 是会话用户,tusers 是提交 post 的用户的别名。我只需要 tuser 检查会话用户是否被允许查看那些 post(按访问级别,论坛 table 中的 rank_id 是允许的最小值排名)。

我只想确认在 JOIN 部分中使用占位符(或者更确切地说,一个变量)是否有效?还是我只能使用 tables?我很确定我没有正确使用它,在这种情况下我还能如何检查用户的等级?

我也不确定我的其他 JOIN 是否有效,呸! (如果你不知道,我是 JOIN 的新手)

可以 JOINON 子句中适当使用占位符。 ON 条件必须是一些表达式,当比较两个 table 之间的行与行时,该表达式的计算结果为 TRUE,因此像

这样的条件
FROM
  t1
  LEFT JOIN t2 ON t1.id = t2.id AND t2.othercol = ?

将是 ON? 占位符的有效使用。在像上面那样的连接条件中,id 匹配 ? 输入值的 othercol 列都必须为真要满足的连接。您会在 LEFT JOIN 中看到这种用法,这时需要的不仅仅是一个列匹配来关联 table,但是添加 WHERE 条件会错误地导致 LEFT JOIN 省略 NULLs,因此表现得像 INNER JOIN.

然而,在你的情况下,看起来你真的只需要将该用户条件移动到 WHERE 子句中以将结果集过滤为请求的用户 ID。

SELECT {Lots of select stuff here}
FROM tab_posts tposts
  INNER JOIN tab_users tusers ON tposts.user_id = tusers.id
  INNER JOIN tab_ranks tranks ON tusers.rank_id = tranks.id
  INNER JOIN tab_avatars tavatars ON tusers.avatar_id = tavatars.id
  INNER JOIN tab_threads tthreads ON tposts.thread_id = tthreads.id
  INNER JOIN tab_forums tforums ON tthreads.forum_id = tforums.id
WHERE 
  /* This condition belongs in the WHERE */
  tusers.id = ?
  tposts.thread_id = ?
  AND tforums.rank_id <= tuser.rank_id

只要您的 table 确实按照联接表达它们的方式进行布局,您其余的联接看起来都是正确的。

为了进一步概括这一点,? 占位符可以用在任何您将在查询中使用标量值的地方;也就是说,字符串或数值(或布尔值、blob 等)。因此,您可以将它们用作函数参数,例如:

/* Truncate a column to some ? number of characters */
SELECT LEFT(column, ?)

SELECT 列表中的标量值:

/* Add an additional string suffix to every row in a column */
SELECT CONCAT(column, ?)

不能 使用 ? 代替 table 或列名。它们仅适用于标量值。