php - 带有内部选择的复杂 SQL 插入更新

标签 php mysql prepared-statement

我必须进行查询,在 1 行中插入或更新。

编辑:我在此处添加WORKING SQL 查询。

    $this->sqlSavePlot = $this->db->prepare(
        "INSERT OR REPLACE INTO plots (id, level, X, Z, name, owner, helpers, denied, biome) VALUES
        ((select id from plots where level = :level AND X = :X AND Z = :Z),
         :level, :X, :Z, :name, :owner, :helpers, :denied, :biome);"
    );

理论上我想在准备好的 MySQL 语句中使用相同的东西

目前的乱象是这样的:

    $this->sqlSavePlot = $this->db->prepare(
        "INSERT INTO plots (`id`, `level`, `X`, `Z`, `name`, `owner`, `helpers`, `denied`, `biome`)
        VALUES(id = (SELECT id FROM plots WHERE level = level AND X = VALUES(X) AND Z = VALUES(Z)), level = ?, X = ?, Z = ?, name = ?, owner = ?, helpers = ?, denied = ?, biome = ?)
        ON DUPLICATE KEY UPDATE
            id = VALUES(id),
            level = VALUES(level),
            X = VALUES(X),
            Z = VALUES(Z),
            name = VALUES(name),
            owner = VALUES(owner),
            helpers = VALUES(helpers),
            denied = VALUES(denied),
            biome = VALUES(biome);"
    );

如你所见,相当困惑。

这是数据库的样子:

The database

因此理论上,如果用户执行savePlot 函数,多个字段 将被替换,就像您在 PHP 代码中看到的那样。 “sqlSavePlot”是我上面显示的查询

对于一些更深入的解释,一些 PHP 代码:

    public function savePlot(Plot $plot): bool{
    print "------------------------------------------------------".PHP_EOL;
    $this->db->ping();

    $helpers = implode(',', $plot->helpers);
    $denied = implode(',', $plot->denied);
    if ($plot->id <= 0){
        $stmt = $this->sqlSavePlot;
        $stmt->bind_param('siisssss', $plot->levelName, $plot->X, $plot->Z, $plot->name, $plot->owner, $helpers, $denied, $plot->biome);
    } else{
        $stmt = $this->sqlSavePlotById;
        $stmt->bind_param('isiisssss', $plot->id, $plot->levelName, $plot->X, $plot->Z, $plot->name, $plot->owner, $helpers, $denied, $plot->biome);
    }
    $result = $stmt->execute();
    var_dump($stmt);
    var_dump($result);
    var_dump($plot);
    $this->lastSave = time();

    if ($result === false){
        $this->plugin->getLogger()->error($stmt->error);
        return false;
    }
    $this->cachePlot($plot);
    return true;
}

如果“空”,绘图的 ID 可以是 -1,或者具有从 savePlot 函数中获取的 ID

我知道困惑的部分是第一个“值”:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?, X = ?, Z = ?, name = ?, owner = ?, helpers = ?, denied = ?, biome = ?) ' at line 2

有人可以解释一下我可以用什么代替吗?

编辑:按要求显示创建表

CREATE TABLE `plots` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `level` text COLLATE utf8_unicode_ci,
 `X` int(11) DEFAULT NULL,
 `Z` int(11) DEFAULT NULL,
 `name` text COLLATE utf8_unicode_ci,
 `owner` text COLLATE utf8_unicode_ci,
 `helpers` text COLLATE utf8_unicode_ci,
 `denied` text COLLATE utf8_unicode_ci,
 `biome` text COLLATE utf8_unicode_ci,
 PRIMARY KEY (`id`),
 KEY `XZ` (`X`,`Z`)
) ENGINE=InnoDB AUTO_INCREMENT=3609 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

最佳答案

我想你想要更像这样的东西:

INSERT INTO plots (`id`, `level`, `X`, `Z`, `name`, `owner`, `helpers`, `denied`, `biome`)
    SELECT id, p.level, p.X, p.Z, ?, ?, ?, ?
    FROM plots p
    WHERE p.level = ? AND X = ? AND Z = ?
    ON DUPLICATE KEY
        UPDATE name = VALUES(name),
               owner = VALUES(owner),
               helpers = VALUES(helpers),
               denied = VALUES(denied),
               biome = VALUES(biome);

您需要注意参数的顺序。我猜 id 是主键并且 (X, Z, level) 被声明为唯一的(你如何识别重复项)。您只指定要在发生碰撞时更改名称,但这会设置所有值(如您的版本)。

关于php - 带有内部选择的复杂 SQL 插入更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45130286/

相关文章:

php - html 格式的 ActionScript 未正确执行

php - 如何将 Composer 供应商文件夹提交到 Git 存储库中?

PHP 多单选按钮数组

php - 如果我使用 MySQLi 准备语句,是否需要转义我的变量?

php - MYSQL-如何为论坛帖子创建单独的表?

php - 如何确定哪个查询执行时间最长

php - 使用 Facebook Graph API 获取纽约市的餐厅列表

mysql - SQL Server 到 MySQL 转换脚本围绕 UUID() 出现错误?

mysql - 按 MYSQL 中搜索次数最多的单词排序

mysql - 准备好的语句如何跳过转义字符?