Sqlite3 user defined datatype - sqlite

I can create table like this:
CREATE TABLE mytable
(
name text,
surname varchar
)
I can also create table like this:
CREATE TABLE mytable2
(
name BLABLA,
surname mygrandpaType
)
I know there is no diff between text and varchar in SQLite. But even in second table I can insert and select querys from it and works fine..
It does not make sense what is it use for datataype approach in SQLite ?

Any column with the exception of INTEGER PRIMARY KEY can hold values of any type. The specified datatype is just a hint and it is called type affinity.
Determining type affinity:
If the declared type contains the string "INT" then it is assigned INTEGER affinity.
If the declared type of the column contains any of the strings "CHAR", "CLOB", or "TEXT" then that column has TEXT affinity. Notice that the type VARCHAR contains the string "CHAR" and is thus assigned TEXT affinity.
If the declared type for a column contains the string "BLOB" or if no type is specified then the column has affinity NONE.
If the declared type for a column contains any of the strings "REAL", "FLOA", or "DOUB" then the column has REAL affinity.
Otherwise, the affinity is NUMERIC.
Therefore your BLABLA column gets the NUMERIC affinity.
Further reading: https://www.sqlite.org/datatype3.html

Related

Query SQLite using uuid returns nothing

I'm querying a SQLite db file using the id column, which is UNIQUEIDENTIFIER type.
The two commands are :
SELECT * FROM scanned_images WHERE id = cast('5D878B98-71B2-4DEE-BA43-61D11C8EA497' as uniqueidentifier)
or
SELECT * FROM scanned_images WHERE id = '5D878B98-71B2-4DEE-BA43-61D11C8EA497'
However, the above commands both returned nothing.
I also tried:
SELECT * FROM scanned_images WHERE rowid = 1
this command returns the correct data.
There is no uniqueidentifier data type in SQLite.
According to the rules of type affinity described here in 3.1. Determination Of Column Affinity, the column's affinity is numeric.
All that this expression does:
cast('5D878B98-71B2-4DEE-BA43-61D11C8EA497' as uniqueidentifier)
is return 5.
You should have defined the column's data type as TEXT, because you have to treat it like TEXT and write the condition:
WHERE id = '5D878B98-71B2-4DEE-BA43-61D11C8EA497'
or:
WHERE id = '(5D878B98-71B2-4DEE-BA43-61D11C8EA497)'
if as shown in the image it contains surrounding parentheses.

How to drop a column's default value?

I have a table with this:
MyField VARCHAR(50) CHARACTER SET LATIN NOT CASESPECIFIC DEFAULT ''
I want to drop the default empty string value so that it defaults to null. I've discovered that I can set the default value to null, but then it actually says DEFAULT NULL in the DDL. This toys with the scripts I use to compare DDL diffs between multiple database environments, so I want to look simply like this:
MyField VARCHAR(50) CHARACTER SET LATIN NOT CASESPECIFIC
Edit: I am wanting this to behave the same as if I were changing a column from NOT NULL to nullable.
Non-nullable column:
n INTEGER NOT NULL
Nullable column:
n INTEGER
Notice how the latter doesn't say:
n INTEGER NULL
You need to drop and create the column as below:
alter table DBC.TEST
drop MY_FIELD
alter table DBC.TEST
ADD MY_FIELD VARCHAR(50)
I have tested it and its working.

How to create SQLite index for different datatype

When I create index on certain column, index is datatype-aware, however I can store data of any type in any column, but it makes the index somewhat useless if I want to compare column content using different comparison rules, e.g. compare numbers as numbers, not strings.
Example:
sqlite> create table foo (key varchar, value varchar);
sqlite> create index foo_ndx on foo (key, value);
sqlite> insert into foo values ('bar', 10);
sqlite> select * from foo where key = 'bar' and value > 9.0;
sqlite> explain query plan select * from foo where key = 'bar' and value > 9.0;
0|0|0|SEARCH TABLE foo USING COVERING INDEX foo_ndx (key=? AND value>?) (~2 rows)
In this case 9.0 gets implicitly casted as varchar and two varchars get compared, index is used fully, but the record cannot be found.
sqlite> select * from foo where key = 'bar' and CAST(value AS REAL) > 9.0;
bar|10
sqlite> explain query plan select * from foo where key = 'bar'
...> and CAST(value AS REAL) > 9.0;
0|0|0|SEARCH TABLE foo USING COVERING INDEX foo_ndx (key=?) (~5 rows)
In this case I cast value to real explicitly and two reals get compared, sqlite finds the record, but the index used only partially.
This is understandable behaviour, however can I somehow create index on foo table that will treat column value as REAL? I've tried using CAST in CREATE INDEX but got syntax error, I can create view on foo table with CAST, but index cannot be created on view.
Indexes are not data type aware.
By default, values in the value column are treated as text, if possible, because the column has text affinity.
Using an index does not change this behaviour.
If you do not want to treat numbers as text, do not declare the column as varchar. (Note: you can declare columns without any data type.)

sqlite3: how to detect rowid alias column (primary key)

Using SQLite3, if you create a table like this:
CREATE TABLE MyTable (
id int primary key,
--define other columns here--
)
it turns out sqlite3_column_type(0) always returns SQLITE_NULL.
If I read on a bit, this may well be by design because this column is actually an alias to the internal rowid field.
Still, what is the programatical way to determine a certain column is an/the alias to the rowid field?
(Perhaps related, can I use sqlite3_column_type(x)==SQLITE_NULL to determine if the field of the current record holds NULL?)
According to http://www.sqlite.org/draft/lang_createtable.html#rowid
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.
So in your case it's "int" so invalid alias

How do I specify a Primary Key in Sqlite

How to define your specified attribute like StudentId in student table as Primary key in sqlite
CREATE TABLE Student(
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT
);
From the Sqlite spec:
One exception to the typelessness of
SQLite is a column whose type is
INTEGER PRIMARY KEY. (And you must use
"INTEGER" not "INT". A column of type
INT PRIMARY KEY is typeless just like
any other.) INTEGER PRIMARY KEY
columns must contain a 32-bit signed
integer. Any attempt to insert
non-integer data will result in an
error.
http://www.sqlite.org/datatypes.html
You can also place a primary key on the arbitrary blobish data eg:
CREATE TABLE Student(id PRIMARY KEY, name)
Its a bit risky cause
INSERT INTO Student(1, "hello")
INSERT INTO Student("1", "hello")
will result in two rows.
If you need a unique constraint on other stuff you can try using the Create Index command
CREATE TABLE Students (
StudentId INTEGER PRIMARY KEY,
Name VARCHAR(80)
)
is one simple way.

Resources