Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No autoincrement for Integer Primary key in sqlite3

Tags:

In the sqlite3 faq, it is mentioned that an integer primary key being fed a null value would autoincrement. But this is not happening for me.

to replicate, a table in sqlite3, CREATE TABLE dummy( serial_num INTEGER PRIMARY KEY, name TEXT); and fill it using python,

import sqlite3 as lite con = lite.connect('some.db') cur=con.cursor() data = "someone's name" cur.execute("INSERT INTO dummy VALUES(NULL, ?)", data) con.commit() 

The first attribute serial_num is being shown blank while the name attribute is fine. When I do SELECT serial_num FROM dummy I just get a bunch of blank spaces. What am I doing wrong?

like image 298
yayu Avatar asked Jul 15 '12 07:07

yayu


People also ask

How can create autoincrement primary key in SQLite?

SQLite AUTOINCREMENT is a keyword used for auto incrementing a value of a field in the table. We can auto increment a field value by using AUTOINCREMENT keyword when creating a table with specific column name to auto increment. The keyword AUTOINCREMENT can be used with INTEGER field only.

What is integer primary key autoincrement?

Auto-increment allows a unique number to be generated automatically when a new record is inserted into a table. Often this is the primary key field that we would like to be created automatically every time a new record is inserted.

Do primary keys need to auto increment?

To have an auto-increment PK makes it easy to create a key that never needs to change, which in turn makes it easy to reference in other tables. If your data is such that you have natural columns that are unique and can never change you can use them just as well.

Does primary key have to be unique SQLite?

Primary keys must contain unique values. A primary key column cannot have NULL values. A table can have only one primary key, which may consist of single or multiple fields.


2 Answers

This is one of SQLite's quirks. From the fine manual:

According to the SQL standard, PRIMARY KEY should always imply NOT NULL. Unfortunately, due to a long-standing coding oversight, this is not the case in SQLite. Unless the column is an INTEGER PRIMARY KEY SQLite allows NULL values in a PRIMARY KEY column. We could change SQLite to conform to the standard (and we might do so in the future), but by the time the oversight was discovered, SQLite was in such wide use that we feared breaking legacy code if we fixed the problem.

The documentation on INTEGER PRIMARY KEY is a little unclear about what precisely is required for a column to be this special INTEGER PRIMARY KEY that auto-increments but the reality is that the column needs to be NOT NULL if you want to use the NULL value to mean "give me the next auto-incrementing value" when inserting:

create table dummy (     serial_num integer primary key not null,     name text ); 

If you leave out the not null, you need to do your inserts like this:

insert into dummy (name) values (?) 

to get the auto-increment value for serial_num. Otherwise, SQLite has no way of telling the difference between a NULL meaning "give me the next auto-increment value" and a NULL meaning "put a NULL value in serial_num because the column allows NULLs".

like image 76
mu is too short Avatar answered Oct 14 '22 22:10

mu is too short


The insert syntax provided above does not seem to work in the absence of not null.

Here's an example - note that the ID field is not autoincremented even though I use the insert format that you specified above.

sqlite> .schema logTable CREATE TABLE logTable (ID INTEGER PRIMARY_KEY, ts REAL, level TEXT, message TEXT); sqlite> INSERT into LOGTABLE (ts, level, message) VALUES (111, "autoinc test", "autoinc test"); sqlite> select * from logtable where ts = 111; |111.0|autoinc test|autoinc test sqlite>  

It does work with the NOT NULL workaround.

sqlite> create TABLE logTable (ID INTEGER PRIMARY KEY NOT NULL, ts REAL, level TEXT, message TEXT); sqlite> INSERT into LOGTABLE (ts, level, message) VALUES (222, "autoinc test", "autoinc test");  sqlite> select * from logtable where ts = 222; 1|222.0|autoinc test|autoinc test 

I apologize for posting this as a new answer instead of commenting on the previous answer, but my reputation score is too low to add comments, and I thought that it was important to note that the alternate insert statement is not an adequate workaround.

like image 22
Shankari Avatar answered Oct 14 '22 22:10

Shankari