Dear All,
I am working on oracle WebLogic forms & reports 12c version: (12.2.1.4)
While calling the reports with pass Lexical parameter from the parameter form the report terminated with error:
REP-56048: Engine rwEng-0 crashed., job Id: 2094.
If I pass the Lexical parameter to report locally in the report developer tool, then it works fine. When I pass only bind parameters to report, then it also works fine. The problem when passing the Lexical parameter from parameter form live.
Please help.
Well, looks like you hit a known problem. Oracle says
... check the Reports Server and engine trace files. A typical crash resembles the following in the Reports Server trace file:
<snip>
2005/6/1 3:38:36:147] State 56016 (JobManager:updateJobStatus): Job 17 status is:
Terminated with error:
REP-56048: Engine rwEng-0 crashed, job Id: 17
[2005/6/1 3:38:36:157] Debug 50103 (JobManager:notifyWaitingJobs): Master job 17
notify its duplicated jobs.
[2005/6/1 3:38:36:157] Debug 50103 (JobManager:updateJobStatus): Finished updating
job: 17
<snip>
Action to be done:
Identify the report that is causing the engine crash. You can do this by identifying the job ID. In the preceding examples, the engine crashed while running jobid 17. In the server trace file, search for the jobid = 17 Get command line string. This line contains the complete command line that includes the report name also. Enable tracing and engine diagnosis. Run the problematic report multiple times to reproduce the crash. When the crash is reproduced, pass on the trace files and diagnosis output to Oracle Support Services for analysis.
Alternatively, as you said
If I pass only bind parameters to report, then it works fine
then use bind parameters (if possible).
[EDIT], based on your comment:
If you are passing several values in the same parameter, then - if they are separated by comma - you can split that string into rows and use values as if they were returned by a subquery. It means that parameter's datatype would then be CHAR, not NUMBER.
I don't have your tables so I'm posting an example based on Scott's schema - passing EMPNO values and retrieving rows for those employees.
In Reports Builder, query would look like this:
select empno, job, ename
from emp
where empno in (select trim(regexp_substr(:par_empno, '[^,]+', 1, level))
from dual
connect by level <= regexp_count(:par_empno, ',') + 1
)
order by empno;
Testing, in SQL*Plus:
SQL> select empno, job, ename
2 from emp
3 where empno in (select trim(regexp_substr('&&par_empno', '[^,]+', 1, level))
4 from dual
5 connect by level <= regexp_count('&&par_empno', ',') + 1
6 )
7 order by empno;
Enter value for par_empno: 7369, 7499, 7521
EMPNO JOB ENAME
---------- --------- ----------
7369 CLERK SMITH
7499 SALESMAN ALLEN
7521 SALESMAN WARD
SQL>
To me, it looks as if you could use such an approach.
It could be that you are running into character set issues. Make sure you have set the correct character set in the reports server configuration file
Related
Is there a way to disable/restrict/alert-when-using some column in Oracle in a where clauses?
The reason that I'm asking this is because I have a very complex system (~30 services span cross millions of lines of code with thousends of sqls in it, in a sensitive production environment) working with an Oracle DB I need to migrate from using one column that is part of a key (and have a very not uniqu name) to another column.
Simple search is impossible....
The steps I'm having are:
populate new column
Add indexes on with the second column whenever there's an index with the first one.
Migrate all uses in where caluses from old to new column
Stop reading from the first column
Stop writing to the first column
Delete the column
I'm currently done step 3 and want to verify I've found all of the cases.
So, you're replacing one column with another. Which benefit do you expect once you're done? How will that improve overall experience with that application? I hope it is worth the effort.
As of your question: query user_source (or expand it to all_source or even dba_source, but you'll need additional privileges to do that) and see where's that very not unique name used. Something like this:
SQL> select * from user_source where lower(text) like '%empno%';
NAME TYPE LINE TEXT
--------------- ------------ ----- --------------------------------------------------------------------------------
P_RAISE PROCEDURE 22 WHERE empno = par_empno;
P_RAISE PROCEDURE 14 WHERE empno = par_empno;
P_RAISE PROCEDURE 1 PROCEDURE p_raise (par_empno IN emp.empno%TYPE)
GET_LIST FUNCTION 7 'select empno, ename, job, sal from emp where deptno = 10 order by '
SQL>
I'm using Spring Data R2DBC with Oracle 11g and I have the following error using method findById of R2dbcCrudRepository
executeMany; bad SQL grammar [SELECT GAME_PHASE.* FROM GAME_PHASE WHERE GAME_PHASE.ID = :P0_id FETCH FIRST 2 ROWS ONLY]
This is the repository declaration
public interface ReactiveGamePhaseRepository extends R2dbcRepository<GamePhase, Long> {
}
I don't understand why FETCH FIRST 2 ROWS ONLY is added to the query and it's the cause of problem.
I have the same problem writing the query using R2dbcEntityTemplate like below:
r2dbcEntityTemplate.selectOne(query(where("id").is(id)), GamePhase.class);
And these are the used dependancies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
<version>2.5.12</version>
</dependency>
<dependency>
<groupId>com.oracle.database.r2dbc</groupId>
<artifactId>oracle-r2dbc</artifactId>
<version>1.0.0</version>
</dependency>
I don't know anything about products you tagged (except Oracle) so I don't know whether this will help or not. Hopefully, it will).
FETCH FIRST 2 ROWS ONLY is added to the query and it's the cause of problem.
That's because - I presume - your Oracle database version doesn't support that syntax. I guess it is 11g or lower. See a demo:
Oracle 11g:
SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
SQL> SELECT *
2 FROM emp
3 WHERE deptno = 10
4 FETCH FIRST 2 ROWS ONLY;
FETCH FIRST 2 ROWS ONLY
*
ERROR at line 4:
ORA-00933: SQL command not properly ended --> that's your "bad grammar"
Oracle 18c:
SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production
SQL> SELECT *
2 FROM emp
3 WHERE deptno = 10
4 FETCH FIRST 2 ROWS ONLY;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7782 CLARK MANAGER 7839 09.06.81 2450 10
7839 KING PRESIDENT 17.11.81 5000 10
SQL>
So, what can you do? Rewrite the query (if possible). For example:
SQL> WITH
2 temp
3 AS
4 (SELECT e.*, ROW_NUMBER () OVER (ORDER BY NULL) rn
5 FROM emp e
6 WHERE deptno = 10)
7 SELECT *
8 FROM temp
9 WHERE rn <= 2;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO RN
---------- ---------- --------- ---------- -------- ---------- ---------- ---------- ----------
7782 CLARK MANAGER 7839 09.06.81 2818 1 10 1
7839 KING PRESIDENT 17.11.81 5750 1 10 2
SQL>
(Note that - without the ORDER BY clause - you can't really know which rows will be returned. If you're happy with any two rows, then OK. If not, include ORDER BY).
I think Littlefoot did a great job explaining why this is causing problems for you. Let me explain why that clause is there in the first place.
selectOne has the following contract:
Execute a SELECT query and convert the resulting item to an entity ensuring exactly one result.
This means it needs to try to fetch at least 2 elements to ensure that there actually isn't a second element.
This could be done by selecting all matching rows.
But it would never look at anything beyond the second row, so all the other rows would be selected in vain.
And possibly worse, the execution plan might differ significantly when the database tries to load all rows vs when it only tries to fetch the first few.
Therefore the limit is applied to the query.
It uses the syntax that works for later versions of Oracle because those are the only ones supported by Spring Data JDBC.
You could avoid the problem by creating and registering your own Dialect that does not support any kind of limiting or paging and replaces ist with a noop.
Of course you need to make sure that you don't try to use such features in your application, since they obviously won't work.
Due to the interesting syntax required by older Oracle versions to implement this correctly it is not easily possible to properly implement paging and limiting for older Oracle versions.
The better option would be to migrate to a recent version of Oracle, although it is understood, that this often isn't easy for a variety of reasons.
Of course you always have the alternative to create your SQL statements in your code using either #Query annotations or custom methods.
If you're willing to use a third party library, you could translate the Oracle 12c compatible SQL using FETCH FIRST to Oracle 11g compatible SQL using jOOQ's ParsingConnection, which acts like an R2DBC Connection proxy, translating all incoming SQL to the target dialect. On Oracle 11g, the FETCH clause will be generated via ROWNUM filtering.
You could obviously also replace your Spring Data usage by jOOQ API usage to get the correct behaviour automatically. jOOQ supports R2DBC out of the box.
If that's not an option, then you'll have to write your SQL manually instead of relying on the DSL API of Spring Data or other third parties.
Disclaimer: I work for the company behind jOOQ.
My understanding as per standard practice is that HAVING is to be used along with GROUP BY for filtering conditions, while WHERE is supposed to be used for general row-wise filtering conditions.
However, there are online discussions with mixed conclusions as to whether use HAVING as a superset of WHERE clause. That is, whether it can be used even without GROUP BY in which case it works as a WHERE clause.
I want to understand what is the industry practice in using HAVING clause across Oracle, Microsoft SQL server, MySQL, PostGreSQL and other tools.
A funny thing I observed when executing this query:
SELECT *
FROM SH.SALES
WHERE amount_sold > 1000
HAVING amount_sold < 2000;
It gives an error when executing in Oracle SQL developer desktop whereas runs successfully in Oracle SQL developer web.
This is a great question AND puzzle!
Oracle SQL Developer Web is provided via Oracle REST Data Services (ORDS). There is a RESTful Web Service used to execute 'ad hoc' SQL statements and scripts.
Instead of bringing back all the rows from a query in a single call, we page them. And instead of holding a resultset open and process running, we stick to the RESTful way, and do all the work on a single call and response.
How do we make this happen?
Well, when you type in that query from your question and execute it, on the back end, that's not actually what gets executed.
We wrap that query with another SELECT, and use the ROW_NUMBER() OVER analytic function call. This allows us to 'window' the query results, in this case between rows 1 and 26, or the the first 25 rows of that query, your query.
SELECT *
FROM (
SELECT Q_.*,
ROW_NUMBER() OVER(
ORDER BY 1
) RN___
FROM (
select *
from sh.sales
where amount_sold > 1000
having amount_sold < 2000
) Q_
)
WHERE RN___ BETWEEN :1 AND :2
Ok, but so what?
Well, Optimizer figures out this query can still run, even if the having clause isn't appropriate.
The optimizer is always free to re-arrange a query before searching for best execution plans.
In this case, a 10053 trace shows that a query such as below that came from SQL Dev Web (I'm using EMP but the same applies for any table)
SELECT *
FROM (
SELECT Q_.*,
ROW_NUMBER() OVER(
ORDER BY 1
) RN___
FROM (
SELECT *
FROM emp
WHERE sal > 1000
HAVING sal < 2000
) Q_
)
WHERE RN___ BETWEEN :1 AND :2
got internally transformed to the following before being optimized for plans.
SELECT
subq.EMPNO EMPNO,
subq.ENAME ENAME,
subq.JOB JOB,
subq.MGR MGR,
subq.HIREDATE HIREDATE,
subq.SAL SAL,subq.COMM COMM,
subq.DEPTNO DEPTNO,
subq.RN___ RN___
FROM
(SELECT
EMP.EMPNO EMPNO,
EMP.ENAME ENAME,
EMP.JOB JOB,EMP.MGR MGR,
EMP.HIREDATE HIREDATE,
EMP.SAL SAL,
EMP.COMM COMM,
EMP.DEPTNO DEPTNO,
ROW_NUMBER() OVER ( ORDER BY NULL ) RN___
FROM EMP EMP
WHERE EMP.SAL>1000 AND TO_NUMBER(:B1)>=TO_NUMBER(:B2)
) subq
WHERE subq.RN___>=TO_NUMBER(:B3)
AND subq.RN___<=TO_NUMBER(:B4)
Notice the HAVING has been transformed/optimized out of the query, which lets it pass through onto the execution phase.
Major 👏 to #connor-mcdonald of AskTom fame for helping me parse this out.
And so that's why it works in SQL Developer Web, but NOT in SQL Developer Desktop, where the query is executed exactly as written.
I need to combine multiple rows in Oracle SQL but have no access to LISTAGG or wm_concat (EVALUATE_AGGR disabled).
Note: I need this to work in Oracle OBIEE 11.1.1.9.
Grateful for any help or tips at all.
Ugh. I hate writing this as an Answer, but I found that the sys_connect_by_path solutions, both at Oracle-Base (see Alex Poole's comment) and on William Robertson's web site (quoted in the Oracle-Base article), are less than perfect, and this won't fit in a comment.
Oracle-Base link: https://oracle-base.com/articles/misc/string-aggregation-techniques#row_number
William Robertson web site: http://www.williamrobertson.net/documents/one-row.html
The solution on Oracle-Base uses two calls to row_number() when only one is needed, and it uses an aggregate query instead of connect_by_isleaf. Perhaps that's the solution originally posted by William, but his page currently has the better solution, using just one row_number() call and connect_by_isleaf instead of aggregation.
However, on William's page, he uses ltrim() without the argument that shows which character to trim, so in fact it has no effect. And he subtracts 1 from the value of row_number(), so in the result the first token in each comma-separated list is left out.
Here is the corrected solution - for reference; I claim no originality to any of this. The illustration is run on the EMP table in the standard SCOTT schema.
select deptno
, ltrim(sys_connect_by_path(ename,','), ',') as name_list
from ( select deptno
, ename
, row_number() over (partition by deptno order by ename) as seq
from emp )
where connect_by_isleaf = 1
connect by seq = prior seq + 1 and deptno = prior deptno
start with seq = 1;
DEPTNO NAME_LIST
------ ------------------------------------
10 CLARK,KING,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
Is there a option to see if existing table/record from a Oracle database is updated?
From a monitoring perspective (not intended to find previous changes), you have several options including but not limited to triggers, streams, and a column with a default value of sysdate. A trigger will allow you to execute a bit of programming logic (stored directly in the trigger or in an external database object) whenever the record changes (insert, update, delete). Streams can be used to track changes by monitoring the redo logs. One of the easiest may be to add a date column with a default value of sysdate.
Are you talking about within a transaction or outside of it?
Within our program we can use things like SQL%ROWCOUNT to see whether our DML succeeded...
SQL> set serveroutput on size unlimited
SQL> begin
2 update emp
3 set job = 'SALESMAN', COMM=10
4 where empno = 8083;
5 dbms_output.put_line('Number of records updated = '||sql%rowcount);
6 end;
7 /
Number of records updated = 1
PL/SQL procedure successfully completed.
SQL>
Alternatively we might test for SQL%FOUND (or SQL%NOTFOUND).
From outside the transaction we can monitor ORA_ROWSCN to see whether a record has changed.
SQL> select ora_rowscn from emp
2 where empno = 8083
3 /
ORA_ROWSCN
----------
83828715
SQL> update emp
2 set comm = 25
3 where empno = 8083
4 /
1 row updated.
SQL> commit
2 /
Commit complete.
SQL> select ora_rowscn from emp
2 where empno = 8083
3 /
ORA_ROWSCN
----------
83828780
SQL>
By default ORA_ROWSCN is set at the block level. If you want to track it at the lower level your need to create the table with the ROWDEPENCIES keyword.
These are ad hoc solutions. If you want to proactive monitoring then you need to implementing some form of logging. Using triggers to write log records is a common solution. If you have Enterprise Edition you should consider using Fine Grained Auditing: Dan Morgan's library has a useful demo of how to use FGA to track changes.
You can see if a table definition has change by querying the last_ddl_time from the user_objects view.
Without using triggers or materialized logs (which would be a total hack) there is no way I know of to see when any particular row in a table has been updated.