Prepared statement and serial data type - java

This is my PostgreSQL code:
CREATE TABLE "user" (
id serial UNIQUE,
username varchar,
password varchar,
email varchar,
);
I want to create Java method, which adds new user to my table user:
public static void addUser(Connection con) throws SQLException {
String sql = "INSERT INTO user VALUES (?, ?, ?)";
try(PreparedStatement ps = c.prepareStatement(sql)) {
ps.setString(1, "test");
ps.setString(2, "test");
ps.setString(3, "test#email.com");
ps.executeUpdate();
}
}
}
Because column id is serial, I don't create prepared statement for this column (even without java, I would make insert only with remaining values, since id would be generated automatically). Hovewer, when I run this code, I get the following error:
ERROR: column "id" is of type integer but expression is of type character varying
What am I doing wrong?

Always specify the target columns in an INSERT statement. And as user is a reserved keyword, you have to quote it (but it would be better if you found a different name)
String sql = "INSERT INTO \"user\" (username, password, email) VALUES (?, ?, ?)";

Related

Duplicate entry for primary key - registration form

I have one simple registraton form with jsp, servlet and mysql. But, I can register only one user, then i got this error:
Severe: Message: Duplicate entry '1' for key 'PRIMARY'. Of course, when I delete that user from database I can create again but just one user. Also, I put auto increment on that column:
CREATE TABLE user (id int(3) NOT NULL AUTO_INCREMENT ...
This is also my method for insert in db:
public class UserDAO {
public int registerUser(User User) throws ClassNotFoundException, SQLException {
String INSERT_USERS_SQL = "INSERT INTO user"
+ " (id, firstName, lastName, username, password, email) VALUES "
+ " (?, ?, ?, ?, ?, ?)";
int result = 0;
Class.forName("com.mysql.jdbc.Driver");
try (Connection connection = DriverManager
.getConnection("jdbc:mysql://localhost:3306/cs230projekat","root","");
// Step 2:Create a statement using connection object
PreparedStatement preparedStatement = connection.prepareStatement(INSERT_USERS_SQL)) {
preparedStatement.setInt(1, 1);
preparedStatement.setString(2, User.getFirstName());
preparedStatement.setString(3, User.getLastName());
preparedStatement.setString(4, User.getUsername());
preparedStatement.setString(5, User.getPassword());
preparedStatement.setString(6, User.getEmail());
System.out.println(preparedStatement);
// Step 3: Execute the query or update query
result = preparedStatement.executeUpdate();
} catch (SQLException e) {
// process sql exception
printSQLException(e);
}
return result;
}
Thank you.
You are always setting the value of your id column to 1 via preparedStatement.setInt(1, 1). Since you say you have an auto-increment on the id column, remove id from your SQL, remove the aforementioned line and adjust the column indexes (first arguments) for all the other setString() method calls.
With auto increment set you don’t have to specify the ‘id’ column in your sql insert statements.
Here’s some information on the auto increment from MySQL’s website: https://dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html
From your code it looks like you are inserting the value 1 always for the id column, try implementing the autoGenerate properly. For more help, you can have a look on similar implementation

How to getGenerated id from parent table and insert into child table

try {
currentCon = ConnectionManager.getConnection();
psParent=currentCon.prepareStatement("insert into accommodation (type,name,price,description,username)values(?,?,?,?,?)", PreparedStatement.RETURN_GENERATED_KEYS);
psParent.setString(1,type);
psParent.setString(2,name);
psParent.setFloat(3,price);
psParent.setString(4,username);
psParent.executeUpdate();
accid= 0;
rs = psParent.getGeneratedKeys();
if (rs.next())
accid = rs.getInt(1);
rs.close();
psParent.close();
psChild=currentCon.prepareStatement("insert into room (accid, bed)values(?,?)");
psChild.setInt(1,accid);
psParent.setString(2,bed);
psChild.executeUpdate(); }
after I run this, I got this error message : failed: An Exception has occurred! java.sql.SQLRecoverableException: internal error
Is there's something wrong with the code? Thank you for your help
Your usage of getGenereatedKeys() actually looks correct to me for Oracle, but the problem is actually with your first insert statement. You have placeholders (and column names) for 5 columns, but you only bind 4 values. Try something like this:
String sql = "insert into accommodation (type, name, price, description, username) ";
sql += "VALUES (?, ?, ?, ?, ?)";
String generatedColumns[] = { "ID" };
psParent = currentCon.prepareStatement(sql, generatedColumns);
psParent.setString(1, type);
psParent.setString(2, name);
psParent.setFloat(3, price);
psParent.setString(4, description); // I ADDED THIS LINE
psParent.setString(5, username);
psParent.executeUpdate();
I am assuming that you have a variable containing a description to be inserted. If not, then remove description and its placeholder from the prepared statement entirely, or just insert null.

General error in JDBC(updating database)

private void sUpdateBtnActionPerformed(java.awt.event.ActionEvent evt) {
String query = "UPDATE Student SET lastname = ?, firstname = ?, course = ?, yearlvl = ?, username = ?, password = ?";
dbConn = DbConnection.dbConnect();
prepState = dbConn.prepareStatement(query);
prepState.setString(1, sLnTf.getText());
prepState.setString(2, sFnTf.getText());
prepState.setString(3, courseTf.getText());
prepState.setInt(4, Integer.parseInt(yearLvlTf.getText()));
prepState.setString(5, sUserTf.getText());
prepState.setString(6, sPassTf.getText());
prepState.executeUpdate();
}catch(Exception e){
appendEvent(sdf.format(new Date()) + " Error: " + e);
}
}
Method for connecting to the database:
import java.sql.*;
import javax.swing.*;
public class DbConnection {
Connection dbConn = null;
public static Connection dbConnect(){
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection dbConn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)}; DBQ=H:/Integ Ongoing Project/_Midterm Project/Server/src/database/Database.accdb");
return dbConn;
}catch(Exception e){
System.out.println(e.getMessage());
return null;
}
}
}
Password is a reserved word. If you must keep that as your field name, enclose it in brackets in your query to reduce the likelihood of confusing the database engine.
UPDATE Student
SET
lastname = ?,
firstname = ?,
course = ?,
yearlvl = ?,
username = ?,
[password] = ?
WHERE student_id = ?
Note I included a WHERE clause, as Stephen suggested, because it seems unlikely you would want those same field values applied to every row in the Student table. I used student_id as a placeholder name for the table's primary key ... the field which uniquely identifies each row. My intention is that you revise the WHERE clause to reference the primary key for the student whose record you want to alter.
If you're actually trying to add a new record, instead of update an existing record (or records), use an INSERT statement.
INSERT INTO Student (
lastname,
firstname,
course,
yearlvl,
username,
[password]
)
VALUES (
?,
?,
?,
?,
?,
?
)
And if you have autonumber as the data type of your primary key, the db engine will manage it for you.
I think that the problem is that your SQL statement is missing a WHERE clause. (I know that WHERE is optional in some dialects of SQL ... but a missing WHERE makes no sense to me here.)
The reason I think this is wrong is that even if the SQL dialect allows this, it is not clear which row of the table you are "setting". Even if the SQL engine can figure it out, a WHERE clause makes it a lot clearer. (And the fact that it "works" in the other case, doesn't mean that it is necessarily correct.)
Another thing that is potentially the cause of the problem is that "password" is a reserved word in some SQL dialects. Change the column name, or escape it.
Finally, the actual SQL error message should be in the exception stacktrace, or failing that in the log files. Those should be the first places to look if you are trying to find a problem in your database code. Look for the evidence ... rather than hoping someone else guess the right answer for you.

Insert new data into specific table in a the database

I design a system and I want from the user firstly to choose from a combo box the name of the table he want to insert then he will enter the rest of the fields.. My question is that how can I let the user enter the name of the table using sql statement .. I write the following doesn't but it doesn't work ??
try {
Object service = Service_ComboBox.getSelectedItem();
String ref = "0";
String title = title_TextField1.getText();
Object riskRating = riskRating_ComboBox3.getSelectedItem();
Object rootCause = rootCause_ComboBox4.getSelectedItem();
Object impact = impact_ComboBox1.getSelectedItem();
Object likelihood = likelihood_ComboBox2.getSelectedItem();
String efforts = efforts_TextField7.getText();
String finding = finding_TextField9.getText();
String implication = implication_TextArea1.getText();
String recommendation = recommendation_TextArea2.getText();
Connection conn= DriverManager.getConnection ("jdbc:oracle:thin:#localhost:1521:XE","SYSTEM","*******");
String query = "insert into ? (Service,Ref,Title,Risk_Rating,Root_cause,Impact ,Likelihood,Efforts,Finding,Implication,Recommendation)values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?)";
PreparedStatement myStatment = conn.prepareStatement(query);
myStatment.clearParameters();
myStatment.setString(1, service.toString());
myStatment.setString(2, service.toString());
myStatment.setString(3, ref);
myStatment.setString(4, title);
myStatment.setString(5, riskRating.toString());
myStatment.setString(6, rootCause.toString());
myStatment.setString(7, impact.toString());
myStatment.setString(8, likelihood.toString());
myStatment.setString(9, efforts);
myStatment.setString(10, finding);
myStatment.setString(11, implication);
myStatment.setString(12, recommendation);
boolean myResult = myStatment.execute();
System.out.println("done");
} catch (SQLException ex) {
JOptionPane.showMessageDialog(this, "Information is missing or incorrect! Please Make sure to enter correct information");
Logger.getLogger(Insert_info.class.getName()).log(Level.SEVERE, null, ex);
return;
}
JOptionPane.showMessageDialog(this, "Your information was saved successfully!");
insert into ?
You cannot use a bind variable for schema object names. The reason being that when you prepare the statement, the database needs to know what tables are involved, and decide which indexes to use, so the query SQL needs to be known (only the data can change).
So if you want to do this, you have to use string interpolation to construct the query (only for the table name, continue to use bind variables for the data!).
String query = "insert into "+ tableName + ....
Make sure that you validate this tableName. In your case, it can probably be checked against a HashSet of valid table names. Do not let this become an SQL injection problem.
Use the folowing sintax:
String query = "insert into " &tablename "bla bla predicates"
To avoid the sql injection create roles in your databases and give access to the tables you want to be used by your visitors/users.
Or you can use a wildcard :
Create a Variable tbl_name
String query = "insert into "(select table_name from user_tables where table_name like '%tbl_name%')"<br/>
- next create a decision "IF" and throw the output of the wildcard in it.If it matches the tables you have then ok if not treat it with an error message.

Error setting mysql primary key field with preparedStatement

This is my code for inserting a row. The columns are: primary id, name, and artist.
Am I passing the primary id correctly because it keeps on giving me an error? It is set to one and it increments every time a row is added.
try {
//Database
String query = "INSERT INTO lyrics1(lyrics1_id, name, artist) values(?, ?, ?)";
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(2, nameOfSong.getText()); // set input parameter 2
statement.setString(3, artist.getText());
statement.setLong(i, i);
ResultSet rs = statement.executeQuery("SELECT * FROM lyrics1");
while (rs.next()){
System.out.println(rs.getString(1));
}
statement.execute();
rs.close();
statement.close();
connection.close();
i++;
} catch (SQLException insertException) {
displaySQLError(insertException);
}
The error is:
SQLException: No value specified for parameter 1 SQLState: 07001 VendorError: 0
If your primary key is AUTO_INCREMENT, which it sounds like it is, you do not pass it with the INSERT statement, it is handled automatically for you. This would be what you want to do:
INSERT INTO lyrics1(name, artist)
VALUES(?, ?)
(This assumes your primary key isn't AUTO_INCREMENT and that you're passing it for a reason.)
I think you have a simple typo:
statement.setLong(i, i);
should probably be
statement.setLong(1, i);
// ^-- 1, not i
Being an old fuddy-duddy, I'd also probably move that statement above the other two so you're doing them in order.
If you have auto_increment in primary key:
String query = "INSERT INTO lyrics1(name, artist) values(?, ?)";
Don't forget to add the quotes when inserting a TEXT or VARCHAR value, like "INSERT INTO lyrics1(lyrics1_id, name, artist) VALUES ("id","name","artist").
Also, if the key is auto-incremental, do not pass it, the SQL will do it by itself. The query should then be "INSERT INTO lyrics1(name, artist) VALUES ("name","artist")."
As far as I know, you should have a ; in the string at the end like so:
String query = "INSERT INTO lyrics1(lyrics1_id, name, artist) values(?, ?, ?)";
however, it may work anyway.
You have a typo on the line you setting a value for primary key:
statement.setLong(i, i);
Here, did you see the first argument, it is i instead of 1. So it has to be changed to
statement.setLong(1, i);
But, if you ran the program for a second time, if the value of your i is initialized to a constant, you will get a primary key violation exception. Since, you are using MySQL, and if you used AUTO_INCREMENT for primary key column, then you can avoid that field in INSERT query. MySQL will automatically assign a value for the field. So you may use something like this:
INSERT INTO lyrics1(name, artist) values(?, ?)

Categories