autoincrement column remembers its last value in SQLite table - sqlite

In one table I have a column that's an auto-incrementing primary key.
The problem is this scenario:
4 rows are inserted
those 4 are then subsequently deleted
insert a new row, and the the auto-increment column value is 5
How can I get this auto-increment column to have value of 1?

An SQLite Autoincrement field will increment forever.It will not replace the deleted value.It will replace deleted value only if it exists maximum possible value.See this . What you are trying to achieve is not possible using autoincrement field.You have to do it programtically.

Instead of using auto increment you can just use integer primary key it will work fine. Even if your row is deleted one by one, the next increment will be done properly. If you leave the integer primary key field empty, the max value of the row is taken and a 1 is added (it's like max(value)+1). It works fine for me.

if we have a primary which is autoincrement, the value will not be same even if you delete all the existing entries. It will continue from where it stopped on last insert. if you want the primary key to start from 1 again, you need to truncate the table or delete & recreate the table.
In SQLite "truncate" command is not valid. You can use a "Delete from tablename" and "vacuum tablename" to reset the primary key count to start from 1. Please make sure there is no "where" clause in delete command.

Related

SQLite Copy Table Content from one Table to another Table and Update

I have two SQLite files, each of them has one table and the same table design. One Column is set as Primary Key. I want to copy all data from ItemsB into ItemsA. All data should be updated. The ItemsB Table is the newer one.
I've tried:
ATTACH DATABASE ItemsB AS ItemsB;
INSERT INTO ItemsA.PMItem (ItemID,VarID,Name1) SELECT ItemID,VarID,Name1 FROM ItemsB.PMItem;
Obviously this can't work due the Primary Key (which is the column VarID).
Then I tried it with ON CONFLICT:
ON CONFLICT (VarID) DO UPDATE SET Name1=excluded.Name1
But this won't work either.
Example Table:
CREATE TABLE PMItem (
ItemID INTEGER,
VarID INTEGER PRIMARY KEY,
Name1 TEXT
);
You need a WHERE clause with an always true condition, to overcome the ambiguity that is raised when ON CONFLICT is used after a SELECT statement:
INSERT INTO PMItem (ItemID,VarID,Name1)
SELECT ItemID,VarID,Name1
FROM ItemsB.PMItem
WHERE 1
ON CONFLICT(VarID) DO UPDATE
SET Name1 = EXCLUDED.Name1;

Insert or ignore every column

I have a problem with a sqlite command.
I have a table with three columns: Id, user, number.
The id is continuing. Now if I put a user and a number inside my list, my app should compare if such a user with this number already exist. The problem is, if I use a standard "insert or ignore" command, the Id column is not fixed, so I will get a new entry every time.
So is it possible just two compare two of three columns if they are equal?
Or do I have to use a temporary list, where are only two columns exist?
The INSERT OR IGNORE statement ignores the new record if it would violate a UNIQUE constraint.
Such a constraint is created implicitly for the PRIMARY KEY, but you can also create one explicitly for any other columns:
CREATE TABLE MyTable (
ID integer PRIMARY KEY,
User text,
Number number,
UNIQUE (User, Number)
);
You shouldn't use insert or ignore unless you are specifying the key, which you aren't and in my opinion never should if your key is an Identity (Auto number).
Based on User and Number making a record in your table unique, you don't need the id column and your primary key should be user,number.
If for some reason you don't want to do that, and bearing in mind in that case you are saying that User,Number is not your uniqueness constraint then something like
if not exists(Select 1 From MyTable Where user = 10 and Number = 15)
Insert MyTable(user,number) Values(10,15)
would do the job. Not a SqlLite boy, so you might have to rwiddle with the syntax and wrap escape your column names.

SQLite: Reset primary key field error

i am working with sqlite and i need to reset the auto increment values,
I found on StackOverflow:
SQLite Reset Primary Key Field
but when i do
delete from sqlite_sequence where name='my_table';
all I got is :
Error: no such table: sqlite_sequence
Did someone know the problem ?
I am on an iMac with sqlite3.
Thanks for help !
Have a nice day
There are two types of autoincrementing columns, ones declared as INTEGER PRIMARY KEY, and ones declared as INTEGER PRIMARY KEY AUTOINCREMENT.
Columns with AUTOINCREMENT have a record in the sqlite_sequence table, and can be reset with the above DELETE statement.
Plain INTEGER PRIMARY KEY columns are still autoincrementing, but derive the next value from the largest actual value in the table.
These can be simply reset by deleting all records from the data table itself.
I tested it on my own sqlite DB and it works fine.
See my Fiddle Demo.
Maybe in your case it could simply be a mistake of your spelling of your table name?
Or a misspelling on keyword sqlite_sequence maybe.

The ids of a table in my sqlite database have been reset

I have an iPhone app and one of my users found a really strange problem with my application. I can't reproduce the problem and I can't figure out why it's happening. Maybe you can?
In Sqlite I have a table with about 1000 rows, each with a unique id. But for some reason the id of that table has restarted, before it was around 1000 but now it's restarted from 80 something. So everytime the user inserts a new row the new assigned id starts around 80 something and I get two duplicates ids that should be unique and yeah you can understand the problem. I have looked at all queries that does anything to that table and none of them could have done this. I always relay on the built in mechanism where the ids are assigned automatically.
Have you seen anything like this?
The schema of the table looks like this:
CREATE TABLE mytable(
id INTEGER PRIMARY KEY
);
As you can see I don't use AUTOINCREMENT. But from what I understand even if the user deletes a row with id 80, it is ok to give a new inserted row id 80 but not like it works now where the database just keeps incrementing the ids even if I have already have rows with the same id. Shouldn't it work like this:
HIGHEST ROWID IS 1000, ALL IDS FROM 0-1000 ARE TAKEN
USER DELETES ROW WITH ID 80
INSERT A NEW ROW
THE ID OF THE INSERTED ROW MIGHT NOW BE 80
SETS THE ID OF THE INSERTED ROW TO 80
INSERT A NEW ROW
THE ID OF THE INSERTED ROW CAN NOT BE 81 AS THIS IS ALREADY TAKEN
SETS THE ID OF THE INSERTED ROW TO 1001
Isn't that how it should work?
Did you declare your id column as a(n autoincrementing) primary key?
CREATE TABLE mytable(
id INTEGER PRIMARY KEY AUTOINCREMENT
);
By adding the autoincrement keyword you ensure that all keys generated will be unique over the lifetime of your table. By omitting it, the keys will still be unique, but it may generate keys that have already been used by other, deleted entries. Note that using autoincrement can cause problems, so read up on it before you add it.
Edit This is a bit of a long-shot, but sqlite only supports one primary key per table. If you have more than one primary key declared, you need to declare all but the one you actually want to use as a primary key as "unique". Hence
CREATE TABLE mytable(
id INTEGER PRIMARY KEY,
otherId INTEGER UNIQUE
);
Hard to say without the code and schema, but my instinct is that this unique ID is not defined as either unique nor primary key, which they should.
How do you make sure (in theory) id's are unique? What is your insert query like?

Set start value for AUTOINCREMENT in SQLite

How can I set the start value for an AUTOINCREMENT field in SQLite?
From the SQLite web site:
SQLite keeps track of the largest ROWID that a table has ever held using the special SQLITE_SEQUENCE table. The SQLITE_SEQUENCE table is created and initialized automatically whenever a normal table that contains an AUTOINCREMENT column is created. The content of the SQLITE_SEQUENCE table can be modified using ordinary UPDATE, INSERT, and DELETE statements. But making modifications to this table will likely perturb the AUTOINCREMENT key generation algorithm. Make sure you know what you are doing before you undertake such changes.
I tried this, and it works:
UPDATE SQLITE_SEQUENCE SET seq = <n> WHERE name = '<table>'
Where n+1 is the next ROWID you want and table is the table name.
Explicitly insert the value-1 into the table, then delete the row.
Edit: the next comment down, which discusses editing the SQLITE_SEQUENCE table directly is probably preferable: https://stackoverflow.com/a/692871/10093
I am using the below query which solves the problem when the sqlite_sequence does not have a record for the table (i.e. first record was not added yet to the table), otherwise it updates the sequence.
BEGIN TRANSACTION;
UPDATE sqlite_sequence SET seq = <n> WHERE name = '<table>';
INSERT INTO sqlite_sequence (name,seq) SELECT '<table>', <n> WHERE NOT EXISTS
(SELECT changes() AS change FROM sqlite_sequence WHERE change <> 0);
COMMIT;
One way to do it is to insert the first row specifying explicitly the row id you want to start with. SQLite will then insert row ids that are higher than the previous highest.
In solution with SQLITE_SEQUENCE table, the entry into this table seems to be added after the first insert into the table with the autoincrement column is added. In some cases this might cause troubles (i.e autoincrement still starts from 1, not from wanted value).
Just wanted to add a few notes to the very much appreciated answer from iTech:
The name column in sqlite_sequence is case sensitive. (Perhaps its only me, but coming from other databases I always assume that string comparison is case insensitive).
SQLite seems to be robust: if the number in sqlite_sequence is wrong and would lead to a duplicated rowid value, sqlite will use the next available number for the rowid (checked with sqlite 3.28)
Same is true if the row in sqlite_sequence gets deleted.
I used as suggested in a comment the "WHERE NOT EXISTS SELECT name from sqlite_sequence WHERE name = 'table'" instead of checking "changes()"
I tried this and it works good:
FOR INSERT
INSERT INTO sqlite_sequence (name, seq) VALUES ('<table name>', <value>)
TO UPDATE
UPDATE sqlite_sequence SET seq = <value> WHERE name= '<table name>'

Resources