How can i pass output associative array of pl/sql to java? - java

For Nested table i have done it in follwing way?
This is pl/sql stored procedure.
CREATE or REPLACE PROCEDURE TEST(
activationStartDate IN DATE,
activationEndDate IN DATE,
deActivationStartDate IN DATE,
deActivationEndDate IN DATE
Out_Entity OUT TEST1.RefCsr
)
AS
FirstNameListTable LIST_TABLE;
{--COMMENT :LIST_TABLE is nested table :create or replace TYPE "LIST_TABLE" as table of varchar2(20);-----Nested Table Declaration
/
}
totalSameFirstName NUMBER;
j NUMBER := 1;
BEGIN
SELECT first_name BULK COLLECT INTO FirstNameListTable FROM Employee where start_date between activationStartDate AND activationEndDate
MINUS
SELECT first_name FROM Employee where start_date between deActivationStartDate AND deActivationEndDate
OPEN Out_Entity FOR SELECT * FROM TABLE(
CAST (
FirstNameListTable AS LIST_TABLE
)
) Nos;
END;
/
My JavaCode is
--First getConnection
--prepare sql string : sql = "{ Call Test(?,?,?,?,?) } ";
--Use prepareCall function on Connection object and passed this sql string and retrived CallableStatement class object.
stmt.setTimestamp(1,activationStartDate);
stmt.setTimestamp(2,activationEndDate);
stmt.setTimestamp(3,deActivationStartDate);
stmt.setTimestamp(4,deActivationEndDate);
stmt.registerOutParameter(5,-10);
stmt.execute();
List result = new ArrayList();
ResultSet rs = (ResultSet)stmt.getObject(5);
int i=0;
while (rs.next())
{
System.out.println(i+". "+rs.getString(1));
i++;
}
Then what if i want to select more than one column from EMPLOYEE and pass to my javaCode......How my javaCode and Pl/Sql will look like?

you need to use nest loop
for example in the result set get the column count value
and try like this
List<List> result = new ArrayList()<List>;
List col = new ArrayList();
ResultSet rs = (ResultSet)stmt.getObject(5);
ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
while (rs.next())
{
col = new ArrayList();
for(int j=1;j<numberOfColumns;j++)
col.add(rs.getString(j);
result.add(col);
}
here first loop for getting the rows and the nested loop to getting the columns value
this value are store in the col list object and need to each time create new object

Related

How can I search all Columns and Update specific value SQLite

I have a SQLite database with 44 Columns and 700 rows. I created a user interface with Java ( I have two textFields and a Button) to search all columns with a specific value in first textField and update it with another value in second textField.
The problem is I don't know which column has the entered value in first textField, that's why I cant use directly "Update table_name SET column_name ..." Statement.
What I tried is ;
"Select * FROM table_name WHERE '%" + TextField.getText() + "%';
But it didn't work.
Can you help me to build right query?
You could look into FTS tables as CL mentioned but another way is to create an easier way to query every column. You would create a function to loop through every column to make its where clause and join them all together using OR. One way to automate this and save writing all 44 column names is to query the database for all the column names and use that later for the query.
public String columnsLike(String like, String... cols) {
return columnsLike(like, Arrays.asList(cols));
}
public String columnsLike(String like, List<String> cols) {
List<String> where = new ArrayList<>();
for(String column : cols) {
where.add(column+" LIKE '"+like+"'");
}
return where.stream().collect(Collectors.joining(" OR "));
}
public List<String> getColumns(String table) {
ResultSet rs = statement.executeQuery("SELECT * FROM "+table);
ResultSetMetaData rsmd = rs.getMetaData();
List<String> columns = new ArrayList<String>();
for (int i = 1; i < rsmd.getColumnCount(); ++i) { columns.add(rsmd.getColumnName(i)); }
return columns;
}
String query = "SELECT * FROM table_name WHERE "+columnsLike('%'+textField.getText()+'%', "column1", "column2", "column3", "column4", "column5");
// Result:
// SELECT * FROM table_name WHERE column1 LIKE '%hello%' OR column2 LIKE '%hello%' OR column3 LIKE '%hello%' OR column4 LIKE '%hello%' OR column5 LIKE '%hello%'
// However you could save time from writing out every column and load them once into an array.
List<String> columns = getColumns("table_name");
// Then call columnsLike('%'+textField.getText()+'%', columns);
To go about updating the values in the row that matched the select query you will have to go through the ResultSet rows and check them again in order to update that specific column. However, since I do not know if all of your columns are Strings I am using getObject() instead of getString() but you can change that if all of your columns are strings. Also, without knowing the data, multiple columns could match so this will update as many matches as it finds.
public void updateColumns(String tableName, List<String> cols, ResultSet rs, String like, String newValue) {
PreparedStatement ps = conn.prepareStatement("UPDATE "+tableName+" SET "+column+" = ? WHERE "+column+" = ? ");
while(rs.next()) {
for(String column : cols) {
String value;
if((value = rs.getObject(column).toString()).matches(".*"+like+".*")) {
ps.setString(1, newValue);
ps.setString(2, value);
ps.addBatch();
}
}
}
ps.executeBatch();
ps.close();
// rs.close();
}
// updateColumns("table_name", columns, resultSet, textField.getText(), textField2.getText());

UPDATE TABLE with dynamic COLUMN name

I have a dynamic number of data values in an array fetched from an HTML form.
Now I want to update my table with these data.
The column names are column1 , column2 ... and so on;
I have data in the array[] and number of columns to update in unumber
I am using this code but its not working.
P.S: I am new to coding so it might be naive.
for(int i=1; i<=unumber; i++)
{
String username = "someuser";
String column = "column" + Integer.toString(i);
PreparedStatement pr = null;
String query1 = "update table1 set (?) = (?) where username = (?)";
pr = con.prepareStatement(query1);
pr.setString(1, column);
pr.setString(2, array[i]);
pr.setString(3, someuser);
int s = pr.executeUpdate();
}
AFAIK, you can't use "prepared statements" for this. You can resolve it by performing the insertion in the query yourself:
String query1 = "update table1 set "+column+" = ? where username = ?";
pr = con.prepareStatement(query1);
pr.setString(1, array[i]);
pr.setString(2, someuser);
But be aware of sql injection. You better check whether the possible values of column can't be altered. Validate all input that leads to determining the column name.
Make sure a user can't specify the column his/herself: otherwise one could for instance set the column to password and set a password for some user. And then login with that password. Or one could try to set the column to '; drop table foo; select * where x
PreparedStatments can only bind values, not syntactic elements or object names, like columns, so this approach won't work. You'll have to fall back to string manipulation:
for(int i=0; i<unumber; i++) {
String username = "someuser";
String column = "column" + Integer.toString(i);;
PreparedStatement pr = null;
String query1 = "update table1 set " + column + " = (?) where username = (?)";
pr = con.prepareStatement(query1);
pr.setString(1, column);
pr.setString(2, someuser);
int s = pr.executeUpdate();
}
Moreover, since you're updating several columns with the same where clause, you could loop over the columns and construct just one update statement. It will force you to have two loops (one for constructing the query and one for binding the values once the query is prepared), but it should still be considerably faster, as you're accessing the database only once instead of N times:
String username = "someuser";
StringBuilder sql = new StringBuilder("update table1 set ");
for(int i=0; i < unumber; i++) {
sql.append("column")
.append(i).
.append(" = ?");
if (i != (unumber - 1)) {
sql.append(", ");
}
}
sql.append("where username = (?)");
PreparedStatement pr = con.prepareStatement(sql.toString());
for(int i = 0; i < unumber; i++) {
pr.setString(i, array[i]);
}
pr.setString(unumber, someuser);
int s = pr.executeUpdate();

How do I show changes in my SQL table when I combined the values using GROUP BY?

I have this database table named Store_Data and I show three columns in the JTable.
Here are the columns:
NUMBERS
AMOUNT
DATE
How do I show the other columns in the jtable? The other columns are missing
I managed to obtain combined values using this SQL command, "SELECT NUMBERS, SUM(AMOUNT) FROM Store_Data GROUP BY NUMBERS", and I managed show it in the JTable.
However, In the JTable I only see the column NUMBERS and another column showing all the sum of the AMOUNT values. I don't see the other columns in the Jtable.
Here is my code,
private JTable showRecords(Connection con)
{
try
{
column.clear();
data.clear();
_stmt = con.createStatement();
//String getColumn = "SELECT * FROM APP.NYPMTRIPLESTRAIGHT";
/*this is only a test*/
String test = "SELECT NUMBERS, SUM(AMOUNT) FROM Store_Data GROUP BY NUMBERS";
ResultSet rs = _stmt.executeQuery(test);
//this will collect the data from the database
ResultSetMetaData metaData = rs.getMetaData();
//this will count all the columns from
int column_count = metaData.getColumnCount();
for(int j = 1; j <= column_count; j++)
{
column.add(metaData.getColumnName(j));
}
while(rs.next())
{
Vector<Object> vector = new Vector<Object>();
for(int i = 1; i <= column_count; i++)
{
vector.add(rs.getObject(i));
}
data.add(vector);
}
_records = new JTable(data, column);
return _records;
} catch (SQLException ex)
{
JOptionPane.showMessageDialog(null, ex.getMessage());
}
return _records;
}
NOTE: I know it is wrong to use Vector. I am only using it for testing.
Your query sums all the values of AMOUNT and displays the sum using a Group by clause.
Group by will group similar values into one entity based on the functions used. ["sum" in your case].
You need to get the numbers and amount from your database simply
SELECT NUMBERS, AMOUNT FROM APP.NYPMTRIPLESTRAIGHT;
then display the resultset data in your JTable.
Try this:
SELECT
t1.NUMBERS,
CONCAT(YEAR(T1.DATE) , '-' , MONTH(t1.DATE) , '-' ,DAY(t1.DATE)) as DATE,
SUM(AMOUNT) AS AMOUNT
FROM table1 t1
GROUP BY 1, 2
And here you have the sqlfiddle

How to get COUNT from ResultSet object?

I am passing the following query to a ResultSet object:
String query = "SELECT COUNT( DISTINCT KEY ), SOURCE FROM MY_TBL\n" +
"GROUP BY SOURCE\n" +
"ORDER BY SOURCE";
I want to capture the counts I am getting for each SOURCE and sum them into a total. How can I capture these counts via ResultSet since COUNT isn't a column name in the ResultSet and I don't think I can return it's value via rs.getInt("COUNT")?
getInt is overloaded, use index (an int) instead of a column name:
rs.getInt(1); // the first column is 1
Try having alias
String query = "SELECT COUNT( DISTINCT KEY ) AS COUNT, SOURCE FROM MY_TBL\n" +
"GROUP BY SOURCE\n" +
"ORDER BY SOURCE";
I Think it is better to use
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * from Customer");
ResultSetMetaData rsmd = rs.getMetaData();
int numCols = rsmd.getColumnCount();
I think "getColumnCount" retinto number of column in a table instead of number of rows...

Resultset To List

I want to convert my Resultset to List in my JSP page. and want to display all the values. This is my query:
SELECT userId, userName
FROM user;
I have executed that using preparedstatement and got the Resultset. But how to convert it as a List and want to display the result like this:
userID userName
------------------
1001 user-X
1006 user-Y
1007 user-Z
You need to iterate over the ResultSet object in a loop, row by row, to pull out each column value:
List ll = new LinkedList();
ResultSet rs = stmt.executeQuery("SELECT userid, username FROM USER");
// Fetch each row from the result set
while (rs.next()) {
int i = rs.getInt("userid");
String str = rs.getString("username");
//Assuming you have a user object
User user = new User(i, str);
ll.add(user);
}
You could always use Commons DbUtils and the MapListHandler. From the doc:
ResultSetHandler implementation that
converts a ResultSet into a List of
Maps
so it'll take a lot of boilerplate code out of your hands.
A ResultSet should never get as far as a JSP. It should be mapping into a data structure or object and closed inside the method scope in which it was created. It's a database cursor, a scarce resource. Your app will run out of them soon if you persist with such a design.
var rs = stmt.executeQuery();
List<Map<String, Object>> result = new ArrayList<>();
while (rs.next()) {
Map<String, Object> resMap = new HashMap<>();
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
resMap.put(rs.getMetaData().getColumnName(i), rs.getObject(i));
}
result.add(resMap);
}
You can make a list of lists.
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM TABLE2");
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
List row = null;
List table = new List();
while(rs.next())
{
for(int i = 0; i < n; i++)
row.add(rs.next(i);
tabla.add(row)
}

Categories

Resources