我尝试实施 UPSERT 时出现问题

问题描述 投票:0回答:1

我在检查更新 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();
}
?>
php postgresql if-statement prepared-statement upsert
1个回答
0
投票

您指的是

$arr
,但从您发布的代码中并不清楚它的分配位置。不管怎样,如果你想将
acessos
的当前值增加 1,这种方法在多用户环境中是完全不安全的

您也完全接受SQL注入。请改用准备好的语句。

自 Postgres 9.5 (!) 起,您可以使用 UPSERT 实现在单个语句中完成此操作

INSERT ... ON CONFLICT ... DO UPDATE
。需要对
UNIQUE
进行
PRIMARY 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_prepare
pg_execute
。对于单个呼叫,请使用
pg_query_params
:

pg_query_params($sql, array($_POST[nome_download]
                          , $_POST[email_download]
                          , $_POST[estado_download]
                          , $_SESSION[nome_arquivo_download]));
© www.soinside.com 2019 - 2024. All rights reserved.