Java 避免在同一表中插入重复项
我有一个JAVA程序,它在数据库中创建一个表,然后在这个表中插入行。 该表创建如下:Java 避免在同一表中插入重复项,java,sql,sqlite,duplicates,upsert,Java,Sql,Sqlite,Duplicates,Upsert,我有一个JAVA程序,它在数据库中创建一个表,然后在这个表中插入行。 该表创建如下: String sql = "CREATE TABLE IF NOT EXISTS weather (\n" + " city string,\n" + " temp real,\n" + " feels_like real,\n"
String sql = "CREATE TABLE IF NOT EXISTS weather (\n"
+ " city string,\n"
+ " temp real,\n"
+ " feels_like real,\n"
+ " temp_min real,\n"
+ " temp_max real,\n"
+ " pressure integer,\n"
+ " humidity integer\n"
+ ");";
添加行时,我不希望名为“city”的字段有重复的行。
因此,例如,如果我已经有了伦敦的数据,我不想再添加它,即使它的所有数据可能已经改变了。我只想在桌子上放一次
我有以下要插入的查询:
String sql = "INSERT INTO weather VALUES(?,?,?,?,?,?,?);";
我想修改它,这样我就不会插入重复的城市。
有人能帮我吗?谢谢 您现在可以使用。这要求您在city
上具有唯一的索引/约束,但它已定义为主键。检查
insert into weather ( . . . )
values ( . . . )
on conflict (city) ignore;
SQLite还允许这种速记:
insert or ignore into weather ( . . . )
values ( . . . );
在“有效的标准SQL”中没有办法做到这一点* 但是,每个单独的DB引擎通常都有一些实现这一目标的方法 这个概念被称为合并或升级-这些是你可以在网上搜索的术语。例如,只需搜索“如何升级postgres”。之所以称为upsert,是因为更一般的应用是:如果我插入的值的某个子集在DB中还不存在,请插入一个包含此数据的新行。否则,请为该子集找到具有相同值的行,然后用它更新所有其他值。例如:“找到ID为12345的学生,然后将其名称更改为‘Joe Bloggs’。如果没有包含该名称的行,则将其更改为” 将所有值都设置为“关键值”,然后将“插入,如果已经存在则忽略”减少为标准的UPSERT 在psql中,您可以在冲突上执行操作。搜索“mysql upsert”会让你看到博客文章,这些文章根据你的具体需要提供不同的策略,从使用
INSERT IGNORE
(我建议不要这样做,这会忽略任何和所有错误,而不是只忽略“已经在这里”错误)、重复密钥更新(更好的主意,这一点)或使用REPLACE
您在这里使用的任何db引擎都可以找到类似的博客文章
*)未定义为“根据SQL标准的某些版本”,但定义为:“适用于大多数现有DB引擎”。如果您使用的SQLite版本为3.24.0+,并且对列
city
有唯一的约束,如果发生唯一约束冲突,您可以使用该选项执行无操作
或更新
表格。在这种情况下:
String sql =
"INSERT INTO weather VALUES(?,?,?,?,?,?,?) " +
"ON CONFLICT DO NOTHING";
如果您试图插入一个包含现有城市的行,则该语句将不会出错。
但是,如果新行包含其他列的最新数据,并且希望更新该行,则可以执行以下操作:
String sql =
"INSERT INTO weather VALUES(?,?,?,?,?,?,?) " +
"ON CONFLICT(city) DO UPDATE SET "
"temp = excluded.temp, " +
"feels_like = excluded.feels_like, " +
"temp_min = excluded.temp_min, " +
"temp_max = excluded.temp_max, " +
"pressure = excluded.pressure, " +
"humidity = excluded.humidity";
其他6列将被您提供的新值覆盖
如果没有为city
定义唯一约束,并且您不想或无法定义一个约束,则可以避免在不存在的情况下插入同一城市两次,如下所示:
String sql =
"INSERT INTO weather SELECT ?,?,?,?,?,?,? " +
"WHERE NOT EXISTS (SELECT 1 FROM weather WHERE city = ?);
在这种情况下,您必须将Java代码作为附加的第8个参数再次传递city
的值。我尝试了这两个参数,但它们似乎都不起作用。他们不断添加同一城市的行。您使用的是哪个版本的SQLite?自SQLite版本3.24以来,就一直支持这一点。否决票是相当粗鲁的,因为这个答案引用了说明代码工作的SQLite文档。@GordenLinoff这是PSQLese,除非您有一个正确的唯一索引或PK定义,否则根本不起作用。它也不适用于mssql、mysql和许多其他DB引擎。。。。哦,这个问题的标签(现在?)包括sqlite。没关系,继续:)@GordonLinoff这是3.32版。为什么不把城市定义为独一无二的呢?我尝试了你所有的选择,但都不起作用。他们不断添加同一个城市。@WillWost我注意到你编辑了你的问题并从城市中删除了主键。为什么?如果city是主键,那么前两个查询应该可以工作。最后一个在任何情况下都有效。发布您实际执行的Java代码。我编辑它是因为我不希望城市成为主键。这只是我做的一个测试,但我忘了删除它。我现在通过创建一个新的数据库重试,您向我提出的第一个查询可以工作。这正常吗?我为城市添加了两个约束:notnull和UNIQUE。@WillWost当然这是正常的。这就是它的工作原理。如果存在唯一的约束冲突,ON CONFLICT DO NOTHING
子句将使语句不执行任何操作。我还有另一个问题,请回答。在第二个查询中,排除的是什么?我不明白。非常感谢你!