When using a content provider for SQLite database access
Is it better practice to have a content provider for each table or to use one for all tables?
How to handle one-to-many relationships when creating new records?
A ContentProvider is not a database
A ContentProvider is a way to publicly (or semi-publicly) access data as content. This may be done in a number of ways, via file access, SQLite or even web access. A ContentProvider in and of itself is not a database, but you can program a database for it. You may also have multiple ContentProviders accessing the same database, but distributing different levels of access, or the same content in different ways according to the requestor.
What you are really asking is not a ContentProvider question, but a database question "How to handle relationships in an SQLite database" because the ContentProvider doesn't use any database code unless you tell it to via an SQLiteOpenHelper and other similar classes. So, you simply have to program your database access correctly and your SQLite database will work as desired.
A database is a database
In the old days, databases were simply flat files where each table was often its own entity to allow for growth. Now, with DBMS, there is very little reason to ever do that. SQLite is just like any other database platform in this regard and can house as many tables as you have space to hold them.
SQLite
There are certain features that SQLite handles well, some that it handles - but not well, and some that it does not handle at all. Relationships are one of those things that were left out of some versions of Android's SQLite, because it shipped without foreign key support. This was a highly requested feature and it was added in SQLite 3.6.22 which didn't ship until Android 2.2. There are still many reported bugs with it, however, in its earliest incarnations.
Android pre 2.2
Thankfully being SQL compliant and a simple DBMS (not RDBMS at this time), there are some easy ways to work around this, after all, a foreign key is just a field in another table.
You can enforce database INSERT and UPDATE statements by creating CONSTRAINTs when you use your CREATE TABLE statement.
You can query the other table for the appropriate _id to get your foreign key.
You can query your source table with any appropriate SELECT statement using an INNER JOIN, thus enforcing a pseudo-relationship.
Since Android's version of SQLite does not enforce relationships directly, if you wanted to CASCADE ON DELETE you would have to do it manually. But this can be done via another simple SQL statement. I have essentially written my own library to enforce these kinds of relationships, as it all must be done manually. I must say, however, the efficiency of SQLite and SQL as a whole makes this very quick and easy.
In essence, the process for any enforced relationship goes as follows:
In a query that requires a foreign key, use a JOIN.
In an INSERT use a CONSTRAINT on the foreign key field of NOT NULL
In an UPDATE on the primary key field that is a foreign key in another TABLE, run a second UPDATE on the related TABLE that has the foreign key. (CASCADE UPDATE)
For a DELETE with the same parameters, do another DELETE with the where being foreign_key = _id (make sure you get the _id before you DELETE the row, first).
Android 2.2+
Foreign keys is supported, but is off by default. First you have to turn them on:
db.execSQL("PRAGMA foreign_keys=ON;");
Next you have to create the relationship TRIGGER. This is done when you create the TABLE, rather than a separate TRIGGER statement. See below:
// Added at the end of CREATE TABLE statement in the MANY table
FOREIGN KEY(foreign_key_name) REFERENCES one_table_name(primary_key_name)
For further information on SQLite and its capabilities, check out SQLite official site. This is important as you don't have all of the JOINs that you do in other RDBMS. For specific information on the SQLite classes in Android, read the documentation.
As for first question: you don't need to create content provider for every table. You can use in with multiple tables, but the complexity of provider increased with each table.
A Content Provider is roughly equivalent to the concept of a database. You'd have multiple tables in a database, so having multiple tables in your content provider makes perfect sense.
One to many relationships can be handled just like in any other database. Use references and foreign keys like you would with any other database. You can use things like CASCADE ON DELETE to make sure records are deleted when the records they reference in other tables are also deleted.
Related
I'm trying to implement databases linked with foreign keys and I've been told it's better (more secure) to stick to queries instead of rawQueries in general, but I'm unsure how far. What's the best approach to CRUD operations; to use multiple queries (.query(.)) or use more sophisticated rawQueries?
For example
If I want to delete a row from a table iff there is no other table linking to that particular row.
Or are there perhaps better ways when constructing the database that makes such operations smoother?
Also, when inserting into a table and there's already a row (and the column is unique or similar restraint), is there a quick way to find the rowId of the value being inserted regardless of whether or not it was inserted or already exists?
I tried `insertWithOnConflict(.)`
but it throws -1 instead of the rowId when already exists. Is there a better way than to execute another query afterwards upon failure?
I am using Android's content providers as a wrapper around an SQLite3 database. It's never been my choice to use content providers for stand alone app centric databases due to the limited flexibility and bloat they can cause. However I'm working on a pre-existing code base. I need to write an insert query with a WHERE NOT EXISTS clause. However, I see that the insert command of the ContentProvider only permits a URL (which I used to identify the table) and a ContentValues object containing the data to insert as a new row.
Is there any way to do a this, or something that is in effect the same, without manually performing essentially an inefficient checking select query before the insert for checking purposes?
I don't want to modify the DB table structures or constraints as there are to many dependencies which may break with alterations.
I have an app which requied more than one table.
The DB is mosly for read purposes and i want to know what is the best way to manage my tables.
I tought about 2 options.
Create new DB class with new DB for each table.
Create new table in the exits DB.
What is the best for better performance in reading?
hat is the best for better performance in reading?
For sure don't create new database but put all tables you need in one database. Reasons are more there, for instance now you don't know whether you will need sometime in a future to create some relations between these tables.
I's not "good" to have more db files which will represent one table, it's not comfortable and efficient as well. So my suggestion to you is to keep only one db file and put all tables in this one.
The best approach to manage SQLite database is to use SQLiteOpenHelper class that wraps all required logic for reading and writing from/to database. Then, SQLiteDatabase itself provides some API methods for inserting, updating and deleting from db.
At the end as my personal recommendation. If you'll have more than one table just how i mentioned create one SQLiteOpenHelper subclass for creating database and then for each table create object that will represent table "in objects" e.q. columns in table will become properties of object.
Finally for each table create DAO classes that will wrap CRUD operations and some specific methods for each table.
If you don't know how to start check these tutorials:
Android SQLite Database and ContentProvider - Tutorial
Android SQLite Database Tutorial
You can use SQLiteDatabase.
SQLiteDatabase has methods to create, delete, execute SQL commands, and perform other common database management tasks.
Database names must be unique within an application, not across all applications.
Read: Documentation
I can't find the Ormlite DataType mapping for Android to Sqlite. I've found OrmLite SQL Data Types but the Sqlite column is blank. Anyone know were I can find them?
I need them to update my database schema ie:
meetingDao.executeRaw("ALTER TABLE meeting ADD closed ????");
I'm not exactly sure what you are asking but Sqlite is a type-less database. Everything is stored as a string basically with certain functions allowing numerical, time, etc. calculations at runtime on those strings.
To quote from the Sqlite data-type docs:
SQLite is "typeless". This means that you can store any kind of data you want in any column of any table, regardless of the declared datatype of that column. (See the one exception to this rule in section 2.0 below.) This behavior is a feature, not a bug. A database is suppose to store and retrieve data and it should not matter to the database what format that data is in. The strong typing system found in most other SQL engines and codified in the SQL language spec is a misfeature - it is an example of the implementation showing through into the interface. SQLite seeks to overcome this misfeature by allowing you to store any kind of data into any kind of column and by allowing flexibility in the specification of datatypes.
In the SQL Data Types page you mentioned, the Sqlite column is blank because it uses the base data columns without the need to override them. Even if I changed the base types for a class, Sqlite will not override any of the types because, again, it is a type-less database.
Actually, the mapping table linked by the original question: OrmLite SQL Data Types shows the correct types that ORMLite is using, although it only shows differences for each database from the Base Database column. For example a Java long is created as a column with the BIGINT type.
While SQLite3 doesn't have types, it has the concept of type affinities which ORMLite uses when creating the table.
You should probably include the types in database upgrades as well, or you'll get a different table definition when ORMLite is automatically creating the table form scratch and when you upgrade.
I am trying to create multiple database tables in android where each table will represent an account. I am struggling to get more then one table per database
Would anyone have any sample code they could show me? Or any suggestions?
Thanks
I don't know anything about your app, but the way you're designing your database schema sounds a little questionable. Does creating a table for every account (whatever an "account" might be) really make the most sense?
Regardless, creating tables in SQLite is pretty straightforward. In your SQLiteOpenHelper class, you can call db.execSQL(CREATE_TABLE_STATEMENT) to create a table, where CREATE_TABLE_STATEMENT is your SQL statement for a particular table. You can call this for every table you need created. This is typically going to be called in your SqliteOpenHelper's onCreate method when the database is initialized, but you can call it outside of the helper as well.
If you are going to use a fair amount of tables and data, including a prepopulated database in your assets folder is another way to go.
When I started to use databases on android I found this very helful.
http://developer.android.com/resources/tutorials/notepad/index.html
ps now that you mentioned that there are only 2-3 accounts, creating one table/account sounds much more reasonable than first expected.
But it really depends on what you are planning to do with the data and where your performance requirements are. One could even use one single table or as well multiple tables for each (fixed) type of transaction - if the data for transaction types have very different structure.
Creating database table in Android is pretty straghtforward:
db.execSQL(CREATE_TABLE_STATEMENT);
where db is SQLiteDatabase object and CREATE_TABLE_STATEMENT is your create table sql statement
As in your question you did not explain clearly the requirement of your app, but I can see a few cons in your approach of creating one table for each user
If there are many users created, u will have many tables in ur database
If later on you have some information, settings that would be shared across some users or all user, you will have to replicate them in every user single table.
My recommendation would be you have one table for users, and another table for transactions with one column is user_id to link back to the user table. It would be easier to expand or maintain your database later.
Hope it helps :)