I want to make a function in java that executes two queries, in which I want to do this:
Example:
String s ="CREATE TABLE ClassRoom(ID int AUTO_INCREMENT PK ,
name char (2) not null,
section char (2) not null,
numberSt int not null,
)";
String s1 ="INSERT INTO ClassRoom VALUES (null,'5','A',25)";
pst = conn.prepareStatement(s);
pst.executeUpdate();
pst = conn.prepareStatement(s1);
pst.executeUpdate();
I want to put some values in the table when I create the table.
The first time it works perfectly, but the second time s is not called as there is IF NOT EXISTS, but the s1 is called again another time.
I want the s1 to be called only if the s has been executed or the table has been created. IF the table already exists i don't want to call s1 query.
Depending on your SQL database the easiest way will be to use an upsert. This inserts the data already if it doesn't exist, updating otherwise. You would need to remove the generated key and use a compound key from whatever values uniquely identify the room though.
You can check if the table exists with the following query:
SELECT *
FROM information_schema.tables
WHERE table_schema = 'yourdb'
AND table_name = 'ClassRoom'
LIMIT 1;
You have to test if the table has been created.
boolean existsTable = false;
// use significative variable names... always!
String createQuery =
"CREATE TABLE ClassRoom( " +
"ID int AUTO_INCREMENT PK, " +
"name char (2) not null, " +
"section char (2) not null, " +
"numberSt int not null, " +
")";
String defaultValuesQuery ="INSERT INTO ClassRoom VALUES (null,'5','A',25)";
String checkTableQuery = "SELECT * " +
"FROM information_schema.tables " +
"WHERE table_schema = 'yourdb' " +
"AND table_name = 'ClassRoom' " +
"LIMIT 1;";
PreparedStatement pst = conn.prepareStatement(checkTableQuery);
ResultSet rs = pst.executeQuery();
// if the check query returns some value then table exists!
if (rs.next()) {
existsTable = true;
// if table don't exists, create it
} else {
pst = conn.prepareStatement(createQuery);
pst.executeUpdate();
}
// execute query only if table exists
if (existsTable) {
pst = conn.prepareStatement(defaultValuesQuery);
pst.executeUpdate();
}
Related
I'm working with a MySQL-Server and I'm trying to select an ID from another table and insert that ID in a table but it doesn't work all the time.
Code:
public void submit() throws Exception {
Connection connection = getConnection();
Statement stmt = connection.createStatement();
Statement stmt1 = connection.createStatement();
ResultSet asset_id = stmt.executeQuery("SELECT id FROM cars.asset_type WHERE asset_type.name =" + "'" + sellables.getValue()+ "'");
while (asset_id.next()) {
System.out.println(asset_id.getInt("id"));
}
double value = parseDouble(purchased.getText());
System.out.println(value);
LocalDate localDate = purchased_at.getValue();
String insert = "INSERT INTO asset (type_id, purchase_price, purchased_at) VALUES ('"+ asset_id + "','" + value +"','" + localDate +"')";
stmt1.executeUpdate(insert);
}
I keep getting the same error message.
Caused by: java.sql.SQLException: Incorrect integer value: 'com.mysql.cj.jdbc.result.ResultSetImpl#1779d92' for column 'type_id' at row 1
There's no value in doing two client/server roundtrips in your case, so use a single statement instead:
INSERT INTO asset (type_id, purchase_price, purchased_at)
SELECT id, ?, ?
FROM cars.asset_type
WHERE asset_type.name = ?
If you really want to insert only the last ID from your SELECT query (as you were iterating the SELECT result and throwing away all the other IDs), then use this query instead:
INSERT INTO asset (type_id, purchase_price, purchased_at)
SELECT id, ?, ?
FROM cars.asset_type
WHERE asset_type.name = ?
ORDER BY id DESC -- I guess? Specify your preferred ordering here
LIMIT 1
Or with the JDBC code around it:
try (PreparedStatement s = connection.prepareStatement(
"INSERT INTO asset (type_id, purchase_price, purchased_at) " +
"SELECT id, ?, ? " +
"FROM cars.asset_type " +
"WHERE asset_type.name = ?")) {
s.setDouble(1, parseDouble(purchased.getText()));
s.setDate(2, Date.valueOf(purchased_at.getValue()));
s.setString(3, sellables.getValue());
}
This is using a PreparedStatement, which will prevent SQL injection and syntax errors like the one you're getting. At this point, I really really recommend you read about these topics!
I have used this method without using the join in the query and it was working as expected. But I added a inner join and now it can't update the "used" column
public HashMap<String, Comparable> getPhoneNumberAndMarkAsUsed() {
String[] colNames = { "phone_number.id", "phone_number.phone_number",
"phone_number.account_id", "phone_number.used AS used",
"(now() AT TIME ZONE account.timezone)::time AS local_time" };
String query = "select " + Stream.of(colNames).collect(Collectors.joining(", "))
+ " from account INNER JOIN phone_number ON account.id = phone_number.account_id where phone_number.used = false order by id DESC limit 1 for update";
HashMap<String, Comparable> account = new HashMap<String, Comparable>();
try (Connection conn = DriverManager.getConnection(url, props); // Make sure conn.setAutoCommit(false);
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(query)) {
conn.setAutoCommit(false);
ResultSetMetaData rsmd = rs.getMetaData();
int columnsNumber = rsmd.getColumnCount();
while (rs.next()) {
for (int i = 1; i <= columnsNumber; i++) {
if (i > 1)
System.out.print(", ");
String columnValue = rs.getString(i);
System.out.print(columnValue + " " + rsmd.getColumnName(i));
}
// Get the current values, if you need them.
account.put("phone_number", rs.getString("phone_number"));
account.put("account_id", rs.getLong("account_id"));
rs.updateBoolean("used", true);
rs.updateRow();
}
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
return account;
}
the loop prints the following
7223 id, 10001234567 phone_number, 1093629 account_id, f used, 23:32:42.502472 local_time
accourding to the output above, then I am use that column "used" is part of the ResultSet. But I get the following Exception
org.postgresql.util.PSQLException: ERROR: column "used" of relation "account" does not exist
This is the query when printed
select phone_number.id, phone_number.phone_number, phone_number.account_id, phone_number.used AS used, (now() AT TIME ZONE account.timezone)::time AS local_time from account INNER JOIN phone_number ON account.id = phone_number.account_id where phone_number.used = false order by id DESC limit 1 for update
used belongs to the phone_number table not the account table. How can this be resolved?
here is the problem in your code:
rs.updateBoolean("used", true);
this statement will try to update the data of table through resultset but to do that you cannot user join and also there is one problem.
As you are updating via resultset it will try to update account table and if we find used column is account table then error occurs.
so your code is trying to find column "used" in account table but it is not there.
try this one:
String query = "select " + Stream.of(colNames).collect(Collectors.joining(", "))
+ " from phone_number INNER JOIN account phone_number ON account.id = phone_number.account_id where phone_number.used = false order by id DESC limit 1 for update";
rs is always true even when table employee is not present in servlet Database, want to create table only when table is not present in database
and what will SELECT count(*)FROM INFORMATION_SCHEMA.TABLES WHERE(TABLE_SCHEMA = 'servlet') AND (TABLE_NAME = 'employee')"
will return when executed with PreparedStement and result stored in resultSet when table is not there and when table is there for both the cases
public class Table {
public static void main(String[] args)
{
Connection con=null;
PreparedStatement pstmt=null;
PreparedStatement pstmt1=null;
PreparedStatement pstmt2=null;
ResultSet rs=null;
String qry="SELECT count(*)FROM INFORMATION_SCHEMA.TABLES WHERE(TABLE_SCHEMA = 'servlet') AND (TABLE_NAME = 'employee')";
String qry1="CREATE TABLE servlet.Employee (" +
" ID INT(6) NOT NULL AUTO_INCREMENT, " +
" NAME VARCHAR(50) NOT NULL, " +
" Department varchar(20) NOT NULL, " +
" Salary DECIMAL(8,2) NOT NULL, " +
" PRIMARY KEY (ID))";
String qry2="insert into servlet.Employee values(?,?,?,?)";
Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection("jdbc:mysql://localhost:3306?user=root&password=passworD");
pstmt=con.prepareStatement(qry);
rs=pstmt.executeQuery();
System.out.println(rs.next());
if(true==!rs.next()){
pstmt1=con.prepareStatement(qry1);
pstmt1.executeUpdate();
pstmt2=con.prepareStatement(qry2);
pstmt2.setInt(1,id);
pstmt2.setString(2, name);
pstmt2.setString(3, dept);
pstmt2.setDouble(4, salary);
pstmt2.executeUpdate();
}
else{
pstmt2=con.prepareStatement(qry2);
pstmt2.setInt(1,id);
pstmt2.setString(2, name);
pstmt2.setString(3, dept);
pstmt2.setDouble(4, salary);
pstmt2.executeUpdate();
}
}
}
If the table exists the value will be 1 else will be 0. So a record always exists. As the documentation says:
ResultSet.next: Moves the cursor forward one row. Returns true if the cursor is now positioned on a row and false if the cursor is positioned after the last row.
rs.next will always return true since there it position the cursor on the first record in your case. You need to process the logic based on the value of count(*). You do not need the else clause since you are not doing something vary different.
if(rs.next())
int count = rs.getInt(1);
if (count == 0) {
pstmt1=con.prepareStatement(qry1);
pstmt1.executeUpdate();
}
pstmt2=con.prepareStatement(qry2);
pstmt2.setInt(1,id);
pstmt2.setString(2, name);
pstmt2.setString(3, dept);
pstmt2.setDouble(4, salary);
pstmt2.executeUpdate();
}
I am starting now to use the package java.sql and I am doing some experiments with it.
I have these two tables
the first is:
`user` (
`userID` INT NOT NULL AUTO_INCREMENT ,
`nickname` VARCHAR(20) NULL ,
PRIMARY KEY (`userID`) )
and the second is:
`club` (
`clubID` INT NOT NULL AUTO_INCREMENT ,
'clubName` VARCHAR(20) NOT NULL ,
`userID` INT NULL ,
PRIMARY KEY (`clubID`) ,...
where userID is a foreign key associated to the userID of the first table.
And this is the code that should explain what I want to do. (this is only for one user-club)
Class.forName("com.mysql.jdbc.Driver");
this.connect = DriverManager.getConnection("jdbc:mysql://localhost/" + this.database + "?user=" + this.user + "&password=" + this.password);
String s;
s = ("insert into " + this.database + ".user (nickname) values (?)");
this.preparedStatement = this.connect.prepareStatement(s);
this.preparedStatement.setString(1, "username");
this.preparedStatement.executeUpdate();
s = ("SELECT userID from " + this.database + ".user where nickname = 'username'");
this.preparedStatement = this.connect.prepareStatement(s);
this.resultSet = this.preparedStatement.executeQuery();
int n=0;
while (resultSet.next())
{
n = this.resultSet.getInt("userID");
}
s = ("insert into " + this.database + ".club (clubName, userID) values (?, ?)");
this.preparedStatement = this.connect.prepareStatement(s);
this.preparedStatement.setString(1, "club");
this.preparedStatement.setInt(2, n);
this.preparedStatement.executeUpdate();
If I would do this process for more couples (username, clubname), for example saved in an HashMap how could I use the addBatch() method of preparedStatement Inteface??
I should use three batches one for eache action:
1 insertion of username
2 selection (and recording) of userID
3 insertion of clubname associated to the correct userID
Or I could include all the process in only one batch??
And another question, why If i try to remove the while cycle surrounding the resultSet.getInt() method it gives me an error??
Thanks in advance to all who will try to help me!
You cannot include all the process in only one batch. The batch is intended for a single query. Here is the reference link for a good example.
You can execute multiple queries as different batches as follows .
try {
DataSource dataSource = null;// specify data source
Connection con = dataSource.getConnection();
Statement s = con.createStatement();
// or
// PreparedStatement s =
// con.prepareStatement("INSERT INTO profile (fullname) VALUES ('Visruth CV')");
s.addBatch("INSERT INTO tran1 (username, password, profileid) VALUES ('visruth', 'password', 1)");
s.addBatch("INSERT INTO testtab (name) VALUES ('testtab')");
s.executeBatch();
} catch (SQLException e) {
e.printStackTrace();
}
If you remove the while (resultSet.next()) loop, it will make a NullPointerException because the current position of the cursor in the resultSet is in the default row, when you make resultSet.next() the cursor will jump in to the next row if there is a row available (from the default row to first row, first row to second row etc...) and at the same time resultSet.next() will return true (only if it jumps) otherwise false. If resultSet contains more than one row, it can be put inside a while loop, if not just need to use the if condition there.
Through the following snippet, I am trying to run a query that either updates the data or inserts a new data into the table named JustPinged. The table contains a column named NodesThatJustPinged and LastPingedAt. If there is already a node in NodesThatJustPinged then the time in milliseconds in LastPingedAt is updated. Otherwise a new node information is inserted.
The problem is, that the following snippet is unable to insert the data into the database's table. The reason is the statement:
boolean duplicateExists = searchToEliminateDuplicates.execute();
returns true to start with. (Initially the table is empty) Why does this statement return true? According to the documentation it returns true if the first result is a ResultSet object; false if the first result is an update count or there is no result. So here the boolean should contain a false value. But it contains a true value and thus the if statement always works. (And in if section,update query works when there is nothing to update !)
String searchQuery = "select NodesThatJustPinged from JustPinged where NodesThatJustPinged = '" + nodeInfo + "'";
PreparedStatement searchToEliminateDuplicates = connection.prepareStatement(searchQuery);
boolean duplicateExists = searchToEliminateDuplicates.execute();
if(duplicateExists) {
// update the LastPingedAt column in the JustPinged table
String updateQuery = "update JustPinged set LastPingedAt='" + pingedAt + "' where NodesThatJustPinged = '" + nodeInfo + "'";
PreparedStatement updateStatement = connection.prepareStatement(updateQuery);
updateStatement.executeUpdate();System.out.println("If statement");
} else {
// make a new entry into the database
String newInsertionQuery = "insert into JustPinged values('" + nodeInfo + "','" + pingedAt + "')";
PreparedStatement insertionStatement = connection.prepareStatement(newInsertionQuery);
insertionStatement.executeUpdate();System.out.println("else statement");
}
So how should I edit the code, so that duplicate values are updated and new values are inserted?
Your searchQuery will return ResultSet. hence the execute method returns 'true'. Try using executeQuery instead.
So your code would become:
String searchQuery = "select NodesThatJustPinged from JustPinged where NodesThatJustPinged = '" + nodeInfo + "'";
Statement searchToEliminateDuplicates = connection.createStatement();
ResultSet duplicateExists = searchToEliminateDuplicates.executeQuery(searchQuery);
if(duplicateExists.next()) {
// update the LastPingedAt column in the JustPinged table
String updateQuery = "update JustPinged set LastPingedAt='" + pingedAt + "' where NodesThatJustPinged = '" + nodeInfo + "'";
PreparedStatement updateStatement = connection.prepareStatement(updateQuery);
updateStatement.executeUpdate();System.out.println("If statement");
} else {
// make a new entry into the database
String newInsertionQuery = "insert into JustPinged values('" + nodeInfo + "','" + pingedAt + "')";
PreparedStatement insertionStatement = connection.prepareStatement(newInsertionQuery);
insertionStatement.executeUpdate();System.out.println("else statement");
}
P.S. If you are using PreparedStatement, then use parameters in your query and call ps.setString etc.
PPS. Don't use execute() method. Use executeQuery or executeUpdate. execute() is used where you don't know in advance whether your query is INSERT or UPDATE.
PPPS Close your resultset and statements as soon as you are done with them.
PPPPS A more better approach is to use count aggregate function in your SQL statement i.e.
select count(NodesThatJustPinged) from JustPinged where NodesThatJustPinged = '" + nodeInfo + "'";
Now you can check whether count is 0 or greater than 1 and branch your code accordingly.
A SELECT statement that returns zero rows will still return a ResultSet -- just one that immediately returns false when calling next(). You need to check the number of rows in the returned ResultSet.