I am trying to add a few details to a table named questionpaper from my front end JSP and from another table named questions.
In table questionpaper I have a column named ExamID to which I have to add a value of ExamId column from another table named question. This ExamId value has to be added simultaneously with the data added from the JSP page. The data from the JSP page is getting added without any error but the ExamId cannot be added simultaneously.
public int QuestionPaper(Questions paramQues) {
// TODO Auto-generated method stub
String query ="insert into questionpaper(Question,Opt1,Opt2,Opt3,Opt4,Answer,Marks,NegMarks,ExamId)values(?,?,?,?,?,?,?,?,?)";
int status=0;
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/onlineexam", "root", "admin");
PreparedStatement stat1 = con.prepareStatement(query);
if((paramQues.getAns1()!=null)&&(paramQues.getAns2()!=null)&&(paramQues.getAns3()!=null)&&(paramQues.getAns4()!=null)&&(paramQues.getMarks()!=null)&&(paramQues.getNegM()!=null)&&(paramQues.getQues()!=null))
{
System.out.println("implementation "+paramQues.getOption());
System.out.println("Marks-->"+paramQues.getMarks());
System.out.println("Ans->>"+paramQues.getAns1());
stat1.setString(1,paramQues.getQues());
stat1.setString(2,paramQues.getAns1());
stat1.setString(3,paramQues.getAns2());
stat1.setString(4,paramQues.getAns3());
stat1.setString(5,paramQues.getAns4());
stat1.setString(6,paramQues.getOption());
stat1.setInt(7,paramQues.getMarks());
stat1.setInt(8,paramQues.getNegM());
System.out.println("Ans->>"+paramQues.getAns1());
String query2="SELECT * FROM questions ORDER BY ExamId DESC LIMIT 1";
PreparedStatement stat2 = con.prepareStatement(query2);
ResultSet rs1 = stat2.executeQuery(query2);
Integer Examid= rs1.getInt("ExamId");
System.out.println("exam id-->"+Examid);
stat1.setInt(9,Examid);
stat1.executeUpdate();
Integer TotalQues= rs1.getInt("TotalQuestions");
String query3="SELECT * FROM questionpaper ORDER BY PaperId DESC LIMIT 1";
PreparedStatement stat3 = con.prepareStatement(query3);
ResultSet rs2 = stat3.executeQuery(query3);
Integer PaperId= rs2.getInt("PaperId");
if(PaperId<=TotalQues)
status=1;
else
status=0;
}
}
catch (Exception e)
{
System.out.println("Exception in FacultyTry->" + e);
}
return status;
}
Output:
Answer:l
j
d
d
options-->o3
Marks-->2
NegMarks-->1
implementation o3
Marks-->2
Ans->>l
Ans->>l
Exception in FacultyTry->java.sql.SQLException
You have mentioned, your tables contain ExamID column & you are using ExamId in SQL query. Either of the below query contains wrong column name.
Your SQL query :
String query ="insert into questionpaper(Question,Opt1,Opt2,Opt3,Opt4,Answer,Marks,
NegMarks,ExamId)values(?,?,?,?,?,?,?,?,?)";
OR
String query2="SELECT * FROM questions ORDER BY ExamId DESC LIMIT 1";
Required SQL Query :
String query ="insert into questionpaper(Question,Opt1,Opt2,Opt3,Opt4,Answer,Marks,
NegMarks,ExamID)values(?,?,?,?,?,?,?,?,?)";
OR
String query2="SELECT * FROM questions ORDER BY ExamID DESC LIMIT 1";
In your code you don't need to prepare a statement that has no parameters denoted by ?.
Use the statement to execute query
ResultSet rs1 = stat1.executeQuery(query2);
or
Statement stat2 = con.createStatement();
ResultSet rs1 = stat2.executeQuery(query2);
Related
I'm trying to use prepared statements to set a table name to select data from, but I keep getting an error when I execute the query.
The error and sample code is displayed below.
[Microsoft][ODBC Microsoft Access Driver] Parameter 'Pa_RaM000' specified where a table name is required.
private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [?]"; //?=date
public Execute(String reportDate){
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection conn = DriverManager.getConnection(Display.DB_MERC);
PreparedStatement st = conn.prepareStatement(query1);
st.setString(1, reportDate);
ResultSet rs = st.executeQuery();
Any thoughts on what might be causing this?
A table name can't be used as a parameter. It must be hard coded. So you can do something like:
private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [" + reportDate + "?]";
If you need a solution which is not vulnerable to SQL injection, you have to duplicate the query for all tables you need:
final static String QUERIES = {
"SELECT x FROM Table1 x WHERE a=:a AND b=:b AND ...",
"SELECT x FROM Table2 x WHERE a=:a AND b=:b AND ...",
"SELECT x FROM Table3 x WHERE a=:a AND b=:b AND ...",
...
};
And yes: the queries are duplicates and only the table name differs.
Now you simply select the query that fits your table, e.g. like
...
PreparedStatement st = conn.prepareStatement(QUERIES[index]);
...
You can use this approach wich JPA, Hibernate, whatever...
If you want a more verbose approach consider using an enum like
enum AQuery {
Table1("SELECT x FROM Table1 x WHERE a=:a AND b=:b AND ..."),
Table2("SELECT x FROM Table2 x WHERE a=:a AND b=:b AND ..."),
Table3("SELECT x FROM Table3 x WHERE a=:a AND b=:b AND ..."),
...
private final String query;
AQuery(final String query) {
this.query = query;
}
public String getQuery() {
return query;
}
}
Now use the either an index
String sql = AQuery.values()[index].getQuery();
PreparedStatement st = conn.prepareStatement(sql);
...
Or use a table name
String sql = AQuery.valueOf("Table1").getQuery();
PreparedStatement st = conn.prepareStatement(sql);
...
This is technically possible with a workaround, but very bad practice.
String sql = "IF ? = 99\n";
sql += "SELECT * FROM first_table\n";
sql += "ELSE\n";
sql += "SELECT * FROM second_table";
PreparedStatement ps = con.prepareStatement(sql);
And then when you want to select from first_table you set the parameter with
ps.setInt(1, 99);
Or if not, you set it to something else.
As a number of people have said, you can't use a statement parameter for a table name, only for variables as part of the condition.
Based on the fact you have a variable table name with (at least) two table names, perhaps it would be best to create a method which takes the entity you are storing and returns a prepared statement.
PreparedStatement p = createStatement(table);
You can't set table name in prepared statement
As said before, it is not possible to set the table name in a prepared statement with preparedStatement.setString(1, tableName). And it is also not possible to add parts of the SQL query to a prepared statement (eg preparedStatement.addSql(" or xyz is null")).
How to do it right without risking SQL injections?
The table name must be inserted into the SQL (or JQL) query you want to execute with string operations like "select * from " + tableName or String.format("select * from %s", tableName)
But how to avoid SQL injections?
If the table name does not come from user input, you are probably safe.
For example, if you make a decision like here
String tableName;
if(condition) {
tableName = "animal";
} else {
tableName = "plant";
}
final String sqlQuery = "delete from " + tableName;
...
If the table name depends on the users input, you need to check the input manually.
For example, with a white-list containing all valid table names:
if(!tableNamesWhitelist.contains(tableName)) {
throw new IllegalArgumentException(tableName + " is not a valid table name");
}
String sqlQuery = "delete from " + tableName;
or with an enum:
public enum Table {
ANIMAL("animal"),
PLANT("plant");
private sqlTableName;
private TableName(String sqlTableName) {
this.sqlTableName= sqlTableName;
}
public getSqlTableName() {
return sqlTableName;
}
}
and then convert the user-input string like ANIMAL into Table.ANIMAL. An exception is thrown, if no fitting enumeration value does exist.
eg
#DeleteMapping("/{table}")
public String deleteByEnum(#PathVariable("table") Table table) {
final String sqlQuery = "delete from " + table.getSqlTableName();
...
}
Of course these examples work with select, update, ... too and a lot of other implementations to check the user input are possible.
This might help:
public ResultSet getSomething(String tableName) {
PreparedStatement ps = conn.prepareStatement("select * from \`"+tableName+"\`");
ResultSet rs = ps.executeQuery();
}
I'm not sure you can use a PreparedStatement to specify the name of the table, just the value of some fields. Anyway, you could try the same query but, without the brackets:
"SELECT plantID, edrman, plant, vaxnode FROM ?"
String table="pass";
String st="select * from " + table + " ";
PreparedStatement ps=con.prepareStatement(st);
ResultSet rs = ps.executeQuery();
I'm trying to use prepared statements to set a table name to select data from, but I keep getting an error when I execute the query.
The error and sample code is displayed below.
[Microsoft][ODBC Microsoft Access Driver] Parameter 'Pa_RaM000' specified where a table name is required.
private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [?]"; //?=date
public Execute(String reportDate){
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection conn = DriverManager.getConnection(Display.DB_MERC);
PreparedStatement st = conn.prepareStatement(query1);
st.setString(1, reportDate);
ResultSet rs = st.executeQuery();
Any thoughts on what might be causing this?
A table name can't be used as a parameter. It must be hard coded. So you can do something like:
private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [" + reportDate + "?]";
If you need a solution which is not vulnerable to SQL injection, you have to duplicate the query for all tables you need:
final static String QUERIES = {
"SELECT x FROM Table1 x WHERE a=:a AND b=:b AND ...",
"SELECT x FROM Table2 x WHERE a=:a AND b=:b AND ...",
"SELECT x FROM Table3 x WHERE a=:a AND b=:b AND ...",
...
};
And yes: the queries are duplicates and only the table name differs.
Now you simply select the query that fits your table, e.g. like
...
PreparedStatement st = conn.prepareStatement(QUERIES[index]);
...
You can use this approach wich JPA, Hibernate, whatever...
If you want a more verbose approach consider using an enum like
enum AQuery {
Table1("SELECT x FROM Table1 x WHERE a=:a AND b=:b AND ..."),
Table2("SELECT x FROM Table2 x WHERE a=:a AND b=:b AND ..."),
Table3("SELECT x FROM Table3 x WHERE a=:a AND b=:b AND ..."),
...
private final String query;
AQuery(final String query) {
this.query = query;
}
public String getQuery() {
return query;
}
}
Now use the either an index
String sql = AQuery.values()[index].getQuery();
PreparedStatement st = conn.prepareStatement(sql);
...
Or use a table name
String sql = AQuery.valueOf("Table1").getQuery();
PreparedStatement st = conn.prepareStatement(sql);
...
This is technically possible with a workaround, but very bad practice.
String sql = "IF ? = 99\n";
sql += "SELECT * FROM first_table\n";
sql += "ELSE\n";
sql += "SELECT * FROM second_table";
PreparedStatement ps = con.prepareStatement(sql);
And then when you want to select from first_table you set the parameter with
ps.setInt(1, 99);
Or if not, you set it to something else.
As a number of people have said, you can't use a statement parameter for a table name, only for variables as part of the condition.
Based on the fact you have a variable table name with (at least) two table names, perhaps it would be best to create a method which takes the entity you are storing and returns a prepared statement.
PreparedStatement p = createStatement(table);
You can't set table name in prepared statement
As said before, it is not possible to set the table name in a prepared statement with preparedStatement.setString(1, tableName). And it is also not possible to add parts of the SQL query to a prepared statement (eg preparedStatement.addSql(" or xyz is null")).
How to do it right without risking SQL injections?
The table name must be inserted into the SQL (or JQL) query you want to execute with string operations like "select * from " + tableName or String.format("select * from %s", tableName)
But how to avoid SQL injections?
If the table name does not come from user input, you are probably safe.
For example, if you make a decision like here
String tableName;
if(condition) {
tableName = "animal";
} else {
tableName = "plant";
}
final String sqlQuery = "delete from " + tableName;
...
If the table name depends on the users input, you need to check the input manually.
For example, with a white-list containing all valid table names:
if(!tableNamesWhitelist.contains(tableName)) {
throw new IllegalArgumentException(tableName + " is not a valid table name");
}
String sqlQuery = "delete from " + tableName;
or with an enum:
public enum Table {
ANIMAL("animal"),
PLANT("plant");
private sqlTableName;
private TableName(String sqlTableName) {
this.sqlTableName= sqlTableName;
}
public getSqlTableName() {
return sqlTableName;
}
}
and then convert the user-input string like ANIMAL into Table.ANIMAL. An exception is thrown, if no fitting enumeration value does exist.
eg
#DeleteMapping("/{table}")
public String deleteByEnum(#PathVariable("table") Table table) {
final String sqlQuery = "delete from " + table.getSqlTableName();
...
}
Of course these examples work with select, update, ... too and a lot of other implementations to check the user input are possible.
This might help:
public ResultSet getSomething(String tableName) {
PreparedStatement ps = conn.prepareStatement("select * from \`"+tableName+"\`");
ResultSet rs = ps.executeQuery();
}
I'm not sure you can use a PreparedStatement to specify the name of the table, just the value of some fields. Anyway, you could try the same query but, without the brackets:
"SELECT plantID, edrman, plant, vaxnode FROM ?"
String table="pass";
String st="select * from " + table + " ";
PreparedStatement ps=con.prepareStatement(st);
ResultSet rs = ps.executeQuery();
The function below will pick the highest value and it will display value which are in column place1(in table placeseen) as output based on the ID.So far I only can get the highest value but not the value in place1.
I don't know what's wrong with my coding because the output is always shows empty.
private void pick_highest_value_here_and_display(ArrayList<Double> value) throws Exception {
// TODO Auto-generated method stub
double aa[]=value.stream().mapToDouble(v -> v.doubleValue()).toArray();
double highest=aa[0+1];
for(int i=0;i<aa.length;i++)
{
if(aa[i]>highest){
highest=aa[i];
String sql ="Select* from placeseen where ID =aa[i]";
DatabaseConnection db = new DatabaseConnection();
Connection conn =db.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
if (rs.next())
{
String aaa;
aaa=rs.getString("place1");
System.out.println(aaa);
}
ps.close();
rs.close();
conn.close();
}
}
System.out.println(highest);
}
instead of
String sql ="Select * from placeseen where ID =aa[i]";//aa[i] taking a value
use
String sql ="Select place1 from placeseen where ID =?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setDouble(1, aa[i]);
passing aa[i] variable value .
Avoid sql injection
You can try this
// as you are using preparedStatement you can use ? and then set value for it to prevent sql injection
String sql = "Select * from placeseen where ID = ?";
DatabaseConnection db = new DatabaseConnection();
Connection conn = db.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ps.setDouble(1, aa[i]); // 1 represent first attribute represented by ?
System.out.println(ps); // this will print query in console
ResultSet rs = ps.executeQuery();
if (rs.next()) {
System.out.println("Inside rs.next()"); // for debug purpose
String aaa;
aaa=rs.getString("place1");
System.out.println(aaa);
}
// remaining code
private void User_combo() {
try {
String sql = "insert into asset_update(User) select (Concat(first_name), ' ', (last_name)) from user";
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
while (rs.next()) {
String name = rs.getString("User");
jComboBox_Users.addItem(name);
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
}
it gives me the error "can not issue data manipulation statements with executeQuery();"
can someone please help me with this? Thank you in advance
Use PreparedStatement#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
executeQuery() for database QUERY statement(Like select)
executeUpdate() for database UPDATE statements
update
String sql = "insert into asset_update(User) select (Concat(first_name), ' ', (last_name)) from user";
pst = conn.prepareStatement(sql);
int i = pst.executeUpdate();//since it is insert statement use executeUpdate()
if(i>0){
pst = conn.prepareStatement("Select User from asset_update");
rs = pst.executeQuery();//since it is select statement use executeQuery()
while (rs.next()) {
String name = rs.getString("User");
jComboBox_Users.addItem(name);
}
}
I have a database with the following layout
databasename:macfast
table name:users
columns
id,
user_name,
password,
fullName
I want to retrieve all the values from the column user_name and check each values with another one string which is already retrieved from a TEXTFIELD.But I can't(NullpointerException). Please help me.
public void deleteFclty() {
PreparedStatement stmt = null;
ResultSet rs = null;
String username=removeText.getText();
String qry = "SELECT user_name From users ";
try {
stmt = (PreparedStatement) connection.prepareStatement(qry);
rs = stmt.executeQuery();
while (rs.next()) {
String check=(rs.getString("user_name"));
System.out.println(check);
if(check.equals(username)){
Util.showErrorMessageDialog("EQUAL");
}else{
Util.showErrorMessageDialog("NOT EQUAL");
}
}
}catch (SQLException ex) {
Logger.getLogger(RemoveFaculty.class.getName()).log(Level.SEVERE, null, ex);
}
}
Problem is with the prepared statement (you don't put id into statement, which should be there instead of question mark).
Also I would recommend to do condition as "username.equals(check)", that can prevent null pointer exception.
"SELECT user_name From users where id=?"
This query has a parameter and you're not setting any value to it. Use PreparedStatement#setInt() or similar to set it, e.g.:
stmt.setInt(1, 1);
The problem is with PreparedStatement as you are using Question mark ? in your query for that you have to set the Id value.
String qry = "SELECT user_name From users where id=?";
stmt = (PreparedStatement) connection.prepareStatement(qry);
stmt.setInt(1,1001);
rs = stmt.executeQuery();
For your question in comment below:
List<String> values = new ArrayList();
while (rs.next()) {
values.add(0,rs.getString(<>))
}
// here do whatever you want to do...
// for example
for ( String value: values )
{
// check if value == TEXTFIELD
// if true then do something..
// else don't do anything
}