Querying SQLite in android( Summation of column values) - sql

Hi guys I want to get the summation of column values from my sqlite database in android.
and am trying to use this to get me the sum of column KEY_COST.
public Cursor fetchAllCost() {
return mDb.query(
DATABASE_TABLE,
new String[] { "SUM(KEY_COST)"},
null,
null,
null,
null,
null);
}
but its giving me a cursor and I do not know how to get the value from the Cursor object. Any one help!!!

You can return scalar values like so:
public int getColumnData() {
mDb = mDbManager.getReadableDatabase();
final SQLiteStatement stmt = mDb
.compileStatement("SELECT SUM(KEY_COST) FROM...");
// Cast as appropriate
return (int) stmt.simpleQueryForLong();
}
Or alternatively, depending on the data type use simpleQueryForString().

You should just move to the first result in the cursor with cursor.moveFirst() and then you can do cursor.getInt(1) to get the scalar value.

rawQuery
Sum value is on first column - cursor.getInt(0);
Cursor cursor = database.rawQuery(
"SELECT SUM(" + COL_NAME + ") FROM " + TABLE_NAME, null);
if(cursor.moveToFirst()) {
return cursor.getInt(0);
}
query
String[] columns = new String[] {
"sum(" + DbHelper.C_COUNT_OF_WORDS + ")"
};
String where = null;
String whereArgs[] = null;
String groupBy = null;
String having = null;
String order = null;
String limit = null;
database = dbHelper.getReadableDatabase();
Cursor cursor = database.query(DbHelper.TABLE_STATISTICS, columns, where, whereArgs, groupBy, having, order, limit);
if(cursor.moveToFirst()) {
return cursor.getInt(0);
}

Related

Dapper for NET Core: Insert into a table and return id of inserted row [duplicate]

This question already has answers here:
How do I perform an insert and return inserted identity with Dapper?
(9 answers)
Closed 6 months ago.
I have the following method in my repository. As of now, i believe the int returned is simply one indicating whether or not the operation was successful. I want the int to be the id (which is the single column of the table) to be returned after a successful execution. How do i accomplish this?
public async Task<int> AddNewGroup()
{
using(_connection)
{
_connection.Open();
var id = await _connection.ExecuteAsync("INSERT INTO groups").Single();
}
}
You can run a query which has 2 parts, first is your INSERT part and second is a SELECT part. In the SELECT part, you can return(select) whatever column value you want.
For example, If your group table has a primary key column called GroupId and you have set that column for Identity value generation(automatic value generation), you can call the SCOPE_IDENTITY() to get the generated value.
We will use the QueryAsync method.
public async Task<int> AddNewGroup()
{
using(_connection)
{
_connection.Open();
var q = #"INSERT INTO Groups(Name,Description) VALUES
(#name, #desc); SELECT CAST(SCOPE_IDENTITY() as int)"
var result = await _connection.QueryAsync<int>(q,
new { #name="some name", #desc="some desc"});
return result.Single();
}
}
You don't have to create by hand the insert query, you can use Dapper.Contrib github which helps you to manage CRUD operations.
Using Dapper.Contrib you can do something like:
public async Task<int> AddNewGroup(Group entity)
{
using (_connection)
{
_connection.Open();
var id = await _connection.InsertAsync(entity);
}
}
If you're using SQL Azure / SQL Server, you need to return the inserted value from the query using something like
INSERT INTO groups OUTPUT inserted.id VALUES (...)
and then instead using ExecuteAsync use ExecuteScalarAsync
Reference to the OUTPUT clause here:
https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-2017
public static void Main()
{
string sql = #"INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country)
Values (#CustomerName, #ContactName, #Address, #City, #PostalCode, #Country);
SELECT CustomerID FROM Customers WHERE CustomerID = SCOPE_IDENTITY();";
using (var connection = new SqlConnection(GetConnectionString()))
{
Customer c = new Customer("Brian Adams", "Brian", "12 Jones Place", "New York", "NY12", "CA");
var id = connection.QueryFirstOrDefault<int>(sql, c);
Console.WriteLine("The Customer ID is " + id);
sql = "Select * FROM CUSTOMERS WHERE CustomerID = #ID";
var rc = connection.QueryFirstOrDefault<Customer>(sql, new{ #ID = id });
}
}
}
The "correct" way that I took is (Showing repository method using Guid Id to return):
public async Task<Guid> CreateClient(ClientEntity clientModel)
{
const string sql = #"
INSERT INTO dbo.Clients
(
ClientCode,
Name,
IsActive
)
OUTPUT Inserted.ClientId
VALUES
(
#ClientCode,
#Name,
#IsActive
)";
using var dbConnection = await _databaseProvider.GetConnection();
var result = await dbConnection.ExecuteScalarAsync(sql, new
{
ClientCode = clientModel.Code,
Name = clientModel.Name,
IsActive = clientModel.IsActive
});
if (result != null)
{
return Guid.Parse(result.ToString());
}
else {
return Guid.Empty;
}
}
You can use the RETURNING id in the insert statement. This is using C# and dapper.
private readonly NpgsqlConnection _connection = new NpgsqlConnection();
var sqlInsert = $""""
INSERT INTO tabel_name (column_name)
VALUES ('value')
RETURNING id;
"""";
var id = await _connection.ExecuteScalarAsync(sqlInsert);
And if you want to determine the key type coming back you can use:
var id = await _connection.ExecuteScalarAsync<int>(sqlInsert);
Where you specify the type in the <> brackets. If you do not specify, it will return the object type.

Deleting the last row in a table. SQL/Netbeans

In java, i am trying to delete the last row of my database. The database has 15 rows and i want to the delete the 15th one. The columns are called Initials and Score.
Intials Scores
rows# 1. ADS 2343
2. DDE 5454
15. TBK 332
I can't have it selecting TBK because i'm wanting it to delete the 15th one no matter what it is so a new one can be added. Everywhere I've looked it's always has to be specific or a delete all rows. Can anyone help? Many thanks to those who help. :)
Assuming id is an identity column
DELETE FROM table
WHERE id = (SELECT MAX(id) FROM table)
OP : I am trying to delete the last row of my database.
make resultset updatable : ResultSet.CONCUR_UPDATABLE);
set cursor to last record : resultSet.last();
delete last Record : resultSet.deleteRow();
for further use of rs you should set : resultSet.beforeFirst();
private static int delLastRow(ResultSet resultSet) {
if (resultSet == null) {
return 0;
}
try {
resultSet.last();
int delID = resultSet.getInt(1);
resultSet.deleteRow();
System.out.println("Deleted id :" + delID);
resultSet.beforeFirst();
return delID;
} catch (SQLException exp) {
exp.printStackTrace();
} finally {
try {
resultSet.beforeFirst();
} catch (SQLException exp) {
exp.printStackTrace();
}
}
return 0;
}
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try{
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
//rs will be scrollable, will not show changes made by others,
//and will be updatable
String sql;
sql = "SELECT * FROM `order details`";
ResultSet rs = stmt.executeQuery(sql);
System.out.println("Deleted id :"+ delLastRow(rs));
....
}

Most efficient way to deal with ORA-01795:maximum number of expressions in a list is 1000 in hibernate

I have to perform a select on which I have more than 1000 elements via hibernate, and then I received the error "ORA-01795:maximum number of expressions in a list is 1000" when I'm using the Oracle brand.
SELECT * FROM matable WHERE column IN (?,?,...) (>1000 items)
I found many solutions :
Split the list with OR
where A in (a,b,c,d,e,f)
becomes
where (A in (a,b,c) OR a in (d,e,f)) ...
Create a table with UNION ALL
SELECT * FROM maintable
JOIN (
SELECT v1 a FROM DUAL UNION ALL
SELECT v2 a FROM DUAL UNION ALL
SELECT v3 a FROM DUAL UNION ALL
...
SELECT v2000 a FROM DUAL) tmp
on tmp.a = maintable.id
Using tuples to get rid of the limit
where (column,0) in ((1,0),(2,0),(3,0),(4,0), ... ,(1500,0))
Using a temporary table..
where A in SELECT item FROM my_temporary_table
References here and there and also there.
My question is the following : what is the best practice to deal with this issue? By best practice I mean the most performant, but not only for Oracle; if I use hibernate, I don't want to create and manage a different code for each brand of database (I'm concerned by Oracle, MS SQL and PostGre only).
My first reaction would have been to use a temporary table, but I don't know what has the most impact.
Use a temporary table and make the values primary keys on the table. This should allow very efficient optimizations for comparison. The most like is simply an index lookup, although if the table is very small, Oracle might choose some other method such as a table scan.
This method should be faster than 1,000 or conditions, in almost any database. Sometimes in is optimized in a similar way (using a binary tree to store the values). In such databases, the performance would be similar.
I fixed this issue with some changes in hibernate-core jar.
I made a helper class to split an expression in more joins like: ... t.column IN (: list_1) OR t.column IN (: list_2) ... , Then I changed AbstractQueryImpl.expandParameterList method from hibernate to call my method if the collection exceeds the limit.
My hibernate-core version is 3.6.10.Final, but it work fine and for 4.x versions - I tested it.
My code is tested for next cases:
where t.id in (:idList)
where (t.id in (:idList))
where ((t.id) in (:idList))
where 1=1 and t.id in (:idList)
where 1=1 and (t.id in (:idList))
where 1=1 and(t.id) in (:idList)
where 1=1 and((t.id) in (:idList))
where 1=1 and(t.id in (:idList))
where t.id not in (:idList)
where (t.id not in (:idList))
where ((t.id) not in (:idList))
AbstractQueryImpl.expandParameterList :
private String expandParameterList(String query, String name, TypedValue typedList, Map namedParamsCopy) {
Collection vals = (Collection) typedList.getValue();
Type type = typedList.getType();
boolean isJpaPositionalParam = parameterMetadata.getNamedParameterDescriptor( name ).isJpaStyle();
String paramPrefix = isJpaPositionalParam ? "?" : ParserHelper.HQL_VARIABLE_PREFIX;
String placeholder =
new StringBuffer( paramPrefix.length() + name.length() )
.append( paramPrefix ).append( name )
.toString();
if ( query == null ) {
return query;
}
int loc = query.indexOf( placeholder );
if ( loc < 0 ) {
return query;
}
String beforePlaceholder = query.substring( 0, loc );
String afterPlaceholder = query.substring( loc + placeholder.length() );
// check if placeholder is already immediately enclosed in parentheses
// (ignoring whitespace)
boolean isEnclosedInParens =
StringHelper.getLastNonWhitespaceCharacter( beforePlaceholder ) == '(' &&
StringHelper.getFirstNonWhitespaceCharacter( afterPlaceholder ) == ')';
if ( vals.size() == 1 && isEnclosedInParens ) {
// short-circuit for performance when only 1 value and the
// placeholder is already enclosed in parentheses...
namedParamsCopy.put( name, new TypedValue( type, vals.iterator().next(), session.getEntityMode() ) );
return query;
}
// *** changes by Vasile Bors for HHH-1123 ***
// case vals.size() > 1000
if ((vals.size() >= InExpressionExpander.MAX_ALLOWED_PER_INEXPR) && isEnclosedInParens) {
InExpressionExpander inExpressionExpander = new InExpressionExpander(beforePlaceholder, afterPlaceholder);
if(inExpressionExpander.isValidInOrNotInExpression()){
List<String> list = new ArrayList<String>( vals.size() );
Iterator iter = vals.iterator();
int i = 0;
String alias;
while ( iter.hasNext() ) {
alias = ( isJpaPositionalParam ? 'x' + name : name ) + i++ + '_';
namedParamsCopy.put( alias, new TypedValue( type, iter.next(), session.getEntityMode() ) );
list.add(ParserHelper.HQL_VARIABLE_PREFIX + alias );
}
String expandedExpression = inExpressionExpander.expandExpression(list);
if(expandedExpression != null){
return expandedExpression;
}
}
}
// *** end changes by Vasile Bors for HHH-1123 ***
StringBuffer list = new StringBuffer(16);
Iterator iter = vals.iterator();
int i = 0;
while (iter.hasNext()) {
String alias = (isJpaPositionalParam ? 'x' + name : name) + i++ + '_';
namedParamsCopy.put(alias, new TypedValue(type, iter.next(), session.getEntityMode()));
list.append(ParserHelper.HQL_VARIABLE_PREFIX).append(alias);
if (iter.hasNext()) {
list.append(", ");
}
}
return StringHelper.replace(
beforePlaceholder,
afterPlaceholder,
placeholder.toString(),
list.toString(),
true,
true
);
}
My helper class InExpressionExpander:
package org.hibernate.util;
import org.hibernate.QueryException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
/**
* Utility class for expand Hql and Sql IN expressions with a parameter with more than IN expression limit size (HHH-1123).
* <br/>
* It work for expression with formats:
* <pre>
*
* where t.id in (:idList)
* where (t.id in (:idList))
* where ((t.id) in (:idList))
* where 1=1 and t.id in (:idList)
* where 1=1 and (t.id in (:idList))
* where 1=1 and(t.id) in (:idList)
* where 1=1 and((t.id) in (:idList))
* where 1=1 and(t.id in (:idList))
*
* where t.id not in (:idList)
* where (t.id not in (:idList))
* where ((t.id) not in (:idList))
* </pre>
* <p/>
* Example:
* <pre>
* select t.id from tableOrEntity t where t.id IN (:idList)
* </pre
*
* #author Vasile Bors
* #since 13/12/2015.
*/
public class InExpressionExpander {
private static final Logger log = LoggerFactory.getLogger(InExpressionExpander.class);
public static final int MAX_ALLOWED_PER_INEXPR = 1000;
private static final int MAX_PARAMS_PER_INEXPR = 500;
private Stack<String> stackExpr = new Stack<String>();
private StringBuilder toWalkQuery;
private final String beforePlaceholder;
private final String afterPlaceholder;
private boolean wasChecked = false;
private boolean isEnclosedInParens = false;
private boolean isInExpr = false;
private boolean isNotInExpr = false;
public InExpressionExpander(String beforePlaceholder, String afterPlaceholder) {
this.toWalkQuery = new StringBuilder(beforePlaceholder);
this.beforePlaceholder = beforePlaceholder;
this.afterPlaceholder = afterPlaceholder;
}
public boolean isValidInOrNotInExpression() {
if (!wasChecked) {
String lastExpr = extractLastExpression();
if ("(".equals(lastExpr)) {
isEnclosedInParens = true;
lastExpr = extractLastExpression();
}
isInExpr = "in".equalsIgnoreCase(lastExpr);
}
wasChecked = true;
return isInExpr;
}
public String expandExpression(List paramList) {
if (isValidInOrNotInExpression()) {
final String lastExpr = extractLastExpression(false);
if ("not".equalsIgnoreCase(lastExpr)) {
isNotInExpr = true;
extractLastExpression(); //extract "not" and consume it
}
extractColumnForInExpression();
StringBuilder exprPrefixBuilder = new StringBuilder();
for (int i = stackExpr.size() - 1; i > -1; i--) {
exprPrefixBuilder.append(stackExpr.get(i)).append(' ');
}
if (!isEnclosedInParens) {
exprPrefixBuilder.append('(');
}
String expandedExpression = expandInExpression(exprPrefixBuilder, paramList);
String beforeExpression = getBeforeExpression();
String afterExpression = getAfterExpression();
String expandedQuery = new StringBuilder(beforeExpression).append(expandedExpression)
.append(afterExpression)
.toString();
if (log.isDebugEnabled()) {
log.debug(
"Query was changed to prevent exception for maximum number of expression in a list. Expanded IN expression query:\n {}",
expandedExpression);
log.debug("Expanded query:\n {}", expandedQuery);
}
return expandedQuery;
}
log.error("Illegal call of InExpressionExpander.expandExpression() without IN expression.");
return null;
}
private String expandInExpression(StringBuilder exprPrefixBuilder, List values) {
String joinExpr = isNotInExpr ? ") and " : ") or ";
StringBuilder expr = new StringBuilder(16);
Iterator iter = values.iterator();
int i = 0;
boolean firstExpr = true;
while (iter.hasNext()) {
if (firstExpr || i % MAX_PARAMS_PER_INEXPR == 0) {
//close previous expression and start new expression
if (!firstExpr) {
expr.append(joinExpr);
} else {
firstExpr = false;
}
expr.append(exprPrefixBuilder);
} else {
expr.append(", ");
}
expr.append(iter.next());
i++;
}
expr.append(')');// close for last in expression
return expr.toString();
}
/**
* Method extract last expression parsed by space from toWalkQuery and remove it from toWalkQuery;<br/>
* If expression has brackets it will return al content between brackets and it will add additional space to adjust splitting by space.
*
* #return last expression from toWalkQuery
*/
private String extractLastExpression() {
return extractLastExpression(true);
}
/**
* Method extract last expression parsed by space from toWalkQuery, remove it from toWalkQuery if is consume = true;<br/>
* If expression has brackets it will return al content between brackets and it will add additional space to adjust splitting by space.
*
* #param consum if true the method will extract and remove last expression from toWalkQuery
* #return last expression from toWalkQuery
*/
private String extractLastExpression(final boolean consum) {
int lastIndex = this.toWalkQuery.length() - 1;
String lastExpr;
int exprSeparatorIndex = this.toWalkQuery.lastIndexOf(" ");
if (lastIndex == exprSeparatorIndex) { //remove last space from the end
this.toWalkQuery.delete(exprSeparatorIndex, this.toWalkQuery.length());
return extractLastExpression(consum);
} else {
lastExpr = this.toWalkQuery.substring(exprSeparatorIndex + 1, this.toWalkQuery.length());
if (lastExpr.length() > 1) {
if (lastExpr.endsWith(")")) {
//if parens are closed at the end we need to find where it is open
int opensParens = 0;
int closedParens = 0;
int startExprIndex = -1;
char c;
for (int i = lastExpr.length() - 1; i > -1; i--) {
c = lastExpr.charAt(i);
if (c == ')') {
closedParens++;
} else if (c == '(') {
opensParens++;
}
if (closedParens == opensParens) {
startExprIndex = i;
break;
}
}
if (startExprIndex > -1) {
lastExpr = lastExpr.substring(startExprIndex, lastExpr.length());
exprSeparatorIndex = exprSeparatorIndex + startExprIndex
+ 1; // +1 because separator is not space and don't must be deleted
}
} else if (lastExpr.contains("(")) {
int parentsIndex = exprSeparatorIndex + lastExpr.indexOf('(') + 1;
this.toWalkQuery.replace(parentsIndex, parentsIndex + 1, " ( ");
return extractLastExpression(consum);
}
}
if (consum) {
this.toWalkQuery.delete(exprSeparatorIndex, this.toWalkQuery.length());
}
}
if (consum) {
stackExpr.push(lastExpr);
}
return lastExpr;
}
private String extractColumnForInExpression() {
String column = extractLastExpression();
String beforeColumn = extractLastExpression(false);
long pointIndx = beforeColumn.lastIndexOf('.');
if (pointIndx > -1) {
if (pointIndx == (beforeColumn.length() - 1)) {
throw new QueryException(
"Invalid column format: " + beforeColumn + ' ' + column
+ " . Remove space from column!");
}
}
return column;
}
private String getBeforeExpression() {
return this.toWalkQuery + " (";
}
private String getAfterExpression() {
if (StringHelper.getFirstNonWhitespaceCharacter(afterPlaceholder) == ')') {
return afterPlaceholder;
}
return afterPlaceholder + ") ";
}
}
I am happy to receive any suggestions for improving this solution.

How to query database and return single row only

I'm new to programming and I'm trying to do simple projects to learn more. I've done researching, but I can't seem to find a solution to my problem. Perhaps, my program is not properly structured, but here it goes:
THIS BLOCK WILL VALIDATE IF THE ENTERED EMPLOYEE ID ALREADY EXISTS IN DATABASE. THIS IS CALLED IN A SERVLET
public boolean login(String employeeID) throws SQLException {
String sql = "select count(*) as count from employees where emp_id=?";
statement = connection.prepareStatement(sql);
statement.setString(1, employeeID);
rs = statement.executeQuery();
if (rs.next()) {
count = rs.getInt("count");
}
rs.close();
if (count == 0) {
return false;
} else {
return true;
}
}
/* METHOD BELOW ITERATES THE FIELDS FROM MYSQL DATABASE, BUT IT DISPLAYS ALL OF IT.
I JUST WANT TO GET A SINGLE ROW MATCHING THE EMPLOYEE ID PARAMETER ENTERED.*/
public List<EmployeeNumber> _list() throws SQLException {
List<EmployeeNumber> result = new ArrayList<>();
String sql = "select * from employees";
statement = connection.prepareStatement(sql);
rs = statement.executeQuery();
if (rs.next()) {
EmployeeNumber emp = new EmployeeNumber();
emp.setEmployeeNumber(rs.getString(1));
emp.setFirstName(rs.getString(2));
emp.setLastName(rs.getString(3));
emp.setEmail(rs.getString(4));
emp.setDepartment(rs.getString(5));
emp.setFirstApprover(rs.getString(6));
emp.setSecondApprover(rs.getString(7));
result.add(emp);
}
if (rs != null) {
rs.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
return result;
}
}
I think it has something to do with my SQL Query statement but I can't figure out how to fix it.
So in a nutshell, when I submit the employee ID from JSP page, it will validate if that exists, and if it does, I want to display all the column fields within the same row where this employee ID is positioned. How do I do that? Results will be displayed on another JSP page.
Thank you.
You're first counting how many employees have the given ID. Then you're selecting all the rows from the employee table.
Skip the first query, and only use the second one, but by adding a where clause, just as you did with the first query:
select * from employees where emp_id=?
Then after you've bound the parameter (as you did for the first query), test if there is a row returned:
if (rs.next()) {
// get the data, and return an EmployeeNumber instance containing the data
}
else {
// no employee with the given ID exists: return null
}
Note that the method shouldn't return a List<EmployeeNumber>, but an EmployeeNumber, since you only want to get 1 employee from the table.
Maybe try something like this?
String sql = "select count(*) as count from employees where emp_id=?";
statement = connection.prepareStatement(sql);
statement.setString(1, employeeID);
int count = statement.ExecuteScalar();
if (count == 0) {
return false;
} else {
return true;
}
}
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar(v=vs.110).aspx
You can also set a breakpoint and step through your code and see where the exception is being thrown. That would help us, knowing the exception message and where it's breaking.

Searching for data in SQLite DB table

I have a text view in which user enters a string. I need to search for that string in a table and return a boolean value if a string matches.
I am not into SQL, so can anyone please help me figure out how to do it.
Assuming that you know the basics & the object db of type SQLiteDatabase exists in your DataAccessLayer, below is the function which returns true false based on whether the location exists or not?
public boolean IsRecordExists(long empid) throws SQLException
{
String where = "empid =" + empid;
Cursor mCursor = db.query(true, "employeeinfo", new String[] {"empid"}, where, null,null, null, null, null);
if (mCursor != null)
{
if(mCursor.moveToFirst())
return true;
else
return false;
}
return false;
}