I want to filter my table to show records by month so i make a textboxes for the user input. Now i dont know if my query is correct. I dont have any error but also doesnt have any results. I use LIKE because i dont have specific day provided. Can someone suggest a better way?
ConnectToDatabase conn = null;
conn = ConnectToDatabase.getConnectionToDatabase();
String query = "Select * from inventoryreport where InDate LIKE "+txtYear.getText()+""+ txtMonth.getText()+"";
conn.setPreparedStatement(conn.getConnection().prepareStatement(query));
conn.setResultSet(conn.getPreparedStatement().executeQuery());
java.sql.ResultSetMetaData metaData = conn.getResultSet().getMetaData();
int columns = metaData.getColumnCount();
for (int i = 1; i <= columns; i++) {
columnNames.addElement(metaData.getColumnName(i));
}
LIKE it's wrong choise becouse your db doesn't use index and will be slow (and doesn't work).
The query is like this:
SELECT * FROM inventoryreport WHERE YEAR(Date_column) = 2014 AND MONTH(Date_column) = 3;
So your code is:
String query = "Select * from inventoryreport where YEAR(InDate) = " +txtYear.getText()+" AND MONTH(InDate) = "+ txtMonth.getText();
I think it is a small mistake in the date format:
Your format : YYYYMM (no seperation symbol)
Right format: YYYY-MM-DD (with a '-' to seperate)
I think
String query = "Select * from inventoryreport where InDate LIKE "+txtYear.getText()+"-"+ txtMonth.getText()+"-00";
should fix it, if your database only includes monthly exact values.
Otherwise you should use
Select * from inventoryreport where InDate BETWEEN '2014-03-18' AND '2014-03-20'
A SQL query can take advantage of indexes when a column in not surrounded by a function. The following where clause would allow the use of indexes:
SELECT *
FROM inventoryreport
WHERE Date_Column >= str_to_date(concat_ws('-', txtYear.getText(), txtMonth.getText(), '01'), '%Y-%m-%d') and
Date_Column < adddate(str_to_date(concat_ws('-', txtYear.getText(), txtMonth.getText(), '01'), '%Y-%m-%d'), interal 1 month)
Although more complicated, all the manipulations are on constants, so the query engine can still take advantage of an index on Date_Column.
Related
I have a query with a condition but it is returning an empty result even though I have the data that matches these conditions. I am a beginner, so I'm not sure if this query is correct.
public Cursor raw() {
SQLiteDatabase db = this.getReadableDatabase();
String select = "SELECT * FROM table_person WHERE data >= " + SelecionarPeriodo.dataInicial + " AND " + "data <=" + SelecionarPeriodo.dataFinal;
Cursor res = db.rawQuery( select, new String[]{});
Log.i("String", select);
return res;
}
If I remove this condition and use a query as follows
SELECT * FROM table_person
I have the results and the columns corresponding to the dates I'm trying to get.
The way you have written your query you are actually comparing the column data with 0, because a value like 14/12/2020 is considered as an expression containing divisions between the numbers 14, 12 and 2020 which has 0 as result.
If you want to compare dates in SQLite you must use a comparable format like YYYY-MM-DD, which is the only valid text date format for SQLite.
So if you stored the dates in the column data in any other format you'd better change it to YYYY-MM-DD.
You must also use the same format for the parameters SelecionarPeriodo.dataInicial and SelecionarPeriodo.dataFinal which will be compared to data.
Then use the recommended and safe way to pass the parameters in the 2nd argument of rawQuery():
public Cursor raw() {
SQLiteDatabase db = this.getReadableDatabase();
String select = "SELECT * FROM table_person WHERE data >= ? AND data <= ?" + ;
Cursor res = db.rawQuery(select, new String[]{SelecionarPeriodo.dataInicial, SelecionarPeriodo.dataFinal});
Log.i("String", select);
return res;
}
I only need the two most current items in a result set and was wondering what the best way to do that would be without a break. I realize that rs.next() returns true or false and tried to stop it with a counter but that failed. I have this at the moment:
while(rs.next()){
String name = rs.getString("name");
String startTime = rs.getString("starting_time");
String endTime = rs.getString("ending_time");
String date = rs.getString("directory");
String loc = rs.getString("location");
htmlBuilder.append("<li><a href='public/committees/calendar'>"+ name+"<br>");
htmlBuilder.append(date +" "+startTime+" - "+endTime+"</a> <!-- Link/title/date/start-end time --><br>");
htmlBuilder.append("<strong>Location: </strong>"+loc+"<br>");
htmlBuilder.append("</li>");
}
html = htmlBuilder.toString();
As you can tell, this returns everything from the ResultSet but I only need the first two entries.
Here is my correct query:
SELECT to_char(to_date(to_char(x.starting_date), 'J'),'mm/dd/yyyy') as start_date, to_char(to_date(to_char(x.ending_date), 'J'),'mm/dd/yyyy') as end_date, to_char(to_date(to_char(x.starting_date), 'J'),'yyyy-mm-dd') as directory, x.starting_time, x.ending_time, x.description, x.description as location, x.name, x.short_name, x.add_info_url, x.contact_name, x.contact_info FROM calitem x, calendar x, calitemtypes x WHERE x.calendar_id = x.calendar_id AND x.short_name LIKE ? AND x.style_id = 0 AND x.starting_date > to_char(sysdate-1, 'J') AND x.item_type_id = x.item_type_id AND ROWNUM <= 3 ORDER BY to_date(to_char(x.starting_date), 'J')
Adding the rownum attribute worked perfectly and the query was ordered before return. Thanks for the help
You should limit the query to return only the two most current rows. This can by achieved by a LIMIT clause (exists in MySQL, not sure about other DBs) and an ORDER BY clause.
There is not need to add an index that would count the rows returned by the ResultSet.
Suppose that I have a query, something like SELECT * FROM my_table where name = 'Debbie O'Brian'. As you may know in SQL Server we just need to put another ' to make it ignore single quotes. Here is what I like to do automatically.
Briefly, I need to replace all occurrences of ' with '' between two enclosing '.
Here is what I have so far:
String text = "SELECT * FROM my_table where name = 'Debbie O'Brian'";
String[] splitArray = text.split(" '");
for (int i = 0; i < splitArray.length; i++) {
String str = splitArray[i];
if (str.endsWith("'"))
str = str + " ";
// replace all single quotes
str = str.replace("'", "''");
// revert last replacement
str = str.replace("'' ", "' ");
splitArray[i] = str;
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < splitArray.length; i++) {
builder.append(splitArray[i]).append(" '");
}
System.out.println(builder.substring(0, builder.length() - 2).toString());
The problem is that I am relying on existence of a white space before starting '. My question is that how can I do this without this pre-assumption?
Any help (even suggestion of an algorithm) is much appreciated. Please mention that there might be more than one single quoted string in query.
EDIT: I am using Hibernate to execute native SQL and getting the whole SQL query as input.
The best way to handle single quotes and other special characters in an SQL query is by using Parametrized Queries. It is also more secure. I would recommend doing a search on 'SQL Injection'. That will teach you how to protect against and handle the single quotes in your query.
If you use JDBC use
PreparedStatement ps = conn.prepareStatement("SELECT * FROM my_table where name = ?")
ps.setString(1, name);
As you are using Hibernate, similar to what #B.O.B said use parameterised queries:
String queryString = "SELECT * FROM my_table where name = :name";
Query query = getSession().createSQLQuery(queryString);
query.setString("name", name);
OK, as I mentioned above, my problem was not SQL injection. What I was after, at this point seems to be impossible unless I implement a SQL parser which is obviously too much for the requirement. So I am going to stick with my pre-assumption and give up trying to fix the wrong input as two people mentioned in comments.
Thank everybody for your answers.
account_id current_balance opening_date
1 100 2012-03-01
2 100 2012-4-01
3 100 2013-03-1
now when I am running query in sql work bench it's fine
select count(acc.account_id)
from daily_account acc
where acc.opening_date < '2013-03-01'
but when I am running this in NetBeans it is not giving proper output.
select count(acc.account_id)
from daily_account acc
where acc.opening_date < '"+ new Date((Integer.parseInt(FromYearComboBox.getSelectedItem().toString())-1900),FromMonthComboBox.getSelectedIndex(),Integer.parseInt(FromDateComboBox.getSelectedItem().toString()))).toString()
can any one help me why is this happening?
Edit :
rs = st.executeQuery("select count(acc.account_id) from daily_account
acc where acc.opening_date < '"+ new
Date((Integer.parseInt(FromYearComboBox.getSelectedItem().toString())-1900),FromMonthComboBox.getSelectedIndex(),(Integer.parseInt(FromDateComboBox.getSelectedItem().toString()))).toString()+"';");
rs.next();
tabledata[0][2]=rs.getString(1);
Edit ::
It is giving me wrong answer ...it is counting all the account id...
You seem to have an extra closing braces ) in the end i.e toString()))). It should be one less e.g.
select count(acc.account_id) from daily_account acc where acc.opening_date < '"+ new Date((Integer.parseInt(FromYearComboBox.getSelectedItem().toString())-1900),FromMonthComboBox.getSelectedIndex(),Integer.parseInt(FromDateComboBox.getSelectedItem().toString())).toString()+"'";
One note This is really making your query string complex to maintain. Try constructing the date string before hand and then append in the query.
Another Note: Date constructor with arguments is deprecated, and it also seems that you really don't need the date but string. In that case, why don't you write something simple as :
String dateStr =
String.valueOf(Integer.parseInt(
FromYearComboBox.getSelectedItem().toString())-1900)
+ FromMonthComboBox.getSelectedIndex()
+FromDateComboBox.getSelectedItem().toString();
String queryStr = "select count(acc.account_id) from daily_account acc "+
" where acc.opening_date < '"+ dateStr +"'";
I am trying to implement PreparedStatement, which won't work with sql DB.
Suppose I have the following sql query:
String selectSqlQuery = "SELECT * FROM customer WHERE f1 = ? AND f2 =? AND f3 > ?";
and the following code:
//----
prest = con.prepareStatement(selectSqlQuery );
prest.setString(1, "val1");
prest.setString(2, "val2");
prest.setInt(3, 108);
ResultSet rs = prest.executeQuery();
//---
My question is how to implement setString and setInt methods for injecting params?
For now I save parameters' indexes and values into HashMap, but after it I can't make injection into sql query string.
implementation of sql's java interfaces are part of vendor specific jdbc driver. You probably just need to get the proper jdbc jar file for you database. writing implementations of such stuff is usually just needed if you intend to write your own database driver...
Since you're writing your own driver, you can play with your class a little. Let's change the approach. If you have a query like this one:
"SELECT * FROM table WHERE id = ? AND name = ?"
Replace the ? to turn it into
"SELECT * FROM table WHERE id = {0} AND name = {1}"
About your set methods, those will have to save your new parameters in an Object array, again matching against the index.
Object parameterArray = new Object[1];
public boolean setString(int paramIndex, String param) {
if(paramIndex < 0 || paramIndex > parameterArray.length)
throw new IllegalArgumentException("Can't set parameter " + paramIndex + ", The query only has " + parameterArray.length + " parameters.");
parameterArray[paramIndex - 1] = param;
}
Before executing the query, take advantage of your formatted string and set the parameters:
MessageFormat messageFormat = new MessageFormat(query);
String newQuery = messageFormat.format(parameterArray);
The format method will replace the {number} substrings for the corresponding element in the index represented by the number between brackets.