SQLite UPSERT / UPDATE OR INSERT

后端 未结 7 625
时光说笑
时光说笑 2020-11-28 18:08

I need to perform UPSERT / INSERT OR UPDATE against a SQLite Database.

There is the command INSERT OR REPLACE which in many cases can be useful. But if you want to k

7条回答
  •  有刺的猬
    2020-11-28 18:40

    Option 1: Insert -> Update

    If you like to avoid both changes()=0 and INSERT OR IGNORE even if you cannot afford deleting the row - You can use this logic;

    First, insert (if not exists) and then update by filtering with the unique key.

    Example

    -- Table structure
    CREATE TABLE players (
        id        INTEGER       PRIMARY KEY AUTOINCREMENT,
        user_name VARCHAR (255) NOT NULL
                                UNIQUE,
        age       INTEGER       NOT NULL
    );
    
    -- Insert if NOT exists
    INSERT INTO players (user_name, age)
    SELECT 'johnny', 20
    WHERE NOT EXISTS (SELECT 1 FROM players WHERE user_name='johnny' AND age=20);
    
    -- Update (will affect row, only if found)
    -- no point to update user_name to 'johnny' since it's unique, and we filter by it as well
    UPDATE players 
    SET age=20 
    WHERE user_name='johnny';
    

    Regarding Triggers

    Notice: I haven't tested it to see the which triggers are being called, but I assume the following:

    if row does not exists

    • BEFORE INSERT
    • INSERT using INSTEAD OF
    • AFTER INSERT
    • BEFORE UPDATE
    • UPDATE using INSTEAD OF
    • AFTER UPDATE

    if row does exists

    • BEFORE UPDATE
    • UPDATE using INSTEAD OF
    • AFTER UPDATE

    Option 2: Insert or replace - keep your own ID

    in this way you can have a single SQL command

    -- Table structure
    CREATE TABLE players (
        id        INTEGER       PRIMARY KEY AUTOINCREMENT,
        user_name VARCHAR (255) NOT NULL
                                UNIQUE,
        age       INTEGER       NOT NULL
    );
    
    -- Single command to insert or update
    INSERT OR REPLACE INTO players 
    (id, user_name, age) 
    VALUES ((SELECT id from players WHERE user_name='johnny' AND age=20),
            'johnny',
            20);
    

    Edit: added option 2.

提交回复
热议问题