How to concatenate sql query in java? - java

I'm beginning to learn sql and java and I have a problem.
The logic for the code is:
The first part of the sql statement should be "a.stdn_code_ts" and as more elements (in this case student code) are included, I need to concatenate with and OR-Statement.
student codes could be a single value or a range, say for example: '567777' is valid as well as '567777-876677'.
If it is single value, just add "=" then the student code. In the example if the user entered '567777' then the query should be something like "a.stdnt_code_ts = '567777'"
If it is a range, add the first student code then "BETWEEN" second code. I.e.: if the user entered '567777-876677', the query should be "a.stdnt_code_ts BETWEEN '567777' AND '876677'".
and as I mentioned above, if there are 2 or more student codes the query should be concatenated with an "OR a.stdnt_code_ts" then checks again if it is a single value or a range.
I already have this code and got stuck:
private void formatStudentCode(Connection connection) throws Exception {
studentCode = "a.stdnt_code_ts ";
for(int i=0; i < stdntCode.size(); i++) {
if (stdntCode.get(i).indexOf("-")==-1) {
studentCode += "= '" + stdntCode.get(i) + "'";
}
else {
String [] range=stdntCode.get(i).split("-");
studentCode += "BETWEEN '" + range[0] + "' AND '" + range[1] +
"'";
}
}
}

First, this code is incomplete, so I'll need to make some guesses. But let's try.
Let's fix the loop first:
String sql = "SELECT * FROM students";
List<String> terms = new ArrayList<>();
List<String> arguments = new ArrayList<>();
// Don't need index here, for each loop is better
for (String code : codes) {
// No need for IndexOf
if (code.contains("-")) {
terms.add("stdnt_code_ts between ? and ?");
String[] split = code.split("-");
arguments.add(split[0]);
arguments.add(split[1]);
}
else {
// Don't concatenate SQL query parameters
terms.add("stdnt_code_ts = ?");
arguments.add(code);
}
}
Now to put our OR:
if (terms.size() > 0) {
sql += " WHERE " + Strings.join(terms, " OR ");
}
Now to add actual parameters for each question mark:
PreparedStatement preStmt = conn.prepareStatement(sql);
int count = 0;
for (String code : arguments) {
preStmt.setString(++count, code);
}
And finally to execute the query:
ResultSet rs = preStmt.executeQuery();
Note that I'm not running this code, so I may miss a line or two, but that's the general idea of how it should be done correctly.

Related

How should I store data in MySQL to make search and modification fast?

I need to store an array of VAR_CHAR(16) (these strings may only contain A-Z, a-z, 0-9 and _). The 1st column uniqueId is a unique AUTO_INCREMENT INT. The 2nd column is an array itself.
What exactly I need:
I run some command in pseudo-shell like: names add <for whom> <name>, it should:
Pseudo code (like java, but not):
String for_whom = ""; // <for_whom> from the command
String name = ""; // <name> from the command
ResultSet rs = findArrayContaining(for_whom);
if (rs.next()) {
int uniqueID = rs.getInt(1);
String[] array = columnToStrings(rs.get?????(2));
// Sorry, I don't know any better ways to add element to array
List<String> list = Arrays.asList(array);
list.add(name);
array = list.toArray(new String[0]);
rs.close();
// now we need to somehow
String str = convertToString(array);
// and execute
// "UPDATE `sometable` SET `names`='" + str + "' WHERE `uniqueId`=" + id
} else {
String[] array = new String[] { for_whom, name };
// now we need to somehow
String str = convertToString(array);
// and execute
// "INSERT INTO `sometable` (`uniqueId`, `names`) VALUES ('" + str + "', " + id + ")"
}
And when I run following command in pseudo-shell like: names get <whose>, it should:
Pseudo code (like java, but not):
String whose = ""; // <whose> from the command
ResultSet rs = findArrayContaining(whose);
if (rs.next())
System.out.println("Names of user '" + whose + "': " + String.join(", ", columnToStrings(rs.get?????(2))) + ".");
else
System.out.println("User '" + whose + "' has only 1 name.");
rs.close();
So I don't know how to store this data and how to quickly search entries I need.
I described my task as well as I could. I hope I'll get an answer. Thanks in advance. Ask me for more details if needed, tell me which exactly details you need.
And sorry if my English is bad, I always try to improve it
UPDATE: these values are usernames, there aren't any list of specified values.

java return String[] in method,String[].length is not correct

What I want is inserting datas into array String[],and then print the array values.
the returning String[] type method is
public String[] getRequirementDocIDofProject(String testprojectName)
throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
String req_doc_ids[] = null;
String str_sqlQuery = "select * from req_specs INNER JOIN nodes_hierarchy nh " +
"on nh.id=req_specs.testproject_id " +
"INNER JOIN requirements reqs " +
"on req_specs.id =reqs.srs_id where nh.name='" + testprojectName + "'";
int count = 0;
int n = 0;
initDB();
resultSet = statement.executeQuery(str_sqlQuery);
while (resultSet.next()){
count = Integer.parseInt(resultSet.getString(1));
}
req_doc_ids = new String[count];
resultSet = statement.executeQuery(str_sqlQuery);
while (resultSet.next()) {
req_doc_ids[n] = resultSet.getString("req_doc_id");
System.out.println("REQID=" + req_doc_ids[n]);
n++;
}
close();
System.out.println("n==" + n);
return req_doc_ids;
}
the calling method code is
DBConnection dbcon = new DBConnection();
String req_doc_ids[] = dbcon.getRequirementDocIDofProject("XXXX");
System.out.println(req_doc_ids.length);
the print message in Console is
REQID=TECH-6104
REQID=TECH-6686
REQID=TECH-5391
REQID=TECH-5965
REQID=TECH-6530
REQID=TECH-6729
REQID=TECH-7082
REQID=TECH-7107
REQID=TECH-7184
n==9
7166
why req_doc_ids.length 's value is 7166 rather than 9
7166 comes from the 1-th column of the result set - it's the value in the last row.
while(resultSet.next()){
count=Integer.parseInt(resultSet.getString(1));
}
Instead, you perhaps meant:
while(resultSet.next()){
count++;
}
Mind you, this is an unnecessarily inefficient way to create the array. Use a List instead; or, use the method on the result set API to get the number of rows directly.
Your main issue has already been clarified by Andy and this answer is just an extension to help you with your current code.
Couple of improvements possible in your code.
Prefer using PreparedStatement instead of Statement which is not safe and may be at risk to SQL Injection attack as already mentioned by Jon Skeet.
Why to run a db query twice which potentially could be a heavy query just to find out the number of records to correctly initialize your String array.
Use List<String> to store whatever number of rows you get and finally convert the list to array like shown in below code.
Get rid of so many unneeded variables and so many lines of code to make your code appear crisp and clear.
You may try changing your method to this one,
public String[] getRequirementDocIDofProject(String testprojectName)
throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
List<String> reqDocIdList = new ArrayList<String>();
String str_sqlQuery = "select * from req_specs INNER JOIN nodes_hierarchy nh " +
"on nh.id=req_specs.testproject_id " +
"INNER JOIN requirements reqs " +
"on req_specs.id =reqs.srs_id where nh.name='" + testprojectName + "'";
initDB();
resultSet = statement.executeQuery(str_sqlQuery);
while (resultSet.next()){
System.out.println("REQID=" + resultSet.getString("req_doc_id"));
reqDocIdList.add(resultSet.getString("req_doc_id"));
}
close();
System.out.println("n==" + reqDocIdList.size());
return reqDocIdList.toArray(new String[reqDocIdList.size()]);
}

Trim Java String and use in Sql Where Clause

I am trying to get values from MySQL db using a query which gets values from a multiple select. The problem is that I am using StringBuilder to create the query based on the values I am getting. If you see the Where clause used why me, every time a new variable is fetched a comma is added in the end.
How do I remove the last comma added as it is giving me an error in the sql query. Will appreciate any help.
String[] stat = req.getParameterValues("status");
StringBuilder sb = new StringBuilder(200);
if (stat != null) {
for (int i = 0; i < stat.length; i++) {
sb.append("'" + stat[i] + "',");
}
String app = "WHERE status in (" + sb.toString() + ")";
String sqlquery = "SELECT * FROM Table " + app + ";";
}
Result Query:
SELECT * FROM Table
WHERE status in ('Deployed','PendingDisposal','Available','Reserved','Broken',);
I want to get rid of the last comma after 'Broken'
Your problem is with comma in the end, you can append your Strings like this :
String del = "";
for (int i = 0; i < stat.length; i++) {
sb.append(del).append("'" + stat[i] + "'");
del = ",";
}
But in fact this is not really good idea to use this way, because it can cause SQL Injection or syntax error, you have to use PreparedStatement for example :
for (int i = 0; i < stat.length; i++) {
sb.append(del).append("?");
del = ",";
}
try (PreparedStatement ps = connection.prepareStatement(sb) {
for (int i = 0; i < stat.length; i++) {
ps.setString(i, stat[i]);
}
ResultSet result = preparedStatement.executeQuery();//get results
...
}
You can join a string array with commas using Java 8 streams:
String joined = Arrays.asList(stat).stream()
.map(s -> "'" + s + "'")
.collect(Collectors.joining(", "));
But note that joining strings like this is a really bad idea: you are vulnerable to SQL injection attacks, e.g. if one of the element of stat is something like:
'); DROP TABLES Table; --
You are better off building the query using a PreparedStatement. See this question.
Need to update your for loop where you need to append element from array till its second last element and append last element of the array outside the loop.
for(int i=0;i<stat.length-1;i++){ // loop till second last element
sb.append("'"+stat[i]+"',"); //appends , at end
}
sb.append("'"+stat[stat.length-1]+"'"); // append last element
You can use deleteChartAt method:
sb.deleteCharAt(sb.length()-1);
For example:
String[] stat = req.getParameterValues("status");
StringBuilder sb = new StringBuilder(200);
if(stat!=null) {
for(int i=0;i<stat.length;i++){
sb.append("'"+stat[i]+"',");
}
sb.deleteCharAt(sb.length()-1); //---------> This will remove the last comma
String app = "WHERE status in ("+sb.toString()+")";
String sqlquery = "SELECT * FROM Table "+app+";";
}
try something this.
for(int i=0;i<stat.length;i++){
sb.append("'"+stat[i]+"'");
if(i!=stat.length-1){
sb.append(",");
}
}
try
String app = "WHERE status in ("+sb.substring(0, sb.length()-2)+")";

SQL command not properly ended with select

I'm working with Oracle SQL Developer with a Java application. I want to ask to the DB this query:
select * from vocabolario, vocaboli_help where verbo=1 and
vocabolario.id = vocaboli_help.id and vocaboli_help.usato = 0
The query works when I run it from SQL developer, but when run it from Eclipse with the stmt.executeQuery(string), where stmt is a Statement object, it throws the following exception: SQL command not properly ended.
I put also a semicolon at the end of the string, but it doesn't work.
I used the stmt.executeQuery(string) with other queries and in those cases there were no problems. The only difference I can see is that in this case I have where condition in AND.
Java code :
private final static String NOME_DATABASE = "VOCABOLARIO", NOME_DATABASE_HELP ="VOCABOLI_HELP";
String type ="verbo";
String query = "SELECT * FROM " + NOME_DATABASE + ", " + NOME_DATABASE_HELP +" WHERE " + type + " = 1 " +
"AND " + NOME_DATABASE +".ID = " + NOME_DATABASE_HELP +".ID AND "+NOME_DATABASE_HELP+".USATO = 0";
System.out.println(query);
int cont = 0;
String result="";
try {
ResultSet res = statement.executeQuery(query);
while(res.next()) {
String cod = res.getString("ID").trim();
String voc = res.getString("VOCABOLO").trim();
String trad = res.getString("TRADUZIONE").trim();
if(cont == n)
result = cod + "," + voc + "," + trad;
cont++;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
`
select * from vocabolario vo
left join vocaboli_help voh
on vo.id= voh.id
where v.verbo=1 AND voh.usato=0
You just need a simple join.
VOCABOLI_HELP or vocabolario_help your code and your post different
Thank you all, the problem was in the name of the second table, but I think it depends on Java code sintax, as #are suggested.
I updated the code:
private static final String NOME_DATABASE_HELP = "VOCABOLIHELP"
I also modified the table name in the DB and now it works. I think there are issues with the underscore in the name (the problem is only in Java as I said), I don't know why.

Storing rows from a MySQL table into an array in Java

I'm trying to store rows from a table into an array. I can get the first result and store that but I cannot seem to be able to store any of the other data.
This is the code I've written
try
{
test = "select * from Arsenal order by 'MatchNumber' ASC";
rs = st.executeQuery(test);
while (rs.next())
{
//This retrieves each row of Arsenal table and adds it to an array in the Team Results class.
matchno = rs.getString("MatchNumber");
hometeam = rs.getString("HomeTeam");
awayteam = rs.getString("AwayTeam");
homegoals = rs.getString("HomeGoals");
awaygoals = rs.getString("AwayGoals");
result = rs.getString("Result");
teams = (matchno + "," + hometeam + "," + awayteam + "," + homegoals + "," + awaygoals + "," + result); // Takes all the variables containging a single customers information and puts it into a string, seperated by commas.
TeamResults.add(matchno,hometeam,awayteam,homegoals,awaygoals,result);
}
}
Any idea where I'm going wrong?
Change the while-condition to hasNext() and use next() inside of the loop to move the database cursor forward.
Try to use this method bellow :
public void SelectData(String sqlcounter ,String sql){
try {
RsCounter=stmt.executeQuery(sqlcounter);
System.out.println(sqlcounter);
while(RsCounter.next()){
countrow=RsCounter.getInt("COUNTR");
System.out.println(countrow+"\n");
}
System.out.println(sql);
RsSelecting = stmt.executeQuery(sql);
data=new String[countrow][RsSelecting.getMetaData().getColumnCount()];
header= new String[RsSelecting.getMetaData().getColumnCount()];
i=0;
while(RsSelecting.next()){
for(j=0;j<RsSelecting.getMetaData().getColumnCount();j++){
data[i][j]=(RsSelecting.getString(j+1));
header[j]=RsSelecting.getMetaData().getColumnName(j+1);
System.out.print(data[i][j]+"\n");
}
i++;
}
i=j=0;
} catch (SQLException ex) {
ex.printStackTrace();
Logger.getLogger(Connect.class.getName()).log(Level.SEVERE, null, ex);
}
}
where
sqlcounter ="select COUNT(*) as COUNTR from Arsenal order by 'MatchNumber' ASC";
and
sql ="select * from Arsenal order by 'MatchNumber' ASC";
Verify the column names once. Sometimes ALIAS doesn't work out, I am not sure why.
Get the meta data from the result set:
ResultSetMetaData metaData = resultSet.getMetaData();
int size = metaData.getColumnCount();
for (int i = 0; i < size; i ++)
System.out.println(metaData.getColumnName(i);
Also just for performance, list out the column names instead of using * in the SELECT query. Also, you can take a look at com.sun.rowset.CachedRowSetImpl. It's used like:
CachedRowSetImpl crs = new CachedRowSetImpl();
crs.populate(resultSet);
I think it also implements CachedRowSet, but I am not entirely sure.

Categories

Resources