I had to search for many posts regarding these errors, but still I cannot fix the problem. Here is my code, can anyone help me to see what is going wrong?
- (void) copyDatabaseIfNeeded {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"SQL.sqlite"];
if (sqlite3_open([path UTF8String], &newDBconnection) == SQLITE_OK)
{
NSLog(#"Database opened successfully");
if(updateStmt == nil) {
NSString *updStmt = [NSString stringWithFormat: #"UPDATE Coffee SET CoffeeName = '500 Plus', Price = '1.40' Where CoffeeID= '3'"];
const char *mupdate_stmt = [updStmt UTF8String];
if(sqlite3_prepare_v2(newDBconnection, mupdate_stmt, -1, &updateStmt, NULL) != SQLITE_OK){
NSAssert1(0, #"Error while creating update statement. '%s'", sqlite3_errmsg(newDBconnection));
} else {
NSLog(#"Update successful");
}
}
if(SQLITE_DONE != sqlite3_step(updateStmt))
NSAssert1(0, #"Error while updating. '%s'", sqlite3_errmsg(newDBconnection));
else {
sqlite3_reset(updateStmt);
NSLog(#"Step successful");
}
}
else
{
NSLog(#"Error in opening database ");
}
}
There is no table Coffee in SQL.sqlite.
SQLite silently creates the database file if it does not exist. So if you've got the path wrong, you are opening an empty database file, which of course does not contain any tables. Make sure the database file exists there and it is not empty.
You can see what tables are there in the database by running SELECT * FROM sqlite_master; query.
One thing my DBA tells me when I have database problems (Oracle in this case), is to try the query using the command line tools.
This is how you would diagnose problems with sqlite3 and the iPhone simulator:
Run the App in the iPhone Simulator so the database is created/copied in the Documents directory.
Start Terminal
cd ~/Library/Application Support/iPhone Simulator/<version>/Applications/<your-app-hash>/Documents. It's best to have just one App installed in the simulator so it's obvious what App is what.
sqlite3 SQL.sqlite and try your query from there. You can also use the .schema command to see what the schema looks like.
If the query works there and not in your App then you know you have a bug, else you have a sqlite query problem or broken schema.
try reinstalling the app.the tables are created at the time of installing the app.sometimes it might happen because tables are not created
I've had a "no such table error" because the db file was never copied to the bin folder.
One the .db file in the project make sure its property "Copy to Output Directory" is set to either:
Copy always (always copies the blank database)
Copy if newer
Related
I have a very unusual problem.
I'm trying to create a simple database (6 tables, 4 of which only have 2 columns).
I'm using an in-house database library which I've used in a previous project, and it does work.
However with my current project there are occasional bugs. Basically the database isn't created correctly. It is added to the sdcard but when I access it I get a DatabaseException.
When I access the device from the desktop manager and try to open the database (with SQLite Database Browser v2.0b1) I get "File is not a SQLite 3 database".
UPDATE
I found that this happens when I delete the database manually off the sdcard.
Since there's no way to stop a user doing that, is there anything I can do to handle it?
CODE
public static boolean initialize()
{
boolean memory_card_available = ApplicationInterface.isSDCardIn();
String application_name = ApplicationInterface.getApplicationName();
if (memory_card_available == true)
{
file_path = "file:///SDCard/" + application_name + ".db";
}
else
{
file_path = "file:///store/" + application_name + ".db";
}
try
{
uri = URI.create(file_path);
FileClass.hideFile(file_path);
} catch (MalformedURIException mue)
{
}
return create(uri);
}
private static boolean create(URI db_file)
{
boolean response = false;
try
{
db = DatabaseFactory.create(db_file);
db.close();
response = true;
} catch (Exception e)
{
}
return response;
}
My only suggestion is keep a default database in your assets - if there is a problem with the one on the SD Card, attempt to recreate it by copying the default one.
Not a very good answer I expect.
Since it looks like your problem is that the user is deleting your database, just make sure to catch exceptions when you open it (or access it ... wherever you're getting the exception):
try {
URI uri = URI.create("file:///SDCard/Databases/database1.db");
sqliteDB = DatabaseFactory.open(myURI);
Statement st = sqliteDB.createStatement( "CREATE TABLE 'Employee' ( " +
"'Name' TEXT, " +
"'Age' INTEGER )" );
st.prepare();
st.execute();
} catch ( DatabaseException e ) {
System.out.println( e.getMessage() );
// TODO: decide if you want to create a new database here, or
// alert the user if the SDCard is not available
}
Note that even though it's probably unusual for a user to delete a private file that your app creates, it's perfectly normal for the SDCard to be unavailable because the device is connected to a PC via USB. So, you really should always be testing for this condition (file open error).
See this answer regarding checking for SDCard availability.
Also, read this about SQLite db storage locations, and make sure to review this answer by Michael Donohue about eMMC storage.
Update: SQLite Corruption
See this link describing the many ways SQLite databases can be corrupted. It definitely sounded to me like maybe the .db file was deleted, but not the journal / wal file. If that was it, you could try deleting database1* programmatically before you create database1.db. But, your comments seem to suggest that it was something else. Perhaps you could look into the file locking failure modes, too.
If you are desperate, you might try changing your code to use a different name (e.g. database2, database3) each time you create a new db, to make sure you're not getting artifacts from the previous db.
Database that already exists is replaced by calling the method CreateTable <> in SQLite for Windows 8, erasing all the lines and creating a new table. How can I solve? following code to analyze:
using(var db = new SQLite.SQLiteConnection(App.DBPath))
{
db.CreateTable<ListasEntid>();
if (db.ExecuteScalar<int>("select count(1) from ListasEntid")==0)
{
db.RunInTransaction(() =>
{
db.Insert(new ListasEntid() { Nome = "Lista", Eletros = "Teste" });
});
}
}
Not sure what language you are using, but if you can execute raw SQL then you can use the following syntax:
CREATE TABLE IF NOT EXISTS ListasEntid (nome text, eletros text);
This ensures that table ListasEntid exists without nuking any of your previous data.
Thank you for the attention, but the problem was not specifically CreateTable method, but in the application configuration in the application properties, Debug tab, in option start the box was marked, "Unistall and then re-install my packege", erasing all files always initializing the debug.
There are probably many other questions I don't even know to ask yet since I'm new to app programming.
I initially created the database from within the app, copied it to my working folder (which is probably not where it should ultimately reside), then appended my records (about 1,000 of them) from a text file.
The first two questions that come to mind are:
- what folder should the database be in?
- how does it get deployed with the app?
I found quite few examples using the following lines in persistentStoreCoordinator function:
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"myDatabase.sqlite"];
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
But the first line gives me the pre-compile error: "Receiver type 'NSURL' for instance message does not declare a method with selector 'stringByAppendingPathComponent:'. Why is it not working for me?
And is this in fact the best way to bundle my database with the rest of the app?
Thanks!
Easiest solution is to use NSUrl instead of NSString. SO user #trapper already provided a solution in the below link.
importing sqlite to coredata
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"Database.sqlite"];
// If the database doesn't exist copy in the default one
if (![storeURL checkResourceIsReachableAndReturnError:NULL])
{
NSURL *defaultStoreURL = [[NSBundle mainBundle] URLForResource:#"Database" withExtension:#"sqlite"];
if ([defaultStoreURL checkResourceIsReachableAndReturnError:NULL])
{
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager copyItemAtURL:defaultStoreURL toURL:storeURL error:NULL];
}
}
I have built up a basic database application in which user can insert records onto a table and app displays them on a TableView.
Everything is working as it is supposed to be. For example, the new records do display even if we kill the app from app switcher and relaunch it from the springboard.
BUT every time I build and run using Xcode, the database just goes to default records! The new records are just not there.
Is it normal?... but what if I want to test my app for new records? Any fix?
BTW, JFYI, below is the code I use to make editable DB.
-(NSString *)createEditableDatabase{
// Check if DB already exists
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *writableDB = [documentsDir stringByAppendingPathComponent:#"Database.db"];
success = [fileManager fileExistsAtPath:writableDB];
//The editable DB already exists
if (success) {
return writableDB;
}
//The editable DB does not exist
//Copy the default DB into App's Doc Dir.
NSString *defaultPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Database.db"];
success = [fileManager copyItemAtPath:defaultPath toPath:writableDB error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable DB file: '%#'", [error localizedDescription]);
}
return writableDB;
}
While digging deeper, I noticed that the database modify date in finder was not updating when I inserted a record. So, I found out that I was still using old path to perform DB operations (not the Documents one). :) Now everything working fine. Anyways thanks Nick
I am using SQLite for Windows Phone 7 (http://sqlitewindowsphone.codeplex.com/) and I have done every steps from this tutorial (http://dotnetslackers.com/articles/silverlight/Windows-Phone-7-Native-Database-Programming-via-Sqlite-Client-for-Windows-Phone.aspx)
Then I try to make some simple application with basic features like select and delete. App is working properly till I want to make one of this operations. After I click select or delete, compiler shows me errors that he is unable to open database file...
I have no idea why?
I used the same Sqlite client, and had the same problem. This problem occurs because the sqlite try to create file in IsolatedFileStorage "DatabaseName.sqlite-journal" and it does not have enough permissions for that. I solved the problem, so that created "DatabaseName.sqlite-journal" before copying database to IsolatedFileStorage. Here's my method that did it:
private void CopyFromContentToStorage(String assemblyName, String dbName)
{
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
string uri = dbName + "-journal";
store.CreateFile(uri);
using (Stream input = Application.GetResourceStream(new Uri("/" + assemblyName + ";component/" + dbName,UriKind.Relative)).Stream)
{
IsolatedStorageFileStream dest = new IsolatedStorageFileStream(dbName, FileMode.OpenOrCreate, FileAccess.Write, store);
input.Position = 0;
CopyStream(input, dest);
dest.Flush();
dest.Close();
dest.Dispose();
}
}
it helped me, and worked well.
hope this will help you
Are you sure the file exists?
You can check like that:
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
exists = store.FileExists(DbfileName);
}