SQLite - UPSERT *not* INSERT or REPLACE

后端 未结 18 3022
猫巷女王i
猫巷女王i 2020-11-21 23:53

http://en.wikipedia.org/wiki/Upsert

Insert Update stored proc on SQL Server

Is there some clever way to do this in SQLite that I have not thought of?

18条回答
  •  夕颜
    夕颜 (楼主)
    2020-11-22 00:16

    If someone wants to read my solution for SQLite in Cordova, I got this generic js method thanks to @david answer above.

    function    addOrUpdateRecords(tableName, values, callback) {
    get_columnNames(tableName, function (data) {
        var columnNames = data;
        myDb.transaction(function (transaction) {
            var query_update = "";
            var query_insert = "";
            var update_string = "UPDATE " + tableName + " SET ";
            var insert_string = "INSERT INTO " + tableName + " SELECT ";
            myDb.transaction(function (transaction) {
                // Data from the array [[data1, ... datan],[()],[()]...]:
                $.each(values, function (index1, value1) {
                    var sel_str = "";
                    var upd_str = "";
                    var remoteid = "";
                    $.each(value1, function (index2, value2) {
                        if (index2 == 0) remoteid = value2;
                        upd_str = upd_str + columnNames[index2] + "='" + value2 + "', ";
                        sel_str = sel_str + "'" + value2 + "', ";
                    });
                    sel_str = sel_str.substr(0, sel_str.length - 2);
                    sel_str = sel_str + " WHERE NOT EXISTS(SELECT changes() AS change FROM "+tableName+" WHERE change <> 0);";
                    upd_str = upd_str.substr(0, upd_str.length - 2);
                    upd_str = upd_str + " WHERE remoteid = '" + remoteid + "';";                    
                    query_update = update_string + upd_str;
                    query_insert = insert_string + sel_str;  
                    // Start transaction:
                    transaction.executeSql(query_update);
                    transaction.executeSql(query_insert);                    
                });
            }, function (error) {
                callback("Error: " + error);
            }, function () {
                callback("Success");
            });
        });
    });
    }
    

    So, first pick up the column names with this function:

    function get_columnNames(tableName, callback) {
    myDb.transaction(function (transaction) {
        var query_exec = "SELECT name, sql FROM sqlite_master WHERE type='table' AND name ='" + tableName + "'";
        transaction.executeSql(query_exec, [], function (tx, results) {
            var columnParts = results.rows.item(0).sql.replace(/^[^\(]+\(([^\)]+)\)/g, '$1').split(','); ///// RegEx
            var columnNames = [];
            for (i in columnParts) {
                if (typeof columnParts[i] === 'string')
                    columnNames.push(columnParts[i].split(" ")[0]);
            };
            callback(columnNames);
        });
    });
    }
    

    Then build the transactions programmatically.

    "Values" is an array you should build before and it represents the rows you want to insert or update into the table.

    "remoteid" is the id I used as a reference, since I'm syncing with my remote server.

    For the use of the SQLite Cordova plugin, please refer to the official link

提交回复
热议问题