Testing for null inside SQL query - java

I want to implement search filter for this table:
CREATE TABLE ACCOUNT(
ID INTEGER NOT NULL,
USER_NAME TEXT,
PASSWD TEXT,
FIRST_NAME TEXT,
LAST_NAME TEXT,
LAST_LOGIN DATE,
DATE_REGISTERED DATE,
ROLE INTEGER,
CAN_LOGIN INTEGER
)
;
-- ADD KEYS FOR TABLE ACCOUNT
ALTER TABLE ACCOUNT ADD CONSTRAINT KEY1 PRIMARY KEY (ID)
;
SELECT * FROM ACCOUNT
WHERE '" + searchString + "' IN (ID, USER_NAME, FIRST_NAME, LAST_NAME)
ORDER BY %S %S offset ? limit ?;
But when I have empty search filter I get this error:
org.postgresql.util.PSQLException: ERROR: invalid input syntax for integer: "null" Position: 30
How can I edit the SQL query in a way that WHERE clause will be skipped if searchString is empty?
Here is the Java method:
public List<AccountsObj> list(int firstRow, int rowCount, String sortField, boolean sortAscending) throws SQLException
{
String SqlStatement = null;
if (ds == null)
{
throw new SQLException();
}
Connection conn = ds.getConnection();
if (conn == null)
{
throw new SQLException();
}
String sortDirection = sortAscending ? "ASC" : "DESC";
SqlStatement = "SELECT * FROM ACCOUNT "
+ " WHERE '" + searchString + "' IN (ID, USER_NAME, FIRST_NAME, LAST_NAME)"
+ " ORDER BY %S %S offset ? limit ? ";
String sql = String.format(SqlStatement, sortField, sortDirection);
PreparedStatement ps = null;
ResultSet resultSet = null;
List<AccountsObj> resultList = new ArrayList<>();
try
{
conn.setAutoCommit(false);
boolean committed = false;
ps = conn.prepareStatement(sql);
ps.setInt(1, firstRow);
ps.setInt(2, rowCount);
resultSet = ps.executeQuery();
resultList = ProcessorArrayList(resultSet);
conn.commit();
committed = true;
}
finally
{
ps.close();
conn.close();
}
return resultList;
}

Using SQL to check for a null search string you can do:
SELECT * FROM account WHERE ? IS NULL OR ? IN (user_name, first_name, last_name)
Here the ? IS NULL will short-circuit if the parameter is NULL and the second part will not be evaluated.
Note that, I've used two parameter bindings with the same value (your search string) here and that the ID column is gone - you cannot mix varchar and integer in the IN clause.
Edit For wildcard searches you can use LIKE or ILIKE (for case-insensitive searches)
SELECT * FROM account WHERE
(trim(?) = '') IS NOT FALSE
OR user_name like ?
OR first_name like ?
OR last_name like ?
Using a prepared statement you would call it like this (note that you have to bind the same parameter four times)
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, searchString);
ps.setString(2, searchString);
ps.setString(3, searchString);
ps.setString(4, searchString );
try (ResultSet rs = ps.executeQuery()) {
// read data
}
}

You can replace this line of your java code :
+ (searchString == null || searchString.length == 0 ) ? "" : (" WHERE '" + searchString + "' IN (ID, USER_NAME, FIRST_NAME, LAST_NAME)")
It basically checks if searchString is empty, and adds the line only if it is not

Related

Automate changing Statement into Prepared Statement programmatically through Java ( In source code )

I have been assigned a task for automating the conversion of statements into prepared statements for security purpose. Since it's a repetitive task, I want to automate it.
for example
public String getEmployee(Connection connection, Long id , Long groupId) {
String result = "";
try {
Statement stmt = connection.createStatement();
String query = "select * from employee"
+ " where id = " + id ; // flaw 1
if(groupId != null) {
query += " and group_id = " + groupId; // flaw 2
}
ResultSet rs = stmt.executeQuery(query);
}
I want to remove the flaws with :
public String getEmployee(Connection connection, Long id , Long groupId) {
String result = "";
try {
String query = "select * from employee"
+ " where id = ? ";
if(groupId != null) {
query += " and group_id = ? ";
}
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setLong(parameterIndex++, id);
stmt.setLong(parameterIndex++, groupId);
ResultSet rs = stmt.executeQuery();
}
I need to write a java code, that can replace these Statements with Prepared Statements.
Input will be the java file.
I tried a lot, but couldn't find out a possible solution to this problem.
Can you please help me by guiding me, if it's feasible.

Where should ? be placed in a PreparedStatement? [duplicate]

This question already has an answer here:
Having a Column name as Input Parameter of a PreparedStatement
(1 answer)
Closed 7 years ago.
I am using PreparedStatement to select records from a table:
public static String getMemberInfo(String columnName, Integer memberId) {
String memberInfo = "";
String sql = "SELECT ? FROM member WHERE member_id = ?";
DatabaseConnector.setConn();
try(Connection conn = DatabaseConnector.getConn();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, columnName);
ps.setInt(2, memberId);
try(ResultSet rs = ps.executeQuery()) {
if(rs.next()) {
memberInfo = rs.getString(columnName);
}
}
} catch(SQLException se) {
se.printStackTrace();
}
return memberInfo;
}
When I use
SELECT " + columnName + " FROM member WHERE member_id = ?, it works.
But when I use
SELECT ? FROM member WHERE member_id = ?, it does not.
Where should ? be placed in prepared statements?
? is for input values (typically in the WHERE clause conditions).
? is not for selected columns.
Column name must be hard-coded, Only column values can be set using ?.
but you can set dynamic column name by doing something like this :
String sql = "SELECT "+ columnName +" FROM member WHERE member_id = ?";

Java mysql execute update

So I have a method that looks up a foreign key in a database. If the foreign key does not exist it will add an entry into the database. Now what I am doing from that point after inserting the new record, is re-querying again to get the foreign key. Is this overkill or is this the right way to do this? Thanks
private String getTestType(TestResult testResult) {
String testTypeId = "";
String query = String.format("SELECT id FROM test_types WHERE " +
"name='%s'", testResult.getTestType());
try {
st = con.prepareStatement(query);
rs = st.executeQuery();
if (rs.next()) {
testTypeId = rs.getString("id");
} else {
st = con.prepareStatement("INSERT INTO test_types (name, " +
"created_at) VALUES (?, ?)");
st.setString(1, testResult.getTestType());
st.setTimestamp(2, new java.sql.Timestamp(System
.currentTimeMillis()));
st.executeUpdate();
st = con.prepareStatement(query);
rs = st.executeQuery();
if (rs.next()) {
testTypeId = rs.getString("id");
}
}
} catch (SQLException e) {
e.printStackTrace();
System.out.println("There was an issue getting and or creating " +
"test Type");
}
return testTypeId;
}
Since you are inserting a new row into DB, you have to do a query to get back the auto increment field(id). Currently they way you are doing is workable. But there are few alternatives in query:
Obtaining the id using last_insert_id():
rs = st.executeQuery("select last_insert_id() as last_id");
id= rs.getString("last_id");
Another approach can be doing the MAX over the id column of the table.
I believe these are will be much faster than your query as you are doing string comparison in where clause.

How to set list in prepared statement

How can i set list in prepared statement(statement.setString(1, productCode); ).
See below my code snippet.
Thanks
public static List<Message> listAllWonBids(List<Message> productCode,
Connection connection) {
List<Message> winners = new ArrayList<Message>();
String sql = "SELECT b.`id`, b.`msisdn` as msisdn ,b.`productname` as productname, b.`productcode` as productcode, max(b.`amount`) as amount FROM "
+ TableNames.SAVEDBIDSTABLE
+ " b where productcode = ? "
+ " group by amount order by productcode, amount desc limit 1";
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
LOGGER.info(sql);
if (connection == null || connection.isClosed())
connection = DBConnection.getConnection();
statement = connection.prepareStatement(sql);
**statement.setString(1, productCode);**
resultSet = statement.executeQuery();
NOTE: productCode is coming from another list shown below
public static List<Message> allProductCode(Connection connection) {
List<Message> productcodes = new ArrayList<Message>();
PreparedStatement statement = null;
ResultSet resultSet = null;
String sql = "SELECT `productCode` FROM " + TableNames.AUCTIONTABLE1
+ " WHERE date(`endDate`) = curdate() order by `id` desc";
That is not possible, either you generate a where clause programmatically using the IN
"where productcode in (" + listToStringEncoding + ")"
or you loop over the list and call the statement multiple times.
Other possibility is to join the 2 statements...
You could combine those two queries. Something like:
String sql = "SELECT b.`id`, b.`msisdn` as msisdn ,b.`productname` as productname, b.`productcode` as productcode, max(b.`amount`) as amount FROM "
+ TableNames.SAVEDBIDSTABLE + " b where productcode in (SELECT `productCode` FROM "
+ TableNames.AUCTIONTABLE1 + " WHERE date(`endDate`) = curdate() order by `id` desc) group by amount order by productcode, amount desc limit 1";
Then you wouldn't need any parameters

How to insert reference values in database using JDBC?

I am trying to insert values into Oracle 10g database using the code below but its giving an error of "Missing Expression" on execution. I have to pass reference values into the insert clause but do not know the exact syntax or way of doing it.
Please help me through this.
Thanks.
Student Table:-
Sid VARCHAR2(200) PRIMARY KEY CHECK(Sid>0),
Pass_word VARCHAR2(10) NOT NULL,
S_name VARCHAR2(20) NOT NULL,
G_name VARCHAR2(20) ,
Branch VARCHAR2(10) NOT NULL,
D_company VARCHAR2(20) ,
B_Percent INT NOT NULL CHECK(B_Percent<100),
twelth_percent INT NOT NULL CHECK(twelth_percent<100),
tenth_percent INT NOT NULL CHECK(tenth_percent<100),
Certify VARCHAR2(30),
Semester INT NOT NULL CHECK(Semester<9),
D_Birth DATE NOT NULL,
Sex VARCHAR2(6) NOT NULL
CODE:
Connection connection = null;
try
{
// Load the JDBC driver
String driverName = "sun.jdbc.odbc.JdbcOdbcDriver";
Class.forName(driverName);
connection = DriverManager.getConnection("jdbc:odbc:placement","siddharth","sid");
studentID = StudentID.getText();
spassword = PasswordField.getPassword();
studentname = NameField.getText();
Gname = GuardianField.getText();
branch = BranchField.getText();
dcompany = DcompanyField.getText();
bpercent = BtechField1.getText();
twelthpercent = TwelthField.getText();
tenthpercent = TenthField.getText();
semester = SemesterField.getText();
certify = CertificationField.getText();
sex = SexCombo.getActionCommand();
date = (Date) DateTextField1.getValue();
Statement stmt = connection.createStatement();
stmt.executeUpdate("insert into student " +"(sid,pass_word,s_name,g_name,branch,d_company,b_percent,twelth_percent,tenth_percent,certify,semester,d_birth,sex)"+
"values(studentID, spassword,studentname,Gname,branch,dcompany,bpercent,twelthpercent,tenthpercent,certify,semester,date,sex)" );
stmt.close();
connection.close();
}
catch (ClassNotFoundException e) {
// Could not find the database driver
JOptionPane.showMessageDialog(null,e);
}
catch (SQLException e) {
// Could not connect to the database
JOptionPane.showMessageDialog(null,e);
}
Currently your SQL statement looks like:
insert into student (sid, pass_word, ...) values (studentID, spassword, ...)
The variable names mean nothing to the SQL itself.
You should use a prepared statement. For example, your SQL should look like this:
insert into student (sid, pass_word, ...) values (?, ?, ...)
and then you use:
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, studentID);
stmt.setString(2, spassword);
// etc
See the JDBC tutorial on prepared statements for more information.
To be on the safe side you should use prepared statements.
Prepare the Query String
String updateString = "update " + dbName + ".COFFEES " +
"set SALES = ? where COF_NAME = ?";
Create a PrepartedStatement with this query:
updateSales = connnection.prepareStatement(updateString);
Fill the ? spaceholders with you values:
updateSales.setInt(1, myVariable1);
updateSales.setString(2, myVariable2);
execute the Query
updateSales.executeUpdate();

Categories