com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException Insert mysql error - java

This is the whole message I receive:
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 ''user','age','school','password') values ('Admin','22','tei','admin')' at line 1
And this is the code:
String user = textField.getText().trim();
String age = textField_3.getText().trim();
String school = textField_4.getText().trim();
String password = String.valueOf(passwordField.getPassword());
String password1 = String.valueOf(passwordField_1.getPassword());
if(password.equals(password1)){
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/users","root","1234");
PreparedStatement st = con.prepareStatement("insert into user ('user','age','school','password') values ('"+user+"','"+age+"','"+school+"','"+password+"')");
int rs = st.executeUpdate();
JOptionPane.showMessageDialog(frame, "Data Saved Successfully");
Any ideas?

The point of prepared statements is, among others, to not concatenate your queries yourself.
You want to do the following:
//first you "prepare" your statement (where the '?' acts as a kind of placeholder)
PreparedStatement st = con.prepareStatement("insert into user (user,age,school,password) values (?,?,?,?);");
//now you bind the data to your parameters
st.setString(1, user);
...
//and then you can execute it
st.executeUpdate()
For more details see the official tutorial.
There are a couple of things happening behind the scenes that make the query safe, like escaping special characters that would otherwise allow altering the statement (google SQL injections if you want to know more)

Related

Can't reach temp table with using prepared statement for second time

I am using temporary tables inside my code in order to [some long sequnce of reasons here] in SQL Server, Java. I was executing my sql queries with using Stament object in java. However, recently I decided to use PreparedStatement in order to avoid injection thing.
My problem is when create a temporary table with using PreparedStatement, I can not reach it with the same prepared statement again. Here is a simple illustration:
sql = "select * into #someTable from (select someColumns from someOtherTable where smth = ? and smth2 = ?)"
PreparedStatement preparedStatement = conn.prepareStatement(sql);
for(int i=0; i<parameters.size(); i++){
preparedStatement.setString(i+1, parameters.get(i).toString());
}
this.rs = preparedStatement.executeQuery();
Until here, it is ok. After getting ResultSet and doing something with it, or without getting a resultSet just for preparedStatement.execute() does not makes difference, I can not reach the #someTable object again.
sql = "select count(*) from #someTable"
preparedStatement = conn.prepareStatement(sql);
this.rs = preparedStatement.executeQuery();
Here this.rs = preparedStatement.executeQuery(); part gives 'Invalid object name #someTable'. I am doing all of the things above with using one Connection object only and without closing or reopening it. I need to use that temp table again. Is there any way to create temp table with PreparedStatement object in java and reuse this temp table again and again? Regards,
Rather late to the party, but facing the same problem and finding the above answer wrong:
Read this article about the problem: https://learn.microsoft.com/en-us/sql/connect/jdbc/using-usefmtonly?view=sql-server-2017
I found that using a PreparedStatement to create the temp table wouldn't work, but if I changed to use a Statement to create the temp table it would work (even without the useFmtOnly).
So start with this (from the MS article) and build on it:
final String sql = "INSERT INTO #Bar VALUES (?)";
try (Connection c = DriverManager.getConnection(URL, USERNAME, PASSWORD)) {
try (Statement s = c.createStatement()) {
s.execute("CREATE TABLE #Bar(c1 int)");
}
try (PreparedStatement p1 = c.prepareStatement(sql); PreparedStatement p2 = c.prepareStatement(sql)) {
((SQLServerPreparedStatement) p1).setUseFmtOnly(true);
ParameterMetaData pmd1 = p1.getParameterMetaData();
System.out.println(pmd1.getParameterTypeName(1)); // prints int
ParameterMetaData pmd2 = p2.getParameterMetaData(); // throws exception, Invalid object name '#Bar'
}
}
The temp table you create in the first statement exists for the scope\lifetime of that request. As soon as you call another query, you're in a different scope so it is no longer present as it would have been cleaned up.
Solutions are either make 2 requests in the same call (not great) or create a global temp table that can be accessed by the second query (still not great).
The better solution is to create a stored procedure that does everything you need, with the temp table creation, querying and tidy up encapsulated in the procedure.
PS I can't see any surrounding code, but beware of SQL Injection when building queries in code like this.
Related info:
Scope of temporary tables in SQL Server

java.sql.SQLException: Parameter index out of range - whitespaces in String

I'm trying to update a table in a database through PreparedStatement in ServletClass. It raises java.sql.SQLException: Parameter index out of range (2 > number of parameters, which is 1). I guess, the problem is car string consists of more words, so it contains whitespaces, but I don't know how exactly solve it. I tried to remove two apostrophe marks surrounding the second question mark in the prepared statement but it didn't help. After removing quotes, there is still the following error:
java.sql.SQLException: Can not issue data manipulation statements with executeQuery()
Here is an extract of code:
private void updateCarAvailability(int value, String car) throws Exception {
Connection conn = null;
PreparedStatement prst = null;
try {
conn = ds.getConnection();
String sql = "update cars set available=? where name='?'";
prst = conn.prepareStatement(sql);
prst.setInt(1, value);
prst.setString(2, car);
prst.executeQuery(sql);
}
The solution is to remove the ' on where name='?', so it should look like update cars set available=? where name=?, and also you should change executeQuery for execute, once you're using an update command.
Remove the single quotes around the ?
String sql = "update cars set available=? where name=?";
They are not needed as the actual value is not passed as part of the SQL statement but as a bind parameter. And bind parameters don't need "SQL formatting".

SQL query for updating column with values from a local variable

How can I update my SQL Table column with the value that is stored in a local variable.
In my program I have taken value from the HTML page using the following statement:
String idd=request.getParameter("id");
String report=request.getParameter("rprt");
So now I have to update the value of report in my database table named "ptest" and I am using the following query:
Class.forName("com.mysql.jdbc.Driver");
java.sql.Connection con =
DriverManager.getConnection("jdbc:mysql://localhost:3306/tcs","root","root");
Statement st= con.createStatement();
ResultSet rs;
int i=st.executeUpdate("update ptest set result = #reprt where patient_id=
#idd");
out.println("Successfully Entered");
But the value is not being stored in the database instead NULL is being stored.
I have already seen this question and got no help.
Question
Please ignore my mistakes if any in this question as I am new to MYSQL.
You can use prepared statements in java.
setString or setInt can set different data types into your prepared statements.
The parameter 1, 2 are basically the positions of the question mark. setString(1,report) means that it would set the string report in the 1st question mark in your query.
Hope this code helps you in achieving what you want.
String query = "update ptest set result = ? where patient_id = ?";
PreparedStatement preparedStatement = con.prepareStatement(query);
preparedStatement.setString(1, report);
preparedStatement.setString(2, idd);
preparedStatement.executeUpdate();
In JDBC, you use ? as placeholders for where you want to inject values into a statement.
So you should do something like this ...
Class.forName("com.mysql.jdbc.Driver");
java.sql.Connection con =
DriverManager.getConnection("jdbc:mysql://localhost:3306/tcs","root","root");
PreparedStatement st= con.prepareCall("update ptest set result = ? where patient_id=
?");
///now set the params in order
st.setString(1, report);
st.setString(2, idd);
//then execute
st.executeUpdate();
Doing a string concat with the values is dangerous due to sql injection possibilities, so I typically make statement text static and final, and also if your value has a ' in it that could blow up your sql syntax etc. Also, notice the use of executeUpdate rather than query.
Hope this helps

SQLite Query With Parameters Not Working in Java

I have a program that selects from a database given a table and column string.
public void selectAllFrom(String table, String column){
String sql = "SELECT ? FROM ?";
try (Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql)){
pstmt.setString(1, column);
pstmt.setString(2, table);
ResultSet rs = pstmt.executeQuery();
while (rs.next()){
System.out.println(rs.getString(column));
}
} catch (SQLException e){
System.out.println(" select didn't work");
System.out.println(e.getMessage());
}
}
For some reason it is not working and it is going right to catch
Here is the connect() function as well:
private Connection connect(){
Connection conn = null;
// SQLite connection string
String url = "jdbc:sqlite:C:/sqlite/db/chinook.db";
try{
// creates connection to the database
conn = DriverManager.getConnection(url);
System.out.println("Connection to SQLite has been established");
} catch (SQLException e){
System.out.println(e.getMessage());
System.out.println("Connection didn't work");
}
return conn;
}
I know the problem is not with the database because I'm able to run other select queries without parameters. It is the parameters that are giving me the problem. Can anyone tell what the problem is?
A table or column name can't be used as a parameter to PreparedStatement. It must be hard coded.
String sql = "SELECT " + column + " FROM " + table;
You should reconsider the design so as to make these two constant and parameterize the column values.
? is a place holder to indicate a bind variable. When a SQL statement is executed, database first checks syntax, and validates the objects being referenced, columns and access permission for specified objects (i.e metadata about objects) and confirms that all are in place and valid. This stage is called parsing.
Post parsing, it substitutes bind variables to query and then proceeds for actual fetch of results.
Bind variables can be substituted in any place in query to replace an actual hard coded data/strings, but not the query constructs them selves. It means
You can not use bind variables for keywords of sql query (ex: SELECT, UPDATE etc.)
You can not use bind variables for objects or their attributes (i.e table names, column names, functions, procedures etc.)
You can use them only in place of a otherwise hard coded data.
ex: SELECT FIRST_NAME, LAST_NAME, 'N' IS_DELETED FROM USER_DATA WHERE COUNTRY ='CANADA' AND VERIFIED_USER='YES'
In above sample query, 'N','CANADA' and 'YES' are the only strings which can be replaced by a bind variable, not any other word.
Using bind variable is best practice of coding. It improves query performance (when used with large no. of queries in tuned database products like Oracle or MSSQL) and also protects your code against sql injection attacks.
Constructing query by concatenating strings (especially data part of query) is never recommended way. You can still construct a query by concatenation for other parts like table name or column name as long as those strings are not directly taken from input.
Below example is acceptable:
query = "Select transaction_id, transaction_date from ";
if (isHistorical(reportType)
{ query = query + "HISTORY_TRANSACTIONS" ;}
else
{query = query + "PRESENT_TRANSACTIONS" ; }
recommended practice is to use
String query_present = "SELECT transaction_id, transaction_date from PRESENT_TRANSACTIONS";
String query_historical = "SELECT transaction_id, transaction_date from HISTORY_TRANSACTIONS";
if (isHisotrical(reportType))
{
ps.executeQuery(query_historical);
}else{
ps.executeQuery(query_present);
}

How to change table name of from clause in PreparedStatement

Hi i have a small problem, how do i switch tables to get results from??
The code below is not working.However that should give you some idea of what i am trying to do.
Thanks for the help
String typelogin=null;
if(xx){
typelogin="users_table";
}else{
typelogin="admin_table";
}
String sqlStr = "Select * from "+typelogin+" where username=? and userpassword=?";
PreparedStatement stmt = conn.prepareStatement(sqlStr);
The full code:
Statement stmt = conn.createStatement();
String sqlStr = "Select * from "+typelogin+" where username=? and userpassword=?";
PreparedStatement pstmt=conn.prepareStatement(sqlStr);
pstmt.setString(1,user);
pstmt.setString(2,password);
//step 6 Process result
ResultSet rs = pstmt.executeQuery();
The error i am getting:
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 'fromspmovy_admin where username='abc' and userpassword='abc'' at line 1
Answer[SOLVED]:
forgot to put white space
from " + typelogin + " where
From your error message: 'fromspmovy_admin where ... looks like you missed a whitespace between from and your table name. Make sure you're doing this in the right way in all your methods (note that in your current example this won't happen).
If you will use ? for pass the variables, you must use PreparedStatement not Statement. Also according your error message you need to add a white space after from (check fromspmovy_admin)

Categories