I have a sqlite BD with a table that contains coordinates of a large polyline (about 2000 characters). The structure of BD is:
CREATE TABLE "province" (
`_id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
`_line` TEXT,
);
The format of values of _line is:
lat1,lon1;lat2,lon2;lat3,lon3;lat4,lon4 ...
A little example:
28.164033,-15.709076;28.151925,-15.699463;28.134972,-15.703583;28.121650,-15.707703;28.107115,-15.704956;28.079250,-15.713196;28.067133,-15.735168
Right now, field _line is TEXT type on SQLite Android database. In my class DAO I parse this string to an ArrayList, thats is a list of points.
My question is, it will be recomended change of _line datatype from TEXT to BLOB? Will be improve the performance?
In the database itself, TEXT and BLOB values are stored in exactly the same way. The only difference is the type reported to the application, or the behaviour of the built-in string functions.
However, the Android framework will automatically convert TEXT values between the database encoding (UTF-8) and the Java string encoding (UTF-16). This does not happen for BLOB values.
If you store your values as blobs, you can read them out of the database in exactly the same format in which you stored them there, but you risk that that format is UTF-16, which would waste lots of space.
Related
I need to use number value greater than 64 bits do sqlite database will store it.
SQLite only supports five datatypes: TEXT, INTEGER, REAL, BLOB, and NULL. However, both Integer and Real can only store 8-byte values(64-bits). If your big-int variable is greater than 8 digits/bytes you have to use a workaround. First, convert the number to a string before saving it to SQLite and then parse it to an integer/bigInt/double once you retrieve it. If the number is too big (longer than 256 bytes), you can opt to store it as a string using the BLOB data type.
How can I find the tables having column Blob type in Sqlite. I need to get the table names from which I get the column blob type and then want to see the total no. of records where the blob is not empty.
If you wanted tables that have a column defined as a blob then you could use
SELECT * FROM sqlite_master WHERE sql LIKE '%blob%';
as the basis for determining the tables. e.g. this could return results such as :-
However, this does not necessarily find all values that are stored as blobs. This is because with the exception of the rowid column or an alias thereof, any type of value (blob included) can be stored in any column.
e.g. consider the following :-
DROP TABLE IF EXISTS not_a_blob_table;
CREATE TABLE IF NOT EXISTS not_a_blob_table (col1 TEXT, col2 INTEGER, col3 REAL, col4 something_or_other);
INSERT INTO not_a_blob_table VALUES
('test text',123,123.4567,'anything'), -- Insert using types as defined
(x'00',x'12',x'34',x'1234567890abcdefff00') -- Insert with all columns as blobs
;
SELECT typeof(col1),typeof(col2),typeof(col3),typeof(col4) FROM not_a_blob_table;
This results in :-
If you want to find all blobs then you would need to process all columns from all rows of all tables based upon a check for the column type. This could perhaps be based upon :-
SELECT typeof(col1),typeof(col2),typeof(col3),typeof(col4),* FROM not_a_blob_table
WHERE typeof(col1) = 'blob' OR typeof(col2) = 'blob' OR typeof(col3) = 'blob' OR typeof(col4) = 'blob';
Using the table above this would result (only the 2nd row has blobs) in :-
A further complication is what you mean by not empty, null obviously. However what about x'00'? or if you used a default of zeroblob(0) ?.
zeroblob(N)
The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. SQLite manages these zeroblobs very efficiently. Zeroblobs can
be used to reserve space for a BLOB that is later written using
incremental BLOB I/O. This SQL function is implemented using the
sqlite3_result_zeroblob() routine from the C/C++ interface.
If null though then this wouldn't have a type of blob, instead it's type would be null, which could complicate matters if checking for all values stored as blobs.
You may wish to consider having a look at the code from Are there any methods that assist with resolving common SQLite issues?
as this could well be the basis for what you want.
You also wish to have a look at typeof(X) and zeroblob(N).
I am trying to create sqllite db for my Android application use
Is it bad habit to have all the data types as text? The reason is even though some data can be integer in nature (like number of items.. Etc) but many times I need to display the values as a string or get it as input from user. So I thought for easier manipulation I will just make the datatype in the db as text
Thoughts?
The first thing to understand here is SQLite Storage Classes. SQLite allows any data type to be stored in a table's columns, the actual data type defined by the table is just a hint to the database engine.
This means that even if you define a column as type INTEGER, you can still store text in it.
That being said, I haven't found a use case for storing arbitrary data types in a column, or a case for disregarding the defined data types. For readability purposes, it would probably be a good idea to type things properly and obey the defined types.
I'm trying to establish if I have found a bug in sqlite or if it is just with my understanding (as I haven't had a lot of experience with it).
(And, yes I have checked the sqlite bug tracker.)
I have an Android where I want to store doubles in the database. I also want store a record where the value may not be set yet (ie invalid). To track this state I want to store Double.NaN.
So when I create the database table as such
create table Example (myRecordId integer primary key autoincrement, someString text not null, problemDouble REAL);
Insert a record where the problemDouble is Double.NaN and then access via Cursor.getDouble(...) I will get back a Java double with the value 0.0.
Now if I create the table this way (using text instead of real)
create table Example (myRecordId integer primary key autoincrement, someString text not null, problemDouble text);
Insert the record where the Java double is converted to a string and access it the same way I will get back a double with the value NaN.
I thought that that sqlite is supposed to be typeless but it appears to be messing around with the value when the column is a REAL. Or is it that sql REAL don't support a NaN value?
My assumption would be that sqlite is just converting the REAL values to strings in the background.
So would this inconsistency be considered a bug ?
I have a .csv file that I turned into an SQLite database with the first column as a date and time (as a TEXT datatype because it's in the format 7/20/2011 12:00:00 PM), the second column as the subsecond (a REAL, like 0.142857), and the rest of the columns as data about that time. I will be using it as a read-only db in my Android app, in which the user selects a start time and an end time and then the data is displayed graphically for that time period.
This is my first time using a database and I'm not sure how to work with this. I believe I need a unique NUMERIC primary key for each row but simply labeling them by row number is a waste of space. The first column is not unique and is a TEXT datatype anyway, though if the subsecond was to be somehow incorporated then it would be unique. But I really can't re-write the database because it has 65534 rows... How do you suggest I access specific times in this database?
In Android you need a column named _ID in your database (else you'll face some issues later on). You will use that as the primary key.
Dates and times can be stored in SQLite in the form of a text column in the following format (See http://www.sqlite.org/datatype3.html):
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS")
If your database is static, simply use a tool such as SQLite Database Browser to convert it to a format convenient for Android.
If your database is local and external(not remote), than you must have _id and another another table android_metadata which will hold the locale.
If your database was remote. Yes, you can it is only matter of speed if you are write, since you don't. Using WHERE clause will do the work.
Every date can be converted to numeric timestamp quite easy:
Date date = new Date();
long timestamp = date.getTime();
Date otherDate = new Date(timestamp);
Numbers are MUCH easier and faster to process than text fields. If you are completely sure, that you have unique data within column you can use it as primary key.
Importing csv file into table should be also easy:
//just open file in some known way and read it line by line
// we have declared String[] data, String line is line read from your csv somewhere earlier
// in code
data = line.split(",");
//here you have to process values, and execute insert statement
You have to create indexes on every column which will be used to search or order data. Please be also aware, that rows in table has no "default", "natural" or any other order. If you execute this same select statement twice you can get two totally different results in meaning of sorting. So simple select statement should look like that:
select
_id, other_colum_name, some_other_column
from
table_name
where
column_name = 5
and other_column_name = 3
order by
column_name;