Could someone present me the simpliest way to pass the data from sqlite table to 2D array?
Lets assume table with columns: _id, date, value
I assume I have to count records in the table before I define an array
The way that I would usually do this is by creating a Struct with the necessary properties (id,
date, value in your case), and then have an array to hold the instances of the struct.
Related
Is it possible to store objects from a generated Protobuf Java class in a Room database? Do I need to serialize the objects and store the serialized versions inside of an Entity class?
You basically have two options. Serialise and save as a Blob (byte[]) or to have Entities that reflect the objects properties and if those are themselves are objects then like wise break them down. This latter approach is potentially more complicated but it does open the data to being more useful database wise.
In short serialise or not to serialise is a choice that would depend upon what is required. Do you just want to use the database for storage or do you want to take advantage of the searchability aspect offered by SQLite (Room).
As an example lets say you have a contract for an address that has the following properties:-
postbox (int)
street (string)
city (string)
country (string or probably more correctly a reference to a country object)
then if you serialise the object you have a string of bytes (byte[]) and all the data will be stored in a single column.
If you wanted to search for all addresses in a city that would be a) inefficient and also relatively difficult.
If each property were saved in a table with a column per property then that search for the city is straightforward e.g. SELECT your_columns FROM the_table WHERE city = 'MyCity';
If the address object were serialised and saved the you might be fortunate and be able to use SELECT serialised_address FROM the_table WHERE instr(serialised_address,hex('MyCity') > 0;
It depends upon how serialisation generates the underlying data
Underneath Room is SQLite and here's a quick SQLite example that demonstrates the difference assuming that the property markers are the property name (e.g. city) followed by = e.g. city MyCity is stored as city=MyCity converted to hex (bytes).
DROP TABLE IF EXISTS test1;
CREATE TABLE IF NOT EXISTS test1 (serialised_address BLOB);
CREATE TABLE IF NOT EXISTS test2 (postbox INTEGER, street TEXT, city TEXT, country TEXT);
INSERT INTO test1
VALUES(hex('postbox=1,street="The Street",city="MyCity",country="England"')),
(hex('postbox=1,street="The Street",city="NotMyCity",country="England"'))
;
INSERT INTO test2 VALUES(1,'The Street','MyCity','England'),(1,'The Street','NotMyCity','England');
SELECT *,null,null,null FROM test1 UNION SELECT * FROM test2;
SELECT 'S1',serialised_address,null,null,null FROM test1 WHERE instr(serialised_address,hex('MyCity')) > 0
UNION SELECT 'S2',serialised_address,null,null,null FROM test1 WHERE instr(serialised_address,hex('myCity')) > 0
UNION SELECT 'S3',* FROM test2 WHERE city = 'MyCity'
UNION SELECT 'S4',* FROM test2 WHERE city = 'mycity'
;
This creates 2 tables (Entities in Room speak).
Table test1 is for the serialised object address.
Table test2 stores the properties in individual columns.
Both tables are loaded with the equivalent data.
The first query gets the data from both tables using nulls for the 3 columns that don't exist in the test1 table
i.e. all the data is stored in the single column
The second query looks for the city called MyCity expecting to just extract that 1 city.
When run the results are :-
(i.e. 2 rows from each table)
and :-
As you can see 3 rows have been extracted not the expected 2 rows. This is because the search through the byte array for MyCity has also found NotMyCity.
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).
Problem description:
I have a table which primary key is id and I also have an array of ids. The array contains ids from the table but some ids of the table may be missing in the array. I need to delete the rows of which ids are missing in the array.
My approach:
I fetch all the ids from the table and sort the two array. Then comparing two array I find out the missing ids and deleted corresponding rows.
Is there any better( easy and/or efficient) way to do this?
You can write a delete statement like the following:
DELETE FROM table_name WHERE id NOT IN (1, 2, 3, ...)
In my Android app, I need to temporarily store some data in a form of table such as follows:
id | column 1 | column 2 | ... | column n
The data are downloaded from a server whenever users press a button. However, the data table doesn't have a fix number of column (as well as row) every time user downloads it from the server. For example, the server may send data with 3 columns the first time. Then it might send data with 5 columns the second time, etc...
Given this scenario, I think the database is probably the right data structure to use. My plan is to create a database, then add and delete tables as necessary. So I have been reading various tutorials on Android database (one example is this one http://www.codeproject.com/Articles/119293/Using-SQLite-Database-with-Android#). It seems to me I cannot create new table with variable number of columns using the sqlite database. Is this correct? In the onCreate(SQLiteDatabase db) method, the "create table" command must be specified with known number of columns and their data types. I could provide several "create table" commands, each with different number of columns but that seems like very crude. Is there a way to create database tables with variable number of columns on the fly?
Another alternative probably using several hash tables, each storing one column of the data table. I'm seriously considering this approach if the database approach is not possible. Any better suggestion is welcomed.
There is no such thing as a variable number of columns in an SQLite data base. Also, adding and deleting tables dynamically seems like a horrible hack.
It sounds like you want to store an array of values associated with an id. I suggest you think in terms of rows, not columns. Use a table structure like (id, index, value); each array of values returned by the server results in as many rows as necessary to store the values.
The Android app that I am currently working on dynamically adds columns to an SQLite database. The problem I have is that I cannot figure out a way to remove these columns from the database.
If I add column A, B, C, D, and E to the database, is it possible to later remove column C?
I have done a lot of looking around and the closest thing I could find was a solution that requires building a backup table and moving all the columns (except the one to be deleted) into that backup table.
I can't figure out how I would do this, though. I add all the columns dynamically so their names are not defined as variables in my Java code. There doesn't seem to be a way to retrieve a column name by using Android's SQLiteDatabase.
SQLite has limited ALTER TABLE support that you can use to add a column to the end of a table or to change the name of a table.
If you want to make more complex changes in the structure of a table, you will have to recreate the table. You can save existing data to a temporary table, drop the old table, create the new table, then copy the data back in from the temporary table.
For example, suppose you have a table named "t1" with columns names "a", "b", and "c" and that you want to delete column "c" from this table. The following steps illustrate how this could be done:
BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 SELECT a,b FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;
SQLite doesn't support a way to drop a column in its SQL syntax, so its unlikely to show up in a wrapper API. SQLite doesn't often support all features that traditional databases support.
The solutions you've identified make sense and are ways to do it. Ugly, but valid ways to do it.
You can also 'deprecate' the columns and not use them by convention in newer versions of your app. That way older versions of your app that depend on column C won't break.
Oh... just noticed this comment:
The app is (basically) an attendance tracking spreadsheet. You can add
a new "event" and then indicate the people that attended or didn't.
The columns are the "events".
Based on that comment you should just create another table for your events and link to it from your other table(s). You should never have to add columns to support new domain objects like that. Each logical domain object should be represented by its own table. E.g. user, location, event...
Was writing this initially. Will keep it if you're interested:
Instead of dynamically adding and removing columns you should consider using an EAV data model for that part of your database that needs to be dynamic.
EAV data models store values as name/value pairs and the db structure never needs to change.
Based on your comment below about adding a column for each event, I'd strongly suggest creating a second table in which each row will represent an event, and then tracking attendance by storing the user row id and the id of the event row in the attendance table. Continually piling columns onto the attendance table is a definite anti-pattern.
With regards to how to find out about the table schema, you can query the sqlite_master table as described in this other SO question - Is there an SQLite equivalent to MySQL's DESCRIBE [table]?
As per SQLite FAQ, there is only limited support to the ALTER TABLE SQL command. So, the only way you can do is that ou can save existing data to a temporary table, drop the old table, create the new table, then copy the data back in from the temporary table.
Also you can get the column name from the database using a query. Any query say "SELECT * FROM " gives you a cursor object. You can use the method
String getColumnName(int columnIndex);
or
String[] getColumnNames();
to retrieve the names of the columns.