Using select inside insert query with preparedStatement - java

I want to write an insert query using preparedStatement. Inside it I want to put a selection query. I did the following but I get: You have an error in your SQL syntax
protected final String createStudentQuery = " INSERT INTO student (student_id, ed_level) VALUES (SELECT MAX(user_id) FROM user WHERE usertype ='Student' , ?)";
and then
stmt5 = conn.prepareStatement(createStudentQuery);
stmt5.setString(1, ed_level);
stmt5.executeUpdate();
All the declarations(connection, statement) have been made.

There are 2 values that needs to be inserted, student_id and ed_level . But in your select statement there is only one value, MAX(user_id). You have to also add the value for ed_level in the select query.
Also, your query should be:
INSERT INTO <TABLE_1> (COLUMN_1, COLUMN_2,...) SELECT COLUMN_1, COLUMN_2,... FROM <TABLE_2> WHERE <CONDITION>
I have modified the query to something like this:
INSERT INTO student (student_id, ed_level) VALUES ((SELECT MAX(user_id) FROM user WHERE usertype ='Student') , ?)
Hope this helps.

Related

Create table as select with parameter using jdbcTemplate

I want to use jdbcTemplate to create table based on another table under condition. I have postgres database. When I execute this and pass parameter:
String SQL = "create table test as (select * from users where countryId =?)";
jdbcTemplate.update(SQL, new Object[] {3})
I receive table test with all columns from users table but with no rows.
However, when I execute this:
String SQL = "create table test as (select * from users where countryId =3)";
jdbcTemplate.update(SQL)
I receive test table with rows where countryId = 3, so that is what I was expecting to receive in the first solution.
Your passing of the bind variable is not correct, but it does not play any role.
You simple can not use a bind variable in a data definition statement as you immediately see in the triggered error
Caught: org.springframework.jdbc.UncategorizedSQLException:
PreparedStatementCallback; uncategorized SQLException for SQL
[create table test as (select * from users where countryId =?)];
SQL state [72000]; error code [1027];
ORA-01027: bind variables not allowed for data definition operations
So you have two options, either concatenate the statement (which is not recommended due to the danger of SQL injection)
or split the statement in two parts:
// create empty table
sql = "create table test as (select * from users where 1 = 0)";
jdbcTemplate.update(sql)
// insert data
sql = "insert into test(countryId, name) select countryId, name from users where countryId =?";
updCnt = jdbcTemplate.update(sql, new SqlParameterValue(Types.INTEGER,3));
Note that in the insert statement you can see the correct way of passing an interger value of 3 as a bind variable.
You can follow below approach as well:-
jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS employee_tmp (id INT NOT NULL)");
List<Object[]> employeeIds = new ArrayList<>();
for (Integer id : ids) {
employeeIds.add(new Object[] { id });
}
jdbcTemplate.batchUpdate("INSERT INTO employee_tmp VALUES(?)", employeeIds);
Here you may query with 2 operations to avoid SQL injection.
You are using method update from jdbcTemplate in a wrong way.
Try with this:
String SQL = "create table test as (select * from users where countryId = ?)";
jdbcTemplate.update(SQL, 3);

select scope_identity() using createSQLQuery in Hibernate

I am forced to use createSQLQuery to insert values into tables with an Identity column (the first column and the primary key) using hibernate. Using hibernate classes are not an option since the tables are created on the fly for each customer that is added to the system. I have run the query and it successfully inserts into the table. I then execute a "select scope_identity()" and it always returns null. "select ##Identity" works but that is not guaranteed to be the correct one. I have also tried to append "select scope_identity()" to the insert query. Then I tried query.list() and query.uniqueResult() both of which throw the hibernate exception of "No Results ..."
Session session = DatabaseEngine.getSessionFactory().openSession();
String queryString = "insert into table1 (dataid) values (1)"
SQLQuery query = session.createSQLQuery(insertQueryString);
query.executeUpdate();
query = session.createSQLQuery("select scope_identity()");
BigDecimal entryID = (BigDecimal)query.uniqueResult();
The simple example table is defined as follows:
"CREATE TABLE table1 (EntryID int identity(1,1) NOT NULL," +
"DataID int default 0 NOT NULL, " +
"PRIMARY KEY (EntryID))";
Is there a way I am missing to use scope_identity() with createSQLQuery?
Actually the SQLServerDialect class used by Hibernate uses the same "scope_identity()" too.
The reason why it's not working is because you need to execute those in the same statement or stored procedure.
If you execute the scope_identity() call in a separate statement, SQL Server will not be able to give you last inserted identity value.
You cannot do it with the SQLQuery, even Hibernate uses JDBC to accomplish this task. I wrote a test on GitHub to emulate this and it works like this:
Session session = entityManager.unwrap(Session.class);
final AtomicLong resultHolder = new AtomicLong();
session.doWork(connection -> {
try(PreparedStatement statement = connection.prepareStatement("INSERT INTO post VALUES (?) select scope_identity() ") ) {
statement.setString(1, "abc");
if ( !statement.execute() ) {
while ( !statement.getMoreResults() && statement.getUpdateCount() != -1 ) {
// do nothing until we hit the resultset
}
}
try (ResultSet rs = statement.getResultSet()) {
if(rs.next()) {
resultHolder.set(rs.getLong(1));
}
}
}
});
assertNotNull(resultHolder.get());
The code uses Java 8 lambdas instead of anonymous classes, but you can easily port it to Java 1.7 too.

JDBC query RETURNING value

I have a problem trying to figure out how to get the id of the last inserted row using PostgreSQL and JDBC.
CREATE TABLE vet_care (
id serial PRIMARY KEY,
deworming int,
castration int
);
My query is
String insertVetCare = "INSERT INTO vet_care(castration,deworming) VALUES("+castrated+","+dewormed+") RETURNING id";
I want the id value (which is serial) for later use. I tried to execute the query like so:
int id = statement.executeUpdate(insertVetCare);
But this says after compilation, that "A result was returned when none was expected." and it does not insert the other values into table.
How can I get this to work?
If "id" means "generated identity key", then you've got it wrong.
The executeUpdate() method returns the number of affected rows, according to the javadocs.
You want it to return auto generated keys, like this.
More advice: Use PreparedStatement and bind values. Building up a SQL query that way is asking for a SQL injection attack.
// Why make the gc work? This query never changes.
private static final String INSERT_VET_CARE = "INSERT INTO vet_care(castration,deworming) VALUES(?, ?)";
PreparedStatement ps = connection.prepareStatement(INSERT_VET_CARE, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, castration);
ps.setInt(2, deworming);

Insert data to mysql database if not exist

I'm using java and I want to insert to mysql database a data if not exist, Also I want to update that data if exist. but I couldn't find mysql command for this.
I found this code for Insert but this is not what I want
INSERT INTO contacts
(contact_id, contact_name)
SELECT supplier_id, supplier_name
FROM suppliers
WHERE EXISTS (SELECT *
FROM orders
WHERE suppliers.supplier_id = orders.supplier_id);
For update, I found this code. but this is not what I want.
UPDATE suppliers
SET supplier_name = (SELECT customers.customer_name
FROM customers
WHERE customers.customer_id = suppliers.supplier_id)
WHERE EXISTS (SELECT *
FROM customers
WHERE customers.customer_id = suppliers.supplier_id);
What I want to do is something like this
UPDATE student SET student_score = 20 where student_id = 1 WHERE EXIST ( select * from student where student_id = 1;
You can use:
insert into table_name (id, name, firstname) values(1, "Sessi", "Brahim") on duplicate key update name=values(name), firstname=values(firstname)
Adapt it to your query.

problem in setString method.in retrieving data from the table

i have two tables "Table1" with columns user_name,Password and course ID and another table "course" with columns course_id,course_name.I have used the following code to display the course ID from Table1 according to the user_name received from the login page.using ResultSet rs1.now i want to retrieve the course_name from the table "course" according to the course ID receieve from "Table1".for that in the second query pstmt2.setString(1, ); what parameter i should use to get the course_id value from the previous query
HttpSession sess=request.getSession();
String a=(String)sess.getAttribute("user");
String b=(String)sess.getAttribute("pass");
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con=DriverManager.getConnection("jdbc:odbc:ggg");
Statement st = con.createStatement();
String query="select * from Table1 where user_name=?";
PreparedStatement pstmt=con.prepareStatement(query);
pstmt.setString(1,a);
ResultSet rs1=pstmt.executeQuery();
while(rs1.next())
out.println("<h3>COURSE ID: "+rs1.getString("course ID")+"<h3>");
String query2="SELECT * from course where course_id=?";
PreparedStatement pstmt2=con.prepareStatement(query2);
pstmt2.setString(1,);
ResultSet rs2=pstmt2.executeQuery();
while(rs2.next())
{
out.println("<h3>course name: "+rs2.getString("course_name")+"<h3>");
}
why do you go for two turns of database hit, even though you created one time connection object.
modify the query as below
SELECT * from course where course_id = (select course_id from Table1 where user_name=?);
from this query you noneed to give input of courseid also.
No need to hit database twice to get the results that you need. use the query
Select table1.course_id, course.course_name from table1, course where table1.course_id=course_id and table1.user_name=?
This should set the course_id parameter:
pstmt2.setString(1,rs1.getString("course_id"));
Or, as I see the "course_id" column may have a different name in "Table1":
pstmt2.setString(1,rs1.getString("course ID"));
As the other post mentioned there's no need to go to another set of query. Try this example query:
SELECT course.course_id, course.course_name
FROM table1 t1
INNER JOIN course c
ON t1.course_id = c.course_id
WHERE t1.user_name = ?;
Now if you insist your coding the parameter o your pstmt2.setString(1,); is:
pstmt2.setString(1,rs1.getString("course_id")); //or course ID defending on your column name

Categories