一尘不染

mysqli的“ prepare”语句失败,错误为“使用了o表”。

sql

用php编写的新手,我正在使用$ mysqli-> prepare()函数来使语句准备好执行,但是它一直失败,我不知道为什么。$ mysqli->
error内部的错误是“未使用表”,而且我似乎也找不到太多的文档…如果有人可以帮忙,将不胜感激。代码如下:

$datasqli=new mysqli(HOST, USERNAME, PASSWORD, DATABASE); // defined elsewhere
if ($datasqli->connect_errno) {
    printf("Connect failed: %s\n", $datasqli->connect_error);
    exit();
}

if ($usertest = $datasqli->prepare("INSERT INTO eeg (Identifier) 
    SELECT * FROM (SELECT ? ) AS tmp WHERE NOT EXISTS (
    SELECT Identifier FROM eeg WHERE Identifier = ?
    ) LIMIT 1")) {
    // this stuff never gets executed...
} else {
    echo $datasqli->error; // "no table used"
}

我试过直接在mysql环境中执行该代码块,它工作正常。


阅读 141

收藏
2021-05-16

共1个答案

一尘不染

显然,

SELECT * FROM (SELECT ? )

…未被识别为有效的MySQL语法。表名丢失。

编辑 ,关于您的评论:

首先,请注意,在控制台中通过?用常量替换来执行此语句并不能模拟您的情况,因此我认为结果对于比较无效。

但是话又说回来, 替换?而执行它自然会产生错误。

这是因为仅执行选择与您的情况无关。在您的php代码中,失败不是 执行 失败,而是 准备工作
。因此,使用控制台来模拟此操作的正确方法是PREPARE声明。

所以做一个

PREPARE myStmt 
  FROM 'SELECT * FROM (SELECT ? ) AS tmp WHERE NOT EXISTS (
    SELECT Identifier FROM eeg WHERE Identifier = ?
    ) LIMIT 1'

会更准确地重现您的问题。

现在,似乎PREPARE很难理解 _出现在FROM子句中的_参数化嵌套查询。看下面的例子:

PREPARE myStmt FROM "select * from (select ? from eeg) tmp";

(无效)

PREPARE myStmt FROM "select *,? from (select * from eeg) tmp";

(作品)

PREPARE myStmt FROM "select *,? from (select 'asdf') tmp";

(作品)

PREPARE myStmt FROM "select * from eeg where Identifier in (select ?)";

(作品)

行为举止奇怪,但是我只能猜测, 当嵌套SELECTFROM子句中的具有参数时,MySQL会缺少准备语句的线索

至于我的建议,如果我了解您要执行的操作,则在嵌套选择中不需要参数。您可以将其移到外部,并在嵌套的select中硬编码一个常量FROM。以下代码

if ($usertest = $datasqli->prepare("INSERT INTO eeg (Identifier) 
    SELECT ? from (select 1) tmp WHERE ? NOT IN
      (SELECT Identifier FROM eeg WHERE Identifier = ?)")) {

…应该可以解决问题。

2021-05-16