I have compiled my JavaFX application and when I try to take the data from the UI and update the database I get this error:
java.sql.SQLSyntaxErrorException: Lexical Error at line 1 , column 105. Encountered "#" (64) after : ""
at org.apache.derby.client.am.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.client.am.ClientStatement.execute(Unknown Source)
at Query.generateOperation(Query.java:45)
at AdminAccount.addAdmin(AdminAccount.java:27)
at Root.lambdaExpression(Root.java:89)
This is the code which is referenced for Query ->
public void generateOperation(String query) {
try {
Statement statement = connection.createStatement();
statement.execute(query) // line raised by compiler
} catch (SQLException e) {
e.printStackTrace();
}
}
This is the code which is referenced for AdminAccount ->
public void addAdmin(String username, String password, String email) {
int id = generateId(); // return random number for id
String values = id + ", " + username + ", " + password + ", " + email;
DB.generateOperation("insert into APP.ADMINDETAILS (ID , USERNAME , PASSWORD , EMAIL) values (" + values + ")"); // DB is the Query object I use to interact with the database . This line is raised by the compiler
}
This is the code which is called by the user interface
submit.setOnAction(e -> {
if (...) {
adminAccount.addAdmin(usernameEntry.getText(), passwordEntry.getText(), emailEntry.getText()) ; // this is the line raised by compiler
}
});
What should I amend to this code so that I don't get the lexical error when parsing the SQL statement. I think there is trouble parsing the email entry as the compiler references the "#" symbol. Should I be using another method for constructing SQL statements?
The correct way of doing things is to NOT concatenate values into a query string. You need to use PreparedStatement, with placeholders for each value you want to set, and then explicitly set each value before you execute.
Given your code, you would need to do something like:
try (PreparedStatement insertStatement = connection.prepareStatement(
"insert into APP.ADMINDETAILS (ID, USERNAME, PASSWORD, EMAIL) values (?, ?, ?, ?)")) {
insertStatement.setInt(1, id);
insertStatement.setString(2, username);
// Do NOT do this in a real application, hash is with a password hash algorithm
insertStatement.setString(3, password);
insertStatement.setString(4, email);
insertStatement.executeUpdate();
}
The question marks in the statement are the placeholders for values, and using the setXXX methods ensures the values are correctly set before execution. This makes your query safe because it will prevent SQL injection.
Related
so this is my table
CREATE TABLE "client" (
"id" INTEGER,
"name" TEXT COLLATE NOCASE,
"surname" TEXT COLLATE NOCASE,
"number" TEXT UNIQUE COLLATE NOCASE,
"car_brand" TEXT,
"modele" TEXT,
"phone_nbr" TEXT,
PRIMARY KEY("id" AUTOINCREMENT));
when im adding a new statment from my java application i can add only one time NULL to the column number but i can add many nulls from the db browser
this is the code that i use
String number = tf_number.getText();
if(tf_number.getText().trim().isEmpty())
number = null;
String name = tf_name.getText();
String surname = tf_surname.getText();
String phoneNbr = tf_phoneNbr.getText();
String car_brand = tf_brand.getText();
String modele = tf_modele.getText();
Client c = new Client(name, surname, number, car_brand, modele, phoneNbr);
ClientCRUD pcd = new ClientCRUD();
pcd.addClient(p);
and this is the sql error
[SQLITE_CONSTRAINT_UNIQUE] A UNIQUE constraint failed (UNIQUE constraint failed: client.number)
this is the addClient() fonction
public void addClient(Client t) {
try {
String requete = "INSERT INTO CLIENT(name,surname,number,car_brand,MODELE,phone_nbr)"
+ "VALUES ('"+t.getClientName()+"','"+t.getClientSurname()+"','"+t.getNumber()+"',"
+ "'"+t.getCarBrand()+"','"+t.getModele()+"','"+t.getPhone()+"')";
Statement st = MyConnection.getInstance().getCnx()
.createStatement();
st.executeUpdate(requete);
System.out.println("Client added");
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
}
any solution ?
public void save(Person person) {
String query = "INSERT INTO person_info (" +
" name_p, " +
" age, " +
" address, " +
" email " +
")" +
"VALUES(?, ?, ?, ?)";
try(Connection connection = dbConnection.getConnection()) {
PreparedStatement prepStatement = connection.prepareStatement(query);
prepStatement.setString(1, person.getName());
prepStatement.setInt(2, person.getAge());
prepStatement.setString(3, person.getAddress());
prepStatement.setString(4, null);
prepStatement.execute();
}
catch (SQLException e){
e.printStackTrace();
}
}
##This will solve your problem
You code inserts the string "null" and not a real null like your browser do.
So there can be only 1 string with value "null" in that unique column.
You can use preparedStatement with parameters instead of the statement you use.
E.g:
PreparedStatement preparedStatement = connection.prepareStatement(sql))
This answers how to insert null using prepared statement: Insert null using prepared statement
And your sql string for the query should have the parameters.
See more about prepared statements: Prepared Statements Tutorial
So I'm importing information from a .csv file into a database. However I'm having trouble with the user inputted description in the csv file as they contain apostrophes which is breaking the SQL import.
My Import statement is String sqlJob =
"INSERT INTO job (ID, Job_Contact, Internal_Comment, Customer_Name,"
+ " Duration, Job_Location, Job_Completion_Date, Job_Technician,"
+ " Job_Asset, Job_Type, Job_Description) VALUES ('"
+csvRecord.get(i)+"', '"+csvRecord.get(26)+"', '"+csvRecord.get(16)
+"', '"+csvRecord.get(2)+"', '"+csvRecord.get(31)+"', '"+csvRecord.get(27)
+"', '"+csvRecord.get(28)+"', '"+csvRecord.get(29)+"', '"+csvRecord.get(30)
+"', '"+csvRecord.get(33)+"', '"+csvRecord.get(34)+"');";
A simplified form would be
"INSERT INTO job (ID, Description) VALUES ('"
+ csvRecord.get(i) + "', '" + csvRecord.get(34) + "');";
The problem is csvRecord.get(34) will sometimes contain apostrophes. For example "My name's Bob" and that apostrophe in Bob is breaking the surrounding apostrophes that are needed to declare that the value is a string for the SQL.
Is there an easy way to parse the string and add escape characters in front of apostrophes or should I format my original SQL command a different way.
Thanks!
The problem is you are assembling the SQL statement as a String, concatenating the parameter values. This is highly not advisable.
Use PreparedStatements instead that are easier to use. You can pass parameters without any modification and they won't interfere with the correct execution of the SQL statement.
Also as a valuable bonus, your code will be free of SQL Injection problems.
Example from the JDBC Tutorial:
String updateString = "update COFFEES set SALES = ? where COF_NAME = ?";
PreparedStatement updateSales = con.prepareStatement(updateString);
updateSales.setInt(1, numSales);
updateSales.setString(2, coffeeName);
updateSales.executeUpdate();
As you see, the parameters are NOT concatenated into the String, but they will take the place of the ? symbols.
Even if coffeeName has the value "Africa's Best" (apostrophe included) the query will work well.
Use PreparedStatement so you can be in save.
String name = request.getParameter( "ID" );
String message = request.getParameter( "Job_Contact" );
Connection c = null;
try
{
String url = "jdbc:mysql://localhost/**"databasename"**;
String username = "**<Database Login>**";
String password = "**<Database password>**";
**// at the ? section you can add any quantity you need to**
String sql = "insert into **<databasename>**(name, message) values (?, ?)";
c = DriverManager.getConnection( url, username, password );
PreparedStatement pstmt = c.prepareStatement( sql );
pstmt.setString( 1, name );
pstmt.setString( 2, message );
pstmt.executeUpdate();
}
catch( SQLException e )
{
throw new ServletException( e );
}
finally
{
try
{
if( c != null ) c.close();
}
catch( SQLException e )
{
throw new ServletException( e );
}
}
Here is the code:
public static Connection getConnection() throws Exception {
String name1 = "Danny";
String city1 = "Wien";
try {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/supermarket??verifyServerCertificate=false&useSSL=true";
String username = "myuser";
String password = "mypass";
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, username, password);
String sql = "insert into marketinfo "
+ " (name, country)" + " values (" + name1 + ", " + city1 + ")";
Statement insertie = conn.prepareStatement(sql);
insertie.executeUpdate(sql);
} catch (Exception e) {
System.out.println(e);
}
return null;
}
My error is "Unknown column 'Danny' in 'field list'" .
In Sql database my table contains id, name and city. I want to pass the id field because that id is incremented automatically.
There's alot going on in that code, and as others have suggested you should break it up. But actually performing the query can be done like this:
public class YourClass {
private static final String SQL = "INSERT INTO marketinfo (name, country) VALUES (?,?)";
public void addMarketInfo(String name, String city) {
try (Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(SQL)) {
stmt.setString(1, name);
stmt.setString(2, city);
stmt.executeUpdate();
} catch (SQLException e) {
// This is fine for debugging, but you probably want to log this or throw an exception
// Depends on how the rest of your application is set up
e.printStackTrace();
}
}
}
All your code creating the connection should most likely get moved to another class, and then called by the getConnection() method as in my example.
If you're using JDBC, PreparedStatements are used ALOT. It's worth looking more more examples on how they are used. Among other benefits, they're really helpful for avoiding string concatenation bugs like your original question.
This is the wrong way to do it. You should learn about PreparedStatement and how to bind values to parameters.
But it's worse than that.
Your method is getConnection, but it's also performing the query. Methods should do one thing well.
You don't close any of your resources. Another bad idea.
You print a stack trace to the console. Better to log it.
You hard wire your connection parameters instead of passing them in.
There's no connection pooling here.
seems you missed inner quotes around var name1 and city1
String sql = "insert into marketinfo "
+ " (name, country)" + " values ('"+ name1 +"', '"+ city1 +"')";
but most important you should use parametrized query instead of string concat .
To fix this you need to quote your variables in the SQL:
String sql = "insert into marketinfo "
+ " (name, country)" + " values ('"+ name1 +"', '"+ city1 +"')";
However, this is awful code, and you should not do it like this.
See here for why not: https://www.acunetix.com/websitesecurity/sql-injection/
As a hit, your sql should look like this:
String sql = "insert into marketinfo "
+ " (name, country)" + " values (:name, :city)";
Then, you use a prepared statement to set the values. Code like this is why websites get all their private information stolen.
String or varchar type should be between two quotes 'some string', but this still not secure so to avoid Syntax errors (Like you have now) or SQL Injection it's better to use PreparedStatement :
String sql = "insert into marketinfo (name, country) values (?, ?)";
try(PreparedStatement insertie = con.prepareStatement(sql);){
insertie.setString(1, name1);
insertie.setString(2, city1);
insertie.executeUpdate();
//...
}
My java code for SQL Query is
String sqlSt="INSERT INTO users(id,name,place) values ("+null+",'"+request.getParameter("name")+"','"+request.getParameter("place")+"');";
I have tried out
name= a'); DROP TABLE users; --
as well as
place =a'); DROP TABLE users; --
but it returns an Ecxeption as below
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 'DROP TABLE users; --','chennai')' at line 1
Note: when i tried the same in mysql command line. It worked!!!! i don't know what happens in jdbc
The real problem is actually JDBC, it only allows one sql if you dont tell it otherwise.
Look at this question for more info:
Multiple queries executed in java in single statement
But also i would try this instead, name =
a',''); DROP TABLE users; --
Since you specificed 3 columns in your insert:
(id,name,place)
You need to provide 3 values for the sql to be valid, not just 2.
Also you can sent the text null, sending a java null value is not necessary and i am not even sure how that works. I think this might be better:
String sqlSt="INSERT INTO users(id,name,place) values (null,'"+request.getParameter("name")+"','"+request.getParameter("place")+"');";
Instead of null, use an empty string ''
String sqlSt = "INSERT INTO users(id, name, place) values ('', '" + request.getParameter("name") + "', '" + request.getParameter("place") + "');";
It's better to use prepared statements to avoid confusion.
String sqlSt = "INSERT INTO users(id, name, place) values ('', ?, ?)";
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(query);
ps.setString(1, request.getParameter("name"));
ps.setString(2, request.getParameter("place"));
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
ps.close();
}
The real problem is with your Query. It is better to use a PreparedStatement for executing a query.
Your Code should be :
String sqlSt="INSERT INTO users(id,name,place) values (?,?,?)";
PreparedStatement pstmt = null;
try{
pstmt = dbConnection.prepareStatement(sqlSt);
pstmt.setString(1,null);
pstmt.setString(2,request.getParameter("name"));
pstmt.setString(3,request.getParameter("place"));
pstmt.executeUpdate();
}catch (Exception e) {
e.printStackTrace();
} finally {
pstmt.close();
}
If you don't want to use a PreparedStatement, just remove last ; from your query.
So your query will be :
String sqlSt="INSERT INTO users(id,name,place) values ("+null+",'"+request.getParameter("name")+"','"+request.getParameter("place")+"')";
This question already has an answer here:
SQL Command To Delete Entry In Current Textfields For Java App
(1 answer)
Closed 9 years ago.
I use this command to insert a new client, I have a method in Java where I assign the values to the command:
insertNewPerson = connection.prepareStatement(
"INSERT INTO Addresses " +
"(FirstName, LastName, Email, PhoneNumber, ClientAddress ) " +
"VALUES (?, ?, ?, ?, ?)" );
Question: I am looking for something similar but for DELETING whatever entries are in the text fields of the program.
Here is the Java method I use to set the values in the sql command:
public int addPerson(
String fname, String lname, String email, String num, String caddress)
{
int result = 0;
//set parameters, then execute insertNewPerson
try {
insertNewPerson.setString(1, fname);
insertNewPerson.setString(2, lname);
insertNewPerson.setString(3, email);
insertNewPerson.setString(4, num);
insertNewPerson.setString(5, caddress);
//insert the new entry; return # of rows updated
result = insertNewPerson.executeUpdate();
}//end try
catch(SQLException sqlException) {
sqlException.printStackTrace();
close();
}//end catch
return result;
}//end method addPerson
From what I understand, you are looking for the DELETE SQL Command:
delete from Addresses
where FirstName = ?
and LastName = ?
and Email = ?
and PhoneNumber = ?
and ClientAddress = ?
This also takes into consideration your need to delete based on the values on the fields.
You should have a unique value for all records. If you have a primary key you can use this block.
deletePerson = connection.prepareStatement(
"DELETE FROM Addresses " +
"WHERE personID = ?" );