使用 WHERE NOT EXISTS 的 SQL 查询出错

Posted

技术标签:

【中文标题】使用 WHERE NOT EXISTS 的 SQL 查询出错【英文标题】:Error with SQL query with WHERE NOT EXISTS 【发布时间】:2015-01-10 19:51:03 【问题描述】:

我的目标

我正在尝试执行以下 sql 查询:

INSERT INTO api(site,key) VALUES ('example.com','a-random-key') WHERE NOT EXISTS (SELECT * FROM api WHERE site='example.com');

如果该站点还没有一个站点和相应的键,则为了插入一个新行(例如,如果存在,则插入带有关联键“a-random-key”的“example.com” t 网站“example.com”的其他记录)。

什么不工作

我收到以下错误:

#1064 - 您的 SQL 语法有错误;检查与您的 mysql 服务器版本相对应的手册以获取正确的语法使用 'WHERE NOT EXISTS (SELECT * FROM api WHERE site='example.com')'附近 在第 1 行

我尝试过的

我尝试分别执行这两个查询,它们都可以工作。

我的问题

我怎样才能使查询工作?

【问题讨论】:

Where 子句也不能在插入查询中使用,因为您的问题在站点列上添加唯一索引 I'd read that it's possible,我没有注意到第一个“选择”。感谢您的建议:按照它,我能否使用 php 的 mysqli_num_rows() 检查记录是否实际插入? 再次查看链接的答案 where 子句用于选择语句而不是插入 是的,我刚刚注意到了,你是对的,谢谢你的帮助 【参考方案1】:

正如人们所建议的那样,更好的方法是在站点列上添加一个唯一索引(这样,如果站点存在,它就不会被插入)。无论如何,如果这不是一个选项,我会尝试这个查询:

INSERT INTO api(site, `key`)
SELECT * FROM (SELECT 'example.com','a-random-key') AS tmp
WHERE NOT EXISTS (SELECT * FROM api WHERE site='example.com') LIMIT 1;

【讨论】:

谢谢,这行得通!如果我添加一个唯一索引,我是否能够使用 PHP 的 mysqli_num_rows() 检查记录是否实际插入,还是必须使用其他方法? @Stubborn,如果您添加唯一索引,则不会插入记录 - 您可能希望捕获引发的错误。 我很抱歉,它有效,但在 SQL Fiddle 中至少 key 必须被反引号包围 @DavidFaber 谢谢 :) 我将用反引号更新答案【参考方案2】:

我想你想试试这样的:

INSERT INTO api (site, `key`)
SELECT 'example.com','a-random-key'
  FROM dual
 WHERE NOT EXISTS (SELECT * FROM api WHERE site='example.com');

我认为WHERE NOT EXISTS 不能在没有选择的情况下用于INSERT 查询。请参阅SQL Fiddle demo here。此外,如果您不使用FROM dual,上述SELECT 语句将不起作用。

更新第二个问题是key 列应该被反引号包围......我认为 MySQL 对此感到窒息,因为它是一个保留字。

【讨论】:

是的,请参阅我链接到的 SQL Fiddle 演示。我相信它是在 MySQL 5.0 中添加的。 @David Faber:我在您的示例中没有看到FROM DUAL,但是是的,它有效。这很有趣,谢谢。 @zerkms,它在右侧,在表创建之后。至少,我看到了! 就我个人而言,我发现 FROM dual 有效但查询如果省略则不起作用。 @DavidFaber 在给定的链接中是`SELECT * FROM api` :-) 你可能修改了它但没有提供新链接

以上是关于使用 WHERE NOT EXISTS 的 SQL 查询出错的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Laravel Eloquent 创建多个 Where 子句查询?

为啥这个查询使用 where 而不是索引?

如何使用数组查询数据库? WHERE = '数组()'

如何在 WHERE 子句(MySQL)中使用 VIEW?

Swift之where一般使用场景

如何在 laravel 中使用 orWhere() 和 where