Delete from two tables in one statement - java

I want to be able to remove all data from 2 tables where the id of a user = the id given. I am using Java, Derby DB, Netbeans 7.3 Beta 2 and OS X Mountain Lion.
I have two tables (sorry about the huge image):
This is my statement so far:
String stmt2 = "DELETE FROM APP.PERSON JOIN APP.DATAVAULT WHERE PID = ?";
PreparedStatement ps2 = Main.getPreparedStatement(stmt2);
ps2 = conn.prepareStatement(stmt2);
ps2.setInt(1, user.getId());
ps2.executeUpdate();
System.out.println("Deleted");
I don't understand how I delete from APP.DATAVAULT as well as APP.PERSON. As you can see there is a foreign key within APP.DATAVAULT which is a users id.
I have tried many things such as:
String stmt2 = "DELETE FROM APP.PERSON, APP.DATAVAULT WHERE PID = ?";
and
String stmt2 = "DELETE FROM APP.PERSON AND APP.DATAVAULT WHERE PID = ?";
I understand that I must use the foreign key to delete from both, but I don't know how.

Unfortunately, per the docs, you cannot delete multiple tables with a single SQL query in Derby.
You can with some other RDBMS packages, such as MySQL... just not Derby.

Related

SQL State: 42000 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax [duplicate]

I have to add a statement to my java program to update a database table:
String insert =
"INSERT INTO customer(name,address,email) VALUES('" + name + "','" + addre + "','" + email + "');";
I heard that this can be exploited through an SQL injection like:
DROP TABLE customer;
My program has a Java GUI and all name, address and email values are retrieved from Jtextfields. I want to know how the following code (DROP TABLE customer;) could be added to my insert statement by a hacker and how I can prevent this.
You need to use PreparedStatement.
e.g.
String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);";
PreparedStatement ps = connection.prepareStatement(insert);
ps.setString(1, name);
ps.setString(2, addre);
ps.setString(3, email);
ResultSet rs = ps.executeQuery();
This will prevent injection attacks.
The way the hacker puts it in there is if the String you are inserting has come from input somewhere - e.g. an input field on a web page, or an input field on a form in an application or similar.
I want to know how this kind piece of code("DROP TABLE customer;") can
be added to my insert statement by a hacker
For example:
name = "'); DROP TABLE customer; --"
would yield this value into insert:
INSERT INTO customer(name,address,email) VALUES(''); DROP TABLE customer; --"','"+addre+"','"+email+"');
I specially want to know how can I prevent this
Use prepared statements and SQL arguments (example "stolen" from Matt Fellows):
String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);";
PreparedStament ps = connection.prepareStatment(insert);
Also parse the values you have on such variables and make sure they don't contain any non-allowed characters (such as ";" in a name).
You can check THIS article for info on that! :)
I recommend Parameterized Queries:
String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();
An attacker just has to enter something like 'foo#example.com"); DROP TABLE customer; into the field for email and you are done.
You can prevent this by using the proper escaping for JDBC Statements.
That's why you should be using question marks in your string statements:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setInt(2, 110592)
quoted from here
As explained in this post, the PreparedStatement alone does not help you if you are still concatenating Strings.
For instance, one rogue attacker can still do the following:
call a sleep function so that all your database connections will be busy, therefore making your application unavailable
extracting sensitive data from the DB
bypassing the user authentication
And it's not just SQL, but JPQL and HQL can be compromised if you are not using bind parameters:
PreparedStatement ps = connection.prepareStatement(
INSERT INTO customer(name,address,email) VALUES(?, ?, ?)
);
int index = 0;
ps.setString(++index, name);
ps.setString(++index, address);
ps.setString(++index, email);
ResultSet rs = ps.executeQuery();
Bottom line, you should never use string concatenation when building SQL statements. Use a dedicated API for that purpose:
JPA Criteria API
jOOQ
Go for PreparedStatement
Advantages of a PreparedStatement:
Precompilation and DB-side caching of the SQL statement leads to overall faster execution and the ability to reuse the same SQL statement in batches.
Automatic prevention of SQL injection attacks by builtin escaping of quotes and other special characters. Note that this requires that you use any of the PreparedStatement setXxx() methods to set the value
You should also limit the privileges of the account that accesses the database as tightly as possible. For example, for searching, the account only needs to have read access to those tables and columns that are required. This will prevent any damaging SQL injection and limit access to sensitive data.
Even though all the other answers tell you as how can you fix SQL injections in Java, answer by Mukesh Kumar actually tells you as who is actually preventing these kind of attacks. Understand that its actually DB server which is preventing SQL injection attacks provided you as a programmer follow their recommendation of using parametrized queries.
Refer Here - Preventing SQL Injection Vulnerabilities
It wouldn't be possible for Java programmer to sanitize each & every input String so DB vendors have given us options of Prepared Statements and they tell us to prepare & execute queries by using that & rest of the things will be taken care of by the DB vendor.
Things as drastic as DROP TABLE customer; might not happen but basic premise of SQL injection is that nobody should be able to break your query by just providing invalid input ( either intentional or non - intentional ).
OWASP - SQL Injection Prevention Cheat Sheet

JDBC - NetBeans x MySQL

I'm trying to create a Java Application in NetBeans which allows the user to use most MySQL RDBMS functionalities through a GUI. I have successfully written the code for the following :
Creating a Database
Dropping a Database
Creating a Table giving options for table name, no. of columns, data type for every column
I'm stuck at the part where the user gets to insert a record in the table that was just created. I'm unable to figure out how the "insert into table values ..." query can be dynamically created and passed depending on the table the user wants to enter this record in. The table could have any number of columns, of course.
I dont know if this is the correct method, but when I faced this same problem in the past, this is how I solved it :
I ran this query to find the number of columns in the table
SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_catalog = 'database_name' AND table_name = 'table_name'
Then created a dynamic sql query based on no of columns:
String sql = "Insert into tablename values(";
for(int i = 1;i<=columns;i++){
sql += "?";
if (i < columns) {
sql += ", ";
}
}
sql+=");";
Then fired a Prepared Statement
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
If you also don't know the constraints and datatype of the columns, try parsing
desc tablename
I know this must be the shittiest workaround, but it worked for me;)

Unable to get count of table rows using jdbc - for JDEdwards table

I am trying to get the total count of a table rows using the below code.
Connection con = getJdeConnection(userN, password, hostN, dbName);
PreparedStatement p = con.prepareStatement("select count(*) from F0010");
System.out.print("\n----- Connection Success ---------------\n\n");
ResultSet rs = p.executeQuery();
if(rs.next()){
System.out.println("Query = select count(*) from F0010");
System.out.println("count = "+rs.getInt(1));
}else{
System.out.println("zero records");
}
The above code is running fine if am running the above code for my test table. Means it is giving the exact count. But I need to count number of rows in the above table F0010. This is a table in JD Edwards, contains 5203 records. The same sql when am running in JDE sql prompt it is giving count as 5203. But when am running this query from java code it is giving count as 0 (Zero).
My program is not throwing any exceptions.
Please help me. Thanks in advance.
Just to be sure you are running the query on the right schema change it into select count(*) from PRODDTA.F0010
where PRODDTA is the owner of your table.

best way to call two database servers

i want to call two table of different database at once.table of database A contains user id and table of database B contains user location with the user id, so i want to join these two tables and get the location corresponding to user_id.database A and B are in two different servers. so how can i join these two tables. if it is not possible to join this, is there any efficient way to do this.please help.i'm trying to do this using java, mysql.
ps = con.prepareStatement("SELECT user_id FROM A.users");
rs = ps.executeQuery();
while(rs.next())
{
//call select statement for database B to get the location for each user id
}
please suggest an efficient way to do this
Id User_id
===========
1 44
2 23
User_id location
====================
44 india
23 us
Supposing user_id is a long.
PreparedStatement psUserLocation = conB.prepareStatement("SELECT location FROM B.users WHERE user_id = ?");
while(rs.next()) {
//call select statement for database B to get the location for each user id
long userId = rs.getLong(user_id);
psUserLocation.setLong(1, userId)
ResultSet userLocation = ps.executeQuery();
// Do whatever with the location(s)
}
EDIT: one query for all users instead of one query per user:
private final static String QUERY = "SELECT user_id, location FROM B.users WHERE user_id IN (%a)";
StringBuilder userList = new StringBuilder();
while(rs.next()) {
long userId = rs.getLong(user_id);
userList.append(userId);
if (!rs.isLast()) {
userList.append(",");
}
}
String usersLocationQuery = QUERY.replaceAll("%a", userList.toString());
PreparedStatement psUsersLocation = conB.prepareStatement(usersLocationQuery);
ResultSet usersLocation = psUsersLocation.executeQuery();
// Do whatever with the locations
Keep in mind this can fail/work wrong because most DB have a limit for how many items an SQL IN clause can include. Also this second method might allow an SQL injection on the %a replacement.
You may use FEDERATED Storage Engine. The FEDERATED storage engine lets you access data from a remote MySQL database without using replication or cluster technology. Querying a local FEDERATED table automatically pulls the data from the remote (federated) tables. No data is stored on the local tables. This may not be very efficient but it will do the work (JOINs).
If you can do away with join, one possible way is to get all the user_id's from tableA in one go, and then pass the user_id's to tableB at once. Of course, this approach will require you to change code as well.
Something like:
select user_id from tableA (of databaseA);
and
select user_id, location from tableB (of database B) where user_id in (<result_from_above_query)
The above process will require two queries.

Java: updating the MySQL table's id

This is my delete class that gets id as an input.
I succeeded to delete the row(for example row contained id '3' from my database) and now I want to update all the id-s.
for example: my rows were:
1 a5
2 f3
(3 t1 was deleted)
4 r2
so now the result should be updated:
1 a5
2 f3
3 r2
String delete = "DELETE from authors WHERE id = ?";
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, "root", "easttg");
PreparedStatement ps = con.prepareStatement(delete);
//updating the id
String sql = "Select id from authors";
PreparedStatement ps2 = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, id);
ps.executeUpdate();
con.close();
To update some row, you must use an update statement. Not a select statement:
update authors set id = ? where id = ?
That said: IDs are just technical identifiers for rows. They shouldn't be modified generally. And the reason why purely technical IDs are used is that they never need to be modified, which is a good thing because there might be dozens of other tables having foreign keys containing this same ID. The ID might also be part of some URL used to display the row in a web site, that many people could have bookmarked. The ID is... the identity of the row. You don't change an identity. If you do it, all kinds of problems occur, exactly as if you changed your own name.

Categories

Resources