I have table called mpi which contains 23 columns. I have introduced the search field with button for every column where user can enter the query to fetch the records using query
query="select * from mpi where Genus ='"+genus+"'
Now I want to fetch records by giving keywords using LIKE %% but it is not working and not giving any records but if type type the full name it is working perfectly. Here is the code
String uname=request.getParameter("uname");
String full="%"+uname+"%";
dbconn=new DatabaseConnection();
conn=dbconn.setConnection();
pstmt=conn.prepareStatement("select * from mpi where Genus LIKE ?");
pstmt.setString(1, full);
res=pstmt.executeQuery
Could any one tell me where is the mistake and why I am not getting the records when I use half keyword like %keyword%.
It works (apart from the missing parentheses) and the approach with a prepared statement is entirely correct.
However I have seen a couple of code pieces like that, and always the problem lay with variables mix-up or not closing, or simple oversight. Better declare as close as possible.
try (ResultSet res = pstmt.executeQuery()) {
while (res.next()) {
..
}
} // Automatically closes res.
Also handle the life-cycle of pstmt correctly, with closing.
Related
I am trying to retrieve data from DB2 using Java prepared statement
String select_statement = "SELECT * FROM schema_name.table_name where NME='xxx002' and LINE =7200 and FILE_NME='720001042021XYZ002' with ur";
try (Connection connection = DataBaseConnection.getGeoCarDBConnection_TESTDATA();
PreparedStatement ps = connection.prepareStatement(select_statement);) {
ResultSet rs = null;
rs = ps.executeQuery();
}
The problem I am facing is that I include the FILE_NME in the where clause of the query, as shown above, 0 rows are returned. But any other string fields can be passed and I get the desired number of rows.
Any integer fields in the where clause works too.
But only the string fields that are large(In this case, FILE_NME field) are not working. In the DB2 table, where I am pulling the data from, the FILE_NME field is of varchar(30).
Things that did not work for me was
String select_statement = "SELECT * FROM schema_name.table_name where NME='xxx002' and LINE =7200 and FILE_NME = ? with ur";
then I set the String value using,
ps.setString(1, "'720001042021XYZ002'")
ps.setString(1, "720001042021XYZ002")
Both did not work.
None of the google links were helpful. Have spent more than a day on it.
This code used to work flawlessly before, Even the java version hasn't changed(as per my knowledge)
I am running it in windows 10.
Java version : 1.8 ((build 1.8.0_221-b11))
I run the same query in the database client and it works.
Someone please help me or point me in the right direction. I don't know what I am missing
Thank in advance
The problem was that there was indeed no data, I was checking the same query in the database client in a different environment. I am closing this.
I'm having a weird problem with an Grails application accessing data. Going deeper I've isolated the problem to a plain java8 small application using PreparedStatement.executeQuery vs Statement.executeQuery.
Consider the following snippet of code:
// executes in milliseconds
directSql = "select top(10) * from vdocuments where codcli = 'CCCC' and serial = 'SSSS' ORDER BY otherField DESC;";
stmt = con.createStatement();
rs = stmt.executeQuery(directSql);
// More than 10 minutes
sqlPrepared = "select top(10) * from vdocuments where codCli = ? and serial = ? ORDER BY otherField DESC;";
PreparedStatement pStatement = con.prepareStatement( sqlPrepared );
pStatement.setString(1, "CCCC");
pStatement.setString(2, "SSSS");
rsPrepared = pStatement.executeQuery();
Same query.
Data comes from a view on SqlServer (2008, I think, have no access right now) from a table with more than 15 Million records. There are indexes for all needed fields and the same query (the first one) executed from console runs also quite fast.
If I execute the slow PreparedStatement query without the ORDER clause it also runs fast.
It looks clear to me that for any cause the database it's not using indexes and make a full scan when using preparedStatement, but maybe I'm wrong so I'm open to any idea.
I thought maybe the driver (sqlserver official latest and jtds has been tested) was holding the data waiting for any kind of EOF from connection but I've checked with tcpdump on my side and no data is received.
I can't find why this is happening so any idea will be welcomed.
Thank you in advanced!
I've finally found a solution, at least in for my case. I got it here http://mehmoodbluffs.blogspot.com.es/2015/03/hibernate-queries-are-slow-sql-servers.html . Telling (driver? sqlServer?) not to send parameters as Unicode have resolved the problem.
Current connection string it's now:
String connectionUrl = "jdbc:sqlserver://server:port;databaseName=myDataBase;sendStringParametersAsUnicode=false";
And now both direct queries and preparedStatements runs at millisecond speed.
Thank you #DanGuzman for your suggestions!
JDBC has been supporting bulk updates for a long time using addBatch and executeBatch. Why isn't there any support for adding a bunch of prepared statements and getting an array of result sets as response?
For example, if I wanted to load customer details, basic account details, basic card details, basic loan details etc. for a single view, I would prefer to create a bunch of prepared statements and append the prepared statements to an ArrayList and execute them as a batch. I would then loop through the result sets and process the data. Hopefully, several network round trips would be saved (assuming my queries are performant).
Sample bunch of queries:
SELECT custid, first, last, age FROM Customer where custid = ?
SELECT custid, acno, accountname, accounttype, status FROM Account where custid = ?
SELECT custid, cardno, cardname, cardtype, status FROM CreditCard where custid = ?
SELECT custid, loanno, principal, rate FROM Loan where custid = ?
I can imagine several hypothetical reasons why it could be a bad idea. But, I am not sure which is most likely true in the real world.
Hypothetical reasons against having bulk-fetch:
There is some fundamental networking/db stack/memory related issue
which prevents a bunch of select queries to be executed on the same
connection and result-sets kept open.
Response handling code would be too cumbersome, as there could be exceptions at call level and individual statement level. And, several statements would have to be closed correctly.
There is no significant performance gain in reducing the number of network-calls. Query execution is the main bottleneck and network round-trip cost is insignificant.
There could be misuse of such a feature. A single non-performant query batched up like this with other queries could cause application to perform poorly.
The reason I ask this is because often I see a lot of Join queries which merge parent-child relationships into a single SQL query, just for the sake of completing the loading in a single call.
However, as the number of tables grows, the query becomes complex. Also, the parent table information is repeated in every row of every child. So, there is huge amount of data redundancy in the single join-ed result set.
Sample join query:
SELECT custid, first, last, age, acno, accountname, accounttype, a.status, cardno, cardname, cardtype, c.status, loanno, principal, rate
FROM Customer cc, Account a, CreditCard c, Loan l
WHERE a.custid=CC.custid(+) and c.custid=CC.custid(+) and l.custid=CC.custid(+)
The JDBC API does support this.
Statement.getMoreResults() can tell you if the SQL statement you executed through execute() produced more than one ResultSet
Quote from the JavaDocs for getMoreResults():
Moves to this Statement object's next result, returns true if it is a ResultSet object, and implicitly closes any current ResultSet object(s) obtained with the method getResultSet.
There are no more results when the following is true:
// stmt is a Statement object<br>
((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))
However it depends on the backend DBMS and the JDBC driver if you can use this. Some JDBC driver simply reject to run more than one statement with a single execute() call (mainly as a means to prevent SQL injenction), others don't.
So in e.g. Postgres you can do something like this:
boolean hasResult = stmt.execute(
"select * from table_1;\n" +
"select * from table_2;");
while (hasResult)
{
rs = stmt.getResultSet();
while (rs.next())
{
// process the result set
}
hasResult = stmt.getMoreResults();
}
This even allows mixing SELECT and e.g. UPDATE statements if you also check for getUpdateCount()
As far as I know you can also do this with SQL Server. It does not work with Oracle.
I haven't tried this with a PreparedStatement though. But as getMoreResults() is defined for Statement it is available for a PreparedStatement as well.
How about to put queries to a procedure and then use CallableStatement to execute that procedure?
A CallableStatement can return one ResultSet object or multiple
ResultSet objects. Multiple ResultSet objects are handled using
operations inherited from Statement.
try
{
CallableStatement stmt = con.prepareCall(/* call procedure */);
boolean results = stmt.execute();
int rsCount = 0;
while (results)
{
ResultSet rs = stmt.getResultSet();
while (rs.next())
{
}
rs.close();
results = stmt.getMoreResults();
}
stmt.close();
}
catch (Exception e) {
e.printStackTrace();
}
Relational databases are designed and optimized for retrieving data through SQL queries that JOIN data from multiple tables. Executing a single query that (correctly) JOINs data is likely always more efficient than getting the same data with separate queries.
When a single query gets too complex, it should be refactored into a VIEW -- from which you can query, joining data from other TABLEs and VIEWs, if required.
Given the above, I don't see a need for bulk queries.
I get the feeling you don't understand what a prepared statement is.
A prepared statement is an object you declare once, then reuse it all the time with different supplied parameters to it.
You're not telling me that you recreate a prepared statement from scratch each time you wish to execute it again?
Say you have four loops. before executing your loops you do this:
PreparedStatement statement1, statement2, statement3,statement4;
try {
con.setAutoCommit(false);//only needed when also doing updates/inserts
statement1 = con.prepareStatement("SELECT custid, first, last, age FROM Customer where custid = ?");
statement2 = con.prepareStatement("SELECT custid, acno, accountname, accounttype, status FROM Account where custid = ?");
// etc....
for (Map.Entry<String, Integer> e : customers.entrySet()) {
statement1.setInt(1, e.getValue().intValue());
ResultSet rs = statement1.executeQuery();
// do what you need to do
statement2.setInt(1, e.getValue().intValue());
ResultSet rs2 = statement2.executeQuery();
// do what you need to do
}
con.commit();//only needed when also doing updates/inserts
}
}
There is no need to recreate the prepared statements. That is why its calleda prepared statement. You just feed it the new values it needs to query.
This way you can add it to lists, itereate it the way you want to itereate it, etc.. and it's all optimised since the database engine will remember the query plans and the optimisations it makes for it. What you do with the prepared statement object is up to you.
It also does this if you recreate the objects constantly because it will remember the query, but you save the overhead of createing new objects over and over and the memory issues that come with that.
So, without a clearer question this is the best answer I can give you.
I am currently trying to make an update application (Java based) that the user can go through and view the existing database entries (MySQL) and edit them if need be... I was wondering how to get the information for a specific entry (ie 12-1589 which is an example of what the ID or primary key would be) and fill in the text boxes with all of the information from said entry.... I may just need to walk away from the computer for a bit because i may be over-thinking it, but I don't know...
mainly i am unsure with the exact code that you would use to move to that entry and retrieve the data from just that entry.... I know how to step trough a database one entry at a time, but i would rather just jump to a specific row based off of an id number (such as above 12-1589) if at all possible....
I just tried this and i recieved an error.... The error was:
"Unknown column '12-1859' in 'where clause'"
con = DriverManager.getConnection(host, uName, uPass);
stmt = con.createStatement();
String sql = "SELECT * FROM Load_Sheet WHERE Load_Number = 12-1859 limit 1";
rs = stmt.executeQuery(sql);
String BC = rs.getString("BC");
If anyone could give me a hand with that is going wrong i would appreciate it...
I just started getting another error along with the other one... it is :
"illegal operation on empty result set"
Though the result sets are not empty so my guess is, is that i am missing a step somewhere....
What you need is a simple WHERE statement if i understood correctly your question.
SELECT * FROM table_name WHERE entry_col = "12-1589" LIMIT 1
LIMIT 1 is only added so that the MySql query only returns a single row.
I am working a Airsoft application.
I'm trying to add records to a MS Access Database via SQL in Java. I have established a link to the database, with the following:
try
{
//String Driver = "sun.java.odbc.JdbcOdbcDriver";
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection conn = DriverManager.getConnection("jdbc:ucanaccess://" + URL,"","");
Statement stmt = conn.createStatement();
System.out.println("Connection Established!");
ResultSet rs = stmt.executeQuery("SELECT * FROM AirsoftGunRentals");
tblRent.setModel(DbUtils.resultSetToTableModel(rs));
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, "Error");
}
I am using Ucanaccess to access my MS database. It is reading the database and is displaying to a JTable. However, I need to create three JButtons to add, delete and update the table. I have tried to code the add button, and I have tried to add a record, but it crashes and gives me errors.
try
{
//String Driver = "sun.java.odbc.JdbcOdbcDriver";
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection conn = DriverManager.getConnection("jdbc:ucanaccess://" + URL,"","");
Statement stmt = conn.createStatement();
System.out.println("Connection Established!");
String Query= "INSERT INTO AirsoftGunRentals(NameOfGun, Brand, TypeOfGuns, NumberOfMagazines,Extras,NumberAvailable,UnitRent)"+
"VALUES('"+pName+"','"+pBrand+"','"+pTypeOfGun+"','"+pNumMags+"','"+pExtras+"','"+pNumberAvail+"','"+pRent+"');";
ResultSet rs = stmt.executeQuery(Query);
JOptionPane.showMessageDialog(null, "Success!");
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, "Error");
}
I have attempted all three, hoping for a result. But am still getting big errors. The only difference between the buttons is that one adds, one deletes and one updates the table. Other then that, the code is the same, minus variables.
As Brahim mentionned it, you should use stmt.executeUpdate(Query) whenever you update / insert or delete data. Also with this particular query, given your String concatenation (see end of line), there is no space between the ")" and the "VALUES" which probably causes a malformed query.
However, I can see from your code that you are not very experienced with such use-cases, and I'd like to add some pointers before all hell breaks loose in your project :
Use PreparedStatement instead of Statement and replace variables by placeholders to prevent SQL Injection.
The code that you are using here is extremely prone to SQL injection - if any user has any control over any of the variables, this could lead to a full database dump (theft), destruction of data (vandalism), or even in machine takeover if other conditions are met.
A good advice is to never use the Statement class, better be safe than sorry :)
Respect Java Conventions (or be coherent).
In your example you define the String Query, while all the other variables start with lower-case (as in Java Conventions), instead of String query. Overtime, such little mistakes (that won't break a build) will lead to bugs due to mistaking variables with classnames etc :)
Good luck on your road to mastering this wonderful language ! :)
First add a space before the quotation marks like this :
String Query= "INSERT INTO AirsoftGunRentals(NameOfGun, Brand, TypeOfGuns, NumberOfMagazines,Extras,NumberAvailable,UnitRent) "+
" VALUES('"+pName+"','"+pBrand+"','"+pTypeOfGun+"','"+pNumMags+"','"+pExtras+"','"+pNumberAvail+"','"+pRent+"');";
And use stmt.executeUpdate(Query); instead of : stmt.executeQuery(Query);in your insert, update and delete queries. For select queries you can keep it.
I managed to find an answer on how to add, delete and update records to a MS Access DB. This is what I found, after I declared the connection, and the prepped statement. I will try to explain to the best I can. I had to add values individually using this:
(pstmt = Prepped Statement Variable)
pstmt.setWhatever(1,Variable);
And it works fine now. I use the same method to delete and update records.
This is the basic query format:
String SQLInsert = "INSERT INTO Tbl VALUES(NULL,?,?,?,?)";
The NULL in the statement is the autonumber in the table. and .setWhatever() clause replaces the question marks with the data types. Thus manipulating the database.
Thank you everyone for all your contributions. It helped a lot, and made this section a lot more understandable.