I've encountered a strange problem. I've got a table, where I want insert data to from java servlet.
The table consits of 3 fields - id - serial (auto inc), name - text, path - text.
So, when I try to insert data with this code:
PreparedStatement statement = null;
ResultSet rs = null;
statement = context.getDBConnection().prepareStatement("INSERT INTO systems (name, path) VALUES ('" + request.getParameter("system_name") + "','" + request.getParameter("system_path") + "')");
rs = statement.executeQuery();
rs.close();
Nothing happens then. Respone from postresql is "No results were returned by the query" BUT when I insert rows manualy through pgAdmin, their id evaulated like the rows were inserted. For example, I've manualy inserted row, so it got id = 1. Then, after a couple of tries to insert data through servlet, I try to insert data manualy again, and row id is 4, not 2.
UPDATE
Modified code, now getting no error, but nothing happens.
PreparedStatement statement = null;
// ResultSet rs = null;
statement = context.getDBConnection().prepareStatement("INSERT INTO systems (system_name, folder_path) VALUES (?,?)");
statement.setString(1, request.getParameter("system_name"));
statement.setString(2, request.getParameter("system_path"));
int i = statement.executeUpdate();
Related
I am working with Microsoft SQL Server in my project and I am using JDBC as connector. My project runs within Tomcat Server. What I am trying to do is gettiing primary key of a newly inserted value without writing one more select statement.
Here is my java code:
PreparedStatement ps = conn.prepareStatement("INSERT INTO Users(FIRSTNAME,STATUS)VALUES " +
"(?,?)", Statement.RETURN_GENERATED_KEYS);
ps.setString(1, "name");
ps.setInt(2, status);
int updatedRows = ps.executeUpdate();
if(updatedRows > 0){
ResultSet resultSet = ps.getGeneratedKeys();
if (resultSet.next()) {
// do some stuff with resultSet.getInt(1)
// but code does not enter here
}
}
But code does not enter the inner if clause statement as I mentioned in my comment. I also tried this:
PreparedStatement ps = conn.prepareStatement("INSERT INTO Users(FIRSTNAME,STATUS)VALUES " +
"(?,?)", new String[]{"USERID"});
Here USERID is name of the primary key of Users table. Both method did not worked. How can I solve this?
try this:
INSERT INTO Users(FIRSTNAME,STATUS) OUTPUT Inserted.ID VALUES (?,?)
Here is the code for my servlet which recieves username parameter from a registration form
String tusername=request.getParamater("un");
String dbURL="db.com";
String dbusername= "lc";
String dbpassword="lcpw";
Connection con=(Connection) DriverManager.getConnection(dbURL,dbusername,dbpassword);
Statement stmt= con.createStatement();
String query="SELECT * FROM users.username WHERE username=(tusername)";
ResultSet rs= stmt.executeQuery(query);
if(rs.next()==false){
//create new userobject with value of tusername
}
My question is how do I create a new user object with calue of tusername, would it be like so ?
if(rs.next()==false){
Statement stmt=con.createStatament();
String query="INSERT INTO user.username VALUE 'tusername'";
ResultSet rs= stmt.updateQuery(query);
}
I understand some of this might be archaic (such as not using a prepared statement) , I am just trying to better my understanding and I think I am having some small syntax issues, thanks :)
You should be using a NOT EXISTS query to do the insert, and also you should ideally be using a prepared statement:
String sql = "INSERT INTO user.username (username) ";
sql += "SELECT ? FROM dual WHERE NOT EXISTS (SELECT 1 FROM user.username WHERE username = ?)";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, tusername);
ps.setString(2, tusername);
int result = ps.executeUpdate();
if (result > 0) {
System.out.println("Inserted new user " + tusername + " into username table";
}
else {
System.out.println("User " + tusername + " already exists; no new record was inserted");
}
I don't know what your actual database is. The above should work out of the box for MySQL and Oracle. It might need to be modified slightly for other databases.
An alternative to the above query would be to just use your current insert, but make the username column a (unique) primary key. In that case, any attempt to insert a duplicate would fail at the database level, probably resulting in an exception in your Java code. This would also be a more database agnostic approach.
I have a derby users database which I query, when the user clicks login on the application.
However, when I query the users table with the parameter [user] derby returns a null Object instead of the record it ought to return.
Here is my code:
String ssql = "SELECT * FROM USERS WHERE UNAME LIKE ?";
try{
DriverManager.registerDriver(new org.apache.derby.jdbc.EmbeddedDriver());
con = DriverManager.getConnection(url);
sql = con.prepareStatement(ssql, Statement.RETURN_GENERATED_KEYS);
sql.setString(1, cbox_chooseUser.getSelectedItem().toString());
sql.executeQuery();
ResultSet rs = sql.getGeneratedKeys();
try{
while (rs.next()) {
if(rs.getString("PW").toCharArray().equals(txt_password.getPassword())){
sql.close();
con.close();
return true;
}
} catch (NPE ...) {...}
}
I tried it multiple times wit a test user with both the pw and the username set to "test"; but I always get the same error.
Why is the recordset always Null?
Thanks for your help :)
The documentation says
ResultSet getGeneratedKeys() throws SQLException
Retrieves any auto-generated keys created as a result of executing this Statement
object.
If this Statement object did not generate any keys, an empty
ResultSet object is returned.
Your select statement isn't generating any keys that's why it's returning an empty ResultSet. You aren't inserting anything hence no keys are being generated.
You can try ResultSet rs = sql.executeQuery();. It should work.
You are using it in wrong way.
The generated keys concept should be used only in the case DML of insert type query but not in the case of select query.
select simply select the rows from the table. In this case there is no chance of any keys getting generated.
In the case of insert query if any column is configured as auto increment or kind of functionality then some keys will get generated. These keys can be caught using Statement.RETURN_GENERATED_KEYS in java.
As you are using select query there is no need of using Statement.RETURN_GENERATED_KEYS.
You just modify below lines and everything will be fine.
sql = con.prepareStatement(ssql, Statement.RETURN_GENERATED_KEYS);
sql.setString(1, cbox_chooseUser.getSelectedItem().toString());
sql.executeQuery();
ResultSet rs = sql.getGeneratedKeys();
with
sql = con.prepareStatement( ssql );
sql.setString( 1, cbox_chooseUser.getSelectedItem().toString() );
ResultSet rs = sql.executeQuery();
I have a H2 database named PRODUCTS, with 5000 rows and 55 columns per row. I'm currently using a PreparedStatement to add rows of values to the database, but it does not check whether the row exists already. Instead, I need to only insert the row if the column name "id" (type VARCHAR) does not contain a certain alpha-numeric string, and if the column name "id2" (type VARCHAR) does not a certain alpha-numeric string, and if the column name "raw_yn" (type BOOLEAN) contains false. The values I enter into the prepared statement are provided via a method.
The question here is very close to what I'm asking, with the difference being the fact that it's solution is based on adding rows to an empty DB, and ensures the database is empty. The creator of H2 commented saying:
Then the "where not exists" ensures this rows are only inserted if the
table [TABLE] is empty.
How do I adapt this code so that it only performs the INSERT query if my above 3 requirements are met (whether or not DB is empty)?
Currently I have:
import java.sql. *;
static final String JDBC_DRIVER = "org.h2.Driver";
static final String DB_URL = "jdbc:h2:~/myDB";
static final String USER = "test";
static final String PASS = "test";
static final Connection conn = null;
static final Statement stmt = null;
public class DataBaseManager {
public void insertIntoDB(String id1val, String id2val, Boolean raw_yn_val, ...,...) {
try {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USER, PASS);
myStatement = "INSERT INTO PRODUCTS VALUES(?,?,?,..,...)";
stmt = conn.prepareStatement(myStatement);
stmt.setString(1, id1val);
stmt.setString(2, id2val);
stmt.setBoolean(3, raw_yn_val);
stmt.setString(4,....);
// Continue up to 55
stmt.executeUpdate();
}
[catch&finally blocks]
}
}
What should myStatement be changed to? I'm confused because if I use select 0, 'id1' union like below, how does that fit into my PreparedStatement of stmt.setString(1, id1val); ??. Thanks for your help.
INSERT INTO PRODUCTS SELECT * FROM(
select 0, 'id1' union // <--- How does this fit into Prepared Statement?
select 1, 'id2' union
select 2, 'raw_yn' union
) x where not exists(SELECT * FROM PRODUCTS); // <--- Ensures only works when empty
UPDATE:
Following Gord's suggestion, I've put together the following code. If the database is empty, n will return 0. This takes about 1 minute to add 5000 rows to the empty database. However, if there IS a match, it's taking nearly 5x longer, even though I'm merely using return as opposed to using additional INSERT code. So shouldn't it be faster?
try {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USER, PASS);
statement = conn.createStatement();
String sql = "SELECT COUNT(*) AS n FROM PROPERTIES WHERE id1='" + id1 + "' AND id2='" + id2 + "' AND raw_yn='true'";
rs = statement.executeQuery(sql);
rs.next();
if (rs.getInt("n") == 0) {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USER, PASS);
myStatement = "INSERT INTO PROPERTIES VALUES(?,?,?,...)";
stmt = conn.prepareStatement(myStatement);
stmt.setString(1, id1);
stmt.setString(2, id2);
stmt.setBoolean(3, raw_yn);
stmt.executeUpdate();
} else {
return; // <-- Takes 5x longer to go through ???
}
}
[catch & finally blocks]
Consider using a staging temp table where you append all data as is into a similar structured table, ProductsTemp, and then migrate to final table, Products, filtered for the unique rows. Below are the SQL statements to incorporate in your Java code in this order:
Staging Append (two statements)
DELETE FROM ProductsTemp;
INSERT INTO ProductsTemp VALUES (?,?,?,..,...);
Final Migration
INSERT INTO Products (id, id2, raw_yn, ...)
SELECT id, id2, raw_yn, ...
FROM ProductsTemp temp
WHERE NOT EXISTS (SELECT 1 FROM Products sub
WHERE sub.id = temp.id
AND sub.id2 = temp.id2
AND sub.raw_yn = temp.raw_yn);
I am using oracle sequence for inserting log id into tableA as follows,
String SQL_PREP_INSERT = "INSERT INTO tableA (LOG_ID,USER_ID,EXEC_TIME) VALUES"
+ " (logid_seq.nextval, ?, ?)";
Then getting the recently inserted value,
String SQL_PREP_SEL = "SELECT max(LOG_ID) FROM tableA ";
stmt = con.prepareStatement(SQL_PREP_SEL);
stmt.execute();
ResultSet rs = stmt.getResultSet();
if (rs.next()) {
logid = rs.getInt(1);
}
And inserting it into tableB,
String SQL_PREP_INSERT_DETAIL = "INSERT INTO tableB (LOG_ID, RESPONSE_CODE, RESPONSE_MSG) VALUES"
+ " (?, ?)";
stmt = con.prepareStatement(SQL_PREP_INSERT_DETAIL);
stmt.setInt(1, logid);
stmt.setString(2, respCode);
stmt.setString(3, respMsg);
stmt.execute();
Is there a way to generate sequence in Java instead of Oracle and insert into both tables at once, instead of selecting from tableA and inserting into tableB?
In general, selecting the MAX(log_id) is not going to give you the same value that logid_seq.nextval provided. Assuming that this is a multi-user system, some other user could have inserted another row with a larger log_id value than the row you just inserted before your query is executed.
Assuming that both INSERT statements are run in the same session, the simplest option is probably to use the logid_seq.currval in the second INSERT statement. currval will return the last value of the sequence that was returned to the current session so it will always return the same value that was generated by the nextval call in the first statement.
INSERT INTO tableB (LOG_ID, RESPONSE_CODE, RESPONSE_MSG)
VALUES( logid_seq.currval, ?, ? )
Alternatively, you could use the RETURNING clause in your first statement to fetch the sequence value into a local variable and use that in the second INSERT statement. But that is probably more work than simply using the currval.
String QUERY = "INSERT INTO students "+
" VALUES (student_seq.NEXTVAL,"+
" 'Harry', 'harry#hogwarts.edu', '31-July-1980')";
// load oracle driver
Class.forName("oracle.jdbc.driver.OracleDriver");
// get database connection from connection string
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:sample", "scott", "tiger");
// prepare statement to execute insert query
// note the 2nd argument passed to prepareStatement() method
// pass name of primary key column, in this case student_id is
// generated from sequence
PreparedStatement ps = connection.prepareStatement(QUERY,
new String[] { "student_id" });
// local variable to hold auto generated student id
Long studentId = null;
// execute the insert statement, if success get the primary key value
if (ps.executeUpdate() > 0) {
// getGeneratedKeys() returns result set of keys that were auto
// generated
// in our case student_id column
ResultSet generatedKeys = ps.getGeneratedKeys();
// if resultset has data, get the primary key value
// of last inserted record
if (null != generatedKeys && generatedKeys.next()) {
// voila! we got student id which was generated from sequence
studentId = generatedKeys.getLong(1);
}
}