Database tool for Android other than SQLite? - android

I am new to Android programming and I have made a few simple apps which use SQLite to store user's data. Now I am working on a little more complex app in which I need to implement many-to-many relationship among the tables.
So basically, I have three layers (3 Tables) that would be connected to each other and I can't find a good tutorial or any documentation on how to do it. I've spent weeks on researching this. I also looked into realm-database but it's complicated for many-to-many table setup.
So is there any easier solution to this for a beginner? Or is there another tool that I can use to accomplish my task. Any suggestions would be helpful. Thank you :)

Your example isn't a many to many relationship. It's a one to many, each country can only exist in one continent and each state in only one country.
You can get the structure you want by adding a reference to the parent type's ID.
CREATE TABLE continent (
_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
)
CREATE TABLE country (
_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
continentId INTEGER NOT NULL,
name TEXT NOT NULL,
FOREIGN KEY continentId REFERENCES continent(_id)
)
CREATE TABLE state (
_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
countryId INTEGER NOT NULL,
name TEXT NOT NULL,
FOREIGN KEY countryId REFERENCES country(_id)
)
To select all the countries on a continent, just ask SQL using the correct ID.
SELECT *
FROM country
WHERE continentId = ?
Or you can join them together.
SELECT *
FROM continent
JOIN country ON continent._id = country.continent
JOIN state ON country._id = state.countryId

You can do many-to-may relationships with SQLite. For the example shown you just need some XREF tables. For example (pseudocode):
Table CONTINENT(
ContinentID
,ContinentName
)
Table COUNTRY(
CountryID
,CountryName
)
Table CONTINENT_COUNTRY_XREF (
Continent_Country_XrefID
,ContinentID
,CountryID
)
Hope this helps.

Yes you can use Ultralite database from SAP. It supports joins as well.
More details here
http://scn.sap.com/community/developer-center/mobility-platform/blog/2012/08/23/how-to-open-an-ultralite-db-udb

To connect two tables in a many to many relationship, create a third table with three columns. The first column is just a standard is for the primary key. The other two columns are secondary keys into the two original tables. Googling " many to many relationship" will provide more details.

Related

SQLIte how to insert unique data on change of column value

I am using SQLite Database for my application. I have 4 columns- Student_Name,Student_Enroll, Student_Mob, Student_Address in my database. Now I can add new record if and only if one of four column value is different or all values are different. If all column values are same then no new record should be generated.
Can you please guide me to solve this issue?
To enforce that a set of columns must be unique, add a UNIQUE constraint:
create table Students (
/* ID INTEGER PRIMARY KEY, */
Student_Name TEXT,
Student_Enroll TEXT,
Student_Mob TEXT,
Student_Address TEXT,
UNIQUE (Student_Name, Student_Enroll, Student_Mob, Student_Address)
);
This allows new rows only if at least one of the four columns has a different value.
With a plain INSERT, attempting to insert a duplicate row will result in an error. If you simply want to ignore it instead, use INSERT OR IGNORE:
INSERT OR IGNORE INTO Students ...;
Despite of set your column as UNIQUE you also need to resolve the conflict created on each column when you try to insert new data.
To do so, define the behavior to solve the conflict:
"CREATE TABLE table (your columns here...(UNIQUE unique colums here...) ON CONFLICT REPLACE);"
During Create Database line insert UNIQUE ...for each column to insert only unique record.
Solution 1: (Simple)
Define all columns as unique:
create table TableName (id integer primary key autoincrement,
Student_Name text not null unique,
Student_Enroll text not null unique,
Student_Mob text not null unique);
You can add Student_Address as well, if you need to
Solution 2: (bit complex)
Use AND Operator with WHERE clause
INSERT INTO TableName (Student_Name, Student_Enroll, Student_Mob)
SELECT varStudentName, varStudentEnroll, varStudentMob
WHERE NOT EXISTS(SELECT 1 FROM TableName WHERE Student_Name = varStudentName OR Student_Enroll = varStudentEnroll OR Student_Mob = varStudentMob );
//If a record already contains a row, then the insert operation will be ignored.
You can find more information at the sqlite manual.
Live Example:
Open SQLite Online
Paste following code:
INSERT INTO demo (id,name,hint)
SELECT 4, 'jQuery', 'is a cross-platform JavaScript library designed to simplify the client-side scripting of HTML'
WHERE NOT EXISTS(SELECT 1 FROM demo WHERE name = 'jQuery' OR hint = 'is a cross-platform JavaScript library designed to simplify the client-side scripting of HTML' );
SELECT * from demo
Hit RUN
This won't insert 4th record and if you modify both values of WHERE clause then record will be inserted.

SQLite: how to organize my data base

I am having a simple android app and want to know the best way to organize my database tables (mysql).
The idea of the app is a list of categories then the user presses on one of these categories and he gets another list of items and when he clicks on one of them, he gets details about it.
For example, the first list (countries) has (UK, US, China, Japan, and other countries)
You click on US, you get another list (states) has (California, NY, Arizona,...)
You click on California, you get its details (population, area, capital)
Same thing would happen if you click UK then London...
So, how should I arrange my data, should I make:
one table for countries and another table for each country,
only one big table for all states and it will have a column to say which country does it belong to.
any other suggestion?
Try something like the following.. and go from there..
create table countries (
id int(11) not null auto_increment,
name varchar(255) not null,
primary key (id)
);
create table states (
id int(11) not null auto_increment,
name varchar(255) not null,
country_id int(11) not null,
primary key (id)
constraint foreign key (country_id) references countries(id) on delete cascade
);
create table properties (
name varchar(255) not null,
primary key (name)
);
create table state_properties (
id int(11) not null auto_increment,
property varchar(255) not null,
state_id int(11) not null,
primary key(id),
constraint foreign key (property) references properties(property) on delete cascade,
constraint foreign key (state_id) references states(id) on delete cascade
);
edited: typo
You should make the 3 table 1 for countries and another for states and another for details.
Reason:
By this there will not be redundant data and it follows the normalization rules.
you will get the only data which you want not other than that.
You can use the form submit or ajax to get the data from the tables.
EDITED:
As per asked by IAM the data in the database as you will store the data of details corresponding of states and then states corresponding of countries then there you will enter the countries name multiple times in a single column for each states. Then such the data of countries and states will be multiple time in database and your database will be heavy.
Assuming that the information is stored as JSON or XML blobs, you should have TWO tables. Not one or three. Build from the ground up.
CREATE TABLE locale (locID int PRIMARY KEY, data BLOB )
CREATE TABLE localGrouping (
groupID int PRIMARY KEY,
groupName varchar(255),
parentGroup int NULL,
locID int NULL
)
You mentioned that want to have a list of countries, and then drill down to cities or states. Which is all find and dandy, but what happens if you want to include stats at the state level above the city? Or the city level above the neighborhood?
A proper database normalization, as in any proper programming, follows the "Zero One Infinity" rule. Especially when it comes to hierarchical data sets.
(Of course, feel free to add however many tables are apporopriate from LOCALE on down. But unless you're going to be running comparative indexes on a locale's properties, a serialized data object should be fine.)

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.

Automatically Create Insert Statements to Fill Junction Table in a Pre-Created DB

For a simple android app I'm creating as a teaching tool for myself (for using relational dbs/SQL among other things - pardon the simplicity of the question if you will). I'm pre-creating a sqlite db to ship with the application. I'm doing this based on the following SO question.
I've got two tables with a many to many relationship and a junction table to define those relationships as follows:
CREATE TABLE Names (_id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE Categories (_id INTEGER PRIMARY KEY,
category TEXT
);
CREATE TABLE Name_Category (name_id INTEGER,
category_id INTEGER,
PRIMARY KEY (name_id, category_id),
foreign key (name_id) references Names(_id),
foreign key (category_id) references Categories(_id)
);
I've got sets of insert statements to fill the Names and Categories tables. I'm now faced with the task of filling the junction table. I'm sure that I could create the insert statements by hand by looking up the ids of the names and categories that I want to match, but that seems a bit silly.
In order to automatically create the insert statements for the junction table, I imagine that I could create a script based on a set of name and category pairs that will search for the appropriate ids and dump an insert statement. (I came up with this as I was asking the question and will research it. Don't you love it when that happens?)
Does anybody have any suggestions for ways to do this?
EDIT I added the foreign keys because, as pointed out below, they'll help maintain integrity between the tables.
EDIT #2 To solve this, I created a simple Perl script that would take a text file with name - category pairs and dump them out into another file with the appropriate SQL statements.
The name - category text file has a format as follows:
'Name' 'Category'
The Perl script looks like this:
use strict;
use warnings;
open (my $name_category_pair_file, "<", "name_category.txt") or die "Can't open name_category.txt: $!";
open (my $output_sql_file, ">", "load_name_category_junction_table.sqlite") or die "Can't open load_name_category_junction_table.sqlite: $!";
while (<$name_category_pair_file>) {
if (/('[a-zA-Z ]*') ('[a-zA-Z ]*')/) {
my $sql_statement = "INSERT INTO Name_Category VALUES (
(SELECT _id FROM Names WHERE name = $1),
(SELECT _id FROM Categories WHERE category = $2))\;\n\n";
print $output_sql_file $sql_statement;
}
}
close $name_category_pair_file or die "$name_category_pair_file: $!";
close $output_sql_file or die "$output_sql_file: $!";
You can use this insert in your script or code (replacing the strings or using ?):
insert into Name_Category values(
(select _id from Categories where category='CAT1'),
(select _id from Names where name='NAME1'));
Also, you can alter the Name_Category table to constraint on the values that can be inserted and/or deleted:
CREATE TABLE Name_Category ( name_id INTEGER NOT NULL,
category_id INTEGER NOT NULL,
PRIMARY KEY (name_id, category_id),
foreign key (name_id) references Names(_id),
foreign key (category_id) references Categories(_id));
create two main tables first and then create a junction table in which primary key of both main tables will be available as foreign key.. Primary key of junction table will be union
of primary key of first and second main table.
Create trigger now to automatically insert into junction table...
Also don't forget to create table with cascade deletion and cascade updatation so that any value updated or deleted in main tables will be automatically reflected in junction table

Android composite primary key?

Can anyone tell me how to declare a composite primary key in Android 1.6 which includes an autoincrement _id column? I'm not sure of the syntax. I've ended up just enforcing it in Java when I try to add values (where registrationNumber + date has to be unique in the table):
Cursor fuelUpsCursor = getFuelUps(registrationNumber, date);
if(!fuelUpsCursor.moveToNext())
{
//add registrationNumber and date
}
I don't really need the _id column but it can make life tricky if tables don't have one.
Cheers,
Barry
Your question does not make much sense. Your subject line asks for a "composite foreign key", your first sentence asks for a "composite primary key" with an AUTOINCREMENT that your sample code then ignores.
I am going to interpret your question this way: You want an _ID INTEGER PRIMARY KEY AUTOINCREMENT column in your table to be able to use Android's CursorAdapter, but you want to also make sure that the combination of two other columns is unique.
In that case, I think that you want to use a UNIQUE constraint:
Multiple Unique Columns in SQLite
SQLite table constraint - unique on multiple columns
http://sqlite.org/lang_createtable.html

Categories

Resources