Clob in where clause
Hi
I'm trying to query simple select where in clause is Clob but it's not working.
set serveroutput on
declare
l_clob clob := '''SYS''';
l_clob2 clob :=null;
vzm varchar2(15);
begin
dbms_output.put_line( to_char(l_clob) );
select username into l_clob2 from dba_users where username = to_char(l_clob);
dbms_output.put_line( to_char(l_clob2) );
end;
so l_clob is returned as string 'SYS'
but l_clob2 show errors :
ORA-01403: no data found
ORA-06512: at line 9
01403. 00000 - "no data found"
#which is not right because there is user SYS in dba_users.
so my question is how to use clob in where clause to query some table? this is just a easiest example ;
ok thanks in one value it's working but how with this example
when I have a list of values to IN() clause so clob like 'SYS','SYSTEM'.etc
set serveroutput on
declare
l_clob clob := '''SYS'',';
l_clob2 clob :=null;
vzm varchar2(15);
begin
vzm:='''SYSTEM''';
dbms_lob.writeappend( l_clob, length(vzm),vzm );
dbms_output.put_line( to_char(l_clob) );
select username into l_clob2 from dba_users where username IN(to_char(l_clob));
dbms_output.put_line( to_char(l_clob2) );
end;
l_clob is 'SYS','SYSTEM' so it should be fit to IN('SYS','SYSTEM') but it not:
l_clob2 ORA-01403: no data found
ORA-06512: at line 9
01403. 00000 - "no data found"
*Cause:
how to do it when the list of user is really long more then 600 and i have to use IN clause with ' ,' in it?
Similar Messages
-
Using CLOB datatypes in WHERE clause
Hi All,
I have a table with two columns as CLOB datatype. I'm using Oracle 8i Enterprise Edition. I can do a query, insert, update and even delete the data in the CLOB field using Oracle's SQL Plus.
What I want is to do a search on those fields.. that is include that field in a WHERE clause. I'm using this datatype to store large number of data.
I'd like to see this query working...
SELECT * FROM MyTable WHERE CLOBFLD LIKE 'Something...';
Now this query doesn't work. It returns: 'Inconsistent datatype' near the word CLOBFLD.
Please Help me out.
Regards,
Gopi
nullI presume you want to query based on the contents of the CLOB, right ? If that is true, then you have to create a text index, using Oracle Context and then use "Contains" in the where clause to query. Hope this helps.
-
Is it possible to use LONG columns in WHERE clause or ORDER BY?
Is it possible to use LONG columns in WHERE clause or ORDER BY?
Hi,
LONG data type is deprecated, maybe could you change your column type to LOB ?
Nonetheless below is a workaround which may fit your needs if forced to use LONG.
It uses a function which returns you a CLOB. It allows you to use the converted "LONG" column in a WHERE clause.
Then if you want to order by you have to convert the CLOB to a VARCHAR using DBMS_LOB.SUBSTR.
SQL> CREATE TABLE my_table (id NUMBER, description LONG);
Table created.
SQL> INSERT INTO my_table VALUES (1, 'FIRST LONG');
1 row created.
SQL> INSERT INTO my_table VALUES (2, 'ANOTHER LONG');
1 row created.
SQL> COMMIT;
Commit complete.
SQL> CREATE TYPE my_type_row AS OBJECT (id INTEGER, description CLOB);
2 /
Type created.
SQL> CREATE TYPE my_type_table AS TABLE OF my_type_row;
2 /
Type created.
SQL> CREATE OR REPLACE FUNCTION get_my_long
2 RETURN my_type_table
3 PIPELINED
4 AS
5 v_tab my_type_table := my_type_table ();
6 BEGIN
7 FOR cur IN (SELECT id, description FROM my_table)
8 LOOP
9 PIPE ROW (my_type_row (cur.id, cur.description));
10 END LOOP;
11 RETURN;
12 END;
13 /
Function created.
SQL> SELECT
2 id,
3 description
4 FROM
5 TABLE (get_my_long ())
6 WHERE
7 description LIKE '%LONG'
8 ORDER BY
9 DBMS_LOB.SUBSTR(description);
ID DESCRIPTION
2 ANOTHER LONG
1 FIRST LONG
SQL> SELECT
2 id,
3 description
4 FROM
5 TABLE (get_my_long ())
6 WHERE
7 description LIKE 'FI%';
ID DESCRIPTION
1 FIRST LONG
SQL>Kind regards,
Ludovic -
Hi,
I have code as below
Scenario1
FOR i in (Select .................... from table1 Where id in(select id from Sample_table where status='Submit'))
Loop
End loop;
Scenario2
FOR i in (Select .................... from table1 Where id in(select id from Sample_table where status='Saved'))
Loop
End loop;
Scenario3
FOR i in (Select .................... from table1 Where id in(select id from Sample_table where status='Inprogress'))
Loop
End loop;Query is same here but only chage is where clause
Total length of this query is exceeding varchar2 length. so i cant use variable to hold this query and append where clause dynamically.
Do we have any other method to change where clause dynamically?>
We have around 200 columns to select from multiple tables...Here I gave sample code...
so its exceeding length
>
So 200 columns at 30 bytes per column name is only 6000 bytes. That means the rest of the query is using over 26000 bytes: 260 lines of query if each line was 100 bytes long.
You need to rethink what you are doing. So far your queries are too big, your row-by-row processing is a terrible way to process data and repeating that process multiple times just aggravates the performance even more.
I can't imagine there is ANY justification for doing things that way.
Even if you HAD to do things that way you couldn't exceed the CLOB length so why aren't you using a CLOB variable?
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/openfor_statement.htm
>
OPEN-FOR StatementThe OPEN-FOR statement executes the SELECT statement associated with a cursor variable. It allocates database resources to process the statement, identifies the result set (the rows that meet the conditions), and positions the cursor variable before the first row in the result set.
With the optional USING clause, the OPEN-FOR statement processes a dynamic SELECT statement that returns multiple rows: it associates a cursor variable with the SELECT statement, executes the statement, identifies the result set, positions the cursor before the first row in the result set, and zeroes the rows-processed count kept by %ROWCOUNT.
dynamic_string
A string literal, string variable, or string expression that represents any SQL statement. It must be of type CHAR, VARCHAR2, or CLOB. -
Derive found flag in SQL with where clause using TABLE(CAST function
Dear All,
Stored procedure listEmployees
==========================
CREATE OR REPLACE TYPE STRING_ARRAY AS VARRAY(8000) OF VARCHAR2(15);
empIdList STRING_ARRAY
countriesList STRING_ARRAY
SELECT EMP_ID, EMP_COUNTRY, EMP_NAME, FOUND_FLAG_
FROM EMPLOYEE WHERE
EMP_ID IN
(SELECT * FROM TABLE(CAST(empIdList AS STRING_ARRAY))
AND EMP_COUNTRY IN
(SELECT * FROM TABLE(CAST(countriesList AS STRING_ARRAY))
=================
I have a stored procedure which lists the employees using above simple query.
Here I am using table CAST function to find the list of employees in one go
instead of looping through each and every employee
Everything fine until requirements forced me to get the FOUND_FLAG as well.
Now I wanted derive the FOUND_FLAG by using rownum, rowid, decode functions
but I was not successful
Can you please suggest if there is any intelligent way to say weather the
row is found for given parameters in the where clause?
If not I may have to loop through each set of empIdList, countriesList
and find the values individually just to set a flag. In this approach I can’t use
the TABLE CAST function which is efficient I suppose.
Note that query STRING_ARRAY is an VARRAY. It is very big in size and this procedure
suppose to handle large sets of data.
Thanks In advance
Regards
Charan
Edited by: kmcharan on 03-Dec-2009 09:55
Edited by: kmcharan on 03-Dec-2009 09:55If your query returns results, you have found them... so your "FOUND" flag might be a constant,...
-
Index usage in depending on where clause changes.
Hello Friends,
I need your help for one issue.
I have one query , which is using two table Say T1 and T2, where C1 is common column using which both are joined.
C1 is primary key in T1, but no index available in T2 for C1. T1C2 is the column which we want to select.
(Note that Either of table can be a Master table)
Now see the query:
Select T1C2
From T1, T2
where T2.C1 = T1.C1
Here where clause may have other conditions and From clause may have others tables as per requirements.
I want to know that, if, I change the query like following to let my query use the available index of T1.C1.
Select T1C2
from T1, T2
where T1.C1 = T2.C1
Then, Will the query use the available index of T1. and Will i get better performance. Even a little improvement in performance may help me a lot as this kind of query is being used within a where loop (so it is going to be executed multiple times).
Please advise on this..
Regards,
Dipali..Hi,
18:43:17 rel15_real_p>create table t1(c1 number primary key, c2 number);
Table created.
18:43:26 rel15_real_p>create table t2(c1 number, c2 number);
18:45:08 rel15_real_p>
18:45:09 rel15_real_p>begin
18:45:09 2 for i in 1..100
18:45:09 3 loop
18:45:09 4 insert into t1(c1,c2) values (i,i+100);
18:45:09 5 end loop;
18:45:09 6 commit;
18:45:09 7 end;
18:45:09 8 /
PL/SQL procedure successfully completed.
18:45:09 rel15_real_p>
18:45:09 rel15_real_p>
18:45:09 rel15_real_p>begin
18:45:09 2 for i in 1..100
18:45:09 3 loop
18:45:09 4 insert into t2(c1,c2) values (i,i+200);
18:45:09 5 end loop;
18:45:09 6 commit;
18:45:09 7 end;
18:45:09 8 /
18:45:23 rel15_real_p>select count(*) from t1;
COUNT(*)
100
18:45:30 rel15_real_p>select count(*) from t2;
COUNT(*)
100
18:45:49 rel15_real_p>select index_name,index_type from user_indexes where table
_name='T1';
INDEX_NAME INDEX_TYPE
SYS_C0013059 NORMAL
18:48:21 rel15_real_p>set autotrace on
18:52:25 rel15_real_p>Select T1.C2
18:52:29 2 From T1, T2
18:52:29 3 where T2.C1 = T1.C1
18:52:29 4 /
C2
101
102
103
104
105
C2
200
100 rows selected.
Execution Plan
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=7 Card=100 Bytes=
900)
1 0 HASH JOIN (Cost=7 Card=100 Bytes=3900)
2 1 TABLE ACCESS (FULL) OF 'T1' (TABLE) (Cost=3 Card=100 By
es=2600)
3 1 TABLE ACCESS (FULL) OF 'T2' (TABLE) (Cost=3 Card=100 By
es=1300)
Statistics
0 recursive calls
0 db block gets
21 consistent gets
0 physical reads
0 redo size
1393 bytes sent via SQL*Net to client
562 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
100 rows processed
18:52:31 rel15_real_p>analyze table t1 compute statistics;
Table analyzed.
18:55:35 rel15_real_p>analyze table t2 compute statistics;
18:55:38 rel15_real_p>set autotrace on
18:55:42 rel15_real_p>Select T1.C2
18:55:43 2 From T1, T2
18:55:45 3 where T2.C1 = T1.C1
18:55:46 4 /
C2
101
102
103
104
105
C2
200
100 rows selected.
Execution Plan
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=6 Card=100 Bytes=7
00)
1 0 MERGE JOIN (Cost=6 Card=100 Bytes=700)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T1' (TABLE) (Cost=2 Ca
rd=100 Bytes=500)
3 2 INDEX (FULL SCAN) OF 'SYS_C0013059' (INDEX (UNIQUE)) (
Cost=1 Card=100)
4 1 SORT (JOIN) (Cost=4 Card=100 Bytes=200)
5 4 TABLE ACCESS (FULL) OF 'T2' (TABLE) (Cost=3 Card=100 B
ytes=200)
Statistics
1 recursive calls
0 db block gets
23 consistent gets
0 physical reads
0 redo size
1393 bytes sent via SQL*Net to client
562 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
100 rows processed
18:56:56 rel15_real_p>Select T1.C2
18:56:56 2 From T1, T2
18:56:56 3 where T1.C1 = T2.C1
18:56:58 4 /
C2
101
102
103
104
105
C2
200
100 rows selected.
Execution Plan
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=6 Card=100 Bytes=7
00)
1 0 MERGE JOIN (Cost=6 Card=100 Bytes=700)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T1' (TABLE) (Cost=2 Ca
rd=100 Bytes=500)
3 2 INDEX (FULL SCAN) OF 'SYS_C0013059' (INDEX (UNIQUE)) (
Cost=1 Card=100)
4 1 SORT (JOIN) (Cost=4 Card=100 Bytes=200)
5 4 TABLE ACCESS (FULL) OF 'T2' (TABLE) (Cost=3 Card=100 B
ytes=200)
Statistics
1 recursive calls
0 db block gets
23 consistent gets
0 physical reads
0 redo size
1393 bytes sent via SQL*Net to client
562 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
100 rows processed- Pavan Kumar N -
Urgent: Performance problem with where clause using IN and an OR condition
Select statement is:
select fl.feed_line_id
from ap_expense_feed_lines_all fl
where ((:1 is not null and
fl.feed_line_id in (select distinct r2.object_id
from xxdl_pcard_wf_routing_lists r2,
per_people_f hr2
where upper(hr2.full_name) like upper(:1||'%')
and hr2.person_id = r2.person_id
and r2.fyi_list is null
and r2.sequence_number <> 0))
or
(:1 is null))
If I modify the statement to remove the "or (:1 is null))" part at the bottom of the where clause, it returns in .16 seconds. If I modify the statement to only contain the "(:1 is null))" part of the where clause, it returns in .02 seconds. With the whole statement above, it returns in 477 seconds. Anyone have any suggestions?
Explain plan for the whole statement is:
(1) SELECT STATEMENT CHOOSE
Est. Rows: 10,960 Cost: 212
FILTER
(2) TABLE ACCESS FULL AP.AP_EXPENSE_FEED_LINES_ALL [Analyzed]
(2) Blocks: 8,610 Est. Rows: 10,960 of 209,260 Cost: 212
Tablespace: APD
(6) TABLE ACCESS BY INDEX ROWID HR.PER_ALL_PEOPLE_F [Analyzed]
(6) Blocks: 4,580 Est. Rows: 1 of 85,500 Cost: 2
Tablespace: HRD
(5) NESTED LOOPS
Est. Rows: 1 Cost: 4
(3) TABLE ACCESS FULL XXDL.XXDL_PCARD_WF_ROUTING_LISTS [Analyzed]
(3) Blocks: 19 Est. Rows: 1 of 1,303 Cost: 2
Tablespace: XXDLD
(4) UNIQUE INDEX RANGE SCAN HR.PER_PEOPLE_F_PK [Analyzed]
Est. Rows: 1 Cost: 1
Thanks in advance,
PeterThanks for the reply, but I have already checked what you are suggesting and I am pretty sure those are not causing the problem. The hr2.full_name column has an upper index and the (4) line of the explain plan shows that index being used. In addition, that part of the query executes on its own quickly.
Because the sql is not displayed in an indented format on this page it is a little hard to understand the structure so I am going to restate what is happening.
My sql is:
select a_column
from a_table
where ((:1 is not null) and a_column in (sub-select statement)
or
(:1 is null))
The :1 bind variable is set to a varchar2 entered on the screen of an application.
If I execute either part of the sql without the OR condition, performance is good.
If the :1 bind variable is null with the whole sql statement (so all rows or a_table are returned), performance is still good.
If the :1 bind variable is a not-null value with the whole sql statement, performance stinks.
As an example:
where (('wa' is not null) and a_column in (sub-select statement)) -- fast
where (('wa' is null)) -- fast
where (('' is not null) and a_column in (sub-select statement) -- fast
or
('' is null))
where (('wa' is not null) and a_column in (sub-select statement) -- slow
or
('wa' is null)) -
Cardinality estimator 2014 is off with OR in where clause
Here is my test setup on SQL Server 2014.
-- Create big table
CREATE TABLE [dbo].[Store](
Id int IDENTITY(1,1) NOT NULL,
City int NOT NULL,
Size int NOT NULL,
Name varchar(max) NULL,
CONSTRAINT [PK_Store] PRIMARY KEY CLUSTERED ([Id] ASC)
GO
CREATE NONCLUSTERED INDEX [IX_Store] ON [dbo].[Store] (City ASC, Size ASC)
GO
-- Fill with 100k rows
INSERT Store
SELECT i % 101, i % 11, 'Store ' + CAST(i AS VARCHAR)
FROM
(SELECT TOP 100000 ROW_NUMBER() OVER (ORDER BY s1.[object_id]) AS i
FROM sys.all_objects s1, sys.all_objects s2) numbers
GO
-- Create small table
CREATE TABLE #StoreRequest (City int NOT NULL, Size int NOT NULL)
GO
INSERT #StoreRequest values (55, 1)
INSERT #StoreRequest values (66, 2)
Now I execute the following query (I force the index to show statistics estimates)
SELECT s.City
FROM #StoreRequest AS r
INNER JOIN Store AS s WITH(INDEX(IX_Store), FORCESEEK)
ON s.City = r.City AND s.Size = r.Size
WHERE s.Size <> 1 OR r.City <> 55
Here are the estimates that I get (I'm not allowed to upload pictures):
Index Seek IX_Store
Actual Number of Rows: 90
Estimated Number of Rows: 50000
Fixing WHERE clause to use one table not two makes the estimate perfect:
SELECT s.City
FROM #StoreRequest AS r
INNER JOIN Store AS s WITH(INDEX(IX_Store), FORCESEEK)
ON s.City = r.City AND s.Size = r.Size
WHERE s.Size <> 1 OR s.City <> 55
Index Seek IX_Store
Actual Number of Rows: 90
Estimated Number of Rows: 89.74
Switching to 2012 compatibility mode gives estimate of 1 in both cases:
Index Seek IX_Store
Actual Number of Rows: 90
Estimated Number of Rows: 1
Could anyone explain the first result? I'm a bit worried about it. The fix in this case is trivial, but this problem gave us quite some headache in more complex real life queries with multiple joins.
Thank you!But not full statistics on a field basis, just sometimes some default stats like total row count that some plans will build. Even your StoreRequest table only has one two-field index that will have a full histogram.
But I've seen SQL Server make massively bad plans on two-field indexes.
I've seen SQL Server go wrong one-column indexes, so that is not a very relevant point.
Temp tables or not, the estimate here is clearly incorrect. SQL Server knows the density of Size and City. It knows the cardinality of the temp table. The density information gives how many rows the the join will produce. The WHERE clause will then remove
a certain number of rows. With no statistics for the temp table, it does not now how many, but it will apply some standard guess.
50000 is a completely bogus number, because the join cannot produce that many rows, and SQL Server is able to compute the join with out the WHERE clause decently. (Well, it estimates 90, when the number is 180.) No, this is obviously a case of the cardinality
estimator giving up completely.
It is worth noting that both these WHERE clauses gives reasonable estimates:
WHERE r.Size <> 11 OR r.City <> 550
WHERE s.Size <> 11 OR s.City <> 550
Whereas these two gives the spooky 50000:
WHERE s.Size <> 11 OR r.City <> 550
WHERE r.Size <> 11 OR s.City <> 550
Erland Sommarskog, SQL Server MVP, [email protected] -
Trouble with OR in where clause
Hello,
I'm having trouble with execution speed. The problem seems to be with using OR in my where clause.
Here's the meat of the function where i_pledge_number is an input parm:
BEGIN
SELECT /*+ INDEX (pp) */ SUM(pp.prim_pledge_amount)
INTO return_amount
FROM
primary_pledge pp
WHERE
-- Get total if multiple allocations
pp.prim_pledge_number IN
(SELECT pc.pledge_number
FROM pledge_codes pc
WHERE pc.pledge_code_type = 'M'
AND pc.pledge_code = 'AC'
AND lpad(pc.pledge_comment,10,'0') = i_pledge_number)
-- Get total if single allocation
OR pp.prim_pledge_number = i_pledge_number;
RETURN return_amount;
END;
If I comment out either half of the OR statement (either the subquery or the pp.prim_pledge_number = i_pledge_number half) the function returns a value in .02 seconds. If I leave the OR in, it takes 2.764 seconds to execute?? Can someone please show me a better way (faster) to do this? I tried using nvl() around the subquery but couldn't get it to compile.
ThanksThese things are difficult to diagnose remotely, but here is something you can try....
SELECT */ SUM(pp.prim_pledge_amount)
INTO return_amount
FROM primary_pledge pp
WHERE pp.prim_pledge_number IN (SELECT pc.pledge_number
FROM pledge_codes pc
WHERE pc.pledge_code_type = 'M'
AND pc.pledge_code = 'AC'
AND lpad(pc.pledge_comment,10,'0') = i_pledge_number
UNION ALL
SELECT i_pledge_number FROM dual)
RETURN return_amount;
END;If that doesn't do anything (and it might well not) there are a large number of different ways we can recast this query. To save us further guessing please give us more details: execution plans, database version number, volumetrics.
Cheers, APC -
Function-based index with OR in the wher-clause
We have some problems with functin-based indexes and
the or-condition in a where-clause.
--We use Oracle 8i (8.1.7)
create table TPERSON(ID number(10),NAME varchar2(20),...);
create index I_NORMAL_TPERSON_NAME on TPERSON(NAME);
create index I_FUNCTION_TPERSON_NAME on TPERSON(UPPER(NAME));
The following two statements run very fast on a large table
and the execution-plan asure the usage of the indexes
(-while the session is appropriate configured and the table is analyzed):
1) select count(ID) FROM TPERSON where upper(NAME) like 'MIL%';
2) select count(ID) from TPERSON where NAME like 'Mil%' or (3=5);
In particular we see that a normal index is used while the where-clause contains
an OR-CONDITION.
But if we try the similarly select-statement
3) select count(ID) FROM TPERSON where upper(NAME) like 'MIL%' or (3=5);
the CBO will not use the function-index I_FUNCTION_TPERSON_NAME and we have a full table scan in the execution-plan.
(This behavior we only expect with views but not with indexes.)
We ask for an advice like a hint, which enable the CBO-usage
of function-based indexes in connection with OR.
This problem seems to be artificial because it contains this dummy logic:
or (3=5).
This steams from an prepared statement, where this kind of boolean
flag reduce the amount of different select-statements needed for
covering the hole business-logic, while using bind-variables for the
concrete query-parameters.
A more realistic (still boild down) version of our select-statement is:
select * FROM TPERSON
where (upper(NAME) like 'MIL%' or (NAME is null))
and (upper(FIRSTNAME) like 'MICH% or (FIRSTNAME is null))
and ...;
thank you for time..
email: [email protected]In the realistic statement you write :
select * FROM TPERSON
where (upper(NAME) like 'MIL%' or (NAME is null))
and (upper(FIRSTNAME) like 'MICH% or (FIRSTNAME is null))
and ...;
as far as i know, NULL values are not indexed, "or (NAME is NULL)" have to generate a full table scan.
HTH
We have some problems with functin-based indexes and
the or-condition in a where-clause.
--We use Oracle 8i (8.1.7)
create table TPERSON(ID number(10),NAME varchar2(20),...);
create index I_NORMAL_TPERSON_NAME on TPERSON(NAME);
create index I_FUNCTION_TPERSON_NAME on TPERSON(UPPER(NAME));
The following two statements run very fast on a large table
and the execution-plan asure the usage of the indexes
(-while the session is appropriate configured and the table is analyzed):
1) select count(ID) FROM TPERSON where upper(NAME) like 'MIL%';
2) select count(ID) from TPERSON where NAME like 'Mil%' or (3=5);
In particular we see that a normal index is used while the where-clause contains
an OR-CONDITION.
But if we try the similarly select-statement
3) select count(ID) FROM TPERSON where upper(NAME) like 'MIL%' or (3=5);
the CBO will not use the function-index I_FUNCTION_TPERSON_NAME and we have a full table scan in the execution-plan.
(This behavior we only expect with views but not with indexes.)
We ask for an advice like a hint, which enable the CBO-usage
of function-based indexes in connection with OR.
This problem seems to be artificial because it contains this dummy logic:
or (3=5).
This steams from an prepared statement, where this kind of boolean
flag reduce the amount of different select-statements needed for
covering the hole business-logic, while using bind-variables for the
concrete query-parameters.
A more realistic (still boild down) version of our select-statement is:
select * FROM TPERSON
where (upper(NAME) like 'MIL%' or (NAME is null))
and (upper(FIRSTNAME) like 'MICH% or (FIRSTNAME is null))
and ...;
thank you for time..
email: [email protected] -
Performance - composite index with 'OR' in 'WHERE' clause
I have a problem with the performance of the following query:
select /*+ index_asc(omschact oma_index1) */ knr, projnr, actnr from omschact where ((knr = 100 and actnr > 30) or knr > 100)
and rownum = 1;
(rownum used only for test purpose)
index:
create index on omschact (knr, projnr);
Execution plan:
Id Operation
0 SELECT STATEMENT
1 COUNT STOPKEY
2 TABLE ACCESS BY INDEX ROWID
3 INDEX FULL SCAN
If I'm correct, the 'OR' in the 'WHERE' clause is responsible for the INDEX FULL SCAN, what makes the query slow.
A solution would be then to separate the 'WHERE' clause in 2 separate select's (1 with 'knr = 100 and actnr > 30' and 1 with 'knr > 100' and combine the results with a UNION ALL.
Since it's necessary to have all rows in ascending order (oma_index1) I still have to use an ORDER BY to make sure the order of the rows is correct. This results again in a (too) low performance.
Another solution that does the trick is to create an index with the 2 fields (knr, projnr) concatenated and to use the same in the 'WHERE' clause:
create index oma_index2 on omschact (knr || projnr);
select /*+ index_asc(omschact oma_index2) */ knr, projnr, actnr from omschact where (knr || projnr) > 10030;
I just can't believe this work-around is the only solution, so I was hoping that someone here knows of a better way to solve this.padders,
I'll give the real data instead of the example. The index I really use consists of 4 fields. In this table the fields are just numbers, but in other tables I need to use char-fields in indexes, so that's why I concatenate instead of using formula's (allthough I would prefer the latter).
SQL> desc omschact
Name Null? Type
KNR NOT NULL NUMBER(8)
PROJNR NOT NULL NUMBER(8)
ACTNR NOT NULL NUMBER(8)
REGELNR NOT NULL NUMBER(3)
REGEL CHAR(60)
first methode:
SQL> create index oma_key_001(knr,projnr,actnr,regelnr);
Index created.
SQL> select /*+ index_asc(omschact oma_key_001) */ * from omschact where
2 (knr > 100 or
3 (knr = 100 and projnr > 30) or
4 (knr = 100 and projnr = 30 and actnr > 100000) or
5 (knr = 100 and projnr = 30 and actnr = 100000 and regelnr >= 0));
Execution Plan
Plan hash value: 1117430516
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 11M| 822M| 192K (1)| 00:38:26 |
| 1 | TABLE ACCESS BY INDEX ROWID| OMSCHACT | 11M| 822M| 192K (1)| 00:38:26 |
|* 2 | INDEX FULL SCAN | OMA_KEY_001 | 11M| | 34030 (1)| 00:06:49 |
Predicate Information (identified by operation id):
2 - filter("KNR">100 OR "KNR"=100 AND "PROJNR">30 OR "KNR"=100 AND "PROJNR"=30
AND "ACTNR">100000 OR "ACTNR"=100000 AND "KNR"=100 AND "PROJNR"=30 AND
"REGELNR">=0)
second method (same index):
SQL> select * from (
2 select /*+ index_asc(omschact oma_key_001) */ * from omschact where knr > 100
3 union all
4 select /*+ index_asc(omschact oma_key_001) */ * from omschact where knr = 100 and projnr > 30
5 union all
6 select /*+ index_asc(omschact oma_key_001) */ * from omschact where knr = 100 and projnr = 30 and actnr > 100000
7 union all
8 select /*+ index_asc(omschact oma_key_001) */ * from omschact where knr = 100 and projnr = 30 and actnr = 100000 and regelnr > 0)
9 order by knr, projnr, actnr, regelnr;
Execution Plan
Plan hash value: 292918786
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 11M| 1203M| | 477K (1)| 01:35:31 |
| 1 | SORT ORDER BY | | 11M| 1203M| 2745M| 477K (1)| 01:35:31 |
| 2 | VIEW | | 11M| 1203M| | 192K (1)| 00:38:29 |
| 3 | UNION-ALL | | | | | | |
| 4 | TABLE ACCESS BY INDEX ROWID| OMSCHACT | 11M| 822M| | 192K (1)| 00:38:26 |
|* 5 | INDEX RANGE SCAN | OMA_KEY_001 | 11M| | | 33966 (1)| 00:06:48 |
| 6 | TABLE ACCESS BY INDEX ROWID| OMSCHACT | 16705 | 1272K| | 294 (1)| 00:00:04 |
|* 7 | INDEX RANGE SCAN | OMA_KEY_001 | 16705 | | | 54 (0)| 00:00:01 |
| 8 | TABLE ACCESS BY INDEX ROWID| OMSCHACT | 47 | 3666 | | 4 (0)| 00:00:01 |
|* 9 | INDEX RANGE SCAN | OMA_KEY_001 | 47 | | | 3 (0)| 00:00:01 |
| 10 | TABLE ACCESS BY INDEX ROWID| OMSCHACT | 1 | 78 | | 4 (0)| 00:00:01 |
|* 11 | INDEX RANGE SCAN | OMA_KEY_001 | 1 | | | 3 (0)| 00:00:01 |
Predicate Information (identified by operation id):
5 - access("KNR">100)
7 - access("KNR"=100 AND "PROJNR">30)
9 - access("KNR"=100 AND "PROJNR"=30 AND "ACTNR">100000)
11 - access("KNR"=100 AND "PROJNR"=30 AND "ACTNR"=100000 AND "REGELNR">0)
third method:
SQL> create index oma_test(to_char(knr,'00000000')||to_char(projnr,'00000000')||to_char(actnr,'00000000')||to_char(regelnr,'000'));
Index created.
SQL> select /*+ index_asc(omschact oma_test) */ * from omschact where
2 (to_char(knr,'00000000')||to_char(projnr,'00000000')||
3 to_char(actnr,'00000000')||to_char(regelnr,'000')) >=
4 (to_char(100,'00000000')||to_char(30,'00000000')||
5* to_char(100000,'00000000')||to_char(0,'000'))
Execution Plan
Plan hash value: 424961364
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 553K| 55M| 1712 (1)| 00:00:21 |
| 1 | TABLE ACCESS BY INDEX ROWID| OMSCHACT | 553K| 55M| 1712 (1)| 00:00:21 |
|* 2 | INDEX RANGE SCAN | OMA_TEST | 99543 | | 605 (1)| 00:00:08 |
Predicate Information (identified by operation id):
2 - access(TO_CHAR("KNR",'00000000')||TO_CHAR("PROJNR",'00000000')||TO_CHAR("
ACTNR",'00000000')||TO_CHAR("REGELNR",'000')>=TO_CHAR(100,'00000000')||TO_CHAR(3
0,'00000000')||TO_CHAR(100000,'00000000')||TO_CHAR(0,'000')) -
Can we use where clause in Update on Merge statement?
Hi All,
I tried to execute the following Merge Query:
When this query is executed without ‘Where clause’ in Update statement its working fine. When executed with ‘Where clause’ it throwing the following error:
ORA-00905: missing keyword.
Following is the sample query which I tried to execute:
MERGE INTO TABLE_NAME
USING (SELECT COLUMN FORM TABLES)
ON (CONDITION)
WHEN MATCHED THEN
UPDATE SET
COLUMN UPATES
WHERE CONDITION -- Can we use where clause here?
WHEN NOT MATCHED THEN
INSERT
INSERT VALUES;
Can some one help on this?
Thanks in advance.
DariusYes:
SQL> drop table emp1;
Table dropped.
SQL> create table emp1 as select * from emp where deptno = 30;
Table created.
SQL> update emp1 set sal = sal*2;
6 rows updated.
SQL> commit;
Commit complete.
SQL> select ename,sal from emp1;
ENAME SAL
ALLEN 3200
WARD 2500
MARTIN 2500
BLAKE 5700
TURNER 3000
JAMES 1900
6 rows selected.
SQL> MERGE INTO emp1
2 USING(select * from emp) emp
3 ON (emp1.empno = emp.empno)
4 WHEN MATCHED THEN
5 UPDATE SET sal = emp.sal WHERE ename = 'TURNER'
6 WHEN NOT MATCHED THEN
7 INSERT(ename,sal) VALUES(emp.ename,emp.sal);
9 rows merged.
SQL> select ename,sal from emp1;
ENAME SAL
ALLEN 3200
WARD 2500
MARTIN 2500
BLAKE 5700
TURNER 1500
JAMES 1900
SMITH 800
JONES 2975
CLARK 2450
SCOTT 3000
KING 5000
ENAME SAL
ADAMS 1100
FORD 3000
MILLER 1300
14 rows selected.
SQL> SY. -
Using if logic in the where clause of a select statement
I have a select clause. And in the select clause there is a variable all_off_trt that can be 'Y' or 'N'.
In the where clause I want to make it so that if a form variable is checked and all_off_trt is 'Y' then
exclude it else if the form variable isn't checked then select it no matter what all_off_trt is.
Is there any way to include either and if statement or a case statement within the where clause to acheive this? If not is there another way of doing it?
Basically I am looking for a case statement like this
case
when all_off_trt = 'Y' and mail_para.code = 'Y' then false
else true
end
Message was edited by:
Tugnutt7Ok, so that really doesn't solve my problem. I have 3 different fields that I need to do that with. Each combining in a select statement to print an email list, as well as other thing limiting the where clause.
This is currently what I have, tested and working 100%.
cursor email_cur is
select unique p.email,s.all_off_trt,s.all_deceased,s.no_enroll
from participant p, trialcom t, ethics s
where p.status='A'
and p.surname=t.surname
and p.initials=t.initials
and s.trial_cd = t.tricom
and s.centre = t.centre
and p.email is not null
and (t.centre in (select code from mail_parameters where user_name=user and mail_para='CENTRE')
or 'XX' in (select code from mail_parameters where user_name=user and mail_para='CENTRE'))
and (t.tricom in (select code from mail_parameters where user_name=user and mail_para='TRIAL')
or 'XX' in (select code from mail_parameters where user_name=user and mail_para='TRIAL'))
and (t.role in (select code from mail_parameters where user_name=user and mail_para='ROLE')
or 'XX' in (select code from mail_parameters where user_name=user and mail_para='ROLE'))
and (p.country in (select code from mail_parameters where user_name=user and mail_para='COUNTRY')
or 'XX' in (select code from mail_parameters where user_name=user and mail_para='COUNTRY'))
and (t.represent in (select code from mail_parameters where user_name=user and mail_para='REPRESENT')
or 'XX' in (select code from mail_parameters where user_name=user and mail_para='REPRESENT'));
This is in a program unit that runs when a button is clicked. At the end of that I need to add on the 3 case statements that help further narrow down the selection of emails to be printed. Then it prints the emails selected from this statement into a file. So it has to be done right in the select statement. The three table variables are the all_off_trt, all_deceased, and no_enroll. The form has 3 checkboxes. One for each, that when checked (giving the variable associated with the checkboxes a value of 'Y') excludes all emails that have a 'Y' in the coresponding table variable. -
Nested IF Statement in WHERE clause...
Here is a really abridged sample of my package. I need to ensure that if a salesrep has a status of 'I' (for "inactive") that the next salesrep with a status of 'A' (for "active") will be selected in its place.
Should I include a nested loop within the WHERE clause? Any tips on how I should go about it? I'm a newbie...thanks for the help..
SELECT rsa.name rep_name
,rsa.attribute7 rep_phone
,rsa.arrtibute8 rep_ext
FROM ra_salesreps_all rsa
WHERE rsa.status(+) = 'A'I'm assuming that this is part of your procedure within a package.....
You must be writing a CURSOR here....
Cursors are memory locations that can store retrieved rows and then process them one by one.
create or replace procedure my_proc
(<example_var> IN|OUT TYPE)
IS
cursor my_cursor IS
select <the fields I want>
from <sales type table>
where <my value> = 'A';
BEGIN
<how to process the cursor>
You can write the cursor process 2 ways:
1) FOR x in <name_of_cursor> LOOP
(This does whatever to the data for every record already selected by the cursor)
2) OPEN....FETCH....CLOSE
This is only scratching the surface of cursors...you need to read about these for what you are doing.
Question though...is this something you need to run for a SQL process in Oracle Applications??....if so you don't need to write a package/ procedure. You can write a cursor and load it as type SQL*PLUS, and it will run for you.
null -
AND and OR operations in WHERE clause
Hello, Dear Oracle professionals.
In WHERE clause when I use AND or OR operations, is there any way of working ORACLE server to select rows?
For example
WHERE con1 and con2 and con3 and con4 and con5OR
WHERE con1 or con2 or con3 or con4 or con5How oracle checks this conditions ? From the begining to the end ? in order ?
May be I should put some more probable TRUE condition to the end(or to the begin).
Whant to know how oracle thinks.
Thanks in advance.Hi,
Khayyam wrote:
Hello, Dear Oracle professionals.
In WHERE clause when I use AND or OR operations, is there any way of working ORACLE server to select rows?
For example
WHERE con1 and con2 and con3 and con4 and con5OR
WHERE con1 or con2 or con3 or con4 or con5How oracle checks this conditions ? From the begining to the end ? in order ?It evalauates the one that is likely to make the most difference first. In the case of AND, that means the condition that is least likely to be true (as far as the optimizer can predict).
May be I should put some more probable TRUE condition to the end(or to the begin).It doesn't matter to the optimizer. Do whatever you find easier to read and debug.
In ancient times, using the rule-based optimizer, order did matter, but there's no reason to be using the rule-based optimizer now. Oracle 11 doesn't even have the option.
By the way, be careful not to mix AND and OR without parentheses. That is, never say:
WHERE x AND y OR z -- ***** No! Wrong! ******Instead say
WHERE (x AND y) OR z or
WHERE x AND (y OR z) depending on what you want. If you don't use partentheses, then there are rules about how the expresssion is evaluated, but it's a waste of your time to learn them.
Maybe you are looking for
-
Its almost 2012 and no OS X 10.7 in-browser support
Hello all, According to the Advisory "Adobe Safari 5.1 and Adobe Reader/Acrobat Advisory", a better solution to this whole Safari 5.1 fiasco is to be expected by the end of this year but nothing seems to be in the horizon yet. Its been almost 6 month
-
Making & Burning Slideshow using 'slideshow' at bottom of iPhoto Library?
Hello. I would appreciate if someone can help me from beginning to finished product of making a slideshow using for example the Snapshot effect and music from iTunes. I will go over in point form to the point where I am unable to proceed any further:
-
Hi. i just want to know if there is an aplication to convert ANY kind of video format to another kind of video format. for example: avi to quicktime, or mpg2 to iphone. etc...etc.... working and converting any video format to any format again. please
-
Change Font to Bold in ALV GRID
Hi, I want to display only first row in my ALV in Bold font and rest in normal font. Could anyone help me out?
-
I see in the forums where many people have had this problem. I just dont know the solution. The pictures that show up through desktop manager have transferred over to my mac, but I can't get the ones on device memory (memory/home/user/pictures). (I w