escape character for '#' -- JDBC? - java

I'm making a batch insert to MySQL table:
insert into table1 (field1, field2) values("aa#gmail.com", "f2 value"), ("cc#gmail.com", "another f2 here");
giving error to the character '#' in the value String:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insert into buyers (field1, field2) values ('aa#' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.Util.getInstance(Util.java:408)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3970)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3906)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2524)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2677)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2549)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009)
at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5098)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994)
How can i get around this - is there some kind of escape charactr for JDBC to work this?
Note: I'm aware of JDBC-batch execution. I'm looking for a solution for the above - if any:
pStat.addBatch();
pStat.executeBatch();
TIA.
Further note: The above insert query runs fine directly on MySQL without JDBC in between. Also note: this isn't an issue when JDBC itself sets up the parameter with pStat.getString("aa#gmail.com"); -- thus the batch execn is a solution.

Try using PreparedStatement. It resolves special characters automatically and avoids sql-injection.
String queryStr = "insert into table1 (field1, field2) values(?, ?);"
try {
PreparedStatement preparedStatement = conn.prepareStatement(queryStr);
preparedStatement.setString(1, "aa#gmail.com");
preparedStatement.setString(2, "f2 value");
preparedStatement.executeUpdate();
} catch (SQLException e) {
// Error
} finally {
if (preparedStatement != null) {
preparedStatement.close();
}
if (conn != null) {
conn.close();
}
}
More examples: https://www.mkyong.com/jdbc/jdbc-preparestatement-example-insert-a-record/

I don't think the error message is indicating a problem with the '#' at sign character.
MySQL syntax error "right syntax to use near" usually points to the first token where the problem is encountered. In this case, it looks like MySQL is objecting to INSERT.
... near 'insert into buyers (field1, field2) values ('aa#' at line 1 at
I suspect that there is something before that insert in the SQL text, and MySQL is seeing multiple statements. That's just a guess, we're not seeing the actual code.
I recommend displaying the actual contents of the SQL text, before it's executed or prepared.

Use single quotes:
insert into table1 (field1, field2)
values('aa#gmail.com', 'f2 value'), ('cc#gmail.com', 'another f2 here');

Use the UTF-8 code for special characters when running from Java. UTF-8 code for # is \u0040:
insert into table1 (field1, field2) values("aa\u0040gmail.com", "f2 value"), ("cc\u0040gmail.com", "another f2 here");

Was doing two queries separated by ; in one.
all resolved.
nothing wrong with #.
Thanks for the insightful comments&answers.

Related

MySQLSyntaxErrorException for a join command which is working fine on MySQL workbench

String query = "select Books.BookId, Books.Title, Book_Loans.BranchId, count(Book_Loans.BookLoanId) as NoOfCopies from (Book_Loans join Books"
+ "on (Book_Loans.BookId = Books.BookId)) where Books.BookId = ? group by (Book_Loans.BranchId)";
preparedStatement = connect.prepareStatement(query);
preparedStatement.setLong(1, bookId);
resultSet = preparedStatement.executeQuery();
while(resultSet.next()) {
System.out.println("BookId:"+resultSet.getLong(1)+"\nTitle:"+resultSet.getString(2)+"\nBranchId:"+resultSet.getLong(3)+"\nNoOfCopies:"+resultSet.getInt(4)+"\n");
I am trying to execute the above code snippet but I am getting MySQLSyntaxErrorException as below:
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(Book_Loans.BookId = Books.BookId)) where Books.BookId = 75 group by (Book_Loans' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.Util.getInstance(Util.java:408)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:944)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3976)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3912)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2530)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2683)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2486)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1966)
at libraryModel.CopiesCheckedOutFromEachBranchForABook.numberOfCheckedOutCopies(CopiesCheckedOutFromEachBranchForABook.java:36)
at libraryModel.Main.main(Main.java:47)
The tables related to the queries are as below:
Books(BookId, AuthorName, Title, (Publisher)Name)
Book_Loans(BookLoanId, DateOut, DueDate, BranchId, BookId, CardNo)
I am trying to display the number of copies of books checked out from each branch by asking the user to enter the branchId. The query is working fine when I ran it on MySQL workbench but giving me syntax error on Eclipse.
You are missing a space between "books" and "on". Add it and you should be fine.
The SQL query is not correct You got to add a space between Books and on. ALso, there is no need to put additional parenthesis
Use:
String query = "select Books.BookId, Books.Title, Book_Loans.BranchId, count(Book_Loans.BookLoanId) as NoOfCopies from Book_Loans join Books on Book_Loans.BookId = Books.BookId where Books.BookId = ? group by Book_Loans.BranchId";
Your query doesn't make sense. You are saying to aggregate by the branch, and then including information about books. In most databases -- and even in the more recent versions of MySQL -- this would fail.
Your query should look more like this:
select bl.BranchId, count(*) as NumCopies
from Book_Loans bl join
Books b
on bl.BookId = b.BookId
where b.BookId = ?
group by bl.BranchId;
If you want to include information about the book, then the proper way would be to use aggregation functions or to include the columns in the group by:
select bl.BranchId, count(*) as NumCopies, b.BookId, b.Title
from Book_Loans bl join
Books b
on bl.BookId = b.BookId
where b.BookId = ?
group by bl.BranchId, b.BookId, b.Title;
Notes that table aliases make a query easier to write and read.
Of course, once you get the query correct, you need to implement it correctly in your application, including getting the spacing correct around the lines of the query.

How can I know what happened to each SQL statement given in execute()? [duplicate]

This question already has answers here:
Multiple queries executed in java in single statement
(6 answers)
Closed 4 years ago.
My jdbc driver for mysql db is of version 5.1.25.
I want to execute sql query like so:
statement.execute("select fullName from user where user_id=1; select fullName from user where user_id=2");
And I always receive exception:
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select fullName from user where user_id=2' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2809)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2758)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:894)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:732)
at dbViewer.model.UserConnectionManager.retrieveRoutinesNames1(UserConnectionManager.java:622)
at dbViewer.model.UserConnectionManager.main(UserConnectionManager.java:637)
BUT when I run this same query(separated by semicolon) from command line it works perfectly and outputs two tables as expected.
Using ; in a query for most databases doesn't work as it is usually not part of the statement syntax itself, but a terminator for command line or script input to separate statements. The command line or script processor sees a semi-colon as the signal that the statement is complete and can be sent to the server.
Also in JDBC a single statement prepare (or execute) should only be one actual statement so multiple statements are not allowed and so there is also no need to have a semi-colon, and as for some (most?) databases the semi-colon isn't part of the statement syntax, it is simply a syntax error to have one included.
If you want to execute multiple statements, you need to use separate executes. Technically, MySQL does have an option to support multiple executions which can be enabled by a connection property. This behavior is not compliant with the JDBC specification/API and makes your code less portable. See allowMultiQueries on Driver/Datasource Class Names, URL Syntax and Configuration Properties for Connector/J
I want to execute sql query like so:
statement.execute("select fullName from user where user_id=1; select fullName from user where user_id=2");
This is possible only when you have set one database connection property to allow multiple queries to execute all at once. And the property name is allowMultiQueries=true. This property has to be set and send along with a database connection request to the server. General syntax is like this:
String dbUrl = "jdbc:mysql:///test?allowMultiQueries=true";
This is additional connection property to those if already exists some, like autoReConnect=true, etc.
Acceptable values for allowMultiQueries property are true, false, yes, and no. Any other value is rejected at runtime with an SQLException.
You have to use execute( String sql ) or its other variants to fetch results of the query execution.
multiQuerySqlString = "select fullName from user where user_id=1; ";
multiQuerySqlString += "select fullName from user where user_id=2; ";
// you can multiple types of result sets
multiQuerySqlString += "select last_login from user_logs where user_id=1; ";
boolean hasMoreResultSets = stmt.execute( multiQuerySqlString );
To iterate through and process results you require following steps:
int rsNumber = 0;
while ( hasMoreResultSets ) {
rsNumber += 1;
Resultset rs = stmt.getResultSet();
// based on the structure of the result set,
// you can handle column values.
if ( rsNumber == 1 ) {
while( rs.next() ) {
// handle your rs here
} // while rs
} // if rs is 1
else if ( rsNumber == 2 ) {
// call a method using this rs.
processMyResultSet( rs ); // example
} // if rs is 2
// ... etc
// check whether there exist more result sets
hasMoreResultSets = stmt.getMoreResults();
} // while results
Refer to:
Multiple queries executed in java in single statement
One of the similar postings on SO, for which I gave an answer.
No you can't. What are you expecting to get by calling statement.execute(...)?
It returns one ResultSet (... which means one table).
You can just call "select fullName from user where user_id in (1, 2)" to geht back both results.
Having semicolons in JDBC statements is very error prone in general. Some JDBC drivers do not support this (e.g. IBM's JDBC driver for DB2 10.x throws an exception if you close your SQL statement with ";").

SQL query syntax is wrong

Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost/exam","root","password");
String q="insert into group"
+"(gname,des)"
+"values(?,?)";
PreparedStatement p=con.prepareStatement(q);
p.setString(1,gname);
p.setString(2,des);
p.executeUpdate();
con.close();
This is my code for adding a group. But the error says that my query syntax is wrong. I have tried single cores with the feilds in my table but still getting that error. Firstly i was using create statement that was also giving the same error. Please tell what us wrong with this query?
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group(gname,des)values('Science','')' at line 1
sun.reflect.GeneratedConstructorAccessor16.newInstance(Unknown Source)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
java.lang.reflect.Constructor.newInstance(Constructor.java:423)
com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
com.mysql.jdbc.Util.getInstance(Util.java:408)
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943)
com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527)
com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680)
com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2490)
com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2079)
com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2013)
com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5104)
com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1998)
org.apache.jsp.groupreg_jsp._jspService(groupreg_j
Your query, after stripping out the line breaks in your code, is this:
insert into group(gname,des)values(?,?)
In other words, you are trying to insert into a table named group. This is not allowed because GROUP is a reserved word in MySQL.
From the manual:
Most of the reserved words in the table are forbidden by standard SQL as column or table names (for example, GROUP).
You need to pick a different table name (recommended) or surround the word group with backticks, like this:
INSERT INTO `group` (gname, des) VALUES (?, ?)
See the manual entry on Schema Object Names.
Also, make sure you have appropriate spaces; the lack of spacing you have now will cause additional problems in many contexts.
You could have written the complete query in a single line with proper spacing in Java, instead of the SQL way of writing queries. You should be able to identify that the first mistake is with the spacing. This can be corrected from this (what you've used):
String q = "insert into group"
+"(gname,des)"
+"values(?,?)";
to this (the modified query):
String q = "insert into group (gname, des) values(?, ?)";
The above change once made, makes it readable. The next thing as rightly pointed out by #EdCottrell, refrain from using restricted keywords as table names. Depending on the DB type, there could be issues related to this.
Hope this helps!

Strange behaviour of Java PreparedStatement

I have the following code
try{
sql = "Select Time, Text WHERE Sender =?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, "ABC");
rs = stmt.executeQuery();
}catch(SQLException){
System.out.println(e.getMessage());
}
And get the following error:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE Sender ='ABC'' at line 1
There is an extra ' in my SQL query, how can I fix that?
It's not the "extra" ' that's the issue. You actually need that for your DB to understand the text you're providing.
The issue is that you're issuing a SELECT statement that is requesting fields from a table which you have not specified. You need to add the table name:
Select Time, Text FROM <tablename here> WHERE Sender =?
Edit: Apparently MariaDB doesn't consider time and text as reserved words as #Andreas pointed out in a comment on this answer.

What is reason for following sql code couldn't insert data?

My database have two column. One column is auto increment id(Primary Key) and other is 'Sentence' column. Manually type something and I can insert that value. But when I'm trying insert variable value that gives error message. I tried different ways. ('?') /( ? )/(?) Not work anything for me.
int s1=9;
String s2="Kasuni";
String sql = "INSERT INTO sentences (Sentence) VALUES ( ? )";
PreparedStatement pstmtJ = conn.prepareStatement(sql);
//pstmtJ.setInt(1, s1);
pstmtJ.setString(1,s2);
pstmtJ.executeUpdate(sql);
1st value I didn't insert because of that is auto increment value. I just comment and that shows in my above code.
Error message:
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? )' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
at com.mysql.jdbc.Util.getInstance(Util.java:381)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1030)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3558)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3490)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2109)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2642)
at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1647)
at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1566)
at TestJsoup.main(TestJsoup.java:66)
When I'm tring following code:
int s1=9;
String s2="Kasuni";
String sql = "INSERT INTO sentences (Sentence) VALUES ('?')";
PreparedStatement pstmtJ = conn.prepareStatement(sql);
//pstmtJ.setInt(1, s1);
pstmtJ.setString(1,s2);
pstmtJ.executeUpdate(sql);
That gives following error messages:
Exception in thread "main" java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
at com.mysql.jdbc.PreparedStatement.checkBounds(PreparedStatement.java:3646)
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3630)
at com.mysql.jdbc.PreparedStatement.setString(PreparedStatement.java:4481)
at TestJsoup.main(TestJsoup.java:65)
pstmtJ.executeUpdate(sql); → You're sending the original SQL string, since that is calling Statement.executeUpdate(String).
Use pstmtJ.executeUpdate(); instead (PreparedStatement.executeUpdate()) to execute the prepared statement.
Interface Statement
int executeUpdate(String sql)
Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement. refer java doc
public interface PreparedStatement extends Statement
int executeUpdate()
Executes the SQL statement in this PreparedStatement object, which must be an SQL Data Manipulation Language (DML) statement, such as INSERT, UPDATE or DELETE; or an SQL statement that returns nothing, such as a DDL statement.refer java doc
you are calling executeUpdate(String sql) which is from Statement interface, you have to call executeUpdate() from PreparedStatement interface to resolve issue.
Modified Code :
int s1=9;
String s2="Kasuni";
String sql = "INSERT INTO sentences (Sentence) VALUES ( ? )";
PreparedStatement pstmtJ = conn.prepareStatement(sql);
//pstmtJ.setInt(1, s1);
pstmtJ.setString(1,s2);
pstmtJ.executeUpdate();

Categories