I have been trying to execute an Oracle SQL query using java program through JDBC connectivity.
In the SQL query, I am using XMLAGG function.
Below is the sample of the query that is similar to what I use:
SELECT XMLAGG(XMLELEMENT(E,ename||',')).EXTRACT('//text()') "Result" FROM `employee_names`
The result is supposed to be as shown below:
Result
-------------------------------------------------------------------
SMITH,ALLEN,WARD,JONES,MARTIN,BLAKE,CLARK,SCOTT,KING,TURNER,ADAMS
When I execute this query using a Java program, I am getting null for that column value.
If anyone faced similar issue and resolved it, please let me know the solution.
Thanks
Marshal
XMLAGG returns an aggregated XML document. Did your program use xdb6.jar to parse the document? If not, then retrieval would have hit into XMLParseException when XML document is retrieved as string.
The best workaround would be to use getstringval() method of XMLAGG to retrieve the values as string.
So, your updated query string will look like the following:
String qry = "SELECT XMLAGG(XMLELEMENT(E,ename||',')).EXTRACT('//text()').getstringval()" +
" FROM employee_names";
Following sample program worked fine at my end:
import java.sql.*;
public class XMLAggTest {
public static void main(String[] args) {
try {
Connection con=null;
Class.forName("oracle.jdbc.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:hr/hr#myhost:1521:bct01");
if(con != null)
{
String upq="SELECT XMLAGG(XMLELEMENT(E,first_name||',')).EXTRACT('//text()').getstringval()" +
" FROM employees";
PreparedStatement pStat;
try {
pStat = con.prepareStatement(upq);
ResultSet rSet = pStat.executeQuery();
while(rSet.next()){
System.out.println(rSet.getString(1));
}
rSet = null;
} catch (SQLException e) {
e.printStackTrace();
}
pStat = null;
}
con.close();
} catch(Exception e){e.printStackTrace();}
}
}
Related
Code snippet:
On a button click, actionevent will be called
public void actionPerformed(ActionEvent e)
{
Function f = new Function();
Function is a nested class which i have used to establish the connection with the database.
The code snippet for function class is also provided in the end.
ResultSet rs = null;
String Cid ="cust_id";
String Pno="cust_phone";
String cat="cust_cat";
String start_date="st_date";
String Adv_amt="adv";
String Adv_end="end_date";
String Address="addr";
t2 is the Textfield name which i have used to get entry of customer name. I want to use this customer name as a PK to fetch all the other data about that customer from DB.
rs=f.find(t2.getText());
try{
if(rs.next())
{
t1.setText(rs.getString("cust_id"));
t3.setText(rs.getString("cust_phone"));
t4.setText(rs.getString("cust_cat"));
t5.setText(rs.getString("st_date"));
t6.setText(rs.getString("adv"));
t7.setText(rs.getString("end_date"));
t8.setText(rs.getString("addr"));
}
else
JOptionPane.showMessageDialog(null,"No data for this name");
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null,ex.getMessage());
}
}
Here is the code snippet for nested class Function which is inside the main class:
class Function{
Connection con=null;
ResultSet rs= null;
PreparedStatement ps = null;
public ResultSet find(String s)
{
try
{
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
con = DriverManager.getConnection("jdbc:oracle:thin:#Localhost:1521:xe","system","qwerty");
ps= con.prepareStatement("Select * from gkkdb where cust_name='?'");
ps.setString(1,s);
rs= ps.executeQuery();
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, ex.getMessage());
}
return rs;
}
}
Please help figure out the problem.
Don't put the parameter placeholder ? in single quotes.
This:
ps = con.prepareStatement("Select * from gkkdb where cust_name='?'");
should be
ps = con.prepareStatement("Select * from gkkdb where cust_name = ?");
The ? is not recognized as a placeholder if you enclose it in single quotes.
Sorting out the bind variable will fix your immediate issue.
You should explicitly specify what columns you want selected and that way you'll only get what you need (someone might add a BLOB column later) and you'll get them in the right order (someone might change the table create script before running on another DB instance, although you are looking up the columns by name, a different order would only impact if you were using positional indexes).
Ditto on the other answer re: bind variables (i.e. no quotes)
Plus, "select * from" is never a good idea, ask your DBA.
Obviously your code is for example, but you should make sure you free up any resources (Connection, Statement, ResultSet) as soon as they are done with. Use Java 7 try-with-resources.
I'm trying to print the returned value of a MySQL stored function from the JDBC code which is as follows (I am using MySQL Server 5.7.13):
package jdbc;
import java.sql.DriverManager;
import java.sql.*;
import java.util.Scanner;
public class CallableStatementsCallingFunctions {
public static void main(String... syrt)
{
try
{
try
{
Class.forName("com.mysql.jdbc.Driver");
}
catch(ClassNotFoundException e)
{
System.out.println("Error(class): "+ e);
}
try
{
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/collablestatement","root","mysql") ;
CallableStatement cs = conn.prepareCall("{call ?:=getBalance1(?)}");
String s = new Scanner(System.in).nextLine();
cs.registerOutParameter(1,Types.INTEGER);
cs.setInt(2,Integer.parseInt(s));
cs.execute();
System.out.println("Account number :" + cs.getInt(1));
conn.close();
}
catch(SQLException e)
{
System.out.println("Error(SQL) : "+e);
}
}
catch(Exception e)
{
System.out.println("Error(Fro outer try) : "+ e);
}
}
}
the stored function getBalance1(acno) is shown here
my code output is shown here
I am getting the output from the SQL command but in JDBC I am getting and SQLException saying that
parameter 1 is not an output parameter
I know that parameter 1 has been used as the placeholder of the returned value from the function in jdbc code. In prepareCall I also tried the syntax - {?:= call getBalance1(?)} , but even then getting the same Exception.
Why am I getting the exception?
I think I was getting the SQLException because I am using jdk1.8.xx in which the syntax of calling the stored function is different. The problem was solved by replacing statement
CallableStatement cs = conn.prepareCall("{call ?:=getBalance1(?)}");
in the code with
CallableStatement cs = conn.prepareCall("{? = call getBalance1(?)}");
The syntax of calling the function in the prepareCall() method as parameter is here.
getBalance1() is a MySQL FUNCTION, not a PROCEDURE, so I wouldn't expect using a JDBC CallableStatement to be applicable.
Even in your MySQL console test you are using
select getBalance1(103)
so you simply need to do the same thing in your Java code using a PreparedStatement:
PreparedStatement ps = conn.prepareStatement("select getBalance1(?)");
ps.setInt(1) = 103;
ResultSet rs = ps.executeQuery();
rs.next();
Double bal = rs.getDouble(1);
(It should be noted that since "balance" apparently refers to "money", REAL is not a good choice for the column type; details here.)
I'm using Mysql JDBC driver.. but I have some problem..
the problem is when I use SELECT Query in java source code.
When I use this query:
select * from [name of table]
I've gotten result of query from DB successfully.
but when I use this query:
select * from student where (substring(stu_name,0,1)>= '가' and substring(stu_name,0,1) < '나') ;
I've not gotten result of query from DB..
The difference thing is just that using where or not.
What's the problem?
How can I solve this problem?
this is my code below
this query isn't working
select * from student where (substring(stu_name,0,1)>= '가' and substring(stu_name,0,1) < '나') ;
this query is working very well
select * from student;
The difference thing is just only query information .. rest of the source code is the same absolutely
I added my java source code
public class Center {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String sql = "select * from student where (substring(stu_name,0,1)>= '가' and substring(stu_name,0,1) < '나') ";
String url = "jdbc:mysql://localhost:3306/test";
String driverName = "com.mysql.jdbc.Driver";
String id = "root";
String password = "jsyun0415";
Connection con = null;
PreparedStatement prepareState = null;
Statement stmt = null;
ResultSet rs = null;
ArrayList<String> list = new ArrayList<String>();
ArrayList<String> list_second = new ArrayList<String>();
try {
Class.forName(driverName);
} catch (ClassNotFoundException e) {
System.out.println("Failed to load JDBC driver..");
e.printStackTrace();
return;
}
try {
con = DriverManager.getConnection(url, id, password);
stmt = con.createStatement();
rs = stmt.executeQuery(sql);
while (rs.next()) {
list.add(rs.getNString("stu_no"));
list_second.add(rs.getNString("stu_ename"));
}
//test = list.get(2);
} catch (SQLException sqex) {
System.out.println("SQLException: " + sqex.getMessage());
System.out.println("SQLState: " + sqex.getSQLState());
} finally {
try {
if (stmt != null)
stmt.close();
if (con != null)
con.close();
if (rs != null)
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
You will need to set the the character encoding in the JDBC connection URL:
String url = "jdbc:mysql://localhost:3306/test?useUnicode=yes&characterEncoding=UTF-8";
Otherwise the character encoding between client and server is automatically detected upon connection, this means that the Korean text in your query will be wrongly encoded and will probably cause the query to return zero results.
You can read more about this in the MySQL JDBC driver documentation - Using Character Sets and Unicode
This answer suggests that there's no problem with the Java code; it's your data.
Can you run the query in the MySQL admin tool and get back a result set that's not empty? If yes, there's a problem with your Java code. There must be an error that you either aren't supplying or you swallow with an empty catch block.
Do you get an error message or stack trace, or is the result set empty? If it's the latter, perhaps there is no student row with number 20001001.
MySQL function "substring" parameter 0 is wrong, only more then zero allowed.
Here is my stored procedure:
CREATE OR REPLACE PROCEDURE VIEWBROKERS
(o_username OUT USERS.USERNAME%TYPE)
AS
BEGIN
SELECT USERNAME
INTO o_username
FROM USERS
WHERE Role_ID = 3 ;
END VIEWBROKERS;
Here is my method calling the stored procedure:
public ResultSet pullBrokers() {
ResultSet rs = null;
try {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
con = DriverManager.getConnection(Messages.getString("OracleUserManagement.0"), Messages.getString("OracleUserManagement.1"), Messages.getString("OracleUserManagement.2")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
String storedProcedure = "{call VIEWBROKERS(?)}";
CallableStatement statement = con.prepareCall(storedProcedure);
statement.registerOutParameter(1, java.sql.Types.VARCHAR);
rs = statement.executeQuery();
con.commit();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
And lastly when I tried to print out the results:
public class TEST {
public static void main(String[] args) throws SQLException{
OraclePullListOfUsers pull = new OraclePullListOfUsers();
ResultSet rs = pull.pullBrokers();
try {
while (rs.next()){
System.out.println(rs.getString(1));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
I get the error message ORA-01422: exact fetch returns more than requested number of rows
Which is strange ,because there are only two rows of data in the table...
If someone could point me in the right the direction, that would be awesome!
Looks like you're problem is not related to Java, just on the SQL side. Could it be that both those two rows in the table have Role_ID=3?
The root cause for your problem:
ORA-01422: exact fetch returns more than requested number of rows
is that PL/SQL select into statement expects a query to match to exactly one row. If the query returns no rows or if the query return more than one row (as in your case) it will throw an exception.
You can't use select into to save the results to a single out variable if the query can return more than one row. Instead your subprogram should return a cursor (that is a pointer to a record set) that your Java component can query. Note that returning a cursor is not the only option, but in your case it looks like a good starting point.
This issue has been addressed several times in StackExchange universe. Please take a look e.g.
Return many rows on a plsql Oracle10g
How to return multiple rows from the stored procedure? (Oracle PL/SQL)
Calling Oracle PL/SQL stored procedure from java middle tier using JDBC on Linux?
A Java example Using Ref Cursors To Return Recordsets.
I have created a database using SQLite. I want to update the value of a "features" column( type Blob)...but i do not know how to write the "update" statement .
This is what i tried:
try {
stat = conn.createStatement();
} catch (SQLException e) {
}
try {
byte[] b = getFunction();
stat.executeUpdate("update table set features="+b);
} catch (SQLException e) {
}
i get the follwing error :
java.sql.SQLException: unrecognized token: "[B#13a317a"
so i guess that "b" is the problem ?
[B#13a317a looks like a array to string result (b.toString() in this case). You should use a prepared statement for the blob like:
update table set features=?
An example is here.
Generally, you should never create a SQL by concatenating strings. This is the recipe for SQL injection problems.
Try this one with PreparedStatement:
Connection con = null;
PreparedStatement stmt = null;
try {
byte[] b = getFunction();
con = ...;
stmt = con.prepareStatement("update table set features=?");
stmt.setBytes(1, b);
stmt.executeUpdate();
con.commit();
}
catch (SQLException e) {
//handle exception (consider con.rollback()) and con maybe null here)
}
finally {
//close stmt and at least con here (all maybe null here)
}
Personally I am always using PreparedStatements. When you have to write a lot of this code then consider writing some Utility-Classes to reduce Boilerplate-Code.
In particular you should consider writing Utilty-Classes for null-safe calling methods on Connection, Statement and ResultSet methods when you are dealing with plain JDBC.
EDIT
What Thomas Jung wrote about preventing SQL Injections is another big pro for always using PreparedStatements. +1 for him :-)
stat.executeUpdate("update table set features="+b[0].toString());
you have to use +