I am building an app that allows users to insert data and synchronize with website. User can insert data on the website as well. There are two entity tables (T1 and T2) and one N-M relation table (TR).
Data Structure (it's just illustrative):
T1 (_id, name, modified)
T2 (_id, name, modified)
TR (t1_id, t2_id)
The problem I am facing is data synchronization of IDs. E.g. Device A1 and A2 are offline and record is inserted on both, with the ID = 1. After they are online sync starts and there is a conflict with IDs. I thought about introducing an extra column gid - something like global ID. So the structure would be:
T1 (_id, name, modified, gid)
T2 (_id, name, modified, gid)
TR (t1_id, t2_id, t1_gid, t2_gid)
Global ID would be assigned by website.
But I not sure whether this is a good approach or not (never done anything like this before and cannot tell if there will be any future problem).
You have to use additional ids, suppose network_id, generate all network_ids on the server and use local ids on devices (e.g. UUID). When you are sending create entity request server will generate a real id and return it to you, so you can update a local database with network_id. It is important to use network_id as main field and local_id only if you don't have network_id.
Related
I currently have an app where I store user data in a SQLite database, and one of my fields is a User ID. I would like to add an option to auto-generate User IDs in an mmddyyXXX format, where XXX is a sequential number per user that resets every day.
Does anyone know how I would approach this? I looked at some of the other similar questions, but they don't seem to be helpful.
This is not complicated at all. If your'e similar with SQLite in android just take the date and the userId using a SELECT and generate that string yourself.
If the XXX is not the userId just save another table containing 'tokens' for users. every userId would have a 'token'.
Every new day just change the contents of this table.
I believe you could use a TRIGGER that will generate the userid when a row is inserted.
The following may suit :-
CREATE TRIGGER IF NOT EXISTS newuserid AFTER INSERT ON users
BEGIN
UPDATE users SET userid = strftime('%m%d',date('now'))||substr(strftime('%Y',date('now')),3)||
(
SELECT CAST(substr('000',1,3-length(count()+1)) AS TEXT)||CAST((count()+1) AS TEXT)
FROM USERS
WHERE substr(userid,1,6) = strftime('%m%d',date('now'))||substr(strftime('%Y',date('now')),3)
)
WHERE userid IS NULL;
END;
The trigger is named newuserid
userid is the column for the auto-generated id. The above relies upon it being NULL so it cannot be a PRIMARY INDEX.
There is no reliance upon other columns.
Testing
Starting with an empty table :-
Inserting 4 rows using INSERT INTO users VALUES(null,'This is a new user'); results in :-
To check for another date the rows are adjusted from 041018??? to 040918??? as per :-
4 more rows are inserted using INSERT INTO users VALUES(null,'This is a new user');, resulting in :-
Note this answer isn't intended to be fail-safe but rather the basis of the concept for the answer.
i am really stuck at this point of my android app development.
What i need is a way to save a changing amount of int or string-values (in a sql database). Yet im not even sure if this is the right approach, but let me explain:
In the app i am currently working on, you are able to create certain "events". Users should be able to apply for such events.
I have an external database with 2 tables:
first one for users - every user has a unique ID
second one for events - every event has a unique ID
I need each event to know what users applied for it. And i need each user to know what events they applied for.
I was thinking to save the Event-IDs in the User-Table and vice versa.
I just dont know how to do that since the amount of applicants/ID's can change. Is there a way to save Arrays in the database which can easily be edited (e.g. +/- one ID) and read?
Is this even the right way? I am very happy for any advise!
Thanks in advance!
What you seem to want is a many-to-many relationship. A user can be part of many events, and an event can have many users. That requires an additional table though:
Table: User Columns: UserId, Name, ...
Table: Event Columns: EventId, Name, ...
Table: UserEvents Columns: UserId, EventId, ...
In the new table, UserEvents, you would store the UserId's and EventId's like this:
UserEvents
UserId EventId
1 1
2 1
1 2
This means that if you selected UserId 1, the query would return EventId 1 & 2. If you selected EventId 1 the query would return that UserId 1 & 2 would be attending.
This is the standard and recommended way to deal with many-to-many. It's very flexible and can easily be scaled.
You could either use a Compound key (Composite Key) for this table, or create a column specifically as a Primary Key. The code below can be used, and manipulated, to create both your table and Compound/Composite key (I'm guessing on data types).
CREATE TABLE UserEvents
(
[UserId] INT NOT NULL,
[EventId] INT NOT NULL
CONSTRAINT PK_UserEvents PRIMARY KEY NONCLUSTERED ([UserId], [EventId])
)
I would add a third table (e.g. UserEvents) to store which events a user has applied for, along with other relevant attributes (e.g. ApplicationTime, ApplicationStatus). This association would have a foreign key relationship back to the related tables and resolve the many-to-many relationship between users and events.
What you have there is called a "many-to-many" relationship between to tables which can only be resolved by the introduction of a third table between your two tables that stores the associations.
This table would contain the User-ID and the Event-ID as foreign keys (and maybe additional information).
recently i've started programming on android sqlite and I was debugging my sql commands with Mysql Workbench.
In one of my commands I've got this :
"Select itens.name_item , itens.pot_item from region,itens,item_regions where region.cod_region = "+id+" and itens.cod_item = item_region.cod_item;"
basically I have 3 tables.
region, itens and uniting with foreign keys those 2 inside of item_region.
What i want is by already having the region code, get the name and power of the registered itens in item_regions.
Sry if it's a little confusing, i'm very rusted on my english
Do an inner join:
SELECT name_item, pot_item FROM items
INNER JOIN item_region ON items.cod_item = item_region.cod_item
WHERE item_region.cod_region = ?;
I assume from your example you have the region code in the item_region table, otherwise you'll have to join in the region table as well to compare to the id.
Also be careful that the value of the variable id is sanitized so you don't expose your application to SQL injection.
I'm using ActiveAndroid in an app for database interaction. I need to join a few tables and then filter the results, which I would usually accomplish using a SQL query with a sub-query.
How might one accomplish a sub-query using ActiveAndroid?
If a sub-query cannot be done, is there a way to only return unique Model objects? The join in my query has the effect of creating duplicate rows in the join table, but I only want one instance of each Model to be returned.
EDIT: Providing more info
The model I'm trying to retrieve is called Profile.
With regard to the query, there are 3 tables:
Profiles, Roles, and ProfileRoleJoins
There is a many-to-many relationships between Profiles and Roles and that relationship is maintained by the join-table called ProfileRoleJoins.
My goal is to obtain all Profiles that have a certain "event_id" and are connected to one or more Roles specified by a list of Role types.
Of interest to this query are the following fields:
Profiles
Id
event_id (not a foreign key, just a data field)
Roles
Id
type (TEXT)
ProfileRoleJoins
profile (foreign key)
role (foreign key)
What I've Tried
String eventId = //provided as input to this function
String[] roles = //array of "types" of roles we want to limit to
String whereClause = //built in a loop, looks like "Roles.type = ? OR Roles.type = ?..."
new Select()
.from(ProfileEntity.class)
.where("event_id = ?", eventId)
.join(ProfileRoleJoinsTable.class)
.on("Profiles.Id = ProfileRoleJoins.profile")
.join(RoleEntity.class)
.on("ProfileRoleJoins.role = Roles.Id")
.where(whereClause, roles)
.execute();
The above query has the problem that it returns duplicate Profiles because a single Profile can be associated with multiple Roles which creates duplicates during the join process.
I need to retrieve a list of unique Profiles.
I tried using Distinct(), but that qualifier applies per set of columns - I need entire Profiles back.
The way I would normally accomplish the uniqueness is by doing the above query in a sub-query and return only DISTINCT Profiles.Id values. Then I would run a filter in the main query against the original Profiles table.
I still don't know how to do sub-queries with ActiveAndroid (if its even possible), but I found out the source of my problem. I was using an outdated version of the library and there was some kind of error in the query system that screwed up the results. With the current version of the library I do not get duplicates.
I have limited SQL background, basically a small amount of manipulation through HTML and mostly with pre-existing databases. What I am trying to do is set up a database that will store time information for bus routes. So basically I have different routes with stops for each route and then a list of times that the bus arrives at each stop. Here is an example of a table of times from their website: Link.
I am wondering what would be the best way to layout my database/tables?
Also what is the purpose of the _id field in each table?
Thanks,
Rob!
P.S. Sorry if my lack of knowledge on the subject has caused me to post a duplicate question.
The id field provides a unique id to each row, that can be referenced by other tables in the database. When it is referenced this way, it is called a foreign key. This allows you to have one table with detailed information about say a student (name, address, etc) and then uniquely reference that student in another table that talks about members of a class.
There are generally many different ways to lay out a database, which is best really depends on what you want to do with the data. Most of this design is not unique to SqlLite, so reading up on relational databases in general might be worthwhile.
One way to lay it out your specific example:
Route table: id, name
Stop table: id, name
Time table: id, foreign key to route, foreign key to stop
You asked two questions:
The 'id' field is a good convention as a unique row identification. It is not strictly required, and some data that has its own unique serial number for each row will use that serial number instead. Programs often want to look up the entire record by the unique row identification so the field should be a primary key. The commonly used clause for creating the id is "id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id)". A unique id will be assigned automatically whenever you add a new record. See Tizag's MySQL Tutorial for a verbose breakdown. Personally, some name these "_id", e.g., "route_id", "bus_id", and your style may vary.
Laying out your data depends a bit on what you want to do with it. My guess is that for each bus route, you want to find the next bus at a particular stop after some time and then when that bus arrives at some next stop. Each route has many stops; a stop might be shared among routes; a route varies during the day by skipping some stops; routes go in two directions; etc. I would add the abstraction of a 'run' which one bus run through the stops from start to finish.
My first guess at laying it out would be:
A bus route has a bus name, number, and other info: "#1 Red", "South And West", "SF Muni", "map://..."
A stop has a unique name and other info: "North Grand Mall". "South", "Under the cherry, west of grand avenue."
A run has a route number, days of the week, a direction, maybe a sequence number of the run in that direction that day, maybe a start/stop time for the run: "63 (route_id for #1 Red)", "reverse direction", "MTWRF" (weekdays), "2" (2nd run), "7:00", "7:36".
Then you have a schedule table of "Run_id", "Stop_id", "Stop Sequence Number", "Time".
Write out your planned schema, and then start trying to write schemas against them. Don't be surprised by a couple multiple joins "SELECT * from Schedule as S, Run as R, Bus as B for B ... WHERE B.id == R.bus_id and S.run_id == R.id and B.id = (requested bus) and S.time >= now() and ...." You denormalize for performance after it works.
That's all my free advice. :)