no such column in sqlite android java - java

i try to retrieve data from sqlite with this code:
String sql = "select * from "+Table +" where "+C_LoginName+"=" +user;
Log.d("CREATE DATABASE", "SQL: " + sql);
Cursor c = db.rawQuery(sql, null);
c.moveToFirst();
Log.d("Password is", c.getString(c.getColumnIndex(C_Password)));
but this error shown to me ("no such column....")
i even use single quot(') side every string but not different.but when i use select * from table the loginName is there.
how can solve that?
tnx

Quotes missing around user. Also, make sure C_LoginName contains a valid column name.
String sql = "select * from "+Table +" where "+C_LoginName+"='" +user + "'";

no such column in sqlite android java
This kind of error is usually thrown:
When you forgot to wrap column's value into single quotes (if you are
not using parametrized statements)
You specified icorrect column name(check your database schema)
Recommendation:
I don't like your approach. It's dirty, not very human-readable and very unsafe. I suggest you to use parametrized statements with placeholders where each placeholder will be replacted with value from specified array.
Example:
String query = "select * from tablename where name = ?";
db.rawQuery(query, new String[] {name}); // ? will be replaced with name value
Note:
Usually if you are dealing with database it's very good and handy practise to create some class for example called Const that will hold your column names as final static variables.
This provides more efficient and cleaner dealing with database and you'll avoid typo problems (which are too hard to find out).

Related

is there any advantage of using SQLitestatement bindstring method instead of simple string concatenation for executing sql statements

I wanted to insert values in a table in an SQLite Database in Android Studio.I wanted to ask which method should I prefer from the given two methods below.
I learned the first method from a course,but I want to use the second method.That's why I am asking the question
articleId,articleContent and articleTitle are all of type string.
Please specify the pros and cons of each method if you can.You may suggest another method if you want to.
String sql = "INSERT INTO articles (articleId, title, content) VALUES (?, ?, ?)";
SQLiteStatement statement = articlesDB.compileStatement(sql);
statement.bindString(1, articleId);
statement.bindString(2, articleTitle);
statement.bindString(3, articleContent);
statement.execute();
OR simply using string concatenation:
sqliteDatabase.execSQL("INSERT INTO articles (articleId, title, content) VALUES (" + articleId + ", " + articleTitle + ", " + articleContent + ")");
Yes, it is always recommended to use bindString() to avoid possible attacks in your database through SQL Injection.
In your particular case, it seems that, the values to be inserted are from your code only, not from any dynamic input source - e.g. user input. In that case, it could be safe to use any of the methods you mentioned in your question.
In your case, in stead of string concatenation, you may also use insert() from SQLiteDatabase class, which is safe from any syntax error:
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("articleId", articleId);
values.put("title", articleTitle);
values.put("content", articleContent);
db.insert("articles", null, values);
It returns the row ID of the newly inserted row, or -1 if an error occurred.
However, if you are taking the values from user input, then using string concatenation makes your database completely vulnerable to potential attackers. That's why it is always recommended to use bindString() method of SQLiteProgram class to execute sql where we need to pass values.
Another reason is, bindString() can invoke java.lang.IllegalArgumentException. So, using this method can be helpful for exception handling and debugging purpose in case any syntax error occurs.

Lookup and extract db value based on input (Java & SQL Server)

New to java.
I am attempting to write a class that will input a username, run a query on the username to find the ID, and subsequently use that ID in "where clauses" on all my other classes.
This is the statement that I execute (which will only ever return a recordset of a single row):
String sqlStatement = "SELECT AccountHolderId, Passcode from CIS4720.DBO.AccountHolder " +
"where Username = '" + logonName + "'";
Here is my attempt at extracting the ID via the username...
while (rset.next())
{
if(rset.getInt("Username")==logonName){
int whosOnFirst = rset.getInt("AccountHolderId");
}
I saw another answer on the forum that says you can't assign database values to variables. If that is the case, what is a better strategy?
(Also, I realize I'm not parameterizing, but I'd like to get this working before fixing that issue. This is for a course assignment so I am not worried about hack attacks).
P. S. Thanks I fixed the double equals sign (and the extra parenthesis) in the code above.
Here are some comments about the code:
rset.getInt("Username") will get the column Username from the result but it also looks for an Integer column because of getInt. You are not selecting that column in the sql statement so will error out.
If you select it and get a string, use .equals() instead of == to compare string. Also, one = is assignment and == is comparison.
You can use getString to read Strings from the result set.
You don't need to check the username and match it since your query should return exactly that user's data so I would remove the if condition entirely and just have the getInt line there.

UCASE and UPPER sql functions

I am trying to do the following query:
String query = "SELECT * FROM EMP WHERE UCASE(LAST_NAME) ";
query += "LIKE '" + lastName.toUpperCase() + "%'";
in an example of usage of an servlet to access to a database
But I am getting the error message:
Excepcion java.sql.SQLSyntaxErrorException: ORA-00904: "UCASE": invalid identifier
On the other hand, when I use the UPPER sql function, the example works but the results do not show the values of the LASTNAME column in uppercase. I do not understand what happens.
You're just comparing the upper case values, but you're selecting the actual values with select *
to get the uppercase name in your resultset you need to use UPPER in your select list, not UCASE, like this:
String query = "SELECT UPPER(LAST_NAME) AS UPPERNAME, * FROM EMP WHERE UPPER(LAST_NAME) ";
query += "LIKE '" + lastName.toUpperCase() + "%'";
What your code is doing here is building a query string named query. Once query is complete, it will be sent to the database for parsing and running.
When you are building a query to the database, you have to use the built-in database functions for the part of the query that the database is going to parse and run. So, in your example, Java is doing toUpperCase on lastName and then putting that literal into the query string that will go to the database. UPPER(LAST_NAME) is going into the query string as is, it will get passed to the database just like that and run by the database. So it needs to be a function that the database can parse and run: an Oracle function, not a Java function.
UCASE is a DB2 function & not Oracle. For Oracle, you need to use UPPER .
Second part of your question is already answered by James Z.
Having said that, I am answering because previous answers didn't pointed out SQL injection problem with the way you listed your query.
Make it a habit to always execute parametrized queries with jdbc & not by directly appending values to query string.
String query = "SELECT * FROM EMP WHERE UCASE(LAST_NAME) LIKE ? ";
Your parameter would be - lastName.toUpperCase()+"%"
SQL Injection

Suggestions for building sql strings with jdbctemplate

I currently have this:
MyObject myObject = getJdbcTemplate().queryForObject("select * from my_objects where id = ?",
new Object[]{new Integer(id)},
new MyObjectRowMapper());
Now in my method I want to pass an enumeration:
SortOrder.ASC
SortOrder.DESC
So it will either be:
ORDER BY ID ASC
or
ORDER BY ID DESC
So inside the sql string, do I just add another '?' or do I have to build up the string like:
"select * from abc ORDER BY ID " + sortOrder;
Is there a preferred way?
You have to use the second way. A prepared statement isn't just a "query-replace placeholders by the String I pass". All parameters must be typed values to insert into the syntax tree generated from the query. You can't pass a portion of a query as a parameter.
You can not change the query in PreparedStatements so you can not use ? for asc or desc. I think concatenation is the simplest way you can use.

How do I sanitize SQL without using prepared statements

For some sql statements I can't use a prepared statment, for instance:
SELECT MAX(AGE) FROM ?
For instance when I want to vary the table. Is there a utility that sanitizes sql in Java? There is one in ruby.
Right, prepared statement query parameters can be used only where you would use a single literal value. You can't use a parameter for a table name, a column name, a list of values, or any other SQL syntax.
So you have to interpolate your application variable into the SQL string and quote the string appropriately. Do use quoting to delimit your table name identifier, and escape the quote string by doubling it:
java.sql.DatabaseMetaData md = conn.getMetaData();
String q = md.getIdentifierQuoteString();
String sql = "SELECT MAX(AGE) FROM %s%s%s";
sql = String.format(sql, q, tablename.replaceAll(q, q+q), q);
For example, if your table name is literally table"name, and your RDBMS identifier quote character is ", then sql should contain a string like:
SELECT MAX(AGE) FROM "table""name"
I also agree with #ChssPly76's comment -- it's best if your user input is actually not the literal table name, but a signifier that your code maps into a table name, which you then interpolate into the SQL query. This gives you more assurance that no SQL injection can occur.
HashMap h = new HashMap<String,String>();
/* user-friendly table name maps to actual, ugly table name */
h.put("accounts", "tbl_accounts123");
userTablename = ... /* user input */
if (h.containsKey(userTablename)) {
tablename = h.get(userTablename);
} else {
throw ... /* Exception that user input is invalid */
}
String sql = "SELECT MAX(AGE) FROM %s";
/* we know the table names are safe because we wrote them */
sql = String.format(sql, tablename);
Not possible. Best what you can do is to use String#format().
String sql = "SELECT MAX(AGE) FROM %s";
sql = String.format(sql, tablename);
Note that this doesn't avoid SQL injection risks. If the tablename is a user/client-controlled value, you'd need to sanitize it using String#replaceAll().
tablename = tablename.replaceAll("[^\\w]", "");
Hope this helps.
[Edit] I should add: do NOT use this for column values where you can use PreparedStatement for. Just continue using it the usual way for any column values.
[Edit2] Best would be to not let the user/client be able to enter the tablename the way it want, but better present a dropdown containing all valid tablenames (which you can obtain by DatabaseMetaData#getCatalogs()) in the UI so that the user/client can select it. Don't forget to check in the server side if the selection is valid because one could spoof the request parameters.
In this case you could validate the table name against the list of available tables, by getting the table listing from the DatabaseMetaData. In reality it would probably just be easier to use a regex to strip spaces, perhaps also some sql reserved words, ";", etc from the string prior to using something liek String.format to build your complete sql statement.
The reason you can't use preparedStatement is because it is probably encasing the table name in ''s and escaping it like a string.

Categories

Resources