Account for an indefinite amount of SQLite column? - android

I am trying to make a SQLite table for group of contacts, but I do know the number of contacts that are going to be in that table, so how could I account for ALL the contacts? I could make a single TEXT column and have the String URI of each contact with a delimeter. I would like to support the wide range of users running Android 1.5 and (correct me if I'm wrong) the version of SQLite that runs on Android 1.5 doesn't support foreign keys (only Android 2.2 and above). What should I do?

You can simulate foreign key constraints on older versions of android using triggers: http://www.codeproject.com/KB/android/AndroidSQLite.aspx
From there, you can simply have another table for the groups (and whatever metadata you wanted associated to it), and then another for contacts, and have each contact have a group_id, or if you want multiple groups per contact, you could also have another table containing only contact_id and group_id.
So, let's say you want a set of contacts, and you want a set of contact groups. And you want each group to contain a variable amount of contacts, and you want a contact to be in a variable ammoun of groups, you will want three tables, a group table, a contact table, and a groupcontact table. The group table will have all of the columns that a group needs, plus an additional primary key column (note that it has to be called _id because android assumes it will be called _id). The contact table will have all of the columns needed for a contact, plus an additional primary key. Finally, the groupcontact table will have three columns (although you only care about two of them), a primary key column, a group_id column, and a contact_id column.
Finally, if you want to associate all of the elements of a group, including all of the contacts, you could do something like this:
<group_fileds>, <contact_fields> from <group_table>, <contact_table>, <group_contact_table> where <group_table>._id = <groupid> and <contact_table>._id = <contactid>
Where and are from the groupcontact table. (Note that android has methods demonstrated in their notepad example: http://developer.android.com/resources/samples/NotePad/src/com/example/android/notepad/NotePadProvider.html , also you can see an example of things similar (although a bit simpler) in a recent provider I wrote (although I haven't implemented triggers yet, so it won't work properly in older versions of android): https://github.com/LeifAndersen/NetCatch/blob/master/src/net/leifandersen/mobile/android/netcatch/providers/ShowsProvider.java

Related

SQLITE Android Design

I'm trying to build a chore app where the user can create a group with a password and they can then add chores to the group that they made. My question is I'm using sqlite as the database and I'm wondering if it's possible to add a database column into the table. I'm planning on creating a table inside my db with columns of id, username, password, database. database is where I will create additional databases where it will store the chore table for my app. If I can't do this, can someone lead me along the way on how I can for example, make a table named Group, then for its columns have id, username, password. Then for each Group rows, be able to somehow match it with another corresponding database or table where the table will be chores with columns say name, frequency. And however many Group rows I add, I will need to somehow make another chore table to match with it, but I need to know how to link and refer to it from just my Group table. If there's a better way to do this using SQLite I would love to know. Thank you.
If i get your question correctly, I think all u need is to use PRIMARY_KEY and FOREIGN_KEY. Hope you are aware of constraints in databases.
So basically two tables will share a KEY which is unique, the key will be the PRIMARY_KEY in table 1 and will act as a link or reference to row in second table, where it is a FOREIGN_KEY
check this for more on constraints

New to Android - Is _id a must for databases?

I have an already functioning app running on iOS whose database uses a composite primary key. For discussions sake, lets say "CID" and "RID" make up that composite pk, resulting in something that looks like:
CID-RID
F6uuDTEU1c-1
F6uuDTEU1c-2
F6uuDTEU1c-3
However, there are conditions under which the CID column is altered, resetting the RID column. For example:
CID-RID
...
F6uuDTEU1c-4
F6uuDTEU1c-5
WQq6JnyrDI-1
WQq6JnyrDI-2
WQq6JnyrDI-3
...etc
These databases are to be shared cross-platform (ios - android) and going back and editing the current ios structure is not an option. What issues am I going to run into not having an _id column as my pk running on Android?
I found this here on SO - which seems to state that the db itself does not have to have the _id column, only that ...
"The result set for the cursor must contain _id, not the cursor itself."
... but I could be reading this all wrong. Any input/help is much appreciated.
PS: I already looked at a few (what I thought were) similar questions here, here, and here.
You are free to have any database schema you want. Android doesn't impose any additional restrictrions there.
Only if you use a CursorAdapter, then the Cursor needs an _id column. Any app can be written without using CursorAdapter, it's just there to provide some convenience. sqlite tables always have a ROWID column that aliases to the INTEGER PRIMARY KEY column if the table has one. You can always select it as the _id, e.g. SELECT rowid AS _id ... if needed.

Dynamic Tables in Android SQLite

My question involves databases - The scenario is this:
I have an app that tracks when people borrow items. I have an existing table which tracks who they are, what they have borrowed and so on. What I would like to do is create a separate table to track what the person has borrowed, their contact info, if they returned it, etc.
My idea to do this would be to create a Dynamic table in SQL that would hold the records for 1 person, ie
John Smith
DVD; July 12, 2012; Returned in good condition; etc
As I'm still learning, I wanted to know if:
This is possible, feasible or if there is a smarter way of going about it.
Your answer depends on your scenario;
If you are only interested with "who" borrowed "what" (currently) and not "when" except last occurance, and you are assuming there are always only 1 copy of an item, then you can use one to one relation as:
CREATE TABLE Person
(
PersonId int IDENTITY(1,1) NOT NULL,
Name nvarchar(30) NOT NULL,
Surname nvarchar(30) NOT NULL,
BorrowItemId int NULL FOREIGN KEY REFERENCES Item UNIQUE,
BorrowDate datetime NULL,
ReturnDate datetime NULL,
ReturnCondition nvarchar(50) NULL,
CONSTRAINT PK_Person PRIMARY KEY CLUSTERED (PersonId ASC),
)
CREATE TABLE Item
(
ItemId int IDENTITY(1,1) NOT NULL,
ItemDescription nvarchar(50) NOT NULL,
CONSTRAINT [PK_Item] PRIMARY KEY CLUSTERED (ItemId ASC)
)
If you have multiple copies of each item you should remove the UNIQUE key on BorrowItemId changing relation to one to many. In case;
To see the items borrowed and returned with person information:
SELECT PersonId, Name, Surname, ItemDescription, ReturnDate, ReturnCondition
FROM Person INNER JOIN Item
ON BorrowItemId = ItemId
WHERE BorrowItemId IS NOT NULL
AND ReturnDate IS NOT NULL
You can add PersonId filter in WHERE clause to query for specific person
This isn't a good design since you can insert records without date information or you can even have records with date info but no related BorrowItemId. I suggest using many to many and keep historic data (can be handy) or overwrite using update each time the person borrows a new item
Their contact information could be linked into the table which tracks who they are.
If you have not created a table yet for the returns then I suggest you reference the borrowing table's ID and set in the borrowing table a flag to say this item has been returned.
I am not too sure why you would want to create a new table to collate all the information. If you want to get all the information together then I suggest using the SQL keywrod JOIN when preparing statements. If you really want to store the information later on in a table you can but it will just be duplicates in your database.
A tutorial on the different types of joins you can do : http://www.w3schools.com/sql/sql_join.asp
It is definitely possible to do as you describe. It really isn't a very good strategy, though. Your new table is, exactly, equivalent to an additional column in the existing table that tags the row as belonging to a specific individual.

Can you delete columns in an SQLite database?

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.

SQLite-how to compare two column

friends,
I am doing an Android project in my company, still some small work is remaining, I need your help to complete the task.
The problem is...
I have created two tables in which, table1 has an empty column, for purpose for saving name...
The table2 has a list of names, the objective is only the names from this list should be should be saved in the table1's empty column other than that it shouldn't accept any of the name typed manually.
You appear to want to make the list of names a validation: if the user wishes to save a name to table1, the name must already exist in table2.
Typically this would be done as in the following example, in which only the products listed in PRIZEPRODUCTS can be entered into PRIZEWINNERS table: someone could not win a Boat, for example, given the data below:
PRIZEPRODUCTS
id
productname
1|TV
2|iPad
3|backpack
PRIZEWINNERS
id
productid
winner
ALTER TABLE PRIZEWINNERS
ADD CONSTRAINT PRIZEWINNERS_PRIZEPRODUCTS_FK
FOREIGN KEY(productid) REFERENCES PRIZEPRODUCTS(id)
SQLite doesn't create the foreign key using ALTER TABLE but as part of the create-table statement. See here for the syntax. For enabling foreign key support in Android (2.2), see here.
Now, you can establish the foreign key on the [productname] column if [productname] were the key of PRIZEPRODUCTS. In other words, you could make person-name the key of the table rather than having a PersonID. But if that name is changed in the validation table, it can break the foreign key relationship, unless ON UPDATE CASCADE is enabled, but I am not sure if this is supported in Android.
I hope below query will work for you.
insert into table1(name) values (select name from table2 where id=?).
Thanks.

Categories

Resources