Delete column from Sqlite database - objective-c

Basically I have to enter all textfield values in database then have to use for sending to webservice. So when the one column details send to service then have to delete that column.
I have done this:
-(void)deleteTableDataFromSavedDataTable:(NSString *)lastID {
NSString *sql_str=[NSString stringWithFormat:#"DELETE FROM FormInfoValues where Phone = %#",lastID];
const char *sql = [sql_str UTF8String];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
NSLog(#"sql delete statement is ");
sqlite3_stmt *deleteStmt;
if(sqlite3_prepare_v2(database, sql, -1, &deleteStmt, NULL) == SQLITE_OK)
{
NSLog(#"sql delete statement is %#", deleteStmt);
if(sqlite3_step(deleteStmt) != SQLITE_DONE )
{
NSLog( #"Error: %s", sqlite3_errmsg(database) );
}
else
{
NSLog( #"row id = %lld", (sqlite3_last_insert_rowid(database)+1));
NSLog(#"No Error");
}
}
sqlite3_finalize(deleteStmt);
}
sqlite3_close(database);
}
but its not deleting after sending. Why its not calling?
give me ideas..

It's quite possible I'm not understanding your issue properly -- so I apologize in advance if so.
Regarding: "...then have to delete that column."
-- If you want to clear the data in a column (by setting it to zero, or empty string, or NULL) then you'll want to use the UPDATE command in SQL. The DELETE command always deletes ROWS.
-- If you really must remove a column from a table's schema, you'll have to create a new table in sqlite. (Sqlite allows you to ADD a column via ALTER TABLE command, and some other databases DO allow you to drop a column using ALTER TABLE as well.) You can quickly copy a table (without it's constraints, etc) via e.g.:
CREATE TABLE MyOutput as SELECT a,b,d,f,h,z from MyOriginal;
-- If your output is created by a SELECT statement, just avoid using "*" and specify just the columns you want included.

Related

How to bind a LIKE wildcard in SQLite3

I'd like to run the SQL query: SELECT COUNT(id) AS nbr FROM user WHERE name LIKE '%John%', and get the number of records matched by the keyword John.
So I've written the following code :
unsigned int nbr;
char *sql, *like;
sqlite3 *db;
sqlite3_stmt *stmt;
/* Database connection etc. */
like = _make_string("%%%s%%", keyword); /* keyword: John */
printf("Like clause: %s\n", like);
sql = _make_string("SELECT COUNT(id) AS nbr FROM user WHERE name LIKE ?");
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
sqlite3_bind_text(stmt, 1, like, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) != SQLITE_ROW) {
/* error, SQL execution failed */
}
nbr = sqlite3_column_int64(stmt, 1);
printf("Number of record: %u\n", nbr);
/* Free strings, finalize statement, disconnect db etc. */
For reason of simplicity, some return value tests are ignored in the snippet. _make_string(const char *fmt, ...) is a printf-like function which can form strings, and it did return %John% to me.
However, my code always returns 0 record. I have tried the SQL in sqlite3 command line shell, but it has found 2 records.
Any idea please ?
I've hard coded the LIKE clause and removed the sqlite3_bind_text function, and it doesn't change the result.
sql = _make_string("SELECT COUNT(id) AS nbr FROM client WHERE name LIKE '%John%'");
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (sqlite3_step(stmt) != SQLITE_ROW) {
/* error */
}
nbr = sqlite3_column_int64(stmt, 1);
printf("Number of record: %u\n", nbr);
The program always returns 0 records.
Well, I've found the answer in the mailing list archive of SQLite Why bind indexes start from 1 and column indexes start from 0?
In fact, the bind index starts from 1, but the column index starts from 0. So the code should be modified as the following
nbr = sqlite3_column_int64(stmt, 0);
printf("Number of record: %u.\n", nbr);
Now the program returns 2 (records) !

Print / Log the SQLite Statement after the binding

I like to log the compiled Statement after this:
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
sqlite3_bind_int( compiledStatement, 1, updateThis.web_id);
[...]
}
NSLog(#"Put out the complete SQLite Statement.");
The direct output failed, and i think this is not the way to do it:
NSLog(#"%#",compiledStatement);
You can't print the compiledStatement. What you can do is implement the sqlite3_trace callback function. This will print every executed sql statement.
To implement the function add this before your #implementation block
void sqliteCallbackFunc(void *foo, const char* statement) {
NSLog(#"=> %s", statement);
}
This is the function you will point to.
To point to this function simple call:
sqlite3_trace(db, sqliteCallbackFunc, NULL);

iOS - SQLite not updating but prepare and step are successfully executing

The title is pretty much all the information I have because I cannot find an issue with the code. The same instance of database that is being used in the code below is able to successfully insert, delete and select, but this function does not work. No error code is retured(Always 0), and the program continues to run nominally after executing this function.
Here is the table information:
reminder (uniqueID integer primary key autoincrement, title text not null, details text, time integer)
Code in question:
- (void) updateEntryData:(ReminderData *)data
{
sqlite3_stmt *statement;
char *updateCommand = "UPDATE reminder SET title = '?', details = '?', time = ? WHERE uniqueID = ?";
int e = sqlite3_prepare_v2(database, updateCommand, -1, &statement, nil);
if(e != SQLITE_OK) {
NSLog(#"Problem with updateEntryWithUniqueID");
NSLog(#"Error Code: %d, message '%s'", e, sqlite3_errmsg(database));
return;
}
sqlite3_bind_text(statement, 1, [data.title UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [data.details UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(statement, 3, [data.time timeIntervalSince1970]);
sqlite3_bind_int(statement, 4, data.uniqueID);
NSLog(#"\nID: %d\nTitle: %#\nDetails: %#\nTime: %#", data.uniqueID, data.title, data.details, data.time);
if(sqlite3_step(statement) != SQLITE_DONE) {
NSLog(#"Problems updating entry in reminder");
}
/* Finished */
sqlite3_finalize(statement);
}
Any help would be greatly appreciated; I am stumped.
Edit: Forgot to mention that the sql command used works when entered into the sqlite console.
Just remove the single quotes around the parameters. Wrapping the placeholders will make it a value and not a parameter anymore.
char *updateCommand = "UPDATE reminder SET title = ?, details = ? .....";

Viewing sqlite3_stmt* in command window

I have inherited a SQLite database that is poorly commented and I need to understand what it is querying and receiving. Is there a way to see the value a sqlite3_stmt pointer is pointing to? Is it something that can be printed to the console in a printf() or NSLog()?
Thanks
The best way to do it is to trace the compiled statement. I've found a solution with the help of this question:
The sqlite3_trace command triggers a callback, which you need to code yourself. Once the trace is turned on it will execute for the rest of the program.
I've got all my database access routines in a single class, and I've used this as the callback function (it's a C function, not a method).
void traceCallback( void* udp, const char* sql )
{
printf("{SQL} [%s]\n", sql);
}
I turned the trace on in an init database method: it's turned on once the database is opened.
-(void)initializeDatabase
{
NSString *path = [self createEditableCopyOfDatabaseIfNeeded];
// open the db
if (sqlite3_open([path UTF8String], &db) == SQLITE_OK)
sqlite3_trace(db, traceCallback, NULL);
else {
// error - cleanup
sqlite3_close(db);
NSLog(#"Error opening db");
NSLog(#"Path: %#",path);
}
}
This will turn a SQL statement with bound variables into a string.
From this:
const char *sql2 = "select a.key, b.key from words a left outer join known_words b on a.key = b.word_id where a.word_foreign = :word_foreign";
To this:
{SQL} [select a.key, b.key from words a left outer join known_words b on a.key = b.word_id where a.word_foreign = 'bak.']

sqlite3 datetime not functioning properly on iPhone

I am having trouble getting sqlite3 to do comparisons between datetimes. On my mac, when I run the sql queries, it works. However, on the iPhone, the exact same query fails.
I have a sqlite3 table setup as follows:
CREATE TABLE IF NOT EXISTS `Artists` (
`id` int(11) NOT NULL PRIMARY KEY,
`name` varchar(256) NOT NULL,
`lastUpdate` date NOT NULL default CURRENT_TIMESTAMP ,
...
...
);
I can insert an artist with:
INSERT OR IGNORE INTO `Artists` (`id`,`name`) VALUES ('1','Justin');
I am trying to find the number of artists that have not been updated for the last 2 seconds (to keep it short):
SELECT COUNT(*) FROM `Artists` WHERE `id` = ? AND `lastUpdate` < datetime('now','-2 seconds');
On the iPhone, this returns 0. On my pc, it returns 1. I am expecting the value to be 1. What is the difference? I am retrieving the value by:
-(BOOL) artistNeedsUpdating:(int)artistId
{
[dbLock lock];
BOOL result = NO;
sqlite3_stmt *statement;
const char* query = "SELECT COUNT(*) FROM `Artists` WHERE `id` = ? AND `lastUpdate` < datetime('now','-2 seconds');";
if(sqlite3_prepare_v2(database, query, -1, &statement, NULL) == SQLITE_OK){
sqlite3_bind_int(statement, 1, artistId);
if(sqlite3_step(statement) == SQLITE_ROW){
if(sqlite3_column_int(statement, 0) > 0) // If 0, then we don't need to update
result = YES;
}
sqlite3_finalize(statement);
}
[dbLock unlock];
return result;
}
I am confused as to why it works on one platform but not the other, does anybody have any ideas?
Thank you,
Justin
Nevermind, it was my mistake.
I was updating the row after it got done with
UPDATE `Artists` SET `lastUpdate`='CURRENT_TIMESTAMP';
When it should have been:
UPDATE `Artists` SET `lastUpdate`=CURRENT_TIMESTAMP;