postgres crosstab parameter - sql

I have a crosstab query (using postgres) using prepared statement
I'm trying to add a parameter (center) but it is not working here's my code:
public List<openbookBean> summarylist(String center) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
String querystring = "select team_manager as team_manager2, "
+ "compliance_1 as day1, "
+ "compliance_2 as day2, "
+ "compliance_3 as day3 "
+ "FROM crosstab('select team_manager, date_compliance, compliance from openbook_comp where("
+ "extract(day from date_compliance)= ''1'' or "
+ "extract(day from date_compliance)= ''2'' or "
+ "extract(day from date_compliance)= ''3'') "
+ "and center = '''?''' "
+ "order by 1,2') AS openbook_comp (team_manager text, "
+ "compliance_1 varchar,"
+ "compliance_2 varchar,"
+ "compliance_3 varchar)";
List<openbookBean> summarylist_array = new ArrayList<openbookBean>();
try {
connection = database.getConnection();
statement = connection.prepareStatement(querystring);
statement.setString(1, center);
resultSet = statement.executeQuery();
while (resultSet.next()) {
openbookBean summarylistarray = new openbookBean();
summarylistarray.setTeam_manager2(resultSet.getString("team_manager2"));
summarylistarray.setDay1(resultSet.getString("day1"));
summarylistarray.setDay2(resultSet.getString("day2"));
summarylistarray.setDay3(resultSet.getString("day3"));
summarylist_array.add(summarylistarray);
}
} finally {
try { resultSet.close(); } catch (SQLException logOrIgnore) {}
try { statement.close(); } catch (SQLException logOrIgnore) {}
try { connection.close(); } catch (SQLException logOrIgnore) {}
}
return summarylist_array;
}
}
and here is a part of the servlet
if (request.getParameter("show").equals("summary")) {
try {
List<openbookBean> summarylist_array = openbookDAO.summarylist(region);
request.setAttribute("summarylist_array", summarylist_array);
request.getRequestDispatcher("summary.jsp").forward(request, response);
}
catch (SQLException e) {
throw new ServletException("Cannot retrieve areas", e);
}
}
I always getting this error:
java.lang.NullPointerException
source.openbookDAO.summarylist(openbookDAO.java:358)
source.openbookServlet.doGet(openbookServlet.java:74)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

You are not closing the last parenthesis and there is an extra comma:
+ "order by 1,2') AS openbook_comp (team_manager text, "
+ "compliance_1 varchar,"
+ "compliance_2 varchar,"
+ "compliance_3 varchar)"
And you can use this:
+ "extract(day from date_compliance) in (1, 2, 3) "
If center is numeric don't use quotes and add a space after the parameter:
+ "and center = ? "
If it is not numeric try it like this:
+ "and center = '''?''' "

Related

DB2 - ERRORCODE=-4229, SQLSTATE=null

I'm using a batch class in EJB to INSERT more than 100 rows in the same commit using the command line executeBatch in the DB2.
When I execute the command shows this error: ERRORCODE=-4229, SQLSTATE=null.
The ID sequence is IDENTITY clause on the CREATE TABLE.
Table:
CREATE TABLE table (col1 INT,
col2 DOUBLE,
col3 INT NOT NULL GENERATED ALWAYS AS IDENTITY)
Does anyone have any idea?
ERROR:
Caused by: nested exception is: com.ibm.db2.jcc.am.BatchUpdateException: [jcc][t4][102][10040][4.24.97] Batch failure. The batch was submitted, but at least one exception occurred in an individual batch member.
Use getNextException() to retrieve exceptions for specific batch elements. ERRORCODE=-4229, SQLSTATE=null
It's not an answer, but a suggestion to handle Db2 exceptions to have an ability to deal with such errors.
If you are unable to rewrite your error handling, the only thing you can to is to enable JDBC trace on the client or/and set the Db2 dbm cfg DIAGLEVEL parameter to 4.
PreparedStatement pst = null;
try
{
pst = ...;
...
int [] updateCounts = pst.executeBatch();
System.out.println("Batch results:");
for (int i = 0; i < updateCounts.length; i++)
System.out.println(" Statement " + i + ":" + updateCounts[i]);
} catch (SQLException ex)
{
while (ex != null)
{
if (ex instanceof com.ibm.db2.jcc.DB2Diagnosable)
{
com.ibm.db2.jcc.DB2Diagnosable db2ex = com.ibm.db2.jcc.DB2Diagnosable) ex;
com.ibm.db2.jcc.DB2Sqlca sqlca = db2ex.getSqlca();
if (sqlca != null)
{
System.out.println("SQLCODE: " + sqlca.getSqlCode());
System.out.println("MESSAGE: " + sqlca.getMessage());
}
else
{
System.out.println("Error code: " + ex.getErrorCode());
System.out.println("Error msg : " + ex.getMessage());
}
}
else
{
System.out.println("Error code (no db2): " + ex.getErrorCode());
System.out.println("Error msg (no db2): " + ex.getMessage());
}
if (ex instanceof BatchUpdateException)
{
System.out.println("Contents of BatchUpdateException:");
System.out.println(" Update counts: ");
System.out.println(" Statement.SUCCESS_NO_INFO: " + Statement.SUCCESS_NO_INFO);
System.out.println(" Statement.EXECUTE_FAILED : " + Statement.EXECUTE_FAILED);
BatchUpdateException buex = (BatchUpdateException) ex;
int [] updateCounts = buex.getUpdateCounts();
for (int i = 0; i < updateCounts.length; i++)
System.out.println(" Statement " + i + ":" + updateCounts[i]);
}
ex = ex.getNextException();
}
}
...

Prepare Statement very slow compare with direct query | Oracle DB

I have a prepared statement in my application and it takes 3 minutes to give an results. However, same query i have executed in sql developer and it only takes less than 0.1 seconds to give the results. I have done research on this throughout last week and I couldn't find a proper solution. Here is my code.
public List<ResponseDto> loadData(RequestDto request) throws SQLException {
List<ResponseDto> responseDto = new ArrayList<>();
int sortBy = request.getSortBy();
String sql = "SELECT *" +
"FROM (SELECT r.*, ROWNUM RNUM, COUNT(*) OVER () RESULT_COUNT " +
" FROM (SELECT *" +
"FROM" +
" (SELECT r.VALUE_4," +
" r.DATE," +
" r.ID," +
" r.AMOUNT," +
" r.TO_AGENT_ID," +
" r.FROM_AGENT_ID," +
" a.NAME," +
" r.VALUE_2," +
" r.VALUE_1," +
" r.STATUS," +
" r.VALUE_3," +
" r.TEXT" +
" FROM MY_TABLE r" +
" INNER JOIN AGENT a " +
" ON a.AGENT_ID=r.TO_AGENT_ID" +
" WHERE r.STATUS = 1 " +
" AND r.ID IN" +
" (SELECT T.ID FROM TEST_TABLE T" +
" INNER JOIN AGENT af" +
" ON af.AGENT_ID = T.FROM_AGENT_ID " +
" INNER JOIN AGENT at" +
" ON at.AGENT_ID=T.TO_AGENT_ID" +
" WHERE T.FROM_AGENT_ID=?";
StringBuilder sbQuery = new StringBuilder(sql);
if (request.getToAgentId() != 0) {
sbQuery.append(" AND T.TO_AGENT_ID = ? ");
} else if (request.getQueryParam() != null && !request.getQueryParam().equalsIgnoreCase("")) {
sbQuery.append(" AND UPPER(at.NAME) like UPPER( ? ) ");
}
String secondPart =
" AND T.STATUS = 1" +
" AND TO_DATE(T.DATE) BETWEEN TO_DATE(?, 'yyyy-MM-dd') AND TO_DATE(?, 'yyyy-MM-dd')" +
" ) " +
" or r.VALUE_3=?";
sbQuery.append(secondPArt);
if (sortBy == 1) {
sbQuery.append(" ORDER BY a.NAME ");
} else if (sortBy == 2) {
sbQuery.append(" ORDER BY r.AMOUNT ");
} else if (sortBy == 3) {
sbQuery.append(" ORDER BY r.VALUE_4 ");
}
if (request.getSortingOrder() == 1) {
sbQuery.append("DESC ");
} else if (request.getSortingOrder() == 2) {
sbQuery.append("ASC ");
}
sbQuery.append(" )) R)" +
"WHERE RNUM between ? and ?");
String sqlq = sbQuery.toString();
log.info(sqlq);
try(Connection con = dataSource.getConnection(); PreparedStatement pstmt = con.prepareStatement(sbQuery.toString()) ) {
con.setAutoCommit(false);
String nameParam = "%" + request.getQueryParam() + "%";
pstmt.setLong(1, request.getFromAgentId());
if (request.getToAgentId() != 0) {
pstmt.setLong(2, request.getToAgentId());
} else if(request.getQueryParam() != null && !request.getQueryParam().equalsIgnoreCase("")) {
pstmt.setString(2, request.getQueryParam());
}
pstmt.setString(3, request.getFromDate());
pstmt.setString(4, request.getToDte());
pstmt.setString(5, request.getQueryParam());
pstmt.setLong(6, request.getFromIndex());
pstmt.setLong(7, request.getToIndex());
responseDto = helperMethod(pstmt);
con.commit();
} catch (SQLException e) {
log.error(e.getMessage());
throw e;
}
return responseDto;
}
public List<MyDto> helperMethod(PreparedStatement pstmt) throws SQLException {
List<MyDto> myDtoList = new ArrayList<>();
try( ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
MyDto myDto = new MyDto();
myDto.setValue4(rs.getLong("VALUE_4"));
myDto.setDate(rs.getDate("DATE"));
myDto.setTransactionId(rs.getLong("ID"));
myDto.setAmount(rs.getLong("AMOUNT"));
myDto.setToAgentId(rs.getLong("TO_AGENT_ID"));
myDto.setFromAgentId(rs.getLong("FROM_AGENT_ID"));
myDto.setName(rs.getString("NAME"));
myDto.setValue2(rs.getLong("VALUE_2"));
myDto.setValue1(rs.getLong("VALUE_1"));
myDto.setStatus(rs.getInt("STATUS"));
myDto.setValue3(rs.getString("VALUE_3"));
myDto.setText(rs.getString("TEXT"));
myDtoList.add(myDto);
}
}catch (Exception ex){
log.error(ex.getMessage());
throw ex;
}
return myDtoList;
}
As I said, same query works with in milliseconds. I really don't know what i am doing wrong here.
Any help would be grateful !
This is not a direct answer, but may hopefully point you in the right direction. First off, depending on your conditionals, there are different variations of what SQL is executed. I would try the following:
Edit the select string and embed a unique comment in it so we can find it in the next step. Example : "select /*mytest*/ * from ..."
Execute your program. Then locate the query in the v$sqlarea such as: select sql_id from v$sqlarea where instr(sql_fulltext,'mytest') > 0;
using the sql_id value from Step #2, execute SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR('sql_id',0));
this will show you the execution plan, and hopefully you will see the difference maybe a full table scan is happening or index not getting used. etc. Do similar steps for the direct sql query that is faster and see what the differences are.

EclipseLink doesnt accept DateString?

I got the following em Query and Exceptions:
public List<Service> findServicesFromHelperBetween(long idPerson, String from, String to) throws DAOException {
List<Service> servicesFromHelperBetween = new ArrayList<Service>();
try {
em.getTransaction().begin();
servicesFromHelperBetween = em.createQuery("SELECT S FROM Service S WHERE S.helper.idPerson = " + idPerson + " AND S.date BETWEEN " + from
+ " AND " + to).getResultList();
em.getTransaction().commit();
}
catch (Exception e) {
em.getTransaction().rollback();
throw ExceptionBuilder.findServiceFailedInDAO(e, Service.class);
}
return servicesFromHelperBetween;
}
Exception:
Exception Description: Syntax error parsing [SELECT S FROM Service S WHERE S.helper.idPerson = 8 AND S.date BETWEEN 01.11.2014 AND 30.11.2014].
[71, 73] The identification variable '01' is not following the rules for a Java identifier.
[86, 88] The identification variable '30' is not following the rules for a Java identifier.
Try putting the parameters between single quotes
em.createQuery("SELECT S FROM Service S WHERE S.helper.idPerson = " + idPerson + " AND S.date BETWEEN '" + from
+ "' AND '" + to + "'").getResultList();

Oracle vs Oracle ODBC

The following code works fine from within Oracle's SqlPlus (using Oracle 11.2.02.0g) however when I connect with and ODBC connection via C# code, I get told I have an invalid character.
Since the single quote didn't work in SQLplus, I'm assuming the characters that are consider invalid by ODBC are the double quotes. I've tried braces '{' and brackets '[' but still get the same error -> ERROR [HY000][Oracle][ODBC][Ora]ORA-00911:invalid character <-
Any help would be much appreciated. I still don't understand why SQL statements would be interpreted differently because of the connection type.
CREATE USER "AD1\EGRYXU" IDENTIFIED EXTERNALLY;
Error if ran alone that states the username conflicts with another user or role name. It does create the user in the database.
C# Code is below.
private void button1_Click(object sender, EventArgs e)
{
string happy = "";
string sql1 = "";
string sql2 = "";
string sql3 = "";
string sql4 = "";
string column;
int rownum = -1;
bool frst = false;
string dirIni = "\\\\ramxtxss021-f01\\hou_common_013\\globaluser\\";
string fileIni = "add_users.sql";
string transIniFullFileName = Path.Combine(dirIni, fileIni);
System.Data.Odbc.OdbcConnection conn = new System.Data.Odbc.OdbcConnection();
num_users = (usrdetails.Count > 0);
if (regions && num_users)
{
using (StreamWriter sw = new StreamWriter(transIniFullFileName))
{
for (int y = 0; y < usrdetails.Count; y++)
{
switch(usrdetails[y].add_del.ToUpper())
{
case "A":
sql1 = "CREATE USER \"" + usrdetails[y].userID.ToUpper() + "\" IDENTIFIED EXTERNALLY;";
sql2 = "GRANT EDMROLE TO \"" + usrdetails[y].userID.ToUpper() + "\";";
sql3 = "INSERT INTO MD_SITE_USER VALUES(generate_key(5), (select user_id from MD_SITE_USER where user_name = '" +
usrdetails[y].group + "') , {" + usrdetails[y].userID.ToUpper() + "}, " + usrdetails[y].seclev +
", '" + usrdetails[y].username.ToUpper() + "', 'U', '" + usrdetails[y].isext.ToUpper() + "', 'N');";
sw.WriteLine(sql1);
sw.WriteLine(sql2);
sw.WriteLine(sql3);
break;
case "D":
sql2 = "DELETE MD_SITE_APP_ACTION_OWNER WHERE user_id in (SELECT user_id FROM MD_SITE_USER where user_name = ‘"+ usrdetails[y].userID + "’+ and user_or_group = ‘U’);";
sql3 = "DELETE FROM MD_SITE_USER where user_name = ‘"+ usrdetails[y].userID + "’ and user_or_group = ‘U’;";
sql4 = "DROP USER "+ usrdetails[y].userID + " FROM USERS;";
sw.WriteLine(sql2);
sw.WriteLine(sql3);
sw.WriteLine(sql4);
break;
default:
MessageBox.Show("Add/Delete command argument not recognized for user\r\n" + usrdetails[y].userID + " \r\n Argument -> " + usrdetails[y].add_del);
break;
}
}
sw.Close();
}
for (int x = 0; x < region.Count; x++)
{
OdbcCommand command = new OdbcCommand();
conn.ConnectionString = "Driver={Oracle in OraClient11g_home1};" +
"Dbq=" + region[x].dbname +
";Uid=" + region[x].username + ";Pwd=" + region[x].password + ";";
try
{
string cmdTexts = File.ReadAllText(transIniFullFileName);
conn.Open();
using (conn)
{
command.Connection = conn;
command.CommandText = cmdTexts;
command.ExecuteNonQuery();
OdbcDataReader dr = command.ExecuteReader();
Form6.dataGridView2.AutoGenerateColumns = false;
if (!frst)
{
for (int i = 0; i < dr.FieldCount; i++)
{
column = dr.GetName(i);
Form6.dataGridView2.Columns.Add("col" + i, column);
Form6.dataGridView2.Columns[i].FillWeight = 1;
}
frst = true;
}
rownum++;
dataGridView1.Rows.Add();
dataGridView1.Rows[rownum].Cells[0].Value = "Results for Region -> " + Form5.region[x].dbname;
dataGridView1.Refresh();
while (dr.Read())
{
rownum++;
Form6.dataGridView2.Rows.Add();
for (int i = 0; i < dr.FieldCount; i++)
{
column = dr.GetValue(i).ToString();
Form6.dataGridView2.Rows[rownum].Cells[i].Value = column;
}
}
Form6.dataGridView2.Refresh();
Form6.dataGridView2.Show();
Form6.Show();
}
conn.Close();
Form6.dataGridView2.Refresh();
}
catch (Exception ex)
{
MessageBox.Show("Error Message: " + ex.Message);
}
}
}
else
{
if (!regions)
happy = "Error - You have not selected any regions.\r\n";
else
happy = "Regions are now selected.\r\n";
if (!num_users)
happy = happy + "Error - You have not entered any users.\r\n";
MessageBox.Show(happy);
}
File.Delete(transIniFullFileName);
}
Don't use ";" (semi-colon) in the command text..
The command text within ODBC or ODP should be a command, e.g. not a set of commands, therefore - ";" is not relevant, and is an invalid character.
it appears you are trying to run a script..
if that is your intent, it should be padded with a "begin" and "end" for the code to be able to run:
BEGIN
INSERT...;
DELETE ...;
END;
(refer to http://www.intertech.com/Blog/executing-sql-scripts-with-oracle-odp/ for more info)
Last thing - if you want to run a "create user" (or any other DDL) from within an anonymous block or a procedure you need to run it with "execute immediate" syntax:
BEGIN
execute immediate 'CREATE USER test IDENTIFIED EXTERNALLY';
END;

SQL Syntax error when using SQLCommand.EndExecuteNonQuery

I'm trying to run two SQL statements (MSSQL 2005), asynchronously in a background worker. However, when I call the EndExecuteNonQuery method on the first SqlCommand I get a 'SQL syntax error near' error.
Here is my code:
try
{
SqlCommand sqlCmd = uow.DataLayer.CreateCommand() as SqlCommand;
sqlCmd.CommandText = "DELETE FROM dbo.EligibilityRecordKeyValue WHERE EligibilityRecord IN " +
"(SELECT EligibilityRecord FROM dbo.EligibilityRecord WHERE Organization = '" + map.Organization.Oid + "')";
IAsyncResult result = sqlCmd.BeginExecuteNonQuery();
while (!result.IsCompleted)
{
worker.ReportProgress(0, "Deleting existing record keys");
System.Threading.Thread.Sleep(200);
}
count = sqlCmd.EndExecuteNonQuery(result);
}
catch (SqlException ex)
{
}
catch (InvalidOperationException ex)
{
}
finally
{
worker.ReportProgress(2, String.Format("Existing {0} records keys deleted.", count));
}
try
{
SqlCommand sqlCmd = uow.DataLayer.CreateCommand() as SqlCommand;
sqlCmd.CommandText = "DELETE FROM dbo.EligibilityRecord WHERE Organization = '" + map.Organization.Oid + "'";
IAsyncResult result = sqlCmd.BeginExecuteNonQuery();
while (!result.IsCompleted)
{
worker.ReportProgress(0, "Deleting existing records");
System.Threading.Thread.Sleep(200);
}
count = sqlCmd.EndExecuteNonQuery(result);
}
catch (SqlException ex)
{
}
catch (InvalidOperationException ex)
{
}
finally
{
worker.ReportProgress(5, String.Format("Existing {0} records deleted.", count));
}
It fails on the first count = sqlCmd.EndExecuteNonQuery(result);
Ok, adding WAITFOR DELAY's to both SQL commands seems to have resolved the issue.
sqlCmd.CommandText = String.Format("WAITFOR DELAY '00:00:05'; DELETE FROM dbo.EligibilityRecordKeyValue WHERE EligibilityRecord IN " +
"(SELECT EligibilityRecord FROM dbo.EligibilityRecord WHERE Organization = '{0}')", map.Organization.Oid);
sqlCmd.CommandText = String.Format("WAITFOR DELAY '00:00:05'; DELETE FROM dbo.EligibilityRecord WHERE Organization = '{0}'", map.Organization.Oid);
Anyone know why this happens?