SQite - AUTO INCREMENT does not work - sql

I've a table TABLE1 with my data. Another clean table TABLE2 as follow:
"TABLE2"(ipt TEXT,instant NUM, id integer auto_increment);
I want to select IP and instant in TABLE1 and insert it into TABLE2 but I don't know why the auto_increment doesn't work.
If someone has an idea.

AUTOINCREMENT can only be used in one situation. and that is for a column defined with a type/constraint of INTEGER PRIMARY KEY.
auto_increment is not a valid keyword and if you used column id integer auto_increment the result would be a column named id with a type of integer auto_increment which would then effectively be a column type of INTEGER i.e. the column's type affinity would be INTEGER. Datatypes In SQLite Version 3
i.e. you must have exactly column_name INTEGER PRIMARY KEY AUTOINCREMENT. (case is irrelevant)
It can also only be coded once per table.
INTEGER PRIMARY KEY with or without AUTOINCREMENT is a special case where the named column is made to be an alias of the rowid column. The rowid being a column that uniquely identifies the row, which is generally hidden (for want of a better description). rowid will not exists if the table is created with the WITHOUT ROWID keyword(s). In which case AUTOINCREMENT cannot be coded within a column definition.Clustered Indexes and the WITHOUT ROWID Optimization
Saying that it is almost certain that you do not in fact need to code AUTOINCREMENT just coding column_name INTEGER PRIMARY KEY will very likely be sufficient and better for your needs. The column will still be given a unique identifier. an integer (64 bit signed) 1 for the first row inserted then likely 2, 3, 4 .....
- Note there is no guarantee that numbering will be sequential/monotonically increased.
Adding AUTOINCREMENT only ensures that the unique identifier is greater and in doing so imposes a limit that the identifier when reaching the highest possible value will subsequently result in an SQLITE_FULL exception, whilst without unused/free values (e.g. deleted rows) that are lower than the highest could be utilised.
To quote the SQLite documentation :-
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and
disk I/O overhead and should be avoided if not strictly needed. It is
usually not needed.
SQLite Autoincrement

Related

CockroachDB Unordered Row ID

Why does CockroachDB add a rowid column to my tables? They are INT values and do not look ordered, does this column give up the sort order and/or impact how range scans work?
CockroachDB automatically adds a rowid column that serves as a primary key if no primary key is specified for the table. rowid values are generated as a combination of the insert timestamp and the ID of the node executing the statement, as such, ordering is maintained.
To create your own rowid, two functions are commonly used:
unique_rowid(): ensures a unique integer for a primary key, value always increases
unordered_unique_rowid(): ensures a unique integer for a primary key but the rowid value does not always increase. Having rowid values that do not always increase helps divide the key-space more evenly, preventing range hotspots.
Helpful docs from CockroachDB:
Create a table
Auto-generate unique row ids
ID generation functions
Helpful Blog Post:
CockroachDB Key Generation Part 3 - Unordered RowID

Sqlite - composite PK with two auto-incrementing values [duplicate]

I have a composite primary key {shop_id, product_id} for SQLite
Now, I want an auto-increment value for product_id which resets to 1 if shop id is changed. Basically, I want auto-generated composite key
e.g.
Shop ID Product Id
1 1
1 2
1 3
2 1
2 2
3 1
Can I achieve this with auto-increment? How?
Normal Sqlite tables are B*-trees that use a 64-bit integer as their key. This is called the rowid. When inserting a row, if a value is not explicitly given for this, one is generated. An INTEGER PRIMARY KEY column acts as an alias for this rowid. The AUTOINCREMENT keyword, which can only be used on said INTEGER PRIMARY KEY column, contrary to the name, merely alters how said rowid is calculated - if you leave out a value, one will be created whether that keyword is present or not, because it's really the rowid and must have a number. Details here. (rowid values are generally generated in increasing, but not necessarily sequential, order, and shouldn't be treated like a row number or anything like that, btw).
Any primary key other than a single INTEGER column is treated as a unique index, while the rowid remains the true primary key (Unless it's a WITHOUT ROWID table), and is not autogenerated. So, no, you can't (easily) do what you want.
I would probably work out a database design where you have a table of shops, a table of products, each with their own ids, and a junction table that establishes a many-to-many relation between the two. This keeps the product id the same between stores, which is probably going to be less confusing to people - I wouldn't expect the same item to have a different SKU in two different stores of the same chain, for instance.
Something like:
CREATE TABLE stores(store_id INTEGER PRIMARY KEY
, address TEXT
-- etc
);
CREATE TABLE product(prod_id INTEGER PRIMARY KEY
, name TEXT
-- etc
);
CREATE TABLE inventory(store_id INTEGER REFERENCES stores(store_id)
, prod_id INTEGER REFERENCES product(prod_id)
, PRIMARY KEY(store_id, prod_id)) WITHOUT ROWID;

Date sqlite3 in a CREATE TABLE

I am following a tutorial and encountered the following code. What does date mean here? I thought date was not supported in sqlite3.
create table log_date (
id integer primary key autoincrement,
entry_date date not null
);
SQLite does not have a DATE type, but that doesn't mean it won't let you use it in a CREATE TABLE and then use a different data type underneath.
DATE is converted to NUMERIC as described in Affinity Name Examples.
There's a prioritized set of rules to determine what a not-formally-supported type gets converted to, and DATE/DATETIME both work out to NUMERIC.
date is the type affinity, which due to SQLite's flexibility is actually a type affinity of NUMERIC (see 3.1 in the link below for how the type affinity is determined).
The type affinity specified can be virtually anything (not KEYWORDS and there are limitations in regards to values in parenthesises). A type affinity of grUmpleStiltskin is even usable (again gets converted to the NUMERIC bucket).
However, due to SQLite's flexibility any type of data can be stored in any type of column (with the exception of a column that is an alias of the rowid (as is your id column as it has INTEGER PRIMARY KEY), an alias of the rowid column, or the rowid column itself can only store an Integer value (64 bit signed)).
You may wish to have a read of Datatypes In SQLite Version 3.
one called ID that has to be an integer, it is assigned a unique key
and updates (w.e that means).
As said because you have INTEGER PRIMARY KEY then the id column is an alias of the normally hidden rowid column. If no value is specified when inserting a row then SQLite will attempt to assign a unique 64 bit integer value. It will typically be 1 greater than the highest existing rowid.
AUTOINCREMENT, as you have coded, introduces a rule/constraint that only values higher than the highest used (even if deleted) rowid value. AUTOINCREMENT can only be used for columns that are aliases of the rowid column can be used.
However, the very first sentence in SQLite Autoincrement is :-
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and
disk I/O overhead and should be avoided if not strictly needed. It is
usually not needed.

If I use SQLite auto increment on a column, does it automatically maintain an index on that column?

I am using auto increment on an integer data column in SQLite. Since it is auto increment, the data is already sorted by that column in ascending order. So, I was wondering if SQLite will perform a binary search over the auto increment column whenever a data is searched by that column.
Effectively yes, but not really.
That is, all AUTOINCREMENT does is add a constraint that requires the value assigned to the column to be higher than any existing value, or higher than any value that has been used, in that column.
But there's more to it than that it is your_column INTEGER PRIMARY KEY (AUTOINCREMENT can only be used on such a column and there can only be 1 such column per table) makes that column an alias of the hidden rowid column.
The rowid is what is indexed, and is basically the most primary index and the most efficient, which always exists unless the table is defined using the WITHOUT ROWID keyword.
So an AUTOINCREMENT column is an alias of the rowid column and uses a differnt, more expensive algorithm than an alias of the rowid without AUTOINCREMENT.
That is without AUTOINCREMENT the value generated for the rowid column will find the maximum value in the table and increment it. Unless that value exceeds 9223372036854775807 in which case SQlite will make some attempts to find an unused lower value (normally between 1 and 9223372036854775807).
With AUTOINCREMENT the algorithm takes the higher value of the maximum value and a value stored in the table sqlite_sequence for the respective table and uses that (thus any deleted higher valueswill not be re-used). However if 9223372036854775807 has been used then an SQLITE_FULL error will be raised.
The following should be noted :-
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and
disk I/O overhead and should be avoided if not strictly needed. It is
usually not needed.
SQLite Autoincrement you may well want to read this.
Additional
regrading the comment :-
If I don't use AUTOINCREMENT I have to explicitly create unique
integer IDs and then insert them in database each time a new row is
inserted.
The following demonstrates that there is no requirement for AUTOINCREMENT:-
CREATE TABLE IF NOT EXISTS xyz (ID INTEGER PRIMARY KEY);
INSERT INTO xyz VALUES(null);
SELECT * FROM xyz;
After running twice the result is :-

SQLite: Using ROWID in lieu of a timestamp

Can I use the ROWID in place of a timestamp in an SQLite table?
I need to get the 50 most recent items of an SQLite table, I was thinking about using a separate timestamp field, but then I figured a bigger ROWID means a newer item, and the ROWID is already there, no need to change the schema.
Well, as it says here (with my emphasis):
The data for rowid tables is stored as a B-Tree structure containing
one entry for each table row, using the rowid value as the key. This
means that retrieving or sorting records by rowid is fast. Searching
for a record with a specific rowid, or for all records with rowids
within a specified range is around twice as fast as a similar search
made by specifying any other PRIMARY KEY or indexed value.
However, it also says:
Rowid values may be modified using an UPDATE statement in the same way
as any other column value can, either using one of the built-in
aliases ("rowid", "oid" or "rowid") or by using an alias created by
an integer primary key.
It would certainly be faster, but it sort of hurts my feeling for "open" design, in that you're relying on a feature of the implementation rather than making it specific.
Having said that, the same link also says this:
With one exception noted below, if a rowid table has a primary key
that consists of a single column and the declared type of that column
is "INTEGER" in any mixture of upper and lower case, then the column
becomes an alias for the rowid. Such a column is usually referred to
as an "integer primary key". A PRIMARY KEY column only becomes an
integer primary key if the declared type name is exactly "INTEGER".
Other integer type names like "INT" or "BIGINT" or "SHORT INTEGER" or
"UNSIGNED INTEGER" causes the primary key column to behave as an
ordinary table column with integer affinity and a unique index, not as
an alias for the rowid.
Which I think gives you the perfect answer:
Define an INTEGER primary key on your table and use that for selection. You'll get the speed of using the ROWID (because as it says above, it's just an alias) and you'll get visibility in the schema of what you're doing.