Ambiguous column using JDBC but query works fine in database - java

I am connecting to a SQLite database through java using JDBC.
Schema:
WorkInfo(id, job, salary)
Person(id, name)
This query below runs fine in my database, but when I try it with JDBC:
ResultSet rs = statement.executeQuery("select * from Person join workInfo on (Person.id=WorkInfo.id)");
while(rs.next()){
System.out.println("id: " + rs.getInt("Person.id")); //column does not exist
System.out.println("name: " + rs.getString("name")); //works fine
Output:
If using person.id: no such column: 'person.id'
Without specifying: ambiguous column name 'id'
I've tried using both WorkInfo and Person and using aliases but it keeps throwing the same ambigious column name (if left as id) or column does not exist.

It's always a good practice to explicitly retrieve the columns you want. I would change the query to be:
ResultSet rs = statement.executeQuery("select info.id, info.job, info.salary, "
+ "person.id, person.name from Person person join workInfo info "
+ "on person.id=info.id");
while(rs.next()){
System.out.println("id: " + rs.getInt(4));
System.out.println("name: " + rs.getString(5));
In this case, you can use the column index instead of the label.
Or using the AS clause:
ResultSet rs = statement.executeQuery("select info.id, info.job, info.salary, "
+ "person.id as personId, person.name as personName "
+ "from Person person join workInfo info "
+ "on person.id=info.id");
while(rs.next()){
System.out.println("id: " + rs.getInt("personId"));
System.out.println("name: " + rs.getString("personName"));

After a day of working on this, I achieved it by using resultSet.getMetaData().
private int getIndexFromMeta(String column) {
try {
ResultSetMetaData meta = resultSet.getMetaData();
String[] subs = column.split("\\.", -1);
String tableName = subs[0];
String columnName = subs[1];
for (int i = 1; i <= meta.getColumnCount(); i++) {
if (meta.getTableName(i).equals(tableName) && meta.getColumnName(i).equals(columnName)) {
return i;
}
}
} catch (SQLException e) {
Log.trace(e);
}
return 0;
}

It seems like the ResultSet you're getting back holds the following columns:
id
name
id
job
salary
You have two columns named "id" (none named "Person.id"), so when you try to get its' value you either
Ask for "id" which is ambiguous (which id?)
Ask for "Person.id" which does not exist
Simply try specifying in your query the columns you want and giving them unique aliases. For example:
ResultSet rs = statement.executeQuery("select Person.id AS 'personid', name from Person join workInfo on (Person.id=WorkInfo.id)");
while(rs.next()){
System.out.println("id: " + rs.getInt("personid"));
System.out.println("name: " + rs.getString("name"));

Related

How to Delete rows in table using Variable in SQL

How should I delete a row using a java variable in SQL table?
I am trying to delete a record from table member (with two columns, name and year) using what the user has input (variable newName and newYear). I want to find the row that has the same record as what the user has input (name = newName && year=newYear) and delete it. However, this code doesn't change anything on the table (no row is deleted although what I have input is correct). What's wrong with my code?
String newName = memName.getText();
int newYear = parseInt(memYear.getText());
are the variables used in the code below.
try {
s = c.createStatement();
t = "DELETE FROM member " +
"WHERE (name='" + newName + "'&& year='" + newYear + "')";
s.executeUpdate(t);
s.close();
c.commit();
c.close();
} catch (SQLException ex) {
Logger.getLogger(AddMember.class.getName()).log(Level.SEVERE, null, ex);
}
JOptionPane.showMessageDialog(null, "Saved.");
memName.setText(null);
memYear.setText(null);
I want the row with the info the user input to be deleted from the table, but it didn't make any changes to my table.
the problem you have is that in SQL you cannot use && instead use AND as shown in the following code:
t = "DELETE FROM member " +
"WHERE (name='" + newName + "' AND year='" + newYear + "')";

sql for update "ERROR: column "used" of relation "account" does not exist" even though it does

I have used this method without using the join in the query and it was working as expected. But I added a inner join and now it can't update the "used" column
public HashMap<String, Comparable> getPhoneNumberAndMarkAsUsed() {
String[] colNames = { "phone_number.id", "phone_number.phone_number",
"phone_number.account_id", "phone_number.used AS used",
"(now() AT TIME ZONE account.timezone)::time AS local_time" };
String query = "select " + Stream.of(colNames).collect(Collectors.joining(", "))
+ " from account INNER JOIN phone_number ON account.id = phone_number.account_id where phone_number.used = false order by id DESC limit 1 for update";
HashMap<String, Comparable> account = new HashMap<String, Comparable>();
try (Connection conn = DriverManager.getConnection(url, props); // Make sure conn.setAutoCommit(false);
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(query)) {
conn.setAutoCommit(false);
ResultSetMetaData rsmd = rs.getMetaData();
int columnsNumber = rsmd.getColumnCount();
while (rs.next()) {
for (int i = 1; i <= columnsNumber; i++) {
if (i > 1)
System.out.print(", ");
String columnValue = rs.getString(i);
System.out.print(columnValue + " " + rsmd.getColumnName(i));
}
// Get the current values, if you need them.
account.put("phone_number", rs.getString("phone_number"));
account.put("account_id", rs.getLong("account_id"));
rs.updateBoolean("used", true);
rs.updateRow();
}
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
return account;
}
the loop prints the following
7223 id, 10001234567 phone_number, 1093629 account_id, f used, 23:32:42.502472 local_time
accourding to the output above, then I am use that column "used" is part of the ResultSet. But I get the following Exception
org.postgresql.util.PSQLException: ERROR: column "used" of relation "account" does not exist
This is the query when printed
select phone_number.id, phone_number.phone_number, phone_number.account_id, phone_number.used AS used, (now() AT TIME ZONE account.timezone)::time AS local_time from account INNER JOIN phone_number ON account.id = phone_number.account_id where phone_number.used = false order by id DESC limit 1 for update
used belongs to the phone_number table not the account table. How can this be resolved?
here is the problem in your code:
rs.updateBoolean("used", true);
this statement will try to update the data of table through resultset but to do that you cannot user join and also there is one problem.
As you are updating via resultset it will try to update account table and if we find used column is account table then error occurs.
so your code is trying to find column "used" in account table but it is not there.
try this one:
String query = "select " + Stream.of(colNames).collect(Collectors.joining(", "))
+ " from phone_number INNER JOIN account phone_number ON account.id = phone_number.account_id where phone_number.used = false order by id DESC limit 1 for update";

Populating jTable from postgresql

I am doing java project in NetBeans 8 using databases and GUI.The problem is appearing when I search through the database and add the found values to JTable: all values are being added only to first column of JTable while I need them added separately to corresponding columns. I tried getColumnCount() and it also gave me 1 meaning that I have only one column. How to add database values to JTable's corresponding columns?
I've tried all the populating functions adviced here
My code:
jTable1 = new javax.swing.JTable();
String sql = "SELECT (flight_id, plane_name, dep_city, arival_city, date_month, date_day, eclassnumberofseats, bclassnumberofseats, fclassnumberofseats) FROM flight "
+ "WHERE (dep_city = '" + SearchFlight.getFromCity() + "' AND "
+ "arival_city = '" + SearchFlight.getToCity() + "' AND "
+ "date_month = '" + SearchFlight.getMonth() + "');";
PreparedStatement stat = conn.prepareStatement(sql);
ResultSet rs = stat.executeQuery();
jTable1.setModel(DbUtils.resultSetToTableModel(rs)
);
jScrollPane1.setViewportView(jTable1);
SearchFlight is a GUI class, and its methods return strings obtained in GUI.
DbUtils.resultSetToTableModel(rs)is a method in net.proteanit.sql.DbUtils;
So, it is expected that the data will be filled into 9 columns, hoewever it fills all the data into one column.
SELECT ( ... )
must be
SELECT ....
And better use the PreparedStatement as intended. Otherwise SQL injection still is possible. And try-with-resources closes the things under all circumstances.
String sql = "SELECT flight_id, plane_name, dep_city, arival_city, date_month, "
+ "date_day, eclassnumberofseats, bclassnumberofseats, fclassnumberofseats "
+ "FROM flight "
+ "WHERE dep_city = ? AND "
+ "arival_city = ? AND "
+ "date_month = ?";
try (PreparedStatement stat = conn.prepareStatement(sql)) {
stat.setString(1, SearchFlight.getFromCity());
stat.setString(2, SearchFlight.getToCity());
stat.setString(3, SearchFlight.getMonth());
try (ResultSet rs = stat.executeQuery()) {
jTable1.setModel(DbUtils.resultSetToTableModel(rs));
}
}

more efficient way to inset values into a mysql table

I have a Collection and I want to write Nodes' values into a mysql table. Right now I connect to the database, create a statement and then for each Node in the collection I run
// open the connection then
Statement statement = connect.createStatement();
for (Node n : vertices) {
statement.execute("INSERT INTO " + table + " (name, department) values ('" + n.getName() + "', '" + n.getOrgId() + "')");
}
// then I close the connection
I am wondering if is there a more efficient method to deal with such a task.
Use prepared statements:
String query = "insert into " + table + " (name, department) values (?,?)";
try(PreparedStatement ps = connection.prepareStatement(query)) {
for(Node n : vertices) {
ps.setString(1, n.getName());
ps.setInt(2, n.getOrgId());
ps.addBatch();
}
ps.executeBatch();
} catch(SQLException e) {
// Exception handling
}
Notice that because of the way your query is built it is still vulnerable to SQL injection attacs (because you are building the string with a variable table). I recommend you either remove the table variable or take measures to ensure that that variable is never visible by any user of your program.
Try to prepare the query for a multiple insert, then execute it at once:
String query = "INSERT INTO " + table + " (name, department) values";
for (Node n : vertices) {
query += " ('" + n.getName() + "', '" + n.getOrgId() + "')");
}
statement.execute(query);
You can insert multiple rows at the same time.
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
Check this Link

Adding database column to JComboBox

I've searched around for the answer to this, but to no avail. When I compile this, it just returns the last row of my table in the database and not a list of the entire column as I expect. I believe the problem is from here.. If only I can make it list everything in that column, I'd be grateful for your help.
String query = "SELECT contact_id, first_name, last_name FROM my_contacts";
ResultSet rs = statement.executeQuery(query);
while (rs.next())
{
System.out.println(rs.getInt(1) + " " + rs.getString(2) + " " + rs.getString(3));
String name = rs.getString(2) + " " + rs.getString(3);
names = new JComboBox();
names.addItem(rs.getString("first_name"));
}//end while
When I compile this, it just returns the last row of my table in the
database and not a list of the entire column as I expect. I believe
the problem is from here..
while (rs.next())
{
System.out.println(rs.getInt(1) + " " + rs.getString(2) + " " + rs.getString(3));
String name = rs.getString(2) + " " + rs.getString(3);
names = new JComboBox();
names.addItem(rs.getString("first_name"));
}
your code created a new instance of JComboBox, in each of loop inside while (rs.next()){
create JComboBox as local variable, then just to add Items in while-loop to instance that already exist and is intialized
best of ways is by using DeafultComboBoxModel for add / remove / modify an Items for JComboBox
Got everything up and running with this code.
try {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/recall", "username", "password");
Statement statement = connection.createStatement();
String query = "SELECT * FROM names";
ResultSet rs = statement.executeQuery(query);
while (rs.next())
{
String name = rs.getString("name");
names.addItem(rs.getString("name"));
}//end while
connection.close();
} catch (Exception e) {
e.printStackTrace();
}

Categories

Resources