Date sqlite3 in a CREATE TABLE - sql

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.

Related

Postgresql change column type from UUID to int4

I wanted to change dataType of column from UUID to int4
ALTER TABLE tableA ALTER COLUMN columnA TYPE int4(32);
But it is giving me an error.
ERROR: type modifier is not allowed for type "int4"
I tried to search on internet and found that I have to use USING but don't know how to use it.
You cannot really turn a UID into an int. There are just too many values, so you run the risk of collisions (which rises to 100% as the table gets bigger).
My guess is that you really want an id column on the table. If so, add a new column and remove the old one:
alter table tableA add a_id int generated always as identity,
drop columnA;
Note: in older versions of Postgres, you would use serial instead of int generated always as identity.
Your 32 is syntactically treated as a modifier. Modifiers are allowed for numeric and decimal types, but not for plain ints, int4(xxx) is not a valid type in Postgres (I believe it is in mysql) int4 is just an alias for integer.

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 :-

SQite - AUTO INCREMENT does not work

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

NVARCHAR with variable length?

I want to create a table in SQL which has a string attr for Users of a website. How should I declare this attr, since names don't have a max length? Can I just leave the length empty and do it like this?
CREATE TABLE User(
id NUMBER PRIMARY KEY NOT NULL
name NVARCHAR
)
Also, do I need to say NOT NULL for PRIMARY KEYS, or are primary keys already never null?
Thanks in advance :)
You should declare length as MAX and primary key are automatically NOT NULL
CREATE TABLE User(
id NUMBER PRIMARY KEY
name NVARCHAR(MAX)
)
Since you have later specified dbms as SQL Lite , the documentation says
What is the maximum size of a VARCHAR in SQLite?
SQLite does not enforce the length of a VARCHAR. You can declare a
VARCHAR(10) and SQLite will be happy to let you put 500 characters in
it. And it will keep all 500 characters intact - it never truncates.
How should I declare this attr, since names don't have a max length?
Can I just leave the length empty and do it like this?
Yes, in SQLite you can just declare the column with any “text affinity” type name (CHAR, TEXT, CLOB, etc.) and it will store strings (or blobs) without length restriction (except for the global string length limit, which is 1 GB by default).
If you do want to constrain the length of strings, you can do it with an explicit CHECK constraint, like CHECK(LENGTH(name) <= 100).
Also, do I need to say NOT NULL for PRIMARY KEYS, or are primary keys
already never null?
Per the SQL standard, PRIMARY KEY implies NOT NULL. However, SQLite has a long-standing bug that makes the explicit NOT NULL constraint required.
According to the SQL standard, PRIMARY KEY should always imply NOT NULL. Unfortunately, due to a bug in some early versions, this is not
the case in SQLite. Unless the column is an INTEGER PRIMARY KEY or the
table is a WITHOUT ROWID table or the column is declared NOT NULL,
SQLite allows NULL values in a PRIMARY KEY column. SQLite could be
fixed to conform to the standard, but doing so might break legacy
applications. Hence, it has been decided to merely document the fact
that SQLite allowing NULLs in most PRIMARY KEY columns.

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.