Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 12-10-2008, 08:30 PM   #1 (permalink)
Lost in a sea of code
 
BostonMerlin's Avatar
 
Join Date: Apr 2008
Location: Boston
Posts: 399
BostonMerlin is an unknown quantity at this point
Default SQLITE Multiple Statements at once

I'm trying to execute multiple sqlite statements at the same time back to back but am having a problem. Using MS SQL daily at my full time gig its fairly easy to wrap begin/end statements around inserts, deletes and updates.

I read up on the sqllite site that they support BEGIN and END transactions but whenever i pass more than one statement into sqlite3_prepare_v2 it returns an error.

example: "BEGIN Delete col1 From table1 END BEGIN Update Table2 Set col1=3 END"

I'm processing several thousand rows at a time and am trying to speed things up as much as possible.

Any thoughts?

Thanks John
__________________
----------------------------------------------------------------------
I love being a dad, flying airplanes and writing code.
----------------------------------------------------------------------
Follow me on Twitter: @BostonMerlin
Feed your brain on Twitter: @iPhoneDev101
----------------------------------------------------------------------
iPhone Apps:
BostonMerlin is offline   Reply With Quote
Old 12-10-2008, 08:37 PM   #2 (permalink)
Lost in a sea of code
 
BostonMerlin's Avatar
 
Join Date: Apr 2008
Location: Boston
Posts: 399
BostonMerlin is an unknown quantity at this point
Default

I think adding semicolons after each statement will work.. still need to test.

John
__________________
----------------------------------------------------------------------
I love being a dad, flying airplanes and writing code.
----------------------------------------------------------------------
Follow me on Twitter: @BostonMerlin
Feed your brain on Twitter: @iPhoneDev101
----------------------------------------------------------------------
iPhone Apps:

Last edited by BostonMerlin; 12-10-2008 at 08:49 PM.
BostonMerlin is offline   Reply With Quote
Old 12-11-2008, 12:13 AM   #3 (permalink)
Registered Member
 
Stitch's Avatar
 
Join Date: Aug 2008
Posts: 400
Stitch is on a distinguished road
Default

Hi,

Yes, you need begin and commit statements but you implement them like this:

Code:
int success;
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {
  // BEGIN STATEMENT
  const char *sql1 = "BEGIN EXCLUSIVE TRANSACTION";
  sqlite3_stmt *begin_statement;
  if (sqlite3_prepare_v2(database, sql1, -1, &begin_statement, NULL) != SQLITE_OK) {
    NSAssert1(0, @"Error Message: '%s'.", sqlite3_errmsg(database));
  }
  success = sqlite3_step(begin_statement);
  if (success != SQLITE_DONE) {
    NSAssert1(0, @"Error Message: '%s'.", sqlite3_errmsg(database));
  }


  // DO YOUR NORMAL INSERT STATEMENTS HERE


  // COMMIT
  const char *sql2 = "COMMIT TRANSACTION";
  sqlite3_stmt *commit_statement;
  if (sqlite3_prepare_v2(database, sql2, -1, &commit_statement, NULL) != SQLITE_OK) {
    NSAssert1(0, @"Error Message: '%s'.", sqlite3_errmsg(database));
  }
  success = sqlite3_step(commit_statement);
  if (success != SQLITE_DONE) {
    NSAssert1(0, @"Error Message: '%s'.", sqlite3_errmsg(database));
  }
}
Thanks,
Richard.
__________________
BUZZER! : iTunes Library Music Quiz (1 or 2 Player)
Stitch is offline   Reply With Quote
Old 02-28-2009, 06:11 PM   #4 (permalink)
Registered Member
 
Join Date: Oct 2008
Location: United States
Posts: 132
Knertified is on a distinguished road
Default

I found this thread when searching for transaction help. I think I've found an easier way as it's working for me.

Before your first prepare statement add:
Code:
	sqlite3_exec(database, "BEGIN", 0, 0, 0); // Begin Transaction
After your last SQL reset statement but before your finalize statement add:
Code:
	sqlite3_exec(database, "COMMIT", 0, 0, 0); // Commit Transaction
Knertified is offline   Reply With Quote
Old 02-28-2009, 08:52 PM   #5 (permalink)
Registered Member
 
Join Date: Dec 2008
Posts: 429
lbendlin is on a distinguished road
Default

There is no need for any Prepare statements if you do simple transactions (without BLOBs). You can use exclusively sqlite3_exec, and construct the inner loop statement on the fly with sprintf and a buffer variable that is large enough to hold the statement.

Code:
			sqlite3_exec(database, "PRAGMA synchronous = 0;", NULL, NULL, NULL);
			sqlite3_exec(database, "PRAGMA temp_store = 2;", NULL, NULL, NULL);
			// truncate table
			sqlite3_exec(database, "DELETE FROM table", NULL, NULL, NULL);
			// import data
			char buffer [200];
			//NSLog(@"Beginning transaction");
			sqlite3_exec(database, "BEGIN TRANSACTION;", NULL, NULL, NULL);
			for (int i = 0; i < [chunks count]-2; i++) {

				sprintf(buffer,	"INSERT INTO table VALUES (%s);",[[chunks objectAtIndex:i] UTF8String]); 
				sqlite3_exec(database, buffer, NULL, NULL, NULL);
			}
			//NSLog(@"Committing transaction");
			if(sqlite3_exec(database, "COMMIT TRANSACTION;", NULL, NULL, NULL)== SQLITE_OK) {...
lbendlin is offline   Reply With Quote
Old 09-18-2009, 04:54 AM   #6 (permalink)
Registered Member
 
Join Date: May 2009
Posts: 36
skayser is on a distinguished road
Default

Hi - I'm a beginner programmer and was hoping someone would be able to tell me where I need to put the 'begin' and 'commit' statements. I have a process which takes an sql statement and puts it into this method as the 'sqlString'. Running the method succesfully runs the sql scripts as per my logging but I don't think the data is being committed to the sqlite db as the view isn't updated.

Could someone tell me where in this code I should put the begin and commit statements? THANKS!

Code:
	sqlite3 *database;
	sqlite3_stmt *selectStatement; 
	
	NSString *sqltemp= sqlString;
	const char *sqlStatement = [sqltemp UTF8String];

	if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)

	{
		if(sqlite3_prepare_v2(database, sqlStatement, -1, &selectStatement, NULL) != SQLITE_OK)
		{
			NSAssert1(0,@"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
		}
	}
skayser is offline   Reply With Quote
Old 09-18-2009, 06:01 AM   #7 (permalink)
Registered Member
 
Join Date: Dec 2008
Posts: 429
lbendlin is on a distinguished road
Default

Begin/commit has limited use for a single statement (unless you want to explitly lock the db against other use at that time)

you use begin/commit with loops of SQL for example when you want to insert 1000 rows one by one.
lbendlin is offline   Reply With Quote
Old 07-07-2010, 02:27 PM   #8 (permalink)
Registered Member
 
Join Date: Jun 2010
Posts: 2
junglemason is on a distinguished road
Default

Quote:
Originally Posted by lbendlin View Post
Code:
sqlite3_exec(database, "PRAGMA synchronous = 0;", NULL, NULL, NULL);
sqlite3_exec(database, "PRAGMA temp_store = 2;", NULL, NULL, NULL);
// truncate table
sqlite3_exec(database, "DELETE FROM table", NULL, NULL, NULL);
// import data
char buffer [200];
//NSLog(@"Beginning transaction");
sqlite3_exec(database, "BEGIN TRANSACTION;", NULL, NULL, NULL);
for (int i = 0; i < [chunks count]-2; i++) {
	sprintf(buffer, "INSERT INTO table VALUES (%s);",[[chunks objectAtIndex:i] UTF8String]);
	sqlite3_exec(database, buffer, NULL, NULL, NULL);
}
//NSLog(@"Committing transaction");
if(sqlite3_exec(database, "COMMIT TRANSACTION;", NULL, NULL, NULL)== SQLITE_OK) {...
Thanks, lbendlin!

A few questions, if you don't mind:

- Can I put the delete statement inside the transaction?

- Anything wrong with using pragma synchronous=2 (FULL) instead of 0? I want to be extra safe in case a crash happens mid-transaction.

- char buffer [200]; - I am going to have a thousand rows to insert - will this hold them? Do I just change the number from 200 to 2bajillion?

Thanks again
-Rich
junglemason is offline   Reply With Quote
Old 07-07-2010, 03:55 PM   #9 (permalink)
Registered Member
 
Join Date: Dec 2008
Posts: 429
lbendlin is on a distinguished road
Default

Quote:
Originally Posted by junglemason View Post

- Can I put the delete statement inside the transaction?

- Anything wrong with using pragma synchronous=2 (FULL) instead of 0? I want to be extra safe in case a crash happens mid-transaction.

- char buffer [200]; - I am going to have a thousand rows to insert - will this hold them? Do I just change the number from 200 to 2bajillion?

Thanks again
-Rich
You can put any statement in there, but there will be no speed gain. Only the inserts benefit from that, speed wise.

The buffer is refilled every time. It only needs to be as long as your longest anticipated statement

I have no opinion on the Pragma stuff. I don't understand it entirely, and it also doesn't seem to make any (speed) difference.
lbendlin is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 371
12 members and 359 guests
condor304, dansparrow, dre, dreamdash3, ilmman, LezB44, michelle, Objective Zero, Sami Gh, shagor012, thephotographer, tinamm64
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,663
Threads: 94,119
Posts: 402,896
Top Poster: BrianSlick (7,990)
Welcome to our newest member, LezB44
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 01:36 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0