I query a database and get a lot information back that should be presented to the user. In the database I have fields a, b, c, d and e. Now, the user should be able to indicate which of these fields that should be printed on screen (i.e. the user can choose to view only a subset of the data retrieved from the database).
How do I dynamically create a print statement that sometimes prints two of the fields, sometimes four, sometimes three etc. depending on what the user wants?
If all the hard work is already done and you just have a result set to print, then it could be as simple as a succession of calls to System.out.print() for each result and then finish the line with a \n. It can be nested in a FOR loop, so if you have an int with the number of fields to print, just iterate through them.
In a more complicated case when you have a full list where some fields are chosen and others not, then you could use a (slightly) crude method like this:
...
String[] chosenFields = {"Field 1", "Field 2" /*, (et cetera) */};
for (int i = 0; i < numberOfFields; i++)
{
for (int j = 0; j < chosenFields.length; j++)
{
if (fieldsName[i].equals(chosenFields[j]))
System.out.print(fields[i] + " ");
break;
}
}
System.out.println();
...
Sorry about bad indentation; not sure how to sort it on here!
If field names are indeterminate at runtime and you're using Java to execute queries, consider using class ResultSetMetaData to get them.
EDIT:
As an example, here's some of my code which gets all the field names from a table, then creates a tickbox for each, which the user can select or deselect. All the JFrame GUI stuff I've omitted. When the user presses a submit button, the application check each tickbox and constructs an SQL statement to suit the users request.
...
JCheckBox[] jcb;
ResultSetMetaData rsmd;
private void makeCheckBoxes()
{
initConnection(); // Establish connection to MySQL server
try
{
Statement query = connection.createStatement();
ResultSet rs = query.executeQuery("SELECT * FROM client_db;");
rsmd = rs.getMetaData();
noOfColumns = rsmd.getColumnCount();
jcb = new JCheckBox[noOfColumns];
for (int i = 0; i < noOfColumns; i++)
{
jcb[i] = new JCheckBox(rsmd.getColumnName(i + 1));
jpCheckBoxes.add(jcb[i]);
jcb[i].setEnabled(false);
jcbComboBox.addItem(rsmd.getColumnName(i + 1));
}
jcb[0].setSelected(true);
rs.close();
query.close();
connection.close();
}
catch (SQLException e)
{
System.err.println("!> Caught SQLException:\n" + e.getMessage());
System.exit(1);
}
}
...
if (e.getSource() == jbSubmit)
{
String query = "";
initConnection();
if (jtfSearch.getText().isEmpty() == true) // JTextField
{
jtaResults.setText(null); // JTextArea
jtaResults.append("Please enter some search text in the text box above!\n");
return;
}
else
{
int selectedFields;
if (jrbAll.isSelected() == true) // JRadioButton
{
query = "SELECT *";
selectedFields = -1;
}
else
{
query = "SELECT";
selectedFields = 0;
for (int i = 0; i < noOfColumns; i++)
if (jcb[i].isSelected() == true)
{
try
{
if (selectedFields > 0)
query += ",";
query += " " + rsmd.getColumnName(i + 1);
}
catch (SQLException err)
{
System.err.println("!> Caught SQLException:\n" + err.getMessage());
System.exit(1);
}
selectedFields++;
}
}
if (selectedFields == 0)
{
jtaResults.setText(null);
jtaResults.append("No fields were selected!!\n");
return;
}
else
{
query += " FROM client_db WHERE " + jcbComboBox.getSelectedItem() + " LIKE '%" + jtfSearch.getText() + "%'";
if (jcbCurrentClients.isSelected() == true)
query += " AND currentClient LIKE 'y'";
query += ";";
}
}
System.out.println("Query = \"" + query + "\"");
/* Now, print it out in the text area!! */
try
{
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
ResultSetMetaData rsMetaData = rs.getMetaData();
int columnCount = rsMetaData.getColumnCount();
jtaResults.append("--------------------------------\n");
int noOfResults = 0;
jtaResults.setText(null);
while (rs.next() == true)
{
if (noOfResults > 0)
jtaResults.append("\n");
jtaResults.append("* Search match " + (noOfResults + 1) + ":\n");
for (int i = 0; i < columnCount; i++)
{
jtaResults.append("-> " + rsMetaData.getColumnName(i + 1) + ": " +
rs.getString(i + 1) + "\n");
}
noOfResults++;
}
if (noOfResults == 0)
{
jtaResults.append("No results were returned; please try again with more ambiguous search terms.\n\n");
}
//scroller.setScrollPosition(0, 1048576);
rs.close();
stmt.close();
connection.close();
}
catch (SQLException err)
{
System.err.println("!> Caught SQLException:\n" + err.getMessage());
System.exit(1);
}
}
}
Hopefully this helps. The sustained concatenation to query forms a valid SQL statement based on the fields the user chose. Hopefully a few modifications to this to just print certain fields will help you. The System.out.println() call to print query about two-thirds down is a good place to work from.
The natural way to switch an optional value on or off would be a radiobutton. For 5 fields i.e. an array of 5 radiobuttons.
StringBuffer sb = new StringBuffer (5 * 10);
for (int i = 0; i < 5; ++i)
if (rb[i])
s.append (field[i]).append (" ");
Maybe you're better of only selecting interesting columns from the database? Then a dummy-column is helpful:
sql = new StringBuffer ("SELECT 1 "); // the dummy-column
for (int i = 0; i < 5; ++i)
if (rb[i])
sql.append (", ").append (fieldname[i]);
Related
This question already has an answer here:
Syntax error due to using a reserved word as a table or column name in MySQL
(1 answer)
Closed 3 years ago.
My select statement shows the error
java.sql.SQLSyntaxErrorException: You have an error in your SQL
syntax; check the manual that corresponds to your MySQL server version
for the right syntax to use near 'condition from food' at line 1.
My parameter values are object = "food" and columns[] = {"foodName, foodPrice, condition"}
This function still works for my login though
I already use different versions of mySQL and also put brackets around the statement and it still doesn't work
public static String[][] checkDatabase(String object, String[] columns){
Connection myCon = null;
Statement myStm = null;
ResultSet myRs = null;
try {
myCon = DriverManager.getConnection("jdbc:mysql://localhost:3306/softwaredesignorder", "root","SeanLink_11");
myStm = myCon.createStatement();
String temp = "select ";
for (int i = 0; i < columns.length; i++) {
if (i < columns.length - 1) {
temp = temp + columns[i] + ", ";
} else {
temp = temp + columns[i];
}
}
temp = temp + " from " + object;
//PreparedStatement pStm = myCon.prepareStatement(temp);
//pStm.execute();
myRs = myStm.executeQuery(temp);
myRs.last();
String[][] returner = new String[myRs.getRow()][columns.length];
myRs.beforeFirst();
int row = 0;
while (myRs.next()){
int length = columns.length, col = 0;
while (length != 0) {
try {
returner[row][col] = myRs.getString(columns[col]);
} catch (IllegalArgumentException e1) {
try {
returner[row][col] = Integer.toString(myRs.getInt(columns[col]));
} catch (IllegalArgumentException e2) {
try {
returner[row][col] = Double.toString(myRs.getDouble(columns[col]));
} catch (IllegalArgumentException e3) {
try {
Date date = myRs.getDate(columns[col]);
DateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd");
returner[row][col] = dateFormat.format(date);
} catch (IllegalArgumentException e4) {
System.err.println("Could not retrieve data");
} catch (Exception e) {
System.err.println(e);
}
}
}
}
col += 1;
length -= 1;
}
row += 1;
}
return returner;
} catch (SQLException exSQL) {
System.err.println(exSQL);
}
return null;
};
I want the output to have the data from the entire table but only the selected column.
I believe your problem is that condition is a reserved work in most SQL languages as detailed in https://dev.mysql.com/doc/refman/5.5/en/keywords.html#keywords-5-5-detailed-C, that is why your code works on some cases, is because you don't always have a column named condition you need to escape it using backticks.
Have you try to output back the query you made? i think this one have issue on your query builder. Just simply System.out.println(temp) and check the query syntax before you query on MySQL.
"conditional" is a reserved word in MySQL. You could avoid this error by surrounding your select list items with quotes:
for (int i = 0; i < columns.length; i++) {
String column = "\"" + colunms[i] + "\"";
if (i < columns.length - 1) {
temp = temp + column + ", ";
} else {
temp = temp + column;
}
}
I'm trying to migrate a big db from derby to HSQLDB in a Spring Boot service, like 1.5M regs in few tables of 10 columns. I'm checking with VisualVM; byte and char consume a lot of memory. But the biggest delta in time are in the derby classes.
Sometimes the error is thrown here, but other times thrown in other controllers. I don't want to touch all files to add my catchOutofMemory to restart.
Following is a version of my code, the block comment shows the resume of the process:
run(){//thread inside static function.
while(keepMigrating){
keepMigrating=Migrate();
}
}
private static boolean Migrate(JdbcTemplate derby,JdbcTemplate hsql){
int regs = 100000;
PreparedStatement statement = null;
ResultSet rs = null;
PreparedStatement statementHSQL = null;
try {
for (String table : tables) {//tables contains all tables to migrate
//check how many registers left asd asign to cant, if cant is 0 the empty is true.
PreparedStatement statementUpd[];
while (!empty) {
if (trys <= 0) throw new Exception("redo");
//check how many registers left asd asign to cant, if cant is 0 the empty is true and out of bucle and ready to check next table
/*
*Next process resume as:
*fetch data from derby that hasnt been migrated limited by cant
*create a batch to insert in hsql
*create a update for derby
*create a delete in case someting goes wrong
*excecute insert and update, if someting in batch fail delete the entry in migrate table
*reduce regs to get out of migrate method at some ponint.
*/
statement = derby.getDataSource().getConnection().prepareStatement(
MessageFormat.format(select_all_migrate_false_and_fetch_cant,table));
statementUpd = new PreparedStatement[cant];
ArrayList<String> deleteIds = new ArrayList<>();
StringBuilder columnNames = new StringBuilder();
StringBuilder updateSQL = new StringBuilder();
StringBuilder bindVariables = new StringBuilder();
try {
ResultSetMetaData meta = rs.getMetaData();
for (int i = 1; i <= meta.getColumnCount(); i++) {
if (!meta.getColumnName(i).equals("MIGRATED")) {
if (i > 1) {
columnNames.append(", ");
bindVariables.append(", ");
}
columnNames.append(meta.getColumnName(i));
bindVariables.append('?');
}
}
String sql = "INSERT INTO " + table.substring(4) + " ("
+ columnNames
+ ") VALUES ("
+ bindVariables
+ ")";
statementHSQL = hsql.getDataSource().getConnection().prepareStatement(sql);
HashMap<String, Object> data = new HashMap<>();
int row = 0;
int lastId = 0;
String columnName;
while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
columnName = meta.getColumnName(i);
Object o = rs.getObject(i);
statementHSQL.setObject(i, o);
if (columnName.equals(mainColumn))
deleteIds.add(String.valueOf(o));
if (!(meta.getColumnType(i) == 2004)) data.put(columnName, o);
if (columnName.equals(mainColumn)) id = rs.getObject(i);
}
int c = 1;
String update = MessageFormat.format("INSERT INTO {0}M ({1}M, MIGRATED) VALUES(?, TRUE)",
table.substring(4), mainColumn).replace("\"M", "M\"");//migrated state is saved in other table
lastId = Integer.valueOf(String.valueOf(id));
statementUpd[row] = derby.getDataSource().getConnection().prepareStatement(update);
statementUpd[row].setObject(1, rs.getObject(mainColumn));
updateSQL = new StringBuilder();
statementHSQL.addBatch();
row += 1;
}
/*
* Build delete query in case of inserted values in HSQLDB but not updated in DERBY
*/
StringBuilder builder = new StringBuilder();
builder.append("(");
int count = 1;
for (String s : deleteIds) {
if (count > 1) builder.append(", ");
builder.append("?");
count++;
}
builder.append(")");
String str = builder.toString();
String queryDelete = "DELETE FROM " + table.substring(4) + " WHERE " + mainColumn + " IN " + str;
PreparedStatement statementHSQLDel = hsql.getDataSource().getConnection().prepareStatement
(queryDelete);
int c = 1;
for (String s : deleteIds) {
statementHSQLDel.setObject(c, s);
c++;
}
boolean deletes = statementHSQLDel.execute();
statementHSQLDel.close();
try {
DatabaseUtils.close(statementHSQLDel);
} catch (Exception e) {
catchOutOfMemory(e);
}
int[] result = statementHSQL.executeBatch();
StringBuilder resultS = new StringBuilder();
int stCounter = 0;
int stCounterInsert = 0;
int stCounterUpdate = 0;
String notarydebug;
for (int i : result) {
int upd = 0;
try {
if (i == 1) upd = statementUpd[stCounter].executeUpdate();
} catch (Exception e) {
catchOutOfMemory(e);
}
stCounterInsert += i;
stCounterUpdate += upd;
resultS.append(",").append(String.valueOf(i)).append("-").append(String.valueOf(upd));
stCounter += 1;
}
statementHSQL.clearBatch();
try {
DatabaseUtils.close(statementHSQL);
} catch (Exception e) {
catchOutOfMemory(e);
}
} catch (SQLException se) {
catchOutOfMemory(se);//otherstuff
} catch (Exception e) {
catchOutOfMemory(e);
}
try {
DatabaseUtils.close(rs);
DatabaseUtils.close(statement);
} catch (Exception e) {
catchOutOfMemory(e);
}
regs=regs-cant;
}
}
}catch (Exception e) {
if (e.getMessage().equals("redo")) return true;//end the loop of regs maximun and get out of method.
}
return false;//end migration succesfully
}
private static int catchOutOfMemory(Throwable e) {
if (e == null) return 0;
if (e instanceof OutOfMemoryError) {
Application.restartBat();
return 1;
} else {
return catchOutOfMemory(e.getCause());
}
}
edit:
So I change as sugested inthe comment to accept a commit, something like this:
Connection hsqlCon;
PrepareStatement hsqlStm;
hsqlCon = JdbcHSQLDB.getDataSource().getConnection();
hsqlStm = hsqlCon.prepareStatement(sql);
hsqlStm.addBatch();
hsqlStm.execute();
hsqlStm.close();
hsqlCon.close();
but i got the same heap memory consumpsion:
The type of table in HSQLDB is not clear from the supplied code. You must use this statement once for each table, to make sure the table data is stored in the finename.data file:
SET TABLE tableName TYPE CACHED
The reported sequence of batch INSERT is not correct. Use this sequence:
Connection hsqlCon;
PrepareStatement hsqlStm;
hsqlCon = JdbcHSQLDB.getDataSource().getConnection();
hsqlStm = hsqlCon.prepareStatement(sql);
{ // repeat this block until all is finished
{ // repeat for 1000 rows
hsqlStm.addBatch();
}
hsqlStm.executeBatch(); // after every 1000 rows
}
hsqlStm.close();
hsqlCon.close();
So I selected some values from a database table to divide them in little groups and insert it into another table within the database by putting the selected values in an ArrayList and taking the size of that ArrayList to do the math.
But after I do the math, I'm just left with the variables containing the information I need. But, I cant put them into the other table because they're not the same things that I selected in the beginning. They're just numbers now. I really need to insert those variables into the other table but when I do, I get foreign key constraint fails error and I think that's because the variable is not a foreign key anymore but just a number. I don't know if there is a solution but it would help me allot. Here is my code:
private void spelersVerdelenMouseClicked(java.awt.event.MouseEvent evt) {
String comboBoxValue = jComboBoxDeelnemer.getSelectedItem().toString();
String spelerRonde1 = "SELECT lid, toernooi FROM deelnemer where toernooi LIKE " + comboBoxValue ;
ArrayList<String> dlnmrs = new ArrayList<>();
try {
PreparedStatement pstat = con.prepareStatement(spelerRonde1);
ResultSet rs = pstat.executeQuery();
while (rs.next()) {
dlnmrs.add(rs.getString("lid"));
for (int i = 0; i < dlnmrs.size(); i++) {
}
}
} catch (Exception e) {
JOptionPane.showMessageDialog(rootPane,e);
}
verdeelTafels(1, dlnmrs.size());
private void verdeelTafels(int ronde, int aantalDeelnemers) {
System.out.println(aantalDeelnemers);
int aantalTafels = (int) aantalDeelnemers / AANTAL_SPELERS_PER_TAFEL;
int restSpelerPerRonde = aantalDeelnemers % AANTAL_SPELERS_PER_TAFEL;
if (aantalDeelnemers == (AANTAL_SPELERS_PER_TAFEL * 2)) {
aantalTafels = 1;
restSpelerPerRonde = 0;
}
for (int i = 0; i < aantalTafels; i++) {
int maxSpelersPerTafel = AANTAL_SPELERS_PER_TAFEL;
if (i == aantalTafels - 1) {
maxSpelersPerTafel += restSpelerPerRonde;
}
System.out.println("Tafel " + (i + 1) + " heeft " + maxSpelersPerTafel + " deelnemers.");
//spelersDoorlopen
for (int j = 0; j < maxSpelersPerTafel; j++) {
String query = "insert into spelerPerTafel (lid,tafel,ronde) select lcode,tfcode,rcode from lid,tafel,ronde ";
try{
PreparedStatement pstat = con.prepareStatement(query);
pstat.execute(query);
}
catch (Exception e) {
JOptionPane.showMessageDialog(rootPane,e);
System.out.println(e);
}
}
}
}
try
String query = "insert into tableA select * from tableB where XXX";
using where condition can implement to divide the tableB
How do I to write an entire table to a flat file (text file) using jdbc? So far I've attempted the following:
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("SELECT * FROM tablename");
BufferedInputStream buffer;
FileOutputStream out = new FileOutputStream("flatfile.txt");
while(result.next() )
{
buffer = new BufferedInputStream(result.getBinaryStream("????") );
byte[] buf = new byte[4 * 1024]; //4K buffer
int len;
while( (len = buffer.read(buf, 0, buf.length) ) != -1 )
{
out.write(buf, 0, len );
}
}
out.close();
"????" is just my placeholder. I am stuck on what to pass in as an argument.
You can get all the column names and the entire data from your table using the code below.
writeToFile method will contain the logic to writing to file (if that was not obvious enough :) )
ResultSetMetaData metadata = rs.getMetaData();
int columnCount = metadata.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
writeToFile(metadata.getColumnName(i) + ", ");
}
System.out.println();
while (rs.next()) {
String row = "";
for (int i = 1; i <= columnCount; i++) {
row += rs.getString(i) + ", ";
}
System.out.println();
writeToFile(row);
}
Here's how I dump a table from a JDBC connection, very useful for debugging if you want to see all rows that are in an in memory (ex: HSQL) DB for instance:
public static void spitOutAllTableRows(String tableName, Connection conn) {
try {
System.out.println("current " + tableName + " is:");
try (PreparedStatement selectStmt = conn.prepareStatement(
"SELECT * from " + tableName, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = selectStmt.executeQuery()) {
if (!rs.isBeforeFirst()) {
System.out.println("no rows found");
}
else {
System.out.println("types:");
for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
System.out.print(rs.getMetaData().getColumnName(i + 1) + ":" + rs.getMetaData().getColumnTypeName(i + 1) + " ");
}
System.out.println();
while (rs.next()) {
for (int i = 1; i < rs.getMetaData().getColumnCount() + 1; i++) {
System.out.print(" " + rs.getMetaData().getColumnName(i) + "=" + rs.getObject(i));
}
System.out.println("");
}
}
}
}
catch (SQLException e) {
throw new RuntimeException(e);
}
}
output is like
current <yourtablename> is:
types:ID:INT YOURCOLUMN1:VARCHAR YOURCOLUMN2:VARCHAR
ID=1 YOURCOLUMN1=abc YOURCOLUMN2=null
ID=2 YOURCOLUMN1=def YOURCOLUMN2=ghi
...
result.getBinaryStream("????") will only return for the value for that column as you put as placeholder.
If you want to get all the column, you need to use ResultSetMetaData from ResultSet
ResultSetMetaData metadata = resultSet.getMetaData();
int columnCount = metadata.getColumnCount();
for (int i=1; i<=columnCount; i++)
{
String columnName = metadata.getColumnName(i);
System.out.println(columnName);
}
I have a webservice where from the Client-side some parameters are passed to perform a query on the DB, the Server-Side is supposed to carry out the query and return the results.Since the result might be more than one row and i will have to use it on the client-side to show an output this what i did:
1.Perform the query
2.take each row of the result and put it in an array
3.convert the array to String and pass it to the client side(converted array to String, because it was simple)
BUT the problem is that it doesnt pass the the array-turned-string but only the value which was used to initialize the string, here is the code
String ris = "";
String q;
String beta = null;
String one="";
String errore = connetti();
try {
if (errore.equals("")) {
Statement st = conn.createStatement();
//ESECUZIONE QUERY
q = "SELECT DISTINCT nome FROM malattia WHERE eta='" + age + "' AND sesso='" + sexstr + "' AND etnia='" + etniastr + "' AND sintomi IN(" + tes + ")";
ResultSet rs = st.executeQuery(q);
if (!rs.last()) {
ris = "no";
}
//This is the part which i'm talking about
else {
//getRowCount is another class used to find out number of rows,I use it to declare an array which would contain the result of the query
int two=getRowCount(rs);
String[] alpha= new String[two];
//Loop through the resultstatement and put result from the column **nome** in the array **alpha**
while(rs.next()){
alpha[i]=rs.getString("nome");
i++;
}
//The value of ris which is empty, is returned
ris="";
//instead of this one, where i convert the array **alpha** to String
ris=arrayToString(alpha,",");
}
}
else {
ris = errore;
}
conn.close();
} catch (Exception e) {
ris = e.toString();
}
return ris;
}
//returns the number of rows of **ris**
public static int getRowCount(ResultSet set) throws SQLException
{
int rowCount;
int currentRow = set.getRow(); // Get current row
rowCount = set.last() ? set.getRow() : 0; // Determine number of rows
if (currentRow == 0) // If there was no current row
set.beforeFirst(); // We want next() to go to first row
else // If there WAS a current row
set.absolute(currentRow); // Restore it
return rowCount;
}
//converts the array to String
public String arrayToString(String[] array, String delimiter) {
StringBuilder arTostr = new StringBuilder();
if (array.length > 0) {
arTostr.append(array[0]);
for (int i=1; i<array.length; i++) {
arTostr.append(delimiter);
arTostr.append(array[i]);
}
}
return arTostr.toString();
Thanks alot in advance!
After conn.close() you return beta instead of ris. This may be the cause of the behavior you are experiencing. However, I am not sure because I can not properly see how you open and close the curly brackets.