So I've been learning a lot of SQL in school using MySQL , Oracle and SQL Server. So now i need to work with SQLite on a raspberry pi project. The thing I don't understand is datatypes. When you put your field to be int it can only save whole numbers right? And in SQLite it can save integers inside of a int datatype. So i have been reading about it and how SQLite saves data in these groups:
NULL. The value is a NULL value.
INTEGER. The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value.
REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number.
TEXT. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16LE).
BLOB. The value is a blob of data, stored exactly as it was input.
So it only makes a difference when saving data and not on input? I can't understand it.. How can I make my INT columns not accept integers? Or it isn't possible?
The SQLite dialect of SQL is a dynamically-typed language. Just like Python will let you create an array of mixed types like [None, 42, 3.14, 'Hello, world!', b'\x01\x23'], SQLite will let you store values of multiple types in the same column.
Storage classes
Conceptually, SQLite has five scalar data types, called “storage classes”:
The NULL type is used for the singleton value NULL, which is a sentinel value indicating an unknown or not-applicable value.
The INTEGER type is a 64-bit signed integer. The part about “stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value” is an implementation detail of the file format, and not something you as a programmer need to be concerned with. From the point of view of the C API and the SQL language, it's always 8 bytes.
The REAL type is a 64-bit floating-point number.
The TEXT type is a character string.
The BLOB type is a sequence of octets. SQL literals are X-prefixed strings of hex digits (e.g., X'0123456789ABCDEF').
If you're a Python 3.x programmer, you can think of:
NULL = None (of type NoneType)
INTEGER = int (but limited to 64 bits)
REAL = float
TEXT = str
BLOB = bytes
(This is actually the type mapping used by Python's standard sqlite3 module.)
If you're a C# programmer, you can think of:
NULL = null (but without the arbitrary distinction between value types and reference types)
INTEGER = long
REAL = double
TEXT = string
BLOB = byte[]
SQLite lets you store a value of any data type in any column. (Exception: If a column is declared as INTEGER PRIMARY KEY, and its table is not declared WITHOUT ROWID, then it actually is constrained to contain only integers, because it is an alias for the row ID.)
Column type affinity
Independent of the above list of “storage classes”, SQLite has the concept of type affinity which determines the preferred data type to store in a column. The affinitity of a column is determine by its declared datatype.
Only numeric (INTEGER and REAL) and TEXT values are affected by these automatic type conversions; there is never any implicit conversion to or from the NULL or BLOB storage classes.
So, if you declare a column with integer affinity (e.g., INT or INTEGER), but you insert a text string into it, then SQLite will automatically convert the value to an integer for you. But if it can't, it leaves it as a string. So, the string '42' becomes the integer 42, but the string 'xyz' stays as-is.
Real-affinity columns (REAL, FLOAT, DOUBLE) are similar, except that they attempt to convert strings into REAL values instead of INTEGER values. Numeric-affinity columns (NUMERIC, DECIMAL) convert strings to numbers, but will happily allow INTEGER and REAL values in the same column.
Text-affinity columns (CHAR, VARCHAR, TEXT, CLOB) will make the opposite conversion: All numbers (integer or real) are converted to strings.
Blob-affinity columns (BLOB or no declared data type) leave all values as-is.
No, it is wrong to say that in SQLite if you declare an INT column it will only accept integer values. In SQLite, you can store any datatype in any column. Therefore, you can declare the column AGE INTEGER and store the value 'I am pretty old', of type TEXT in that column.
This is quite different from virtually every other relational database, which requires the type of the value to match the type of the column it is stored in.
The actual value determines the type.
Similar to Excel.
You don't even have to define types for columns, e.g. -
create table t (c1,c2,c3);
https://www.sqlite.org/datatype3.html
Datatypes In SQLite
Most SQL database engines (every SQL database engine other than
SQLite, as far as we know) uses static, rigid typing. With static
typing, the datatype of a value is determined by its container - the
particular column in which the value is stored.
SQLite uses a more general dynamic type system. In SQLite, the
datatype of a value is associated with the value itself, not with its
container. The dynamic type system of SQLite is backwards compatible
with the more common static type systems of other database engines in
the sense that SQL statements that work on statically typed databases
should work the same way in SQLite. However, the dynamic typing in
SQLite allows it to do things which are not possible in traditional
rigidly typed databases.
drop table if exists t;
create table t (studentId int);
insert into t (studentId) values (1),(2),('Say what?'),(3),('Yep!');
select studentId from t;
sqlite> drop table if exists t;
sqlite> create table t (studentId int);
sqlite> insert into t (studentId) values (1),(2),('Say what?'),(3),('Yep!');
sqlite> select studentId from t;
studentId
----------
1
2
Say what?
3
Yep!
sqlite> .header on
sqlite> drop table t;
sqlite> create table t (studentId text);
sqlite> insert into t (studentId) values (1),(2),('Say what?'),(3),('Yep!');
sqlite> select studentId,studentId * 10 from t;
studentId studentId * 10
---------- --------------
1 10
2 20
Say what? 0
3 30
Yep! 0
Related
I'm learning SQL and SQLite at the moment, and from what I understand, SQLite doesn't support a datetime datatype.
However, when I run the command PRAGMA table_info(Orders); it's showing one column as being of type datetime.
I've read that In SQLite, the datatype of a value is associated with the value itself, not with its container. taken from here https://www.sqlite.org/datatype3.html
I'm trying to understand what exactly this means, which may help to explain.
Can someone help me understand what's going on here?
What you see in the column type when you execute:
PRAGMA table_info(tablename)
or:
SELECT * FROM pragma_table_info('tablename');
is the data type that was used for the definition of the column in the CREATE TABLE statement.
SQLite allows the use of anything (even nothing), as long as it is not a reserved word, as a data type.
This:
CREATE TABLE tablename (
column0 integer primary key,
column1 integer,
column2 text,
column3 real,
column4 string,
column5 something,
column6 Jack,
column7, -- no data type defined
column8 real char int -- ??,
column9 datetime
);
is a valid statement!
From all the above column definitions, SQLite will enforce type checking only for the column column0 which is defined as integer primary key.
From Datatypes In SQLite Version 3/Storage Classes and Datatypes:
Any column in an SQLite version 3 database, except an INTEGER PRIMARY
KEY column, may be used to store a value of any storage class.
When you define a column as datetime, don't expect SQLite to understand your intention and set any internal constraints so that the values you store in it will be datetime-like.
Actually, by the rules described in Determination Of Column Affinity, this column will have NUMERIC affinity.
Of course you can store datetime values in a column, as described in Date and Time Datatype, by using INTEGER, REAL or TEXT data type, depending on the form of the datetimes that you want: Unix Times, Julian day numbers or ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS") strings respectively.
In conclusion, SQLite will never complain for any value in any column defined as any data type (except for integer primary key).
It is your responsibility to make sure that you store values in the proper format that you can read/write, make calculations, compare etc.
For example, never store text datetimes in any other format than "YYYY-MM-DD HH:MM:SS.SSS" because all SQLite's datetime functions work with this format only.
To amplify #forpas's excellent answer, you can make up for SQLite's weak type-checking by using CHECK constraints in your table definitions. I frequently do that to enforce integers or string lengths, and you could use SQLite's date functions to verify that the value can be parsed as a date and lies between two values.
New to SQL. Say I run this query:
SELECT COUNT(SupplierID) AS "TotalSuppliers"
FROM Products;
This will return a single row with a field called "TotalSuppliers". In my database, the result was "778".
When tested in C# using typeof, the type for this field was short (the ODBC SMALLINT or OleDB SmallInt data type). This matched the data type of the SupplierID column.
Do I have control over the type used for the alias/temporary column? For example, is it possible to run COUNT or SUM on a column that is ODBC SMALLINT and use the INTEGER or DOUBLE data type in the output?
You can convert in the query:
select cast(count(*) as double) as TotalSuppliers
However, this is the type in the database. ODBC is still responsible for the conversion to your application type.
Note: In most databases, count(*) should be returning an int -- usually 4 bytes. I wonder if on your system smallint is really 4 bytes.
If you're just running a query you can cast the result like Gordon suggested.
If you need the column in a stored table you can create a table and insert the value of the COUNT or SUM to a column in the table that is either ODBC SMALLINT and use the INTEGER or DOUBLE data type.
Using the alias/temporary values you assign it to.
If I create a table in sqlite3 like:
create table sodapops (name text, description varchar(10));
What does the number 10 in varchar do? How would it be any different than 255 or otherwise?
In any other database, it would specify the maximum length of the field.
However, SQLite ignores it. All strings are simply of text type and can be of any length.
As explained in the documentation:
Note that numeric arguments in parentheses that following the type
name (ex: "VARCHAR(255)") are ignored by SQLite - SQLite does not
impose any length restrictions (other than the large global
SQLITE_MAX_LENGTH limit) on the length of strings, BLOBs or numeric
values.
I've got an Sqlite DB where the data looks purely numeric (integers) and the column is typed TEXT. I would like to type it as INTEGER if possible.
What query can check if every cell of a certain column can be successfully casted to INT?
SELECT * FROM table WHERE INT(column) != NULL
Alternatively I would like to check if the cells are numeric (don't have any letters/symbols)
SELECT * FROM table WHERE column NOT LIKE "%a-z%"
As a side note, I wanted to do this to reduce the size of the DB, but since Sqlite uses dynamic typing (per cell typing) would this have ANY effect on the size of the DB?
You have to check whether all values can be converted into an integer:
SELECT *
FROM MyTable
WHERE CAST(MyColumn AS INTEGER) IS NOT MyColumn;
i'm having problems to create a table in particular, this is my table
Create table EmpleadosCursos(Empleado constraint fk1_empleadoscursos references empleados,Curso constraint fk2_empleadoscursos references cursos,constraint pk_empleadoscursos primary key(empleado,curso),fecha date);
But it returns this error "Error: near "fecha": syntax error"
I can't find why, I tried with datetime too, but it didn't work
I believe that you need to have a name for your third column, something like below. :)
CREATE TABLE EmpleadosCursos(
Empleado constraint fk1_empleadoscursos references empleados,
Curso constraint fk2_empleadoscursos references cursos,
COLUMN_NAME constraint pk_empleadoscursos primary key(empleado,curso),
Fecha date
)
There is no date/time field type in SQLite. As described:
Each value stored in an SQLite database (or manipulated by the
database engine) has one of the following storage classes:
NULL. The value is a NULL value.
INTEGER. The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value.
REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number.
TEXT. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16LE).
BLOB. The value is a blob of data, stored exactly as it was input.
Either store Fecha as a text '2016-04-12 12:00:00' or numeric equivalent value, 1460419200 (epoch UTC format or seconds since 1970-01-01). And practically any general purpose language (Java, C#, Perl, Python, PHP) can convert prior to import or update.