【问题标题】:Updating postgres with if conditions on parameters使用参数上的 if 条件更新 postgres
【发布时间】:2020-11-12 17:05:11
【问题描述】:

我正在尝试使用 if 条件进行 postgres 更新,以在尝试更新之前检查参数是否为空。

当参数为空字符串时,期望的结果是不更新。

我似乎无法找出正确的方法来做到这一点。我的第一次尝试如下:

$stmt = $db->prepare("
  UPDATE users SET
    fname = IF(trim(:fname) = '', fname, :fname)
  WHERE username = :username");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':fname', $fname);
$stmt->execute();

然后我的第二次尝试是使用:

$stmt = $db->prepare("
  UPDATE users SET fname =
    IF
      trim(:fname) =  ''
    THEN
      fname
    ELSE
      :fname
    END IF;
  WHERE username = :username
");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':fname', $fname);
$stmt->execute();

使用 IF 语句执行此操作的正确方法是什么?

【问题讨论】:

    标签: php postgresql pdo


    【解决方案1】:
    • 可能最好的方法是不执行该语句; PHP 代码已经知道参数为空,因此它可以避免调用$stmt->execute()(和周围的代码)。这也将节省到数据库的往返时间。
      if (trim($fname) != "") {
         $stmt = $db->prepare("
            UPDATE users
            SET fname = :fname
            WHERE username = :username");
         $stmt->bindParam(':username', $username);
         $stmt->bindParam(':fname', $fname);
         $stmt->execute();
      }
      
    • 如果您确实需要在 PostgreSQL 查询中包含条件,请注意 IF 是语句,而不是表达式。表达式的等价物是CASE,类似于:
      UPDATE users
      SET fname = CASE WHEN trim(:fname) = '' THEN fname ELSE :fname END
      WHERE username = :username
      
    • 在这种特殊情况下,您还可以将条件作为WHERE 子句的一部分:
      UPDATE users
      SET fname = :fname
      WHERE username = :username and trim(:fname) <> ''
      

    【讨论】:

    • 注意:有来自其他人的贡献(现已删除)指出 PHP 数据库绑定(某些版本?)中存在错误/功能,其中每个绑定参数只能使用一次;因此,在使用两次:fname 的选项中,我们将不得不使用:fname1:fname2 并确保我们为两个参数传递相同的值。
    【解决方案2】:

    @sabik 的笔记仅供参考。如果您遇到这种情况,请考虑以将参数传递到 CTE 的方式重写查询,然后将 CTE 用于表达式。因此,对于当前的声明,可能类似于:

    with params (username, fname) as
       ( values (':username', ':fname') )
    update users
       set name = fname
      from params
     where username = username 
       and trim(fname) <> '';
    

    它可能并不总是可行的,但值得一看。特别是如果参数被多次使用并且有多个参数。它避免了匹配值的“协调”,并使它们以正确的顺序排列。您只需将它们单独按正确顺序排列一次即可。此外,当查询本身存在于函数/过程中时,只要不更改 CTE,就可以将查询更改为以任何顺序使用相同的参数。然后你根本不需要改变调用例程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多