Reputation: 3733
I did a couple searches first, and still have a question.
Far and away, the best answer I've found is in this SO answer. Summarized:
SELECT * FROM TABLE WHERE ID = (SELECT MAX(ID) FROM TABLE);
What I want to know is if the following method work just as well (because I'm too lazy to change it and I happen to like it).
SELECT * FROM TABLE ORDER BY ID DESC LIMIT 1
According to the SQLite Autoincrement documentation we have,
If no ROWID is specified on the insert, or if the specified ROWID has a value of NULL, then an appropriate ROWID is created automatically. The usual algorithm is to give the newly created row a ROWID that is one larger than the largest ROWID in the table prior to the insert. If the table is initially empty, then a ROWID of 1 is used. [emphasis added]
and further,
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. If you ever delete rows or if you ever create a row with the maximum possible ROWID, then ROWIDs from previously deleted rows might be reused when creating new rows and newly created ROWIDs might not be in strictly ascending order. [emphasis added]
My question about my proposed SQL statement comes from the last sentence. It seems to indicate that a previously deleted ROWID can be reused if you delete any row, regardless of the whether the maximum ROWID has been used. If we assume that the maximum ROWID is never used (either manually or by just that many records), then we only need to worry about deleting records. In such a case, the first SQLite documnetation excerpt makes it sound like you won't run into any problems with my query.
Does anyone know for sure?
I like my query because it involves only one select (albiet, at the cost of an order by). I suppose, I'm probably focusing too much on tiny optimizations, aren't I?
EDIT: Actually, re-reviewing the SQLite page referenced above, I think that using the AUTOINCREMENT keyword guarantees a monotonically increasing ROWID. The last section talks at length about it.
If a column has the type INTEGER PRIMARY KEY AUTOINCREMENT then a slightly different ROWID selection algorithm is used. The ROWID chosen for the new row is at least one larger than the largest ROWID that has ever before existed in that same table. If the table has never before contained any data, then a ROWID of 1 is used. If the table has previously held a row with the largest possible ROWID, then new INSERTs are not allowed and any attempt to insert a new row will fail with an SQLITE_FULL error.
Seems pretty clear to me now. Just can't fill up the table (maximum of 9223372036854775807).
Sorry that I had only skimmed this portion earlier!
Upvotes: 3
Views: 19009
Reputation: 51
Figured I'd put a little note here about the speed that the two queries run.
On a table with about 15,000 rows, grabbing 1400 of them and then getting the last entered one, here's what results I got:
SELECT macAddr, time, onPeakTotalIn, onPeakTotalOut, offPeakTotalIn, offPeakTotalOut FROM trafficMon WHERE macAddr="02:d2:ee:aa:aa:aa" ORDER BY time DESC LIMIT 1;
CPU Time: user 0.008124 sys 0.000000
Virtual Machine Steps: 58741
Fullscan Steps: 14156
SELECT macAddr, time, onPeakTotalIn, onPeakTotalOut, offPeakTotalIn, offPeakTotalOut FROM trafficMon WHERE id = (SELECT MAX(id) FROM trafficMon WHERE macAddr="02:d2:ee:aa:aa:aa");
CPU Time: user 0.000295 sys 0.000000
Virtual Machine Steps: 49
Fullscan Steps: 3
As you can see, it's a lot easier to do the MAX(id) resource wise and takes much less time to do it.
While 0.008124s is bugger all time, when you run the same command on a MIPS based embedded device (in my case, a router), running it 20-30x in a script along with a bunch of other stuff, it all adds up.
Upvotes: 5
Reputation: 11
If table has a field the type 'autoincrement', then is better to use:
SELECT seq FROM sqlite_sequence WHERE name='TABLE_NAME'
see the sample (for table 'customers'):
SELECT seq FROM sqlite_sequence WHERE name='customers'
Upvotes: 1
Reputation: 328
First of all you should retrieve last inserted row id then from that row id you can get last inserted record by your select query.
RowID = sqlite3_last_insert_rowid(sqlite3Database)
SELECT * FROM tableName where RowID=RowID
this select statement will give you a last inserted record
get more detail in this link.
Upvotes: 1
Reputation: 41170
The two queries you show are equivalent.
As to whether they return the last record, that depends on what you mean by "last." If you delete rows you cannot rely on either query to return the last inserted row.
Upvotes: 3