Query the foreign keys in the two tables - java

How can I query the route in the routes table in my database depends on the lat, longi of stops table and the arrivaltime in arrivaltimes table? So if the lat and longi in the stops table are found I want first to check whether there is arrivaltime (here the current time must be equal to the arrivaltime ) of this stop_id in arrivaltimes table then depend on it I want to retrieve all route from the routes table for this stop_id?
CREATE TABLE IF NOT EXISTS stops
(stop_id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(30) NOT NULL,
lat double(10,6) NOT NULL,
longi double(10,6)NOT NULL)
INSERT INTO stops(name, lat, longi) values
('ABC', '63.838039', '18.700440' ),
('DEF', '63.840642', '18.701246' ),
('HIG', '63.868863', '18.665438' )
CREATE TABLE IF NOT EXISTS arrivaltimes(arrivaltimes_id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
weekday VARCHAR(20) NOT NULL,
arrivaltime time NOT NULL,
stop_id INT, FOREIGN KEY fk_stop_id(stop_id) REFERENCES stops(stop_id) )
INSERT INTO arrivaltimes(stop_id, arrivaltime, weekday) values
('1', 'mon-fri', '05:30' ),
('1', 'mon-fri', '06:07' )
CREATE TABLE IF NOT EXISTS routes
(routes_id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
route INT(11) NOT NULL,
stop_id INT, FOREIGN KEY fk_stop_id(stop_id) REFERENCES stops(stop_id) )
INSERT INTO routes(route) values
('1', '1'),
('1', '9')
The JDBC code:
Calendar now = Calendar.getInstance();
int day = now.get(Calendar.DAY_OF_WEEK);
int hour = now.get(Calendar.HOUR_OF_DAY);
int minute = now.get(Calendar.MINUTE);
String time = hour+":"+minute;
Statement stt = con.createStatement();
PreparedStatement preparedLatLong = con
.prepareStatement("SELECT lat, longi from stops");
ResultSet rsLatLong = preparedLatLong.executeQuery();
while (rsLatLong.next()) {
double lat_stop = rsLatLong.getDouble("lat");
double lon_stop = rsLatLong.getDouble("longi");
double distStops = haversineDistance(latD, longD, lat_stop, lon_stop);
if(distStops <= 10){
// Here how can I query the arrivaltime and the route?
PreparedStatement preparedTime = con.prepareStatement("SELECT arrivaltime from arrivaltimes WHERE arrivaltime=time"
+ "values(?)");
ResultSet rsArrivaletime = preparedTime.executeQuery();
while(rsArrivaletime.next()){
}
}
}
If the first record in the stops table is the location then I want to check the arrivaltime in the arrivaltimes table if the current time = 13:30 then I want to get the 1 and 9 route number from the routes table. I hop it is more clear now.

You can use joins with a where clause load everything together.
SELECT a.route FROM routes a
LEFT JOIN arrivaltimes b ON a.stop_id = b.stop_id
LEFT JOIN stops c ON a.stop_id = c.stop_id
WHERE b.arrivaltime = ?

Related

Data insertion using auto incremented column as primary key

I have two tables whereby the primary key(foreign key on the other table) is auto incremented at run time (using TOAD for mysql).
How can I insert data into the two tables at the same time using a transaction.
This is the ddl for the first table:
CREATE TABLE `suspendedsales` (
`SID` int(11) NOT NULL AUTO_INCREMENT,
`SequenceNo` int(11) NOT NULL DEFAULT '0',
`ProductCode` varchar(100) DEFAULT NULL,
`ItemName` varchar(100) DEFAULT NULL,
`Quantity` int(11) DEFAULT NULL,
`Discount` double DEFAULT NULL,
`ItemCost` double DEFAULT NULL,
PRIMARY KEY (`SID`,`SequenceNo`),
CONSTRAINT `SIDFKey` FOREIGN KEY (`SID`) REFERENCES `suspendedsalesdetails` (`SID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
The ddl for the second table:
CREATE TABLE `suspendedsalesdetails` (
`SID` int(11) NOT NULL DEFAULT '0',
`Date` date DEFAULT NULL,
`Total` double DEFAULT NULL,
PRIMARY KEY (`SID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
N.B: The major challenge would be to get the auto-incremented key value from on the primary key to be inserted into the other table at run time.
Thanks in anticipation.
If your database is a MySql database you can insert a record in the first table use the following function
SELECT LAST_INSERT_ID();
to get the last inserted id and you can use it in the second insert. Commit all only after the second insert
How about this:
private void insert() {
OraclePreparedStatement statement = null;
try {
Connection dbConnection = getConnection();
statement = dbConnection.createStatement();
String insertToSuspendedsales = "insert into suspendedsales (SequenceNo, ProductCode,ItemName,Quantity,Discount,ItemCost) "
+ "values(:segNo, :prodNo, :itmeName, :quantity, :discount, :itemCost) returning SID into ?";
statement.setIntAtName("segNo", intValue);
....
int id = statement.registerReturnParameter(1, OracleTypes.INTEGER)
statement.executeUpdate(insertToSuspendedsales);
String insertToSuspendedsalesdetails = "insert into suspendedsalesdetails (SID, Date, Total) "
+ "values(:sid, :date, :total) returning SID into ?";
statement.setIntAtName("sid", id);
....
statement.executeUpdate(insertToSuspendedsalesdetails);
} catch (SQLException ex) {
ex.printStackTrace();
//rollback
} finally {
//close Connection
}
}

MySQL selection jumps from 300 ms to 20 seconds for 5 rows extra

I have a blob in my database table. If I select 10 rows of the table (each row containing 1 blob), it takes 300 milliseconds.
However, if I select 15 rows, it takes 20 seconds. I don't understand what is going on. The file that is selected is an image of 1 MB.
public void find() throws SQLException, IOException {
ResultSet rs = stm.executeQuery();
while (rs.next()) {
FileOutputStream output = new FileOutputStream(new File(
"C:\\Users\\test\\test.jpg"));
InputStream input = rs.getBinaryStream("photo");
byte[] buffer = new byte[8192];
int count = 0;
while ((count = input.read(buffer)) > 0) {
output.write(buffer, 0, count);
}
}
}
I honestly don't know why such small difference takes up so much time.
Any help is greatly appreciated.
Edit for extra notes:
Yes, the overwriting of the same image is intentional. (sorry for not pointing that out)
Using rs.getBlob("photo").getBinaryStream() has still the same effect.
The execution time of the method find() is being benchmarked via JMH. The piece of code above remains the same.
The exact same code and SQL is running for a 'contact' table that for the first test has 100 rows (of which 10 are selected) and the other 150 rows (of which 15 are selected).
The blob is inside the contact table.
The SQL:
String query = "SELECT * FROM contact c INNER JOIN contact_address ca ON c.id=ca.contact_id INNER JOIN groups_contact gc ON gc.contact_id=c.id INNER JOIN groups gr WHERE ca.country=? AND gr.name=? GROUP by c.id";
stm = conn.prepareStatement(query);
stm.setString(1, "NL");
stm.setString(2, "Friends");
stm.addBatch();
Update:
(measuring method is modified please see the above)
Selecting 10 rows: 239 ms.
Selecting 15 rows: 26378 ms.
Selecting 25 rows: 34888 ms.
Selecting 50 rows: 73267 ms.
Selecting 75 rows: 81885 ms.
Selecting 100 rows: 106528 ms.
Creations of table:
String createUserTable = "CREATE TABLE User (id INTEGER not NULL AUTO_INCREMENT, email VARCHAR(255), password VARCHAR(255), PRIMARY KEY (id))";
String createGroupTable = "CREATE TABLE Groups (id INTEGER not NULL AUTO_INCREMENT , name VARCHAR(255), user_id INTEGER not NULL, PRIMARY KEY (id), FOREIGN KEY (user_id) REFERENCES User(id))";
String createContactTable = "CREATE TABLE Contact (id INTEGER not NULL AUTO_INCREMENT , firstname VARCHAR(255), lastname VARCHAR(255), note VARCHAR(255), photo MEDIUMBLOB, user_id INTEGER, PRIMARY KEY (id), FOREIGN KEY (user_id) REFERENCES User(id))";
String createGroupContactTable = "CREATE TABLE Groups_Contact (id INTEGER not NULL AUTO_INCREMENT, contact_id INTEGER not NULL, group_id INTEGER not NULL, PRIMARY KEY (id), FOREIGN KEY (contact_id) REFERENCES Contact(id), FOREIGN KEY (group_id) REFERENCES Groups(id))";
String createContactAddressTable = "CREATE TABLE Contact_Address (id INTEGER not NULL AUTO_INCREMENT , street VARCHAR(255), number INTEGER, zipcode VARCHAR(255), city VARCHAR(255), country VARCHAR(255), addresstype VARCHAR(255), contact_id INTEGER not null, PRIMARY KEY (id), FOREIGN KEY (contact_id) REFERENCES Contact(id))";
String createContactPhoneTable = "CREATE TABLE Contact_Phone (id INTEGER not NULL AUTO_INCREMENT , type VARCHAR(255), number VARCHAR(255), contact_id INTEGER not null, PRIMARY KEY (id), FOREIGN KEY (contact_id) REFERENCES Contact(id))";
String createContactEmailTable = "CREATE TABLE Contact_Email (id INTEGER not NULL AUTO_INCREMENT , type VARCHAR(255), email VARCHAR(255), contact_id INTEGER not null, PRIMARY KEY (id), FOREIGN KEY (contact_id) REFERENCES Contact(id))";
Are you sure its not the joins? Some joins can be very slow, especially multiple joins. Often we had to run separate queries because joins might slow a query down.
Also what kind of indexes do you have?

MySql Java auto increment

I have a problem with the auto incremented values in preparedStatement. Here is my database
CREATE TABLE `book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`isbn` varchar(10) NOT NULL,
`title` varchar(20) NOT NULL,
`pages` int(11) NOT NULL,
`price` decimal(5,2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `isbn` (`isbn`)
and here is my preparedStatement:
String title = fieldTitle.getText();
String isbn = fieldISBN.getText();
double price = Double.parseDouble(fieldPrice.getText());
int pages = Integer.parseInt(fieldPages.getText());
conn = DBUtil.connect();
try {
prepState = conn.prepareStatement("insert into book values(?,?,?,?)");
prepState.setString(1, isbn);
prepState.setString(2, title);
prepState.setInt(3, pages);
prepState.setDouble(4, price);
prepState.execute();
However, when I fill in the fields I get the following error:
java.sql.SQLException: Column count doesn't match value count at row 1. I know that when the field in the database is autoincremented I do not have to put it in the query...
Any ideas?
Modify you query to include column names:-
INSERT INTO book (isbn, title, pages, price) VALUES (?,?,?,?)

Not getting MySQL SELECT LPAD() in ResultSet

I am trying to select multiple columns from different tables in MySQL.
MySQL:
CREATE TABLE IF NOT EXISTS movie(
movie_id TINYINT(3) UNSIGNED AUTO_INCREMENT,
movie_title VARCHAR(255) NOT NULL,
movie_genre VARCHAR(255) NOT NULL,
movie_rating ENUM('G', 'PG', 'R-13', 'R-16', 'R-18', 'PENDING') NOT NULL,
movie_cast VARCHAR(255) NOT NULL,
movie_runtime TINYINT(3) UNSIGNED NOT NULL,
movie_poster VARCHAR(255) NOT NULL,
PRIMARY KEY(movie_id)
);
CREATE TABLE IF NOT EXISTS mall(
mall_id VARCHAR(255),
mall_name VARCHAR(255) NOT NULL,
PRIMARY KEY(mall_id)
);
CREATE TABLE IF NOT EXISTS schedule(
schedule_id TINYINT(3) UNSIGNED AUTO_INCREMENT,
movie_id TINYINT(3) UNSIGNED NOT NULL,
mall_id VARCHAR(255) NOT NULL,
schedule_cinema TINYINT(2) UNSIGNED NOT NULL,
schedule_price DECIMAL(5, 2) NOT NULL,
schedule_date DATE NOT NULL,
schedule_time TIME NOT NULL,
schedule_seats TINYINT(2) UNSIGNED NOT NULL,
PRIMARY KEY(schedule_id),
FOREIGN KEY(movie_id) REFERENCES movie(movie_id),
FOREIGN KEY(mall_id) REFERENCES mall(mall_id)
ON DELETE CASCADE
ON UPDATE CASCADE
)ENGINE=INNODB;
CREATE TABLE IF NOT EXISTS transaction(
transaction_id SMALLINT(5) UNSIGNED AUTO_INCREMENT,
user_id VARCHAR(255) NOT NULL,
schedule_id TINYINT(3) UNSIGNED NOT NULL,
transaction_date DATE NOT NULL,
PRIMARY KEY(transaction_id),
FOREIGN KEY(user_id) REFERENCES user(user_id),
FOREIGN KEY(schedule_id) REFERENCES schedule(schedule_id)
ON DELETE CASCADE
ON UPDATE CASCADE
)ENGINE=INNODB;
I tested this query directly in XAMPP MySQL and it returned all desired columns. The transaction_id is also left-padded as intended.
SELECT SQL:
SELECT LPAD(transaction_id, 5, 0), transaction_date, movie_title, schedule_price, mall_name, schedule_cinema, schedule_date, schedule_time FROM transaction INNER JOIN schedule ON transaction.schedule_id = schedule.schedule_id INNER JOIN movie ON schedule.movie_id = movie.movie_id INNER JOIN mall ON schedule.mall_id = mall.mall_id WHERE user_id = 'admin';
This method was supposed to return a list of History objects, using the above SELECT SQL.
public List<History> getTransactionHistory(String currentUserId){
History history;
List<History> historyList = new ArrayList<History>();
sql = "SELECT LPAD(transaction_id, 5, 0), transaction_date, movie_title, schedule_price, "
+ "mall_name, schedule_cinema, schedule_date, schedule_time FROM transaction "
+ "INNER JOIN schedule ON transaction.schedule_id = schedule.schedule_id "
+ "INNER JOIN movie ON schedule.movie_id = movie.movie_id "
+ "INNER JOIN mall ON schedule.mall_id = mall.mall_id "
+ "WHERE user_id = ?";
try {
ps = conn.prepareStatement(sql);
ps.setString(1, currentUserId);
rs = ps.executeQuery();
while(rs.next()) {
history = HistoryAssembler.getInstance(
rs.getString("transaction_id"),
rs.getDate("schedule_date"),
rs.getString("movie_title"),
rs.getBigDecimal("schedule_price"),
rs.getString("mall_name"),
rs.getInt("schedule_cinema"),
rs.getDate("schedule_date"),
rs.getTime("schedule_time")
);
System.out.println(history.getTransactionId());
historyList.add(history);
}
} catch(SQLException se) {
se.printStackTrace();
}
return historyList;
}
History (Bean):
public class History {
private String transactionId;
private Date transactionDate;
private String movieTitle;
private BigDecimal schedulePrice;
private String mallName;
private Integer scheduleCinema;
private Date scheduleDate;
private Time scheduleTime;
// getters and setters
}
HistoryAssembler:
public static History getInstance(String transactionId, Date transactionDate, String movieTitle, BigDecimal schedulePrice,
String mallName, Integer scheduleCinema, Date scheduleDate, Time scheduleTime) {
History history = new History();
history.setTransactionId(transactionId);
history.setTransactionDate(transactionDate);
history.setMovieTitle(movieTitle);
history.setSchedulePrice(schedulePrice);
history.setMallName(mallName);
history.setScheduleCinema(scheduleCinema);
history.setScheduleDate(scheduleDate);
history.setScheduleTime(scheduleTime);
return history;
}
However, I am getting a java.sql.SQLException: Column 'transaction_id' not found, when I do have the said column.
From what I understand, LPAD() should return a String, so that is why I set the transactionId in the bean as such.
Your assistance is much appreciated.
After the "LPAD" function the column name is changed and "XAMPP" fixed for you. You must put alias in this query after "LPAD(transaction_id, 5, 0) as transaction_id".
SELECT LPAD(transaction_id, 5, 0) as transaction_id
, transaction_date
, movie_title
, schedule_price
, mall_name
, schedule_cinema
, schedule_date
, schedule_time
FROM transaction INNER JOIN schedule ON transaction.schedule_id = schedule.schedule_id
INNER JOIN movie ON schedule.movie_id = movie.movie_id
INNER JOIN mall ON schedule.mall_id = mall.mall_id
WHERE user_id = 'admin';

Derby and SQL requests issue: how is the default schema determined?

I'm trying to use Derby in my school project but i have some issues.
my DB is named theaterDB, derby 10.2.1, JDBC 3.0.0
Each SQL request i make through java does not succeed... I can't understand why.
For example, the request:
SELECT * FROM User returns an exception:
java.sql.SQLSyntaxErrorException: Schema 'ADMIN' does not exist
Another SQL that is not working :
ALTER table theaterDB."Projection" ADD INDEX(fk_Projection_Movie(Movie_id));
Syntax error: Encountered "" at line 1, column 45.
Here is the java :
public Connection getConnection()
{
try
{
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
System.out.println("Connection to: jdbc:derby:C:\\Users\\acouty\\theaterDB;create=true");
// DriverManager.get
return DriverManager.getConnection("jdbc:derby:C:\\Users\\acouty\\theaterDB;create=true", "admin", "");
}
catch (final Exception e)
{
e.printStackTrace();
return null;
}
}
public List<User> listUsers()
{
final ArrayList<User> users = new ArrayList<User>();
System.out.println("List user request");
try
{
final Connection connection = getConnection();
final String query = "SELECT * FROM User";
System.out.println("query is : " + query);
final ResultSet rs = connection.createStatement().executeQuery(query);
while (rs.next())
{
System.out.println("salut");
}
return null;
}
catch (final Exception e)
{
e.printStackTrace();
}
return null;
}
Here is the .sql :
CREATE TABLE theaterDB."Users"
(
id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
name VARCHAR(45) NOT NULL,
lastname VARCHAR(45) NOT NULL ,
email VARCHAR(45) NOT NULL ,
adress VARCHAR(45) NOT NULL ,
city VARCHAR(45) NOT NULL ,
zip VARCHAR(45) NOT NULL ,
login VARCHAR(45) NOT NULL ,
password VARCHAR(45) NOT NULL ,
admin SMALLINT NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
CREATE TABLE theaterDB."Movie"
(
id INT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
title VARCHAR(45) NOT NULL ,
resume VARCHAR(500) ,
genre VARCHAR(60) ,
grade INT ,
review_pub VARCHAR(200) ,
review_gen VARCHAR(200) ,
poster VARCHAR(100) ,
duration INT ,
release_date VARCHAR(45) ,
PRIMARY KEY (id)
);
CREATE TABLE theaterDB."Projection" (
id INT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
date DATE ,
length INT ,
Movie_id INT NOT NULL ,
price DECIMAL(10,0) ,
location VARCHAR(45) NOT NULL ,
place_nbr INT NOT NULL ,
PRIMARY KEY (id)
);
ALTER TABLE theaterDB."Projection"
ADD FOREIGN KEY(Movie_id)
REFERENCES theaterDB."Movie" (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
CREATE TABLE theaterDB."command"
(
id INT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
Projection_id INT NOT NULL ,
User_id INT NOT NULL ,
paid SMALLINT NOT NULL ,
PRIMARY KEY (id)
);
ALTER TABLE theaterDB."command"
ADD FOREIGN KEY(Projection_id)
REFERENCES theaterDB."Projection" (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
ALTER TABLE theaterDB."command"
ADD FOREIGN KEY(User_id)
REFERENCES theaterDB."Users" (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
Thank you
I had to change executeQuery to execute and Users to "THEATERDB"."USERS"
Here are the working requests:
SELECT * FROM "THEATERDB"."Users"
insert into "THEATERDB"."Users"(NAME, LASTNAME, EMAIL, ADRESS, CITY, ZIP, LOGIN, PASSWORD, ADMIN) values ('salut', 'salut', 'salut', 'salut', 'salut', 'salut', 'salut', 'salut', 1)
Thanks for you help :).

Categories