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.
Related
I´ve created a table in SQL.
CREATE TABLE IF NOT EXISTS data (
id int NOT NULL AUTO_INCREMENT,
Username String,
Countdown double,
PRIMARY KEY(id)
)
Now I want to change the Countdown - field.
try {
final int i = 10; //my new var, which should saved in databank
PreparedStatement ps = connection.prepareStatement(""); //Dont know what to write in SQL here
ps.executeUpdate();
} catch(SQLException e) {
e.printStackTrace();
}
Example : Imagine my field with the field Username "example" has the Countdown 11 and now I want to change this value to 10.
If you want to use a prepared statement, you need to "prepare" your query first, then inject the values. More info here.
First, you need an UPDATE query.
String updateStatement =
"UPDATE data" +
"SET Countdown = ? " +
"WHERE Username = ?";
Then you can prepare your statement with:
PreparedStatement ps = connection.prepareStatement(updateStatement);
And add your values with:
ps.setInt(1, 11);
ps.setString(2, "example");
And you're ready to go!
ps.executeUpdate();
I'm working with my project just for a academic purposes where I encounter a SQL problem. Where the Foreign Key its not getting the value of inserted ID. For me to achieve 2nd Normal Form. I split out in an independent tables. And match them up using the SECTION_ID as foreign keys. Here where I create a two tables.
1st Table
2nd Table
SOURCE CODE:
String inputSectionName = Section_SectionName_TextField.getText();
int inputStudentLimit = Section_Student_Limit_ComboBox.getSelectedIndex();
String inputRoomAssign = Section_Student_Limit_ComboBox2.getSelectedItem().toString();
String inputAdviserAssign = Section_Student_Limit_ComboBox1.getSelectedItem().toString();
String inputSession = Section_Session_Settings_ComboBox.getSelectedItem().toString();
String inputYearLevel = Section_Session_Level_ComboBox.getSelectedItem().toString();
String inputSchoolYear = Section_SchooYear_ComboBox.getSelectedItem().toString();
String insertALLSECTION_LIST = "INSERT INTO ALLSECTIONS_LIST (SECTION_NAME)"
+ "VALUES (?)";
String insertALLSECTIONS_SETTINGS = "INSERT INTO ALLSECTIONS_SETTINGS (SECTION_POPULIMIT,ROOM_ASSGN,ADVISER_ASSIGNED,SESSION_ASSIGNED,YRLEVEL_ASSGN,SCHOOL_YEAR)"
+ "VALUES(?,?,?,?,?,?)";
try (Connection myConn = DBUtil.connect())//Connection
{
myConn.setAutoCommit(false);//Turn off auto commit
try (PreparedStatement myPs = myConn.prepareStatement(insertALLSECTION_LIST))//Prepared Statement
{
myPs.setString(1,inputSectionName);
myPs.executeUpdate();
myConn.commit();
}//end of try
try (PreparedStatement myPs = myConn.prepareStatement(insertALLSECTIONS_SETTINGS))//Prepared Statement
{
myPs.setInt(1,inputStudentLimit);
myPs.setString(2, inputRoomAssign);
myPs.setString(3, inputAdviserAssign);
myPs.setString(4, inputSession);
myPs.setString(5, inputYearLevel);
myPs.setString(6, inputSchoolYear);
myPs.executeUpdate();
myConn.commit();
JOptionPane.showMessageDialog(null, "Insert Successful");
}//end of try
}//end of try
catch(SQLException e)
{
DBUtil.processException(e);
}//end of catch
When I run my query for the 1st Table it gives me output like this.
But when I run my query for the 2nd Table the SECTION_ID column gives a me null value.
Feel free to comment. If I miss something guide me where I go wrong. Thanks.
It looks like you're assuming the SECTION_ID column in your ALLSECTIONS_SETTINGS table will be automatically populated with the last primary-key value that was inserted into the ALLSECTIONS_LIST table. This doesn't happen.
What you need to do instead is to get the value that was automatically generated for the SECTION_ID column in the first PreparedStatement and set it in the second PreparedStatement.
Here's how to modify your first PreparedStatement to obtain the generated SECTION_ID:
int sectionId;
try (PreparedStatement myPs = myConn.prepareStatement(insertALLSECTION_LIST, Statement.RETURN_GENERATED_KEYS))//Prepared Statement
{
myPs.setString(1,inputSectionName);
myPs.executeUpdate();
myConn.commit();
ResultSet generatedKeys = myPs.getGeneratedKeys();
if (generatedKeys.next()) {
sectionId = generatedKeys.getInt(1);
} else {
throw new SQLException("No generated section ID returned");
}
}
The changes are:
add a new variable sectionId to hold the generated section ID,
add Statement.RETURN_GENERATED_KEYS to the call to prepareStatement on the first line. This tells your database to return the generated value for SECTION_ID.
fetch the generated-keys result-set from the statement and read the section ID out of it..
I'll leave it up to you to modify your second PreparedStatement to set the value for the SECTION_ID column when you insert into ALLSECTIONS_SETTINGS.
I'm working with Java JDBC with Apache Derby data base.
I have a table called `company`` with the values :
id, comp_name, password, email.
This method should create a new row of company with name, password, and email received from the user but the ID should be given automatically from the database and increment itself each time a new company is added to the database.
I just can't figure out how to make this work, I obviously get a error
"column 'ID' cannot accept a NULL value."
because the update occours before the ID is setted.
Code:
public void createCompany(Company company) {
Connection con = null;
try {
con = ConnectionPool.getInstance().getConnection();
String sql = "INSERT INTO company (comp_name, password, email) VALUES (?,?,?)";
PreparedStatement pstmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
pstmt.setString(1, company.getCompName());
pstmt.setString(2, company.getPassword());
pstmt.setString(3, company.getEmail());
pstmt.executeUpdate();
ResultSet rs = pstmt.getGeneratedKeys();
rs.next();
company.setId(rs.getLong(1));
pstmt.getConnection().commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
ConnectionPool.getInstance().returnCon(con);
}
During creation of that table you have to write following DDL
CREATE TABLE MAPS
(
comp_id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
comp_name VARCHAR(24) NOT NULL,
password VARCHAR(26)
)
Ref : https://db.apache.org/derby/docs/10.0/manuals/develop/develop132.html
You're doing almost everything right, you just need to let the database assign an unique ID to each inserted row:
CREATE TABLE my_table (
id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
...
);
A problem could be that you made a mistake by creating your table.
You could create your table like this:
CREATE TABLE company
(
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
comp_name VARCHAR(50),
email VARCHAR(50),
password VARCHAR (50)
)
IF you want other values to be not NULL you could add NOT NULL to their lines:
password VARCHAR (50) NOT NULL
Delte your old table and execute the the SQl above on your DB. After that you can use your code without changes.
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();
}
I have a requirement where I need to insert mobile number in mysql if and only if the number is is not present.So for this I am first checking if a number is present in mysql using select query .If number is not present then insert.Following is my code
PreparedStatement pt1=con.prepareStatement("select * from registerSmsUsers where mobile='"+mobile+"'");
PreparedStatement pt=con.prepareStatement("insert into registerSmsUsers values(?,?,?)");
pt.setString(1, name);
pt.setString(2, email);
pt.setString(3, mobile);
ResultSet rs1=pt1.executeQuery();
if(rs1.next())
{pt.executeUpdate();}
i dont know whether this is a efficient way or not.Please suggest me a better way then this
Probably the easiest way in mysql is:
insert ignore into registerSmsUsers values(?,?,?)
When assuming you have unique key on mobile
You may check it here: How to 'insert if not exists' in MySQL?
Or here: http://dev.mysql.com/doc/refman/5.6/en/insert.html
Many of the proposed solutions (including yours) have a race condition that can cause a primary key or unique constraint violation. You code also have a possible SQL injection attack by concatenating SQL rather than using prepared statement parameters. Use SELECT...FOR UPDATE.
PreparedStatement ps = con.prepareStatement("SELECT name, email, mobile FROM registerSmsUsers WHERE mobile=? FOR UPDATE",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
ps.setString(1, mobile);
ResultSet rs = ps.executeQuery();
if (rs.next()) { // it exists already
rs.moveToCurrentRow();
rs.updateString(3, mobile);
rs.updateRow();
} else { // it does NOT exist
rs.moveToInsertRow();
rs.updateString(1, name);
rs.updateString(2, email);
rs.updateString(3, mobile);
rs.insertRow();
}
rs.close();
ps.close();
EDIT: Just make sure you have an index on registerSmsUsers.
CREATE INDEX registerSmsUsers_mobile_ndx ON registerSmsUsers(mobile)
or a unique contraint (which implicitly creates an index):
ALTER TABLE registerSmsUsers ADD CONSTRAINT registerSmsUsers_mobile_unq UNIQUE (mobile)
With an index, even with millions of records the update/insert will basically be instant.
EDIT2: Added cursor/result set options.
I think it would be better to create a stored procedure and then in that stored procedure you can first use the IF NOT EXISTS clause to check if the user exists using the select statement. If the user is not present you can insert the user in database.
Something like this:
IF NOT EXISTS(SELECT 1 FROM `registerSmsUsers` WHERE mobile= #mobile) THEN
BEGIN
INSERT INTO
`registerSmsUsers`
(
//column names
)
VALUES
(
//values
);
END;
END IF;
Also there is a INSERT IGNORE statement which you can use like this:
insert ignore into registerSmsUsers values(?,?,?)
if not exists(select * from registerSmsUsers where mobile='232323') <-- will check your mobile no
begin
insert into registerSmsUsers values(?,?,?)
end
This one is also an efficient way to check your method is also working fine but this also can be done
See difference is you will have only one query here
i hope this will help you thanks
[Edit]
Your questions answer
Ya there is a execution time diff between yours and mine query its depends upon a database size what you are using if you are using small size database (probably 1000 people) then you will not see any diff between your query and mine query but if your are using lakhs of users then your will have a performace issues check include execution plan in mysql you will get realtime difference between two
As requested, here is my tweaked version of brettw's answer:
import java.sql.*;
public class MySQLtest {
public static void main(String[] args) {
Connection con;
try {
con = DriverManager.getConnection(
"jdbc:mysql://192.168.1.3/zzzTest?" +
"useUnicode=yes&characterEncoding=UTF-8" +
"&user=root&password=whatever");
String newName = "Gord";
String newEmail = "gord#example.com";
String newMobile = "416-555-1212";
String sql =
"SELECT " +
"id, " +
"name, " +
"email, " +
"mobile " +
"FROM registerSmsUsers " +
"WHERE mobile = ? " +
"FOR UPDATE";
PreparedStatement pst = con.prepareStatement(
sql,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
pst.setString(1, newMobile);
ResultSet rs = pst.executeQuery();
if (rs.next()) {
rs.moveToCurrentRow();
rs.updateString("name", newName);
rs.updateString("email", newEmail);
rs.updateRow();
System.out.println("Existing row updated.");
}
else {
rs.moveToInsertRow();
rs.updateString("name", newName);
rs.updateString("email", newEmail);
rs.updateString("mobile", newMobile);
rs.insertRow();
System.out.println("New row inserted.");
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
Note that id is the Primary Key for the table: int(11) NOT NULL AUTO_INCREMENT