SQL Delete from two table in Oracle - java

I have to do remove the row (containing the userId) in the table "USERS". This is my query:
#SqlUpdate("delete from USERS where userId = :userId ")
void removeUser(#Bind("userId") String userId);
But first I want to remove that user from the table "USERS_DATA" (that is a daughter of USERS) which also contain the "userId". How can I do? I've tried this:
#SqlUpdate("delete from USERS_DATA where userId = :userId " +
" and delete from USERS where userId = :userId")
void removeUser(#Bind("userId") String userId);
but console tell me: java.sql.SQLSyntaxErrorException: ORA-00936: missing expression

Unlike some other RDBMS, Oracle does not allow you to pass two statements in the same SQL command (this helps to prevent SQL injection).
You can try using wrapping both queries in an anonymous PL/SLQ block:
BEGIN
delete from USERS_DATA where userId = :userId;
delete from USERS where userId = :userId;
END;
/
This will allow you to execute both DML statements together as they are part of the singular containing PL/SQL block.
Unfortunately, I am not familiar with that annotation syntax in Java so I cannot help you convert it to Java but I would guess at:
#SqlUpdate("BEGIN " +
"delete from USERS_DATA where userId = :userId; " +
"delete from USERS where userId = :userId; " +
"END;")
void removeUser(#Bind("userId") String userId);
Alternatively, you can create a procedure in Oracle:
CREATE OR REPLACE PROCEDURE delete_user(
in_userID USERS_DATA.USERID%TYPE
)
AS
BEGIN
DELETE FROM USERS_DATA WHERE userId = in_userId;
DELETE FROM USERS WHERE userId = in_userId;
END;
/
And you can then just call this procedure.

Related

Return array of deleted elements postgresql JDBC

This is my database:
dragons
id, key, name, age, creation_date
users
id, name, user, pass
users_dragons
user_id, dragon_id
So this is my code for deleting dragons from the database that have a bigger key that the passed and belongs to a determination user. The SQL query works perfectly for deleting them but not for returning the array of keys from the deleted elements.
I tried using PreparedStatement but later I checked, as far as I know, that this class doesn't return arrays, and the CallableStatement is only for executing processes in the db, and I don't know how they return arrays.
String query = "" +
"DELETE FROM dragons " +
"WHERE id IN (SELECT d.id FROM dragons d, users u, users_dragons ud" +
" WHERE d.key > ?" +
" AND ud.dragon_id = d.iD" +
" AND ud.user_id in (select id from users where id = ?)) RETURNING key INTO ?";
CallableStatement callableStatement = connection.prepareCall(query);
int pointer = 0;
callableStatement.setInt(++pointer, key);
callableStatement.setInt(++pointer, credentials.id);
callableStatement.registerOutParameter(++pointer, Types.INTEGER);
callableStatement.executeUpdate();
return (int []) callableStatement.getArray(1).getArray();
The code is giving me the error, but is obvious because the CallableStatement needs a postgres function to run and not a simple SQL query
org.postgresql.util.PSQLException: This statement does not declare an OUT parameter.
Use { ?= call ... } to declare one.
at org.postgresql.jdbc.PgCallableStatement.registerOutParameter
.......
It would be really helpful how would be the correct JDBC algorithm to delete the elements from the database and return the array of keys of the deleted items.
You treat such a statement like a normal SELECT statement: use java.sql.PreparedStatement.executeQuery() or java.sql.Statement.executeQuery(String sql) to execute the statement and get a result set.
java.sql.CallableStatement is for calling Procedures (but you don't need it in PostgreSQL).

Sqlite-JDBC update with LIMIT clause?

I am trying to use the update query with the LIMIT clause using sqlite-JDBC.
Let's say there are 100 bob's in the table but I only want to update one of the records.
Sample code:
String name1 = "bob";
String name2 = "alice";
String updateSql = "update mytable set user = :name1 " +
"where user is :name2 " +
"limit 1";
try (Connection con = sql2o.open()) {
con.createQuery(updateSql)
.addParameter("bob", name1)
.addParameter("alice", name2)
.executeUpdate();
} catch(Exception e) {
e.printStackTrace();
}
I get an error:
org.sql2o.Sql2oException: Error preparing statement - [SQLITE_ERROR] SQL error or missing database (near "limit": syntax error)
Using
sqlite-jdbc 3.31
sql2o 1.6 (easy database query library)
The flag:
SQLITE_ENABLE_UPDATE_DELETE_LIMIT
needs to be set to get the limit clause to work with the update query.
I know the SELECT method works with the LIMIT clause but I would need 2 queries to do this task; SELECT then UPDATE.
If there is no way to get LIMIT to work with UPDATE then I will just use the slightly more messy method of having a query and sub query to get things to work.
Maybe there is a way to get sqlite-JDBC to use an external sqlite engine outside of the integrated one, which has been compiled with the flag set.
Any help appreciated.
You can try this query instead:
UPDATE mytable SET user = :name1
WHERE ROWID = (SELECT MIN(ROWID)
FROM mytable
WHERE user = :name2);
ROWID is a special column available in all tables (unless you use WITHOUT ROWID)

java-How to perform SQL injection for testing purposes?

I have a web application that I am trying to "break".There's a login page that requires username and password input. Let's say I have a table Auser that stores username's info in MySQL.
When I hit Login after keying the credentials,it executes this line of code:
String sql = "select object(o) from Auser as o where ausername='" + username + "'";
Now, I know not using preparedStatement makes SQL query vulnerable to SQL injection and I want to perform such a stunt. I created a dummy table called test for the purpose of able to drop this table via the injection command.
I tried various ways like in my username input(root is the username):
root` DROP TABLE test;
And it didn't work. Is there a way to make my injection successful?
Update:
Just extra info, my username column is VARCHAR(255) and my method for getting the username is below:
public Auser get(String username, boolean moreInfo) {
try {
Auser u = null;
String sql = "select object(o) from Auser as o where ausername='" + username + "'";
List resList = em.createQuery(sql).getResultList();
if (resList == null) { // null check for sql query / library error
msg = CoreUtil.wrapMsg(CoreUtil.FUNC_ERROR,
this.getClass().getName(), "get[" + username + "]", "query error AUSER.");
} else if (resList.isEmpty()) {
msg = "User " + username + " not found.";
} else {
u = (Auser) resList.get(0);
}
return u;
} catch (Exception e) {
msg = CoreUtil.wrapMsg(CoreUtil.FUNC_ERROR,
this.getClass().getName(), "get[" + username + "]", e.getMessage());
return null;
}
}
Seems every solution, I tried keeps throwing IllegalArgumetnException and the table still remains.I just want to exploit the vulnerabilities of my program,it can be any kind of injection whether dropping a table, returning all users info,etc.
The EntityManager has some (very) basic protection built in that won't run more than one command in the same SQL statement.
This will protect you from Robert'); DROP TABLE Students; --, but it won't protect from attackers trying to expand/alter the one query that's being run.
For example, in your code an attacker could get the details of another user by entering the username ' OR 1 = 1 --; This would make the SQL string being executed
select object(o) from Auser as o where ausername='' OR 1 = 1 --'
which will select every user in the table (note that the -- at the end of the input will comment out everything after the injected code), and your method will return the first user in the result list This will potentially give the attacker details about another user that they should not have access to. If the first account is an administrator account then they may also have access they should not have.
An attacker can also learn the structure of the table this way - they can try strings like ' and IS_ADMIN = IS_ADMIN --, or ' OR ID = 0 --. If they try enough of these (and attacks like this can be easily automated) they will find valid column names when the query doesn't throw an error. They can potentially then make a more targeted injection attack to gain access to an admin account.
They might also learn things from the error message returned from a failed attempt, such as the DB platform, which can make attacks easier.
String sql = "select object(o) from Auser as o where ausername='" + username + "'";
If you want to delete the test table
username = "x'; DROP TABLE test AND '1'='1"
If you want to see all fields of all ausers entries
username = "x' OR '1'='1"

Error In JDBC Template Querying

I am trying to write this query in order to authenticate the username and password of my API but I am getting error column not found. Both username and passwords are strings and I am using MYSQL database. I think there is a error with quotations as username and password are strings. How can I rectify the below code or is there a better way to write the same.
P.S - I am using spring MVC and this is my first project.
#Override
public TypeInfo getRole(final TypeInfo typeinfo) {
String sql =
"select Role from registartion where UserName=\"" + typeinfo.getUserName() + "and Password=\"" + typeinfo.getPassword() + "/"";
return jdbcTemplate.query(sql, new ResultSetExtractor<TypeInfo>() {
#Override
public TypeInfo extractData(ResultSet rs)
throws SQLException, DataAccessException {
if (rs.next()) {
System.out.println("VALID USER");
TypeInfo typeinfo1 = new TypeInfo();
typeinfo1.setUserName(typeinfo.getUserName());
typeinfo1.setPassword(typeinfo.getPassword());
typeinfo1.setRole(rs.getString("Role"));
return typeinfo1;
}
System.out.println("Not A valid user");
return null;
}
});
}
I am getting a error that "select Role from registartion where UserName=******" column name ******* not found.
That's not the way you should write your query.
JdbcTemplate uses an Object[] array as parameters, to avoid SQL injection.
code it somewhere in the lines of this:
String user = "yourUser";
String password = "yourPassword";
final String sql = "SELECT * from FOO where username = ? and password = ?";
Object[] sqlParameters = new Object[]{user, password};
List<YourEntityClass> list = getJdbcTemplate.query(sql, new BeanPropertyRowMapper<Your Entity Class>(YourEntityClass.class), sqlParameters);
BeanPropertyRowMapper actually maps the values for you. just make sure your entity class has the same property names as the ones on your database
more info here:
jdbcTemplate examples
The proper solution would be to use a PreparedStatement, in order to avoid having to mess with quoting and enhance security.
If you really must construct the statement by string concatination, you should note that string literals in SQL are denoted by single quotes ('), not double quotes ("):
String sql =
"select Role from registartion where UserName='" + typeinfo.getUserName() + "' and Password='" + typeinfo.getPassword() + '";
Try this.
String sql = "select Role from registartion where UserName='" + typeinfo.getUserName() + "' and Password='" + typeinfo.getPassword() + "'";
Change the double quotes (including the escape characters) to single quotes.
Close the single quote enclosing the user name (typeinfo.getUserName()). You need to keep a space between the closing single quote and the subsequent string.
If it still does not work then check the table names and column names. Maybe it is 'registration' and not 'registartion'? Or may be it is 'user_name' and not 'username'?
Tips for beginners: Copy paste the sql string into any database browser, replace the variables with actual values and execute. Check for any errors. It is easier to fix errors this way.
And lastly, use parameterized sql queries to avoid sql injection. In my opinion parameterized queries reduces syntax errors too.
You have to use single qoutes around the column values:
"select Role from registartion where UserName='" + typeinfo.getUserName() + "' and Password='" + typeinfo.getPassword() + "'";
You should better use PreparedStatement. It is easier to read and safer (prevents sql injection).

My Sql prepared statement insert avoid duplicate entry

I want to insert some data into a table named USERLOGIN and be sure that no duplicate data will be inserted.
I wrote this code as my insert quesry in a java program:
String sql = "INSERT INTO USERLOGIN (" + "deleted," + "loginTime," + "userIpAddress," + "username)" + "VALUES(?,?,?,?)"+ "WHERE "+"? NOT IN (SELECT loginTime FROM USERLOGIN )";
I want to check duplicate entries based on loginTime property.
However when I run my code I got this error: You have an error in your sql syntax
Could you please help me with this problem. I really appreciate that.
use this query :-
String sql = "INSERT INTO USERLOGIN (deleted, loginTime, userIpAddress, username) " + "VALUES(?,?,?,?) " + "WHERE "+"? NOT IN (SELECT loginTime FROM USERLOGIN )";

Categories

Resources