内部选择的复杂SQL插入更新

时间:2017-07-16 15:28:39

标签: 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;
}

如果&#34;空&#34;或者具有从savePlot函数获取的ID,则情节的id可以是-1

我知道混乱的部分是围绕第一个&#34;值&#34;:

  

您的SQL语法有错误;检查手册   对应于您的MySQL服务器版本,以便使用正确的语法   接近&#39;?,X =?,Z = ?, name = ?, owner = ?, helpers = ?, denied = ?,   生物群落=?)         &#39;在第2行

有人可以解释一下我可以放的东西吗?

编辑:根据要求,SHOW CREATE TABLE

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

2 个答案:

答案 0 :(得分:0)

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

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)被声明为唯一(如何识别重复项)。您只指定要在发生冲突时更改名称,但这会设置所有值(如您的版本)。

答案 1 :(得分:0)

使用@Gordon Linoff

提供的答案修正了我的查询

原来我甚至有一个合乎逻辑的问题..我混淆了&#34; saveByID&#34;和&#34; saveByXZ&#34; ..

public function savePlot(Plot $plot): bool{
    $this->db->ping();
    $helpers = implode(',', $plot->helpers);
    $denied = implode(',', $plot->denied);

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

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

修正后的查询:

    $this->sqlSavePlot = $this->db->prepare(
        "INSERT INTO plots (`id`, `level`, `X`, `Z`, `name`, `owner`, `helpers`, `denied`, `biome`)
VALUES((SELECT id
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);"
    );
    $this->sqlSavePlotById = $this->db->prepare(
        "UPDATE plots SET id = ?, level = ?, X = ?, Z = ?, name = ?, owner = ?, helpers = ?, denied = ?, biome = ? WHERE id = VALUES(id);"
    );

非常感谢大家!希望这有助于将来的其他人!