FMDB, GCD, and FMDBGCD
Master haomeng is devoted to his contribution and respects the author's Labor achievements. Do not repost them.
If the article is helpful to you, you are welcome to donate to the author, support haomeng master, the amount of donation is free, focusing on your mind ^_^
I want to donate: Click to donate
Cocos2d-X source code download: point I send
Because FMDB is built on SQLite, you should at least read this article from start to end.
At the same time, add the SQLite document page http://www.sqlite.org/docs.html to your bookmarks.
Automatic Reference count (APC) or manual memory management?
Both of them. FMDB will know which one you are using during compilation and then process it accordingly.
Usage
FMDB has three main classes
FMDatabase-indicates a separate SQLite database. The command used to execute SQLite.
FMResultSet-indicates the result set after the FMDatabase executes the query.
FMDatabaseQueue-if you want to execute multiple queries or updates in multiple threads, you should use this class. This is thread-safe.
Database creation
When creating an FMDatabase object, the parameter is the path of the SQLite database file. The path can be one of the following three types:
File Path. This file path does not need to be saved. If it does not exist, it is automatically created.
Empty string (@""). Creates an empty database in the temporary directory. When the FMDatabase link is closed, the file is also deleted.
NULL. An internal database is created. Similarly, when the FMDatabase connection is closed, the data will be destroyed.
(If you need a step-by-step understanding of the temporary database or internal database, please continue to read: http://www.sqlite.org/inmemorydb.html)
FMDatabase * db = [FMDatabase databaseWithPath: @ "/tmp. db"];
Open Database
Before interacting with a database, the database must be opened. If resources or permissions are insufficient to open or create a database, opening will fail.
If (! [Db open]) {
[Db release];
Return;
}
Execute update
All commands that are not the SELECT command are regarded as updates. This includes CREATE, UPDATE, INSERT, ALTER,
COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM, and REPLACE (etc ).
Simply put, the UPDATE command is used as long as the command not starting with SELECT.
Execute the update and return a BOOL value. YES indicates that the execution is successful; otherwise, it indicates that there are errors.
You can call the-lastErrorMessage and-lastErrorCode methods to obtain more information.
Execute Query
The SELECT command is the query, and the method for executing the query starts with-excuteQuery.
If the FMResultSet object is returned successfully when the query is executed, the nil error is returned. It is equivalent to executing the update,
The NSError ** parameter is supported. You can also use-lastErrorCode and-lastErrorMessage to obtain the error message.
To traverse the query results, you can use the while loop. You also need to know how to jump to the next record.
Using FMDB is easy to implement, just like this:
FMResultSet * s = [db executeQuery: @ "SELECT * FROM myTable"];
While ([s next]) {
// Retrieve values for each record
}
You must always call-[FMResultSet next]. Before you access the query return value, you even want only one record:
FMResultSet * s = [db executeQuery: @ "select count (*) FROM myTable"];
If ([s next]) {
Int totalCount = [s intForColumnIndex: 0];
}
FMResultSet provides many methods to obtain the values in the desired format:
IntForColumn:
LongForColumn:
LongLongIntForColumn:
BoolForColumn:
DoubleForColumn:
StringForColumn:
DataForColumn:
DataNoCopyForColumn:
UTF8StringForColumnIndex:
ObjectForColumn:
These methods also include the {type} ForColumnIndex method. The parameter is the index position of the column in the query result set.
You do not need to call [FMResultSet close] to close the result set. When a new result set is generated or its database is closed, it is automatically closed.
Close Database
After using the database, you should close the database connection to release the resources used by SQLite.
[Db close];
Transactions
FMDatabase supports transactions.
Data purification (data formatting)
When using FMDB, do not spend time reviewing your data before inserting it. You can use the standard SQLite Data Binding syntax.
Insert into myTable VALUES (?, ?, ?)
SQLite recognizes "?" Is an Input Point character. Such execution will accept a variable parameter (or other parameters, such as NSArray, NSDictionary, or va_list), which will be escaped correctly.
You can also choose to use the naming parameter syntax.
Insert into myTable VALUES (: id,: name,: value)
The parameter name must start with a false name. SQLite itself supports other characters. When the internal implementation of a Dictionary key starts with a colon. Note that your NSDictionary key does not contain colons.
NSDictionary * argsDict = [NSDictionary dictionaryWithObjectsAndKeys: @ "My Name", @ "name", nil];
[Db executeUpdate: @ "insert into myTable (name) VALUES (: name)" withParameterDictionary: argsDict];
Besides, the Code cannot be written like this (why? Think about it .)
[Db executeUpdate: @ "insert into myTable VALUES (?) ", @" This has \ "lots of 'bizarre \" quotes '"];
You should:
[Db executeUpdate: @ "insert into myTable VALUES (?) ", @" This has "lots of 'bizarre" quotes '"];
Provided to-executeUpdate: all parameters of a method must be objects. Like the following code, it cannot work and will crash.
[Db executeUpdate: @ "insert into myTable VALUES (?) ", 42];
The correct method is to package the number into an NSNumber object.
[Db executeUpdate: @ "insert into myTable VALUES (?) ", [NSNumber numberWithInt: 42];
Alternatively, you can use-execute * WithFormat:, which is an NSString-style parameter.
[Db executeUpdateWithFormat: @ "insert into myTable VALUES (% d)", 42];
-The internal implementation of the execute * WithFormat: method will help you encapsulate data. The following modifiers can be used: % @, % c, % s, % d, % D,
% I, % u, % U, % hi, % hu, % qi, % qu, % f, % g, % ld, % lu, % lld, and % llu. in addition, modifiers may cause unpredictable results.
In some cases, you need to use % characters in SQL statements, and you should use %.
Use FMDatabaseQueue and thread security
It is unwise to use one FMDatabase instance in multiple threads at the same time. Now you can create an FMDatabase object for each thread.
Do not allow multiple threads to share the same instance. It cannot be used in multiple threads at the same time. If this happens, the program will crash from time to time,
Or report exceptions, or the meteorite will fall from the sky and hit your Mac Pro. In short, it will crash.
Therefore, do not initialize the FMDatabase object and use it in multiple threads.
Please use FMDatabaseQueue, which is your friend and will help you.
Use the following methods:
Create a queue first.
FMDatabaseQueue * queue = [FMDatabaseQueue databaseQueueWithPath: aPath];
In this way.
[Queue inDatabase: ^ (FMDatabase * db ){
[Db executeUpdate: @ "insert into myTable VALUES (?) ", [NSNumber numberWithInt: 1];
[Db executeUpdate: @ "insert into myTable VALUES (?) ", [NSNumber numberWithInt: 2];
[Db executeUpdate: @ "insert into myTable VALUES (?) ", [NSNumber numberWithInt: 3];
FMResultSet * rs = [db executeQuery: @ "select * from foo"];
While ([rs next]) {
...
}
}];
In this way, you can easily wrap simple tasks into transactions:
[Queue inTransaction: ^ (FMDatabase * db, BOOL * rollback ){
[Db executeUpdate: @ "insert into myTable VALUES (?) ", [NSNumber numberWithInt: 1];
[Db executeUpdate: @ "insert into myTable VALUES (?) ", [NSNumber numberWithInt: 2];
[Db executeUpdate: @ "insert into myTable VALUES (?) ", [NSNumber numberWithInt: 3];
If (whoopsSomethingWrongHappened ){
* Rollback = YES; return;
}
// Etc...
[Db executeUpdate: @ "insert into myTable VALUES (?) ", [NSNumber numberWithInt: 4];
}];
FMDatabaseQueue will establish a series of GCD queues in the background and execute the blocks you pass to the GCD queue.
This means that you call the call method from multiple threads at the same time, and GCD will also execute according to the order of the blocks it receives.
Master haomeng is devoted to his contribution and respects the author's Labor achievements. Do not repost them.
If the article is helpful to you, you are welcome to donate to the author, support haomeng master, the amount of donation is free, focusing on your mind ^_^
I want to donate: Click to donate
Cocos2d-X source code download: point I send