【问题标题】:Problems with my attempt to implement an UPSERT我尝试实施 UPSERT 的问题
【发布时间】:2016-04-07 10:02:26
【问题描述】:

我在检查条件以更新 PostgreSQL 中的表时遇到了这个问题。它必须检查用户是否下载过一次,如果是,请在acessos 中添加+1。

<?php
$result2 = pg_query("SELECT * from downloads WHERE (nome = $_POST[nome_download] AND email = $_POST[email_download])");
if (pg_num_rows($result2) == 0){
$result = pg_query("INSERT INTO downloads (nome, email, estado, arquivo, acessos) VALUES ('$_POST[nome_download]','$_POST[email_download]','$_POST[estado_download]','$_SESSION[nome_arquivo_download]','1')");
}else{
$arr[acessos] = $arr[acessos] + 1;
$result = pg_query("UPDATE downloads SET acessos = $arr[acessos] WHERE (nome = $_POST[nome_download] AND email = $_POST[email_download])");
}


if (!$result){
echo "Não foi possível realizar o cadastro. Tente fazer o download mais tarde.";
}
else
{
echo "soft_bd";
pg_close();
}
?>

【问题讨论】:

  • 我不确定它为什么不起作用。否则,我什至不执行并让我感到烦恼,因为我无法在 PostgreSQL 中插入相同的数据,以防用户多次下载。
  • 你的SQL注入也有问题。 从不 将用户输入粘贴到 SQL 语句中。此外,pg_num_rows 可以返回 -1
  • 您是否验证过您的 Select 语句返回了您期望的行数?
  • 我对PHP一无所知,但我会删除不必要的select。运行update 作为第一条语句。如果没有更新行,则运行插入。或者,如果只有少数用户多次下载某些内容,则先运行插入,捕获唯一键错误并进行更新。哪个更快,取决于哪个更频繁地发生:更新或插入。如果您可以升级到 Postgres 9.5,您可以使用 insert .. on conflict update,它以事务安全的方式完成所有这些操作
  • 我在使用 if (!$result2) 并遇到了同样的问题。但我会检查一下,@ChrisF。谢谢!

标签: php postgresql if-statement prepared-statement upsert


【解决方案1】:

您指的是$arr,但从您发布的代码中看不到分配的位置。无论哪种方式,如果您想将 acessos 的当前值增加 1,这种方法在多用户环境中完全不安全

你也对SQL注入完全开放。请改用准备好的语句。

Postgres 9.5 中,您甚至可以在 单个语句 中使用新的 UPSERT implementation INSERT ... ON CONFLICT ON ... DO UPDATE 执行此操作 - 假设有 UNIQUEPRIMARY KEY 约束(nome, email)

$sql = 'INSERT INTO downloads AS d (nome, email, estado, arquivo, acessos)
        VALUES ($1, $2, $3, $4, 1)
        ON CONFLICT ON (nome, email) DO UPDATE 
        SET    acessos = EXCLUDED.acessos + 1';

对于重复调用,您可以使用pg_preparepg_execute。对于单个呼叫,请使用pg_query_params

pg_query_params($sql, array($_POST[nome_download]
                          , $_POST[email_download]
                          , $_POST[estado_download]
                          , $_SESSION[nome_arquivo_download]));

【讨论】:

  • 按照您的提示进行操作,现在一切正常。谢谢大家!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-30
  • 2015-11-07
  • 2012-11-06
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
相关资源
最近更新 更多