Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I return inserted ids for multiple rows in SQLite?

Tags:

sqlite

Given a table:

CREATE TABLE Foo(
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    Name TEXT
);

How can I return the ids of the multiple rows inserted at the same time using:

INSERT INTO Foo (Name) VALUES
('A'),
('B'),
('C');

I am aware of last_insert_rowid() but I have not found any examples of using it for multiple rows.

What I am trying to achieve can bee seen in this SQL Server example:

DECLARE @InsertedRows AS TABLE (Id BIGINT);
INSERT INTO [Foo] (Name) OUTPUT Inserted.Id INTO @InsertedRows VALUES 
    ('A'),
    ('B'),
    ('C');
SELECT Id FROM @InsertedRows;

Any help is very much appreciated.

like image 761
MaYaN Avatar asked Oct 05 '16 13:10

MaYaN


People also ask

Does SQLite insert return ID?

SQLite has a special SQL function – last_insert_rowid() – that returns the ID of the last row inserted into the database so getting the ID of a new row after performing a SQL insert just involves executing the last_insert_rowid() command.

Which of the following methods is used to insert multiple rows at a time in sqlite3 Python?

Python Insert multiple rows into SQLite table using the cursor's executemany()

Does SQLite support bulk insert?

SQLite doesn't have any special way to bulk insert data. To get optimal performance when inserting or updating data, ensure that you do the following: Use a transaction. Reuse the same parameterized command.

How do I find the row ID in SQLite?

ROWID doesn't enumerate the rows, it gives you the row ID, which is an internal ID used by sqlite, but ROW_NUMBER() is a function that generates sequential numbers for every result set.

How to get the ID of the last row inserted in SQLite?

SQLite has a special SQL function – last_insert_rowid () – that returns the ID of the last row inserted into the database so getting the ID of a new row after performing a SQL insert just involves executing the last_insert_rowid () command. Here is an example in C# showing how to get the ID of the last row inserted into a table in a database.

How to insert multiple rows into a table in SQLite?

SQLite INSERT – Inserting multiple rows into a table. To insert multiple rows into a table, you use the following form of the INSERT statement: INSERT INTO table1 (column1,column2 ,..) VALUES (value1,value2 ,...), (value1,value2 ,...), ... (value1,value2 ,...); Each value list following the VALUES clause is a row that will be inserted into ...

How to insert individual as well as multiple rows in MSSQL?

We use the INSERT statement to insert the data into the database. In this article, we see how to insert individual as well as multiple rows in a database using the INSERT statement in the MSSQL server.

How do you insert a row in a mySQL table?

SQLite provides various forms of the INSERT statements that allow you to insert a single row, multiple rows, and default values into a table. In addition, you can insert a row into a table using data provided by a SELECT statement.


2 Answers

This is not possible. If you want to get three values, you have to execute three INSERT statements.

like image 177
CL. Avatar answered Oct 23 '22 14:10

CL.


Given SQLite3 locking:

An EXCLUSIVE lock is needed in order to write to the database file. Only one EXCLUSIVE lock is allowed on the file and no other locks of any kind are allowed to coexist with an EXCLUSIVE lock. In order to maximize concurrency, SQLite works to minimize the amount of time that EXCLUSIVE locks are held.

And how Last Insert Rowid works:

...returns the rowid of the most recent successful INSERT into a rowid table or virtual table on database connection D.

It should be safe to assume that while a writer executes its batch INSERT to a ROWID-table there can be no other writer to make the generated primary keys non-consequent. Thus the insert primary keys are [lastrowid - rowcount + 1, lastrowid]. Or in Python SQLite3 API:

cursor.execute(...)  # multi-VALUE INSERT
assert cursor.rowcount == len(values)
lastrowids = range(cursor.lastrowid - cursor.rowcount + 1, cursor.lastrowid + 1)

In normal circumstances when you don't mix provided and expected-to-be-generated keys or as AUTOINCREMENT-mode documentation states:

The normal ROWID selection algorithm described above will generate monotonically increasing unique ROWIDs as long as you never use the maximum ROWID value and you never delete the entry in the table with the largest ROWID.

The above should work as expected.

This Python script can be used to test correctness of the above for multi-threaded and multi-process setup.

Other databases

For instance, MySQL InnoDB (at least in default innodb_autoinc_lock_mode = 1 "consecutive" lock mode) works in similar way (though obviously in much more concurrent conditions) and guarantees that inserted PKs can be inferred from lastrowid:

"Simple inserts" (for which the number of rows to be inserted is known in advance) avoid table-level AUTO-INC locks by obtaining the required number of auto-increment values under the control of a mutex (a light-weight lock) that is only held for the duration of the allocation process, not until the statement completes

like image 31
saaj Avatar answered Oct 23 '22 13:10

saaj