I'm quite new to Android and the SQLite. I'm currently working on an app which requires user to create list of their favourite artists.
I have implemented some charts which already display this artist data. I believe I can easily figure out how to implement adding data to lists.
I was thinking of having two separate tables in SQLite :
Lists (which would store the list names which the user has created)
ChartItems (which would store the chart items and the lists they belong to)
However the Lists table only needs one field in this case "ListName" so I thought it might not be crucial to have a table for this.
Is it possible to dynamically create tables when getting input from a user?
For example : A user creates a list and that value is subsequently used to create a table.
Thanks.
You don't want to be creating new tables on the fly. Your proposal for two tables is fine. The list table should have at least two fields - an integer field called id or _id which is the primary key, and a text field for the list name. The Chartitems table will have a field (listid) which holds the id of the list to which it belongs. This means a chartitem can belong to only one list, and adding a chartitem to a list is achieved by setting the listid field in its record. This is a one-to-many relationship.
If you want to have a single chartitem in more than one list, then you need a many-to-many relationship, which is implemented by having a third table (links). This table will have one field mapping to a list (listid), and one field mapping to a chartitem (itemid.) To add a chartitem to a list, you create the appropriate link entry in the links table. In this case the chartitem table does not need the listid field.
I suggest reading up some more on relationships in databases to clarify these concepts. One principle I strongly suggest following is to have every table contain a field called id which is the primary key for that table, and use that for all references from other tables. In the long run this works much better than using other fields (like name) in relationships.
Related
So, this is my problem. I've been googling for some time now and no other question on this topic seems to approach what bugs me.
In my Android application, I have a class hierarchy, a list of tourist attractions. Every TouristAttraction has, among others, a boolean attribute that specifies whether that attraction is among user's "favorite" attractions.
However, when I insert a specific type of a tourist attraction, say a Monument, Room insert puts both inherited and specific attributes in one table and not in superclass table, so when I want to get a list of all "favorite" attractions, I have to combine results of select queries for every subclass.
Also, when I want to mark something as favorite, this way I first have to see what type of tourist attraction it is, and then get specific DAO... which seems kinda ugly. Is there a way to, when I insert a new row in Monument table, data from inherited fields gets inserted into superclass table?
This problem happens every time I need to collect data that every tourist attraction has, like location etc.
Im not familiar with android-room. But from a sqlite point of view I would structure your TouristAttactions in a separate table without any favorite flags. And then have a second table with the mapping between the user's favorite and attractions.
CREATE TABLE tabTouristAttrations (ID INTEGER AUTOINCREMENT, Name TEXT, ...);
CREATE TABLE mapFavoritesUser (AttrID INTEGER NOT NULL, UserID INTEGER NOT NULL, PRIMARY KEY (AttrID, UserID)
cheers
Andy
first question to SO, so please let me know if I'm stepping on any toes :)
This is a simplified version of my database:
CREATE TABLE products (_id INTEGER PRIMARY KEY, name STRING);
CREATE TABLE product_tag (product_id INTEGER, tag STRING, PRIMARY KEY(product_id, tag));
In one of my activities, I would like to list all products (one row per product) with all tags contained in the row, e.g.
bananas [yellow] [fruit]
ketchup [condiment] [red] [tomato]
mustard [yellow] [condiment]
The options I have considered are:
Using a SimpleCursorAdapter to list all products, querying product_tag in the ViewBinder for each row, and programmatically creating views for each tag and inserting them into the row.
Querying products LEFT JOIN product_tag ON products.id = product_tag.product_id, resulting in one row per tag (or one row per product with no tags) and manually populating the list. This seems more complicated and hacky, and duplicates some data, but avoids querying the db for each row in products.
I'd love it if someone more experienced with Android could comment on the most efficient way to accomplish this! Thanks in advance.
Definitely #2. Database access is slow, so you want to minimize the number of database queries.
Ok, I have a database with id column as timestamp
I made an activity list from the db.
I want to manage the db (delete rows) using the list, but the thing is I don't want to
View the whole timestamp, in every row I'll put only the time with some info and
I want to group the list ,as in contacts grouped by alphabet, by the date.
First, how can I make group in an activity list? (Making groups to the output list not the db)
Second, what is the best way to implement this? When user chooses an item and confims delete
I should delete it from the db but I have only patial timestamp...
(My only link to the db is the timestamp - I don't actually know where to store it in the list and I don't want to put it as a string in the text view, do a substring to get it back - is there another way to do this?)
I tried to search tthe web for some examples but I only found a simple ones.
Thnx :-)
?
I think what you're trying to do is create a database of tasks identified by a timestamp. You probably don't want to use a timestamp as a unique ID for the row. Instead, use an integer and qualify it as "PRIMARY KEY" when you create the database.
group the list? I'm not sure why you want to do this in the structure of the database. It's more common to group the list in the output, and leave the db itself in as flat a structure as possible.
Retrieve the primary key when you display a list of tasks. When the user clicks a task, use the primary key to choose the task to delete. You don't have to display the primary key; it serves as a behind-the-scenes "link" between the displayed info and the db row.
http://www.vogella.com/articles/AndroidListView/article.html
I should use cursor adapter for managing db.
And this one for grouping a list:
http://code.google.com/p/android-amazing-listview/
Thnx for the efforts
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.
I was wondering if it's possible (it should be) to query multiple tables simultaneously (several at once) in SQLite. Basically I have several tables that have the exact same columns, but the data in them is just organized by the table it's in. I need to be able to use SELECT to get data from the tables (I heard UNION could help), which matches a condition, then group the data by the table it's in.
In other words, would something like this be possible?
SELECT * FROM table1,table2,table3,table4,table5,table6 WHERE day=15 GROUP BY {table}
I'd rather not resort to having to query the tables individually as then I would have a bunch of Cursors that I'd have to manually go through and that would be difficult when I only have one SimpleCursorAdapter? Unless a SimpleCursorAdapter can have several Cursors?
Thanks.
EDIT: The structure of my tables:
Main Table - contains references to subtables in a column "tbls"
and meta-information about the data stored in the subtables
Subtable - contains reference to subsubtables in a column "tbls"
and meta-information about the data stored in the
subsubtables
Subsubtable - contains the actual entries
Basically these tables just make it easier to organize the hierarchical data structure. I suppose instead of having the subsubtables, I could keep the actual entries in the subtable but add a prefix, and have a separate table for the meta-information. It just seems it would be harder to delete/update the structure if I need to remove a level in this data set.
You can create view based on your tables, the query of your view is union of your tables.
create view test as select * from table1 union select * from table2
now you can filter data as you want
for more info check union & view
http://www.w3schools.com/sql/sql_union.asp
http://www.w3schools.com/sql/sql_view.asp
In the end, I decided to forgo having many subsubtables, and instead adding another column like Tim and Samuel suggested. It will probably be more efficient as well then chaining SELECTs with UNION.