I have a table and I want to print the content of a row here is the table structure:
CREATE TABLE "quotes_type" ("type_id" INTEGER PRIMARY KEY NOT NULL , "content" TEXT)
I can see the type_id with debug and the value is correctly 1 but I can't return the context value with the help of sqlite3_column_text here is the code:
NSString *qry = [NSString stringWithFormat: #"select * from quotes_type"];
const char *count_stmt = [qry UTF8String];
sqlite3_prepare_v2(contactDB, count_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_ERROR) {
NSAssert1(0,#"Error when selecting rows %s",sqlite3_errmsg(contactDB));
} else {
int myid=sqlite3_column_int(statement, 0);
NSLog(#"Context: %s", sqlite3_column_text(statement, 1));
NSLog(#"myid is %d",myid);
sqlite3_finalize(statement);
sqlite3_close(contactDB);
the problem is this line:
NSLog(#"Data: %s", sqlite3_column_text(statement, 1));
the result is Null
I realized that it doesn't update my sqlite file and it is reading from my previous one how can I force it to read from the new one?even I deleted all .sqlite files but still it is reading it from somewhere
Related
How can I write this query without using stringWithFormat. How can I pass parameters to the SQLite Query. Now my code is this:
NSString *querySQL = [NSString stringWithFormat:#"SELECT name, char_code, sound, status From Tmy_table Where ID=\"%d\"", i];
Thanks in advance
You should use sqlite3 host parameters and sqlite3_bind() to bind variables to them. This would like something like this in your example.
NSString* query = #"SELECT name, char_code, sound, status From Tmy_table Where ID=?";
sqlite3_stmt* myStatement = NULL;
sqlite3_prepare_v2(myDBConnection, [query UTF8String], -1, &myStatement, NULL);
sqlite3_bind_int(myStatement, 1, i);
Points to note:
The two sqlite3 functions return error codes that you must check. I've left that out for clarity.
The second parameter in sqlite3_bind_int() tells you which question mar to replace with the third parameter. The index starts at 1, not 0.
See also docs about binding.
NSString sql = #"SELECT name, char_code, sound, status From Tmy_table Where ID=?";
sqlite3_stmt *stmt = NULL;
if (sqlite3_prepare_v2(database, [sql UTF8String], -1, &stmt, SQLITE_STATIC) == SQLITE_OK)
{
// If 'i' was text:
// if (sqlite3_bind_text(stmt, 1, i, -1, SQLITE_STATIC) == SQLITE_OK)
if (sqlite3_bind_int(stmt, 1, i) == SQLITE_OK) // Note: 1-based column when binding!!!!
{
while (sqlite3_step(stmt) == SQLITE_ROW)
{
const char *name = sqlite3_column_text(stmt, 0); // Note: 0-based column when fetching!!!
const char *sound = sqlite3_column_text(stmt, 1);
const char *status = sqlite3_column_text(stmt, 2);
// ... print the values or whatever
}
}
else
{
NSLog(#"Failed to bind int: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(stmt);
}
else
{
NSLog(#"Failed to prepare statement '%#': %s", sql, sqlite3_errmsg(database));
}
EDIT Changed the bind to sqlite3_bind_text() as i appears to be text...
I have a problem with the inserting and retrieving code
There is no run time error but inserting data is not working and the retrieving code only retrieves the last record from the DB.
Is it better to use NSString or NSMutableString?
NSLog(#"test");
NSString *sql1 = [NSString stringWithFormat:#"INSERT INTO User Values (2,'%#','','F','123','','','','','A','B','123','123',2)",name.text];
char *err;
sqlite3_exec(database, [sql1 UTF8String], NULL, NULL, &err)!= SQLITE_OK ;
const char *sql = "select * from User";
sqlite3_stmt *searchStatement;
if (sqlite3_prepare_v2(database, sql, -1, &searchStatement, NULL) == SQLITE_OK)
{
while (sqlite3_step(searchStatement) == SQLITE_ROW)
{
char * try = (char*)sqlite3_column_text(searchStatement, 1);
if (try){
item = [NSMutableString stringWithUTF8String:try];
}
else{
item = #"";
}
The issue seems to be in your retrieval code. The sqlite3_column_type methods use zero-based indexing, but it looks like you are starting from position 1. Thus each time you step through, you aren't pulling out the information you need. I'm not sure why you are getting the last item, but try going from position 0 and see if that helps.
When I run the following code to delete a row from the MAIN.NOTES table, if tasks.todoDone does not have a match nothing is deleted in MAIN.NOTES. But if one tasks.todoDone is greater than '' then all the rows in MAIN.NOTES are deleted even if task.todoNod is not less than nod.
The second part of the code, deleting from MAIN.TASKS works correctly and only deletes rows that match both tests.
What do I have wrong in my EXISTS (select * line?
if (sqlite3_open(dbpath, &tasksDB) == SQLITE_OK) {
NSString *querySQLNotes = [NSString stringWithFormat:#"DELETE FROM MAIN.NOTES WHERE EXISTS (select * from MAIN.TASKS where tasks.todoNod <'%i' and tasks.todoDone > '')",nod];
char *errMsg;
const char *query_stmtN = [querySQLNotes UTF8String];// this should delete the notes for task that will be deleted next
if (sqlite3_exec(tasksDB, query_stmtN, NULL, NULL, &errMsg) == SQLITE_OK) {
int tc = sqlite3_changes(tasksDB);
NSLog(#"total count of deleted notes %i",tc);
}
NSString *querySQL = [NSString stringWithFormat:#"DELETE FROM MAIN.TASKS WHERE todoNod <'%i' and todoDone > ''",nod];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(tasksDB, query_stmt, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_step(statement) == SQLITE_DONE) {
NSLog(#"Match found and deleted");
} else {
NSLog(#"Match found and not deleted");
}
sqlite3_finalize(statement);
int tc = sqlite3_changes(tasksDB);
NSLog(#"total count of deleted tasks %i",tc);
}
sqlite3_close(tasksDB);
}
Thanks
Very confused by this... my "DiscoveredCars" table begins with two records in it. The first time I call this method with it inserts properly and the last line displays "3" for the number of records.
Yet the second time I call it, the SQL looks perfect yet for some reason it still is showing "3" for the size and does not seem to be inserting properly? Any ideas?
- (void)writeToDiscoveredCars: (Car *)car {
NSString *tempSQL = [NSString stringWithFormat:#"INSERT INTO DiscoveredCars (car_ID) VALUES (%i)", car.ID];
NSLog(#"size of discoveredis %i", [self numberRecordsForTable:#"DiscoveredRecipes"]);
NSLog(#"SQL insert is %#", tempSQL);
const char *sql = [tempSQL UTF8String];
sqlite3_stmt *statement;
int sqlResult = sqlite3_prepare_v2(myDatabase, sql, -1, &statement, NULL);
if (sqlResult == SQLITE_OK) {
sqlResult = sqlite3_step(statement);
if(sqlResult == SQLITE_DONE)
{
}
sqlite3_finalize(statement);
}
else
{
NSLog(#"1. problem with database");
NSLog(#"%s", sqlite3_errmsg(myDatabase));
}
NSLog(#"size of discoveredis %i", [self numberRecordsForTable:#"DiscoveredCars"]);
}
You never execute your query by calling sqlite3_step.
int sqlResult = sqlite3_prepare_v2(myDatabase, sql, -1, &statement, NULL);
if (sqlResult == SQLITE_OK) {
sqlResult = sqlite3_step(statement); //Execute!
//check the result for completion
if(sqlResult == SQLITE_DONE)
{
}
sqlite3_finalize(statement);
}
I'm trying the following code to count the number of rows in my SQLite database table, but it throws an exception. Is these a simpler way to do this?
- (void) countRecords {
int rows = 0;
#try {
NSString *dbPath = [self getDBPath];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
NSString *strSQL;
strSQL = #"SELECT COUNT(*) FROM MYTABLE";
const char *sql = (const char *) [strSQL UTF8String];
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(database, sql, -1, &stmt, NULL) == SQLITE_OK) {
// THIS IS WHERE IT FAILS:
if (SQLITE_DONE!=sqlite3_step(stmt) ) {
NSAssert1(0,#"Error when counting rows %s",sqlite3_errmsg(database));
} else {
rows = sqlite3_column_int(stmt, 0);
NSLog(#"SQLite Rows: %i", rows);
}
sqlite3_finalize(stmt);
}
sqlite3_close(database);
}
}
#catch (NSException * e) {
NSLog(#"Error Counting");
}
}
I came across a solution, using my code above, just replacing the step statement with the code below:
if (sqlite3_step(stmt) == SQLITE_ERROR) {
NSAssert1(0,#"Error when counting rows %s",sqlite3_errmsg(database));
} else {
rows = sqlite3_column_int(stmt, 0);
NSLog(#"SQLite Rows: %i", rows);
}
This usually works for me
- (NSInteger )numberRecordsForTable:(NSString *)table {
NSInteger numTableRecords = -1;
if (sqlite3_open([self.dbPath UTF8String], &database) == SQLITE_OK) {
NSString *sqlStatement = [NSString stringWithFormat: #"select count(*) from %#", table];
const char *sql = [sqlStatement cStringUsingEncoding:NSUTF8StringEncoding];
if(sqlite3_prepare_v2(database, sql, -1, &sqlClause, NULL) == SQLITE_OK) {
while(sqlite3_step(sqlClause) == SQLITE_ROW) {
numTableRecords = sqlite3_column_int(sqlClause, 0);
}
}
else {
printf("could not prepare statement: %s\n", sqlite3_errmsg(database));
}
}
else {
NSLog(#"Error in Opening Database File");
}
sqlite3_close(database);
return numTableRecords;
}
HTH
There is no SQL expression to count rows in a database: you can count rows in a every table and then add them up.
I thought I'd trow in my two cents here as there is an expression to count rows in a database, I use it when dealing with MySQL databases using php scripts all the time. and I tested it in an ios app it's available in there too behold:
sqlite3 *database;
if(sqlite3_open([dbpath UTF8String], &database) == SQLITE_OK)
{
NSString *sql = #"select count(*) from today";
sqlite3_stmt *selectStatement;
int returnValue = sqlite3_prepare_v2(database, [sql UTF8String], -1, &selectStatement, NULL);
if (returnValue == SQLITE_OK)
{
if(sqlite3_step(selectStatement) == SQLITE_ROW)
{
numrows= sqlite3_column_int(selectStatement, 0);
}
}
sqlite3_finalize(selectStatement);
sqlite3_close(database);
}
no need for a fancy loop counter thing. btw if your using an auto increment int for the primary key. it works just slightly different then an array's key. where as in an array that is n items long the valid array elements are from 0 to n-1 in a database the key field is from 1 to n simple enough to work around if you just keep that in mind.
-(void)databaseRecordCount{
int rows = 0;
#try {
sqlite3 *database;
NSString *filePath = [self databaseDocumentsFilePath];
if(sqlite3_open([filePath UTF8String], &database) == SQLITE_OK) {
NSString *query = #"SELECT * FROM MYTABLE";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &compiledStatement, NULL) != SQLITE_OK)
NSLog(#"Error while creating detail view statement. '%s'", sqlite3_errmsg(database));
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &compiledStatement, nil) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
rows++;
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
}
#catch (NSException * e) {
NSLog(#"Error Counting");
}
NSLog(#"SQLite Rows: %i", rows);
NSUserDefaults *userDefaults;
userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:rows forKey:#"databaseRecordCount"];
[userDefaults synchronize];
}
You'll have to count of each table individually. Some pseudo code:
sql = "SELECT name FROM sqlite_master" WHERE type = 'table'
tables() = GetRows(sql)
Dim total As Integer
For Each t As String in tables
sql = "SELECT COUNT(*) FROM " + t
total = total + GetValue(sql)
Next
Show(total)