【问题标题】:MariaDB Syntax for Insert On Duplicate Update OR using CASE重复更新时插入或使用 CASE 的 MariaDB 语法
【发布时间】:2020-02-25 02:48:18
【问题描述】:

我想对设备进行指纹识别,并将结果与​​会话 ID 一起存储在 MariaDb 中。我正在使用 PDO 驱动程序编写 PHP。我在访问的页面上生成打印客户端,并将 XHR 发布到 storePrint.php 我想更新现有记录或插入新记录(如果它们不存在)。下面是源代码的sn-p。打印可能已经存在具有不同的会话 ID,并且打印可能会更改而会话不会更改。我想更新 print、sessionId 和 lastVisited 时间戳(我使用十进制 14,4 和 microtime(true),所以这不是真正的时间戳,而是另一个切线。

storePrint.php:

require_once('./library.php');
if(isset($_POST) && !empty($_POST))
{
    $_POST = sanitize($_POST); // Clean up input.
    $from = $_POST['from'];
    $print = $_POST['clientPrint']; // max length = 32 characters
    $sId = $_POST['sessionId']; // max-length = 64 characters
    updatePrint($sId,$print,$from);
}
library.php:

    function updatePrint($id,$print,$from)
    {
        $now = microtime(true);
        $sql = "INSERT INTO prints (print,sessionId,lastUpdated) VALUES (:print,:sid,:lastC) ON DUPLICATE KEY UPDATE print=:print, sessionId = :sId, lastUpdated = :lastV";

        $import = [":print" => $print,":sid" => $id,
        ":lastC" => $now,
        ":sId" => $id];//       ":lastV" => $now,
        $connection = connectToDB();
        $statement = $connection->prepare($sql);
        $result = $statement->execute($import);
        $count = $statement->rowCount();

        if($count > 0)
        {
        }else
        {
            echo 'Failure';
        }

    }

在加载文档并触发 storePrint.php 的 XHR 后,客户端会生成打印。希望更新记录,或者在该 print OR sessionId 不存在的情况下,创建一个新记录。问题是 print 或 sessionId 都可以更改而另一个更改。我需要找到一种方法(尽可能使用单个查询)来检查是否存在 print 或 sessionId。如果其中任何一个存在,则更新其他(打印,lastVisited,如果我们找到具有相同 sessionId 的记录,或者 sessionId,lastVisited,如果我们找到匹配的打印)。有人指出,我的桌子设计可能不适合我想做的事情。更新会导致违反完整性约束。所以迷路了......我用自动增量制作了 id Primary,并打印了唯一的和 sessionId 唯一的。请把我推向正确的方向。我尝试使用的其他查询是:

INSERT INTO prints (print, sessionId, lastUpdated) VALUES (:print,:sid,:lastC) CASE WHEN print <> :print THEN :print ELSE print END, last_update = CASE WHEN print <> :print THEN :lastV ELSE lastUpdated END;
INSERT INTO prints (print,sessionId,lastUpdated) VALUES (:print,:sid,:lastC) ON DUPLICATE KEY UPDATE print = CASE print WHEN <> THEN :print, ELSE print END, sessionId = CASE sessionId WHEN <> :sid THEN :sid ELSE sessionId END, lastUpdated=now()

INSERT INTO prints (print, sessionId, lastUpdated) VALUES (:print, :sid, :lastC) ON DUPLICATE KEY UPDATE     lastUpdated = CASE WHEN print <> :print THEN :lastC ELSE lastUpdated END, print = CASE WHEN print <> :print THEN :print ELSE print END

我发现使用 PDO 的准备好的语句和使用 VALUE() 会导致我出现语法问题,因为它会转义已经转义的字符串,将它们变成-> VALUES(''88fe273778rs8s...'') 我回去了到第一个准备好的声明,并来到这里寻求指导......

那么最后,我是重写查询还是重新设计表,还是两者兼而有之???

更新: 我遇到的实际问题是我的 sessionId 列上的完整性约束违规。我最终遇到了打印匹配WHERE id=1 和sessionId 匹配WHERE id=14 的冲突 MySQL 决定它将更新id=1 并由于重复的sessionId 导致完整性约束。 如何使用CASEDELETE 的其他匹配记录行?

【问题讨论】:

    标签: php syntax mariadb unique-constraint


    【解决方案1】:

    看来你工作太辛苦了。这不是你想要的吗?

    INSERT INTO prints (print,sessionId,lastUpdated)
          VALUES (:print,:sid,:lastC)
          ON DUPLICATE KEY UPDATE
               print = VALUES(print),
               sessionId = VALUES(sId),
               lastUpdated = VALUES(lastV)
    

    但是...UNIQUE(或PRIMARY)是哪一列? IODKU 需要知道它何时是“重复”。

    假设它是print。如果是这样,则不需要print = VALUES(print)

    【讨论】:

    • id 是PRIMARY Key,sessionId 和 print 分别是UNIQUE
    • 一个表很少有两个唯一键; 3 可能是“错误的”。
    • 我想确保我不会将打印分配给 dup sessionId。当他们浏览整个页面或其他站点时,他们的打印内容会更新为不同的哈希值。有时,当访问者重新进入站点时,他们被分配了一个与前一次访问的打印不匹配的打印,而是他们在差异访问期间拥有的前一个打印,具有差异 sessionId。当这种情况发生时,fubar 出现,服务器再次分发现有的 sessionId,(这是正常和预期的行为,对吗?)所以现在,我有一个打印匹配 @id=1 和一个 sessionId 匹配 id=19
    • 我可以编写查询来检查这一点,还是应该通过 php 检查,在插入/更新表之前运行其他查询?
    • 那么,(print, sessionid) 这对可能是“唯一的”?如果它们是单独唯一的,那么用户每个会话 ID 只能打印一次??
    猜你喜欢
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 2017-01-31
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多