Java 仅当行未插入时插入';不存在

Java 仅当行未插入时插入';不存在,java,mysql,sql,Java,Mysql,Sql,我正在使用PreparedStatement准备sql查询。我想在表中插入一行,当且仅当它不存在时 我试过这个- INSERT INTO users (userId) VALUES (?) ON DUPLICATE KEY UPDATE userId = ? 但这将不必要地更新用户ID 如何在此处插入userId 您可以使用 INSERT INTO users (userId) SELECT ? WHERE NOT EXISTS (

我正在使用PreparedStatement准备sql查询。我想在表中插入一行,当且仅当它不存在时

我试过这个-

INSERT INTO users (userId) VALUES (?) ON DUPLICATE KEY UPDATE userId = ?
但这将不必要地更新用户ID

如何在此处插入
userId

您可以使用

INSERT  INTO users 
        (userId) 
SELECT  ?
WHERE   NOT EXISTS
        (
        SELECT  * 
        FROM    users 
        where   userId = ?
        )
 INSERT IGNORE INTO users (userId) VALUES (?) 

但是您应该理解为什么要忽略错误。

当表是innodb时,重复键上的错误无法正常工作。这恰恰造成了你所描述的问题。如果需要innodb的功能,那么应该首先检查行的存在,否则可以将该表转换为myisam表

编辑:如果在决定插入或更新之前需要检查行的存在性,那么我建议您使用存储过程

DELIMITER //
CREATE PROCEDURE adjustusers(IN pId int)
BEGIN
DECLARE userid int;
  select  count(id) into userid from users where id = pId;
  if userid = 1 then
   update users set id = pId where id = pId;
  else
   insert into users(id) values(pId);
  end if;
END //
DELIMITER ; 

预编译存储过程,就像预编译语句一样。因此,没有SQL注入问题,也没有更多功能,只需对数据库进行一次调用。

让数据库返回重复键上的异常并进行处理。您要查找的关键字是
UPSERT
。我不建议忽略错误。它们应该被处理,而不是被忽略。@LuiggiMendoza。我明白这通常是应该处理的。但如果行存在时确实需要什么都不做,您是否要编写
catch{do nothing}
block?我将处理异常。这取决于结果将如何影响应用程序。例如,如果用户输入数据并试图保存数据,应用程序应该显示一条消息,如抱歉,这是dup条目或其他内容(当然,我会使用正式消息)。如果是针对实习生流程,我至少会记录异常,然后发布一个策略:停止流程,继续发出警告,等等…IDK,但由于您没有得到任何支持,我无法确定哪种方法更好…您的答案还是RiaD的另一个答案?我的答案有更复杂的SQL,RiaD的回答将默默地忽略转换错误。两个人都有话要说。@Andomar。我想补充一点,这是标准SQL。好的,谢谢!我将用你的答案回答一个简单的问题,这个策略是否安全?如果是,请解释这在并行执行时的行为。然后,您没有其他选择,请先检查行的存在: