SQLite Objective-C: How to load the last database version? - objective-c

I've got a database and the user can only read and update his tables.
I don't get how can I add new records to the tables and load the updated database in the App's Document folder without losing users' data.
Example:
Database with 2 tables:
Table A where user inserts and updates his data.
Table B which is a data source, where user can only read.
Now I want to add some new records to the Table B and upload the updated database into the App without losing data stored in Table A.
Btw, The database doesn't get copied as an older version is already stored in the Documents folder.
How can it be done?

A few possible considerations:
Periodic data updates between system releases
If you're talking about ensuring the app can receive updates to table B periodically (i.e. between releases of the app), then you presumably want to design a web service to retrieve updates. If table B is not too large, design a web service that retrieves the entire contents of B in some nice format (e.g. JSON is great for this) and then write the code to contact the web service, request this data and then integrate it into the local copy of the database). If B is large, you might want to design a web service that only retrieves any creation, deletion, or update transactions.
If you haven't done this before, I might refer you to Wenderlich's How To Write A Simple PHP/MySQL Web Service for an iOS App and its companion, How to Write an iOS App That Uses a Web Service.
Migrating databases when releasing new version of app
On the other hand, if you're talking about releasing a new version of your app, but not wanting to lose the customer information in table A, you can open both databases simultaneously (open the documents database, and then use the ATTACH DATABASE command to simultaneously open the other one in the same sqlite3 session), and then you easily copy data from one database to the other using SQL. For example, open the new system database (with the updated table B) and attach to the database with the updated user data in table A:
NSString *sql = [NSString stringWithFormat:#"ATTACH DATABASE \"%#\" AS user_db", customerDbPath];
You can then re-populate userdata (table A) from the user_db database:
DELETE FROM userdata;
INSERT INTO userdata SELECT * FROM user_db.userdata
If you're doing this sort of "database migration" (integrating system updates of table B with user updates of table A), you probably want to use some control mechanism by which the system can quickly compare two databases and make sure that you know you're dealing with the same rendition of table B. You can either use the PRAGMA user_version for this purpose, or I personally generally have my own configuration table in which I'm saving general configuration information and I always have a version number in there.
Separate databases?
One final consideration is that you might contemplate having separate databases for these two tables. This generally is not the right approach, but if you have little interaction between the two tables and if they're radically different types of data, it's another approach to consider.

Related

Access database multiple users

Hello i have a database created with only Microsoft access (meaning no sql have been used) is it possible to make multiple users use it from different computers and the datas they input gets updated in all the computers?
Can someone just briefly tell me how if the answer is yes,
Much appreciated
I have on several occasions used the following technique with success:
(1) Split the Access Database in two:
The Back End: This database should contain the shared tables.
The Front End: A database for forms, queries and basically everything except tables.
Instead of actual tables, this database should contain "linked" versions of those tables which are held in the "back end".
(2) There is a central copy of the front-end database, but no-one opens this directly. Instead, they run a batch file which creates a local copy of that central front-end, and then opens that.
This setup has the advantage that the central "front-end" remains unused, and therefore isn't locked, and so the developer can edit it. The users will get the updates whenever they next launch the database using the batch file.
A second advantage is that the "backend" can be upsized to a "proper" database, and the front-end could then remain largely unchanged, just that the linked tables would no longer be in another Access Database.

Checking for an updated SQLite database

How do I handle updating my SQLite database file when I update my application. Basically when I update, the database needs to be updated to. I thought about adding a table to the database that would have the database version, but my only concern with that is how would I read from two databases with the same name. One would be the one in the Documents Directory (the old one) and the new one (with the same name) would be in the Main Bundle. The application it self does not require any user preferences to be stored in the database so I dont have to worry about over writing users data. But the application does make updates to the database from the internet, but these will ultimately be incorporated into the next release. Any have any tips on how to handle this?
You could use 'NSFileManager' to copy the database from the application bundle into the Documents directory before you open it.

Is there an easy way to track all changes in a SQL 2005 Database

I've been tasked with hooking in our product with another third party product. One of the things I need to do is mimic some of the third-party's product functionality when adding new "projects" - which can touch several database tables. Is there any way to add some kind of global hook to a database that would record all changes made to data?
I'd like to add the hook, create a project using the third-party application, then check out what all tables were affected.
I know it's more than just new rows as well, I've come across a number of count fields that look to be incremented for new projects and I worry that there might be other records that are modified on a new project insert, and not just new rows being added.
Thanks for any help
~Prescott
I can think of the following ways you can track changes
Run SQL Server Profiler which will capture all queries that run on the server. You can filter these by database, schema or a set of tables, etc.
Use a 3rd party Transaction Log reader. This is very much a less intrusive process. You have to ensure that you are set to FULL recovery on the database.
Make sure the log will not be reused:
the database is in full recovery mode (true full, with an initial backup)
the log backup maintenance tasks are suspended for the duration of the test
Then:
write down the current database LSN
run your 3rd party project create
check the newly added log information with select * from ::fn_log(oldcurrentLSN, NULL);
All write operations will apear in the log. From the physical operation (allocation unit ID) you can get to the logical operation (object id).
Now that being said, you should probably have a decent understanding of the 3rd party schema and data model if you plan to interact with it straight at the database level. If you are planning to update the 3rd party tool and you don't even know what tables to update, you'll more than likely end up corrupting its data.

Queries for migrating data in live database?

I am writing code to migrate data from our live Access database to a new Sql Server database which has a different schema with a reorganized structure. This Sql Server database will be used with a new version of our application in development.
I've been writing migrating code in C# that calls Sql Server and Access and transforms the data as required. I migrated for the first time a table which has entries related to new entries of another table that I have not updated recently, and that caused an error because the record in the corresponding table in SQL Server could not be found
So, my SqlServer productions table has data only up to 1/14/09, and I'm continuing to migrate more tables from Access. So I want to write an update method that can figure out what the new stuff is in Access that hasn't been reflected in Sql Server.
My current idea is to write a query on the SQL side which does SELECT Max(RunDate) FROM ProductionRuns, to give me the latest date in that field in the table. On the Access side, I would write a query that does SELECT * FROM ProductionRuns WHERE RunDate > ?, where the parameter is that max date found in SQL Server, and perform my translation step in code, and then insert the new data in Sql Server.
What I'm wondering is, do I have the syntax right for getting the latest date in that Sql Server table? And is there a better way to do this kind of migration of a live database?
Edit: What I've done is make a copy of the current live database. Which I can then migrate without worrying about changes, then use that to test during development, and then I can migrate the latest data whenever the new database and application go live.
I personally would divide the process into two steps.
I would create an exact copy of Access DB in SQLServer and copy all the data
Copy the data from this temporary SQLServer DB to your destination database
In that way you can write set of SQL code to accomplish second step task
Alternatively use SSIS
Generally when you convert data to a new database that will take it's place in porduction, you shut out all users of the database for a period of time, run the migration and turn on the new database. This ensures no changes to the data are made while doing the conversion. Of course I never would have done this using c# either. Data migration is a database task and should have been done in SSIS (or DTS if you have an older version of SQL Server).
If the databse you are converting to is just in development, I would create a backup of the Access database and load the data from there to test the data loading process and to get the data in so you can do the application development. Then when it is time to do the real load, you just close down the real database to users and use it to load from. If you are trying to keep both in synch wile you develop, well I wouldn't do that but if you must, make a nightly backup of the file and load first thing in the morning using your process.
You may want to look at investing in a tool like SQL Data Compare.
I believe it has support for access databases too, and you can download a trial.
I you are happy with you C# code, but it fails because of the constraints in your destination database you temporarily can disable them and then enable after you copy the whole lot.
I am assuming that your destination database is brand new DB with no data, and not used by anyone when the transfer happens
It sounds like you have two problems:
You're migrating data from one database to another.
You're changing your schema.
Doing either of these things is tricky if you are trying to migrate the data while people are using the data.
The simplest approach is to migrate the data based on a static copy of the data, and also to queue updates to that data from the moment you captured the static copy. I don't know how easy this is in Access, but in SQLServer or Oracle you can use the redo logs for this or a manual solution using triggers. The poor-man's way of doing this is to make triggers for all the relevant tables that log the primary key of the records that have changed. Then after the old database is shut off you can iterate over those keys and get those records from the old database and put them into the new database. Just copy the whole record; if the record was deleted then delete it from the new database.
Your problem is compounded by the fact that you can't simply copy the data, you have to transform it. This means you probably have to shut down both databases and re-migrate the records based on the change list. It will take a lot of planning to ensure you get things right and I'd recommend writing a testing script that can validate that the resulting data is correct.
Also I'd ensure that the code for the migration runs inside one of the databases if possible. Otherwise you are copying the data twice and this will significantly harm the performance.

Synchronizing databases

I am developing an Adobe AIR application which stores data locally using a SQLite database.
At any time, I want the end user to synchronize his/her local data to a central MySQL database.
Any tips, advice for getting this right?
Performance and stability is the key (besides security ;))
I can think of a couple of ways:
Periodically, Dump your MySQL database and create a new SQLite database from the dump. You can then serve the SQLite database (SQLite databases are contained in a single file) for your users client to download and replace the current database.
Create a diff script that generates the necessary statements to bring the current database up to speed (various INSERT, UPDATE and DELETE statements). To do this, you must record the time of each change continuously in your database (the time of creation and update for each row, and keep a history of deleted rows).
User's client will download the diff file (a text file of the various statements) and apply it on the local database.
Both approaches have their own pros and cons - by dumping the entire database, you make sure all the data gets through. It is also much easier than creating the diff, however it might put more load on the server, depending on how often does the database gets updated between dumps.
On the other hand, diffing between the database will give you just the data that changed (hopefully), but it is more open to logical errors. It will incur an additional overhead on the client as well, since it will have to create/update all the necessary records instead of just copying a file.
If you're just sync'ing from the server to client, Eran's solution should work.
If you're just sync'ing from the client to the server, just reverse it.
If you're sync'ing both ways, have fun. You'll at minimum probably want to keep change logs, and you'll need to figure out how to deal with conflicts.