does anyone know how to return the count of a query when using FMDB? If I executeQuery #"select count(*) from sometable were..." I get an empty FMResultSet back. How can I get the row count of the query? Do I need to do a query like "select * from sometable where.." and iterate through the result set? Or can I use useCount or whats the best way (in terms of performance) to do this?
Thanks!
Shorter code to accomplish the same thing:
NSUInteger count = [db intForQuery:#"SELECT COUNT(field) FROM table_name"];
Make sure to include the FMDatabaseAdditions.h header file to use intForQuery:.
try this. It works for me. Iterating all the records is not recommended.
FMResultSet *rs = [db executeQuery:#"select count(FIELD) as cnt from TABLENAME"];
while ([rs next]) {
NSLog(#"Total Records :%d", [rs intForColumn:#"cnt"]);
}
May be you should check your Where clause.
Swift 2 Example
This code snippet will print the count for you.
if let rs = db.executeQuery("SELECT COUNT(*) as Count FROM TABLE_NAME", withArgumentsInArray: nil) {
while rs.next() {
print("Total Records:", rs.intForColumn("Count"))
}
}
If it did not work, a few suggestions:
a) Look for a line in your project that says let database = or var database =. If you find one then change db to database
b) Did you change the TABLE_NAME in the Select statement to whatever your table is called?
The first one is also right but by using this method you can retrieve records and count using the same query , no headache to write another one. Just add count(*) as count to your query.
You could always just run the proper SQL statement. I do something like:
FMResultSet *rs = [database executeQuery:#"select count(*) as count from words"];
[rs next];
wordsThatExist = [rs intForColumn:#"count"];
Setting up the SQL query may be quicker and cheaper then iterating.. I believe counts are cheap.
updated for Swift 3 minor change to "int For Column"
if let rs = db.executeQuery("SELECT COUNT(*) as Count FROM TABLE_NAME", withArgumentsInArray: nil) {
while rs.next() {
print("Total Records:", rs.int(forColumn: "Count"))
}
}
updated for Swift 4 minor change in method parameter name
if let rs = db.executeQuery("SELECT COUNT(*) as Count FROM TABLE_NAME", withArgumentsIn: nil) {
while rs.next() {
print("Total Records:", rs.int(forColumn: "Count"))
}
}
Please Try Following Code, this works for me
let objManager = ModelManager.getInstance()
objManager.database?.open()
let resultSet1: FMResultSet! = sharedInstance.database!.executeQuery("SELECT COUNT(Field) FROM TableName”, withArgumentsInArray:nil)
if (resultSet1 != nil)
{
while resultSet1.next()
{
countRecord = Int(resultSet1.intForColumn("COUNT(Field)"))
}
}
print(countRecord)
You Will get Count of Field
If you want to know the count of the rows before make something with the result, you can even do a simple query and ask for the results columnCount that give you the number of rows and you can save one query if you really want to make something with the resultSet
FMResultSet *results = [database executeQuery:#"SELECT * from tableName"];
int numberOfRows = [results columnCount];
while ([results next]){
... do your stuff ...
}
Related
i want get all table names where created person is not "-AOS-" (Dynamics AX). In this code i get only who created first line in table:
for (tablecounter=1; tablecounter<=dict.tableCnt(); tablecounter++)
{
tableId = dict.tableCnt2Id(tablecounter);
common = new DictTable(tableId).makeRecord();
select common where common.createdBy !="";
if(common)
{
info(strFmt('%1---%2',common.createdBy,dict.tableName(common.TableId)));
}
}
You can try with scan over SysModelElement and SysModelElementData tables.
SysModelElement me;
SysModelElementData med;
while select firstOnly10 me
where me.ElementType == UtilElementType::Table
exists join med
where med.ModelElement == me.RecId
&& med.createdBy != '-AOS-'
{
info(me.Name);
}
You could also use the project filter (probably not as fast as a direct SQL query, but depending on your requirements more actionable).
Hello all
I am generating an application in which I am having 4 fields ( product id, product name, product price, product description).
Now I want that the product id would be generated automatically when I save my data, i.e. when I run my app the text field of product id should be generated automatically and when I click on save button this id should be incremented by one and the id of last data should be saved.
So kindly help me out.
You have to take a look on this tutorials
http://upadhyayajayiphone.blogspot.in/2012/11/insert-record-in-sqlite-table-get.html
http://www.techotopia.com/index.php/An_Example_SQLite_based_iOS_4_iPhone_Application
It contains all the operations for you. While you fetching data use SELECT MAX(product_id) from TABLE_NAME to fetch the last data.
try this way....
//fetch the MAX id
[self databaseOpen];
NSString *cc=[NSString stringWithFormat:#"Select MAX(ProductID) from Table"];
NSMutableArray *temp=[[NSMutableArray alloc]init];
temp=[[database executeQuery:cc]mutableCopy];
[database close];
Explaination I am fetching the Maximum product_id from database Table.
int Product_id;
if (temp.count!=0 && ([[temp objectAtIndex:0]valueForKey:#"MAX(ProductID)"] !=[NSNull null]))
Product_id=[[[temp objectAtIndex:0]valueForKey:#"MAX(ProductID)"]intValue]+1;
else
Product_id=1;
//fetch the MAX id
Explaination If there is no record in the Table then Product_id=1
else It will incremented by 1;
Txt_productID.text=[NSString stringwithFormat:#"%d",Product_id];
Explaination Print the Product_id in the Text Field
[self databaseOpen];
NSString *q=[NSString stringWithFormat:#"Insert into Table (NAme,Price,Description) values ('%#','%#','%#')",txt_name.text,txt_price.text,txt_des.text];
[database executeNonQuery:q];
[database close];
Explaination Save the new Record in database.
If u want to achive by NSUserDefaults, then use following code
// get total count
int count=[[NSUserDefaults standardUserDefaults]integerForKey:#"TotalIdCount"];
// on save button click increment count by one and stored it
count=count+1;
[[NSUserDefaults standardUserDefaults ] setInteger:count forKey:#"TotalIdCount"];
[[NSUserDefaults standardUserDefaults] synchronize];
I want to delete all data from table in my database. I am using FMDB.And i have used this code but it will not delete data from my table.
-(BOOL) deleteAll
{
FMDatabase *db = [FMDatabase databaseWithPath:[Utility getDatabasePath]];
[db open];
BOOL success = [db executeUpdate:#"TRUNCATE TABLE customers"];
[db close];
return success;
return YES;
}
Try to use this code.
BOOL success = [db executeUpdate:#"DELETE FROM customers"];
As long as i know Sqlite does not support TRUNCATE query.
Although DELETE command will work it is slow because it selects each row and than proceeds to delete it.
If you are deleting the whole table it is better to DROP the table and than recreate it:
BOOL result = [db executeUpdate:#"DROP TABLE IF EXISTS `customers`;"];
BOOL resultTwo = [db executeUpdate:#"CREATE TABLE IF NOT EXISTS customers(name text primary key, age int)"]; //or course fields in your table will be different
Swift (for completeness sakes):
let dropTable = "DROP TABLE customers"
let result = contactDB.executeUpdate(dropTable, withArgumentsInArray: nil)
if !result {
print("Error: \(contactDB.lastErrorMessage())")
}
let createTable = "CREATE TABLE IF NOT EXISTS customers(name text primary key, age int)"
if !contactDB.executeStatements(createTable) {
print("Error: \(contactDB.lastErrorMessage())")
}
reference: truncate SQLite
Suppose I have one entity 'Person' in core data.
Now i want to search all persons. Either firstname beginning match or lastname beginning match.
For eg :
1) Amit Gupta
2) Ajay Gulati
3) Gunjan Aggarwal
Searching for 'Gu' shows names that match firstname first, then those that match lastname
therefore result is :
Gunjan Aggarwal
Ajay Gulati
Amit Gupta
One option : Fetch all objects , store them in array and then sort.
But what if the search results are very big in number
Second option : Use NSFetchedResultsController
This will fetch all matching but not in the required manner(firstname before lastname).
Cant use sort descriptors as it is not sorting on any key, but upon matching.
Can anybody help ?
EDIT :
First name and lastname are two different attributes of 'Person' entity.
Either Firstname matches or Lastname matches.
I want results with 'Firstname' match before than results with 'Lastname' match.
If you use sort descriptor, which 'Key' or 'attribute' will you mention ???
Try to set Sort Descriptors before fetching:
NSSortDescriptor * firstNameDescriptor;
firstNameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"firstName"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
NSSortDescriptor * lastNameDescriptor;
lastNameDescriptor = [[NSSortDescriptor alloc] initWithKey:#"lastName"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
[firstNameDescriptor release];
[lastNameDescriptor release];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:firstNameDescriptor, lastNameDescriptor, nil]];
then fetch your desired persons.
After you got a sorted result, in order to match your searching, you might need to resort it:
- (NSComparisonResult)compare:(id)anotherOne {
// if the first name matches the searching key word, return NSOrderedAscending;
// else return [self.firstName localizedCaseInsensitiveCompare:anotherOne.firstName];
}
then just apply this to your search result array with sortedArrayUsingSelector: method. No testing code available, but I think you can figure it out by yourself then. ;)
Use a transient property sortName in your Core Data object, make it compare the firstName and lastName properties and just return whichever comes first alphabetically.
Now just use this property as your sortDescriptor and you should get the result you are after.
Something like this...
- (NSString *)sortName
{
[self willAccessValueForKey:#"sortName"];
NSString *string = nil;
if ([self.firstName compare:self.lastName] == NSOrderedAscending) {
string = self.firstName;
} else {
string = self.lasttName;
}
[self didAccessValueForKey:#"sortName"];
return string;
}
Use two fetch requests. When you're providing data to the view, display the results of the first fetch request, followed by the results of the second.
I know that I can use #distinctUnionOfObjects to find something like the following in SQL:
SELECT a_value
FROM my_table
GROUP BY a_value;
What I'm looking for is all of the data returned in an array, not just the array of values that matches the group by expression. Essentially, I'm looking for the equivalent of the following SQL query for core data:
SELECT *
FROM my_table
GROUP BY a_value;
It's analog
SELECT 'Status', COUNT(*) FROM 'Records' GROUP BY 'Status':
NSFetchRequest* fetch = [NSFetchRequest fetchRequestWithEntityName:#"Record"];
NSEntityDescription* entity = [NSEntityDescription entityForName:#"Record"
inManagedObjectContext:myManagedObjectContext];
NSAttributeDescription* statusDesc = [entity.attributesByName objectForKey:#"status"];
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: #"url"]; // Does not really matter
NSExpression *countExpression = [NSExpression expressionForFunction: #"count:"
arguments: [NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName: #"count"];
[expressionDescription setExpression: countExpression];
[expressionDescription setExpressionResultType: NSInteger32AttributeType];
[fetch setPropertiesToFetch:[NSArray arrayWithObjects:statusDesc, expressionDescription, nil]];
[fetch setPropertiesToGroupBy:[NSArray arrayWithObject:statusDesc]];
[fetch setResultType:NSDictionaryResultType];
NSError* error = nil;
NSArray *results = [myManagedObjectContext executeFetchRequest:fetch
error:&error];
Found here
You could try using an NSFetchedResultsController object to provide grouping by way of the sectionNameKeyPath construct in the initializer. Note that FRCs are mainly to be used to couple with a table view, but it's not really necessary. This way you could group your results by your sectionNameKeyPath which could be a transient attribute in your model, too.
As a comment, I wouldn't recommend thinking of Core Data in terms of a database, which it isn't. Core Data is built to make it easier for you to persist and manage object relationships. Just because on the iOS it runs on top of SQLite doesn't make it a database replacement.
Reference: NSFRC Reference
I find this method (roughly similar to the accepted answer) to be a little cleaner and easier to understand. This is the SQL equivalent to:
SELECT COUNT(*), a_value FROM my_table GROUP BY a_value;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[MyTable className]];
// create expression for grouped column
NSExpressionDescription *aValueDescription = [[NSExpressionDescription alloc] init];
aValueDescription.name = #"aValue"; // name of key in result dictionary
aValueDescription.expression = [NSExpression expressionWithFormat:#"aValue"];
aValueDescription.expressionResultType = NSObjectIDAttributeType;
// create expression for count
NSExpressionDescription *countDescription = [[NSExpressionDescription alloc] init];
countDescription.name = #"count"; // name of dictionary key in result dictionary
countDescription.expression = [NSExpression expressionWithFormat:#"aValue.#count"];
countDescription.expressionResultType = NSInteger32AttributeType;
// fill out fetch request
fetchRequest.propertiesToGroupBy = #[#"aValue"];
fetchRequest.propertiesToFetch = #[aValueDescription, countDescription];
//fetchRequest.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"count" ascending:NO]]; // not sure why this crashes
fetchRequest.resultType = NSDictionaryResultType; // required for "group by" requests
NSError *error = nil;
NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
The returned results is an array of NSDictionary. Note that the description name properties can be anything you want - they are just the names of the keys in the returned dictionaries. One can add a predicate to the fetch request to filter rows from the table; this code returns all rows.
Bonus points to anyone who can tell me how to make the sort descriptor work...
I finally found a solution by using NSFetchedResultsController:
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:GROUPBYKEY cacheName:nil]
It will return the sections having grouped objects. Then you can do your operations on it.
You can use Predicate Programming.
EDIT: Sorry you can not use predicates for Group By at least not straight-forward. I just read on the references.
Limitations: You cannot necessarily translate “arbitrary” SQL queries into predicates or fetch requests. There is no way, for example, to convert a SQL statement such as
SELECT t1.name, V1, V2
FROM table1 t1 JOIN (SELECT t2.name AS V1, count(*) AS V2
FROM table2 t2 GROUP BY t2.name as V) on t1.name = V.V1