避免在同一个表的insert中重复

c2e8gylq  于 2021-07-08  发布在  Java
关注(0)|答案(3)|浏览(407)

我有一个java程序,它在数据库中创建一个表,然后在这个表中插入行。表格创建如下:

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(?,?,?,?,?,?,?);";

我想修改它,这样我就不会插入重复的城市。有人能帮我吗?谢谢!

lskq00tm

lskq00tm1#

在“有效的标准sql”中没有办法做到这一点。
但是,每个单独的db引擎通常都有一些方法来实现这个目标。
这个概念被称为合并或升级-这些是你可以在网上搜索的术语。例如,只需搜索“how to postgres upsert”。之所以称为upsert,是因为更一般的应用是:如果我插入的值的某个子集在db中还不存在,请插入一个包含此数据的新行。否则,为该子集找到具有相同值的行,然后用它更新所有其他值。例如:“找到id为12345的学生,然后把名字改成‘joe bloggs’。如果没有争吵,那就做吧”。
将所有值都设为“键”,然后将“insert,ignore if it already there”缩减为标准的upsert。
在psql中,可以对冲突进行处理。搜索“mysql upsert”会让你看到一些博客文章,这些文章会根据你的具体需求提供不同的策略,包括使用 INSERT IGNORE (我不建议这样做,这忽略了任何和所有的错误,而不是只忽略'已经在这里'错误),在重复密钥更新(更好的主意,这),或使用替换。
类似的博客文章将发现任何数据库引擎你在这里使用。

  • )不是定义为“根据sql标准的某些版本”,而是定义为:“适用于大多数现有的db引擎”。
2j4z5cfb

2j4z5cfb2#

如果您使用的sqlite版本是3.24.0+,并且列有唯一的约束 city ,您可以使用 upsert 这给了你一个选择 NOTHING 或者 UPDATE 如果发生唯一约束冲突,则返回表。
在这种情况下:

String sql = 
    "INSERT INTO weather VALUES(?,?,?,?,?,?,?) " +
    "ON CONFLICT DO NOTHING";

如果您尝试插入一个具有现有 city ,则语句将失败而不出错。
但是,如果新行包含其他列的最新数据,并且希望更新该行,则可以执行以下操作:

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 如果你不想或者不能定义一个城市,那么你就可以避免在同一个城市中插入两次 NOT EXISTS 这样地:

String sql = 
    "INSERT INTO weather SELECT ?,?,?,?,?,?,? " +
    "WHERE NOT EXISTS (SELECT 1 FROM weather WHERE city = ?);

在这种情况下,您必须将java代码作为附加的第8个参数传递 city 再一次。

slwdgvem

slwdgvem3#

您现在可以使用 on conflict . 这要求您在上有唯一的索引/约束 city 但它已经被定义为主键。检查。

insert into weather ( . . . )
    values ( . . . )
    on conflict (city) ignore;

sqlite还允许这种速记:

insert or ignore into weather ( . . . )
    values ( . . . );

相关问题