【问题标题】:One query instead of multiple一个查询而不是多个
【发布时间】:2018-09-11 04:55:33
【问题描述】:

我一直在环顾四周,发现了许多类似的问题,但答案似乎不是我想要的。

我网站的注册流程如下:

  1. 用户提供电子邮件和密码
  2. 电子邮件和密码已插入_unverified 表中
  3. 验证链接已发送到电子邮件地址
  4. 一旦用户点击链接,电子邮件和密码将从_unverified转移到_verified

因此,当用户尝试创建帐户时,我必须查询两个表以确保电子邮件尚未在使用中。如下所示,我总是单独执行此操作,这显然会使脚本膨胀。

$statement = $connect->prepare("SELECT account_email FROM users_unverified WHERE account_email = :account_email");
$statement->bindParam(":account_email", $_POST["email"]);
$statement->execute();
$result = $statement->fetch(PDO::FETCH_ASSOC);

if ($result["account_email"]) // verification process is already active or has expired

$statement = $connect->prepare("SELECT account_email FROM users_verified WHERE account_email = :account_email");
$statement->bindParam(":account_email", $_POST["email"]);
$statement->execute();
$result = $statement->fetch(PDO::FETCH_ASSOC);

if ($result["account_email"]) // account already exists

值得注意的是,$_POST["email"] 将出现在一个表中或另一个表中,或者两者都没有。

在我发现的类似问题中,人们建议使用JOINSUNIONS。但是,在阅读了每种方法之后,我不相信 JOINSUNIONS 是我正在寻找的,因为我不想组合行或结果集(当然,除非我仍然能够识别该值位于哪个表中?)。

简单地说,我希望能够使用一条准备好的语句查询两个表,但如果值确实位于其中一个表中,则仍然能够确定该值位于哪个表中。我在想像下面这样的事情,我在this question 中遇到过,但是,我不相信您能够确定该值在哪个特定表中。

$statement = $connect->prepare("SELECT account_email FROM users_unverified, users_verified WHERE account_email = :account_email");

是否有任何方法可以组合这些查询,同时仍然能够识别该值存在于哪个特定表中?

【问题讨论】:

  • 为什么没有经过验证的列而不是单独的表?
  • @chris85 我绝对可以这样做,但我更愿意将表分开,以便_verified 尽可能保持精简,以便尽可能快地保持查询。由于我在共享主机上,我也不想一直手动浏览表格并清除所有过期的、未验证的帐户
  • 我支持@chris85。也许你觉得通过使用某种形式的关系表在这里是可行的。不是在验证用户时。哦,它确实有效,但关系表最适用于现有数据和长期存在的数据。我只是在验证时设置了一个布尔标志。
  • “我也不想手动检查表并清除所有过期的、未验证的帐户” - 为什么不只运行一个 cron为您做这件事并在一段时间内对未经验证的帐户使用 WHERE 子句?或者一个事件处理程序,TRIGGER。
  • @FunkFortyNiner 你能在共享主机上运行 cron 作业吗?!我必须联系我的供应商。对于未来的其他用例,这个问题的答案仍然很高兴

标签: php mysql prepared-statement


【解决方案1】:

你可以试试这个。

    SELECT account_email, 'users_unverified' AS tablename FROM users_unverified WHERE account_email  = :account_email
UNION 
SELECT account_email, 'users_verified' AS tablename FROM users_verified WHERE account_email = :account_email;

【讨论】:

  • 我对 PHP 和 MySQL 还很陌生,因此,由于表的别名仅在查询期间存在,一旦执行查询,我将如何访问这些名称?
  • 表名位于静态列 tablename 中,您可以在这些查询中使用 $result["tablename"] 访问它
  • users_unverified AS unveriusers_verified AS veri 是表的名称,但不是选择什么?或者可以像您在代码中所做的那样选择表的名称(SELECT account_email, users_verified AS veri ...??)
  • 不,您不能在此上下文中选择表的名称。我在“tablename”列中选择了表的名称作为静态字符串。因此,如果存在 users_unverified 的结果,则 tablename 列包含该表中每个结果行的 users_unverified。类似于另一张桌子。
  • @Anthony 这不是一个列,它只是一个你正在选择ing的字符串
【解决方案2】:
SELECT account_email, true AS verified  FROM users_unverified WHERE account_email = :account_email
UNION 
SELECT account_email, false AS verified FROM users_verified WHERE account_email = :account_email;

【讨论】:

  • 那么在执行该语句后, ($result = statement->fetch(PDO::FETCH_ASSOC);) $result["verifiied"] 将返回 truefalse????
  • 就是这样:D
  • 好的,唯一的问题是它在这种情况下不起作用,因为您还需要考虑两个数据库都可能包含条目的事件,在这种情况下还会返回 false 吗?它仍然可能是可行的,但我对 PHP/MySQL 有点陌生,所以我不确定当没有检测到条目时返回什么(一个空数组?),但我知道它评估为 false
  • $result["verifiied"] 将返回 true 或 false,如果查询不在两个表中,则查询将不返回任何结果。因此,您可以轻松区分这三种不同的场景。
  • 它返回的“无结果”是什么?你如何检查? empty($result["verified"])?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-09
  • 1970-01-01
  • 1970-01-01
  • 2012-06-11
  • 2017-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多