簡體   English   中英

避免在同一個表中 INSERT INTO 重復

[英]Avoid duplicates in INSERT INTO in the same table

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

我想修改它,這樣我就不會插入城市重復項。 有人可以幫我嗎? 謝謝!

如果您使用的 SQLite 版本是3.24.0+並且列city有一個唯一約束,您可以使用upsert ,如果發生唯一約束沖突,您可以選擇不執行NOTHINGUPDATE表。

在這種情況下:

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

在“有效的標准 SQL”* 中無法做到這一點。

但是,每個單獨的數據庫引擎通常都有一些方法來實現這個目標。

這個概念稱為合並或更新插入 - 這些是您可以在網絡上搜索的術語。 例如,只需搜索“如何 postgres upsert”。 之所以稱為 upsert,是因為更通用的應用是:如果我要插入的值的某個子集在數據庫中尚不存在,則使用此數據插入一個新行。 否則,為該子集找到具有相同值的行,然后用它更新所有其他值。 例如:“找到 ID 為 12345 的學生,然后將名稱更改為 'Joe Bloggs'。如果沒有包含該行的行,則創建它”。

使所有值成為“關鍵”,並且您已將“插入,如果它已經存在則忽略”減少到標准 UPSERT。

在 psql 中,您可以執行 ON CONFLICT。 搜索 'mysql upsert' 可以讓您閱讀博客文章,根據您的具體需求為您提供不同的策略,從使用INSERT IGNORE (我反對這個,這會忽略任何和所有錯誤,而只忽略“已經在這里”錯誤) ), ON DUPLICATE KEY UPDATE (更好的主意, 這個), 或使用 REPLACE.

您在此處使用的任何數據庫引擎都可以找到類似的博客文章。

*) 不是定義為“根據 SQL 標准的某些版本”,而是定義為:“適用於大多數現有數據庫引擎”。

您現在可以使用on conflict 這要求您對city具有唯一索引/約束,但它已被定義為主鍵。 查看。

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

SQLite 也允許這種速記:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM