Use a bind variable anywhere that you might actually change the value that is passed in.
It probably doesn't make sense, for example, to use a bind variable in the EXISTS
clause in your third example because it seems extremely unlikely that anyone would ever want to pass in a different constant for the EXISTS
clause.
In your second example, it probably does make sense to use a bind variable rather than a hard-coded status assuming that the application(s) are likely to want to run this query for different id
and status
values. On the other hand, if the code would only ever pass in a status
of 2 for this query, it probably doesn't make sense to use a bind variable. Assuming that status
is not evenly distributed, you'd be better off giving the optimizer the information that you're always going to use a status
of 2 rather than trying to rely on bind variable peeking to give the optimizer that information.
If the value is never going to change-- i.e. if the status
in your second query will always be 2-- you can execute the query as many times as you'd like and it will only appear once in v$sql
or v$sqlarea
. In my case, I'll execute the query 10 times
SQL> ed
Wrote file afiedt.buf
1* select * from v$sql where sql_text like '%jc_bind_test%'
SQL> select /* jc_literal_test */ count(*)
2 from emp
3 where ename = 'KING';
COUNT(*)
----------
1
SQL> /
COUNT(*)
----------
1
SQL> /
COUNT(*)
----------
1
SQL> /
COUNT(*)
----------
1
SQL> /
COUNT(*)
----------
1
SQL> /
COUNT(*)
----------
1
SQL> /
COUNT(*)
----------
1
SQL> /
COUNT(*)
----------
1
SQL> /
COUNT(*)
----------
1
SQL> /
COUNT(*)
----------
1
And from v$sql
or v$sqlarea
, you'll see only one row for the query that has the hard-coded literal. That row will show that the query was executed 10 times
SQL> ed
Wrote file afiedt.buf
1* select sql_text, executions, loaded_versions, parse_calls from v$sqlarea where sql_text like '%jc_literal_test%'
SQL> /
SQL_TEXT EXECUTIONS LOADED_VERSIONS PARSE_CALLS
---------------------------------------- ---------- --------------- -----------
select * from v$sql where sql_text like 1 1 1
'%jc_literal_test%'
select sql_text, executions, loaded_vers 5 1 5
ions, parse_calls from v$sql where sql_t
ext like '%jc_literal_test%'
select sql_text, executions, loaded_vers 1 1 1
ions, parse_calls from v$sqlarea where s
ql_text like '%jc_literal_test%'
select /* jc_literal_test */ count(*) 10 1 10
from emp where ename = 'KING'
Seems like you have media corruption. I would consult Automatic Diagnostic Repository (ADR) contents if there are open failures in your database. You can do that via Enterprise Manager or using RMAN command-line utility:
[oracle@oca ~]$ rman target=/
RMAN> list faliure;
If there are failures with status OPEN
listed, you can ask Data Recovery Advisor (DRA) to analyze them and recommend you the solution to repair the failures:
RMAN> advise failure;
Since you have block corruption, DRA will probably suggest you to recover the corrupted blocks and will create the appropriate script which you can run manually or in the same flow with RMAN:
RMAN> repair failure;
After failures are repaired they're automatically closed by DRA. You can check if all failures are closed with one more list failure
command in RMAN, and if not you can get another advice from DRA.
EDIT:
Since the recovery you performed didn't last long (elapsed time: 00:00:00
), I infer that the datafile wasn't written to by RMAN, and maybe even checked. Thus I would recommend you to proactively validate the database; to do that, just issue validate database
in RMAN and analyze the output. RMAN will check all datafiles (including control file and spfile) and show you if there are any corrupted blocks.
In your comment, you said that RMAN returns the message "Block Media Recovery requires Enterprise Edition" in response to one of your commands, and based on the response from RMAN to validate database
command I suspect this feature is also not available in your software edition. If your database is running in ARCHIVELOG
mode (check with select log_mode from v$database
) you could just completely restore and recover your database without loss of committed transaction, but before doing this I would make sure that your media (hard disk) is not damaged.
Best Answer
As mentioned in the comments, Oracle doesn't like the square brackets around identifiers, and it also doesn't support TOP n clauses, however, you can work around that with a couple of simple changes:
First off remove the square brackets, then move your
ORDER BY
clause in T3 to aROW_NUMBER
analytic function aliased asTOP
, then in the outer query of your scalar valued subquery (aliased asEndDate
) change theTOP 1
clause in the select statement to aTOP=1
predicate in the where clause.Also remove the
AS
from table aliases, Oracle doesn't allow it (but it's OK in column aliases.)On closer inspection of your code it looks like your scalar valued subquery is just getting the next chronological
DET_NUMERA
'sSMN_DATEC
and subtracting 1 day from it. That's something really easy to do with Oracle analytic functions without all the scalar valued subqueries: