避免在 INSERT INTO 中出现重复 table

Avoid duplicates in INSERT INTO in the same table

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

        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”的字段出现重复项。 因此,例如,如果我已经拥有伦敦及其数据,我不想再次添加它,即使它的所有数据可能都已更改。我只想在我的 table.

中拥有它一次

我有这个插入查询:

        String sql = "INSERT INTO weather VALUES(?,?,?,?,?,?,?);";

我想对其进行修改,以免插入重复的城市。 谁能帮帮我吗?谢谢!

您现在可以使用 on conflict。这要求您在 city 上有一个唯一的 index/constraint,但它已被定义为主键。检查。

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

SQLite 也允许 shorthand:

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

在 'effectively standard SQL'*.

中无法执行此操作

但是,每个单独的数据库引擎通常都有一些实现此目标的方法。

概念 称为合并或更新插入 - 您可以在网上搜索这些术语。例如,只需搜索 'how to postgres upsert'。之所以称为 upsert,是因为更一般的应用是:如果我要插入的值的某些子集在数据库中尚不存在,则使用该数据插入一个新行。否则,找到该子集具有相同值的行,然后用它更新所有其他值。例如:“找到 ID 为 12345 的学生,然后将姓名更改为 'Joe Bloggs'。如果没有行,则创建它”。

将所有值设为 'the key' 并且您已将 'insert, ignore if it is already there' 缩减为标准 UPSERT。

在 psql 中,您可以执行 ON CONFLICT。搜索 'mysql upsert' 可以让您找到根据您的具体需求提供不同策略的博客文章,使用 INSERT IGNORE (我建议不要这样做,这会忽略所有错误,而只忽略 'already in here' 仅错误),在重复密钥更新时(更好的主意,这个),或使用替换。

对于您在此处使用的任何数据库引擎,都可以找到类似的博文。

*) 未定义为 'as per some version of the SQL standard',而是定义为:'works in the majority of existing DB engines'.

如果你使用的SQLite版本是3.24.0+并且city列有唯一约束,你可以使用upsert如果发生 唯一约束违规 ,这使您可以选择执行 NOTHINGUPDATE table。

在这种情况下:

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 的值。