Subselect in PL/SQL
I am using ORACLE 8.17 and am trying to use a subselect in a sql proc. I am getting an error. Are these not allowed in PL/SQL?
Example
CREATE OR REPLACE PROCEDURE SUBSELECT_TEST
IS
V_DATE DATE;
BEGIN
SELECT (SELECT SYSDATE FROM DUAL) FROM DUAL;
END;
In 8i you could try something like :
CREATE OR REPLACE PROCEDURE SUBSELECT_TEST
IS
cursor my_cursor is
SELECT MY_DATE from (SELECT SYSDATE MY_DATE FROM DUAL);
BEGIN
for c in my_cursor
loop
dbms_output.put_line(c.my_date);
end loop;
END;
Similar Messages
-
SQL Optimization with join and in subselect
Hello,
I am having problems finding a way to optimize a query that has a join from a fact table to several dimension tables (star schema) and a constraint defined as an in (select ....). I am hoping that this constraint will filter the fact table then perform the joins but I am seeing just the opposite with the optimizer joining first and then filtering at the very end. I am using the cost optimizer and saw that it does in subselects last in the predicate order. I tried the push_subq hint with no success.
Does anyone have any other suggestions?
Thanks in advance,
David
example sql:
select ....
from fact, dim1, dim2, .... dim <n>
where
fact.dim1_fk in ( select pf from dim1 where code = '10' )
and fact.dim1_fk = dim1.pk
and fact.dim2_fk = dim2.pk
and fact.dim<n>_fk = dim<n>.pkThe original query probably shouldn't use the IN clause because in this example it is not necessary. There is no limit on the values returned if a sub-select is used, the limit is only an issue with hard coded literals like
.. in (1, 2, 3, 4 ...)Something like this is okay even in 8.1.7
SQL> select count(*) from all_objects
2 where object_id in
3 (select object_id from all_objects);
COUNT(*)
32378The IN clause has its uses and performs better than EXISTS in some conditions. Blanket statements to avoid IN and use EXISTS instead are just nonsense.
Martin -
SQL HEXTORAW with SUBSELECT and INLIST
Hello guys,
i have the following table definition
TAB_A
===========
COL1 RAW(16)
COL2 RAW(16)
TAB_B
===========
COL1 RAW(16)
COL2 RAW(16)
Now the SELECT looks like the following:
SELECT * FROM TAB_A WHERE COL1 IN ( SELECT COL2 FROM TAB_B where COL1 = HEXTORAW('12234CX'));Now i have the problem that the COL1 of TAB_A is indexed, but the index can not be used, because of oracle doesn't do an implicit conversion for COL1 of TAB_A.
How can i use the function HEXTORAW() in that case, that the values that are returned from the SUBSELECT are translated into RAW.
Thanks and Regardsuser11981296 wrote:
Hello John,
the index is also not be used when using a HINT ... so therefore it is not an optimizer problem .. it is a "data type" problem.
RegardsNo, Oracle is fully capable of using an index on a raw column, assuming that one exists.
SQL> desc raw_test
Name Null? Type
ID NUMBER
ADDRESS RAW(8)
SQL> set autot trace explain
SQL> SELECT * FROM raw_test
2 WHERE address = HEXTORAW('5358B2E88');
Execution Plan
Plan hash value: 1291953311
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 897 | 17043 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| RAW_TEST | 897 | 17043 | 3 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | RAW_TEST_ADDR | 359 | | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
2 - access("ADDRESS"=HEXTORAW('05358B2E88') )So, something else is going on. If the hint does not drive it to using the index, then you have hinted incorrectly.
John -
SQL subselect rounds unintentional in SAP B1
Hey everyone,
if I am executing a select-statement with a subselect in sap b1, the result of the subselect is rounded - why? If I run a query without other tables, I get the exact value.
SELECT T0.[TransId], T0.[RefDate],
(SELECT T2.Rate FROM ORTT T2 WHERE T0.RefDate = T2.RateDate AND T2.Currency = 'USD')
FROM OJDT T0 INNER JOIN JDT1 T1 ON T0.TransId = T1.TransId WHERE T1.[ShortName] = 'T0001'
T2.Rate is rounded unintentional to two decimals and so further arithmetic operations are senseless because not exact. If I run the same query with Managment Studio, I get the exact value with four decimals. Several tries with CONVERT and CAST did not solve the problem.
Any suggestions? Thank you!
Best Regards
SebastianHi,
thanks for your reply. I have tried it out and you were right.. but the problem is, that I want to export the results into excel, but there the rounded values are exported.
I have solved the problem by extending the where-clause and putting the T2.Rate into the normal select-clause.. then the values keep their format.
Best Regards
Sebastian -
Global Temp Table vs. PL/SQL Table
Hi,
I'm trying to find out which better (efficient) to use in coding, a Global Temporary Table or PL/SQL table. The process requires evaluation to what data stored in the tbale.
Thanks in advance.Ok, let me restate this.
not carteasian product, carteasian LIKE ... where there is a many to many join between 2 fields (a resolution table).
Anyway, on Sybase/SQL Server if you need 3 fields from a table, 3 tables away,
you are allow to do a bulk / set update
UPDATE tempTable
field1 = t3X
field2 = t3Y
field3 = t3Z
FROM tempTable, t1, t2, t3
Where (joins)
In Oracle, the only way to do this is with 3 subselects
UPDATE tempTable
field1 = ( select t3X FROM tempTable, t1, t2, t3
Where (joins) ) ,
field2 = (select t3Y FROM tempTable, t1, t2, t3
Where (joins) ),
field3 = (select t3Z FROM tempTable, t1, t2, t3
Where (joins) ),
while this works, it does not seem effcient or elegant compared to the Sybase Solution.
By the way I am dealing with a design that preceeds me and I joined the team from a DIFFERERENT TEAM with a DIFFERENT background. I am neither stupid nor a poor designer, however I am ignorant of the Oracle ways and figured this would be the best place to look for the answer. Hans seems to have the best grasp of the request, does he have a CONSTRUCTIVE comment?
Thank you in advance.
Gary -
Kind of loop in sql? Any alternative?
Hi,
We have the following table
create table orders
order_id NUMBER(10),
vehicle_id NUMEBR(10),
customer_id NUMBER(10),
data VARCHAR(10)
order_id, customer_id and vehicle_id are indexed.
In this table are stored multiple orders for multiple vehicles.
I need an sql-statements which returns me the last 5 orders for each truck.
For only one vehicle its no problem:
select * from orders
where vehicle_id = <ID>
and rownum <=5
order by order_id desc;
But I need something like a loop to perform this statement for each vehicle_id.
Or is there any way to put it into a subselect?
Any ideas are welcome ;-)
Thanks in advance,
AndreasHello
Effectively by having the bind variable in there you are partitioning by customer and vehicle id, so by adding customer_id into the partition statement, the optimiser should be able to push the bind variable right down to the inner most view...
XXX> CREATE TABLE dt_orders
2 ( order_id NUMBER NOT NULL,
3 customer_id NUMBER NOT NULL,
4 vehicle_id NUMBER NOT NULL,
5 some_padding VARCHAR2(100) NOT NULL
6 )
7 /
Table created.
Elapsed: 00:00:00.23
XXX> INSERT INTO dt_orders SELECT ROWNUM ID, MOD(ROWNUM,100),MOD(ROWNUM,100), lpad(
2 /
10000 rows created.
Elapsed: 00:00:00.43
XXX> CREATE INDEX dt_orders_i1 ON dt_orders(customer_id)
2 /
Index created.
Elapsed: 00:00:00.17
XXX> select *
2 from (
3 select o.*, rank() over(partition by vehicle_id order by order_id desc) rk
4 from dt_orders o
5 where customer_id = :var_cust_id
6 )
7 where rk <= 5;
5 rows selected.
Elapsed: 00:00:00.11
Execution Plan
Plan hash value: 3174093828
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 107 | 11128 | 22 (5)| 00:00:01 |
|* 1 | VIEW | | 107 | 11128 | 22 (5)| 00:00:01 |
|* 2 | WINDOW SORT PUSHED RANK | | 107 | 9737 | 22 (5)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| DT_ORDERS | 107 | 9737 | 21 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | DT_ORDERS_I1 | 43 | | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("RK"<=5)
2 - filter(RANK() OVER ( PARTITION BY "VEHICLE_ID" ORDER BY
INTERNAL_FUNCTION("ORDER_ID") DESC )<=5)
4 - access("CUSTOMER_ID"=TO_NUMBER(:VAR_CUST_ID)) <----
Note
- dynamic sampling used for this statement
Statistics
36 recursive calls
0 db block gets
247 consistent gets
2 physical reads
0 redo size
518 bytes sent via SQL*Net to client
239 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
5 rows processedyour original statement showing that the bind variable has been applied to access the dt_orders table via the index (predicate 4)
If I change the statement to put the bind variable outside the inline view, we now do a full scan and you can see from predicate 1 that the customer id is being filtered at the highest level.
XXX> select *
2 from (
3 select o.*, rank() over(partition by vehicle_id order by order_id desc) rk
4 from dt_orders o
5 )
6 where rk <= 5
7 AND customer_id = :var_cust_id ;
5 rows selected.
Elapsed: 00:00:00.32
Execution Plan
Plan hash value: 3560032888
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10696 | 1086K| | 268 (2)| 00:00:04 |
|* 1 | VIEW | | 10696 | 1086K| | 268 (2)| 00:00:04 |
|* 2 | WINDOW SORT PUSHED RANK| | 10696 | 950K| 2216K| 268 (2)| 00:00:04 |
| 3 | TABLE ACCESS FULL | DT_ORDERS | 10696 | 950K| | 39 (3)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("RK"<=5 AND "CUSTOMER_ID"=TO_NUMBER(:VAR_CUST_ID)) <---
2 - filter(RANK() OVER ( PARTITION BY "VEHICLE_ID" ORDER BY
INTERNAL_FUNCTION("ORDER_ID") DESC )<=5)
Note
- dynamic sampling used for this statement
Statistics
4 recursive calls
0 db block gets
240 consistent gets
0 physical reads
0 redo size
519 bytes sent via SQL*Net to client
239 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
5 rows processedBut those two statements are really the same. By applying the filter inside the view as in your original, it means it's only going to calculate the rank for those customers. So we can add the customer id to the partition by statement which means the optimiser can safely push the predicate back down to the access of the orders table..
XXX> select *
2 from (
3 select o.*, rank() over(partition by customer_id,vehicle_id order by order_id desc) rk
4 from dt_orders o
5 )
6 where rk <= 5
7 AND customer_id = :var_cust_id ;
5 rows selected.
Elapsed: 00:00:00.04
Execution Plan
Plan hash value: 3174093828
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 107 | 11128 | 22 (5)| 00:00:01 |
|* 1 | VIEW | | 107 | 11128 | 22 (5)| 00:00:01 |
|* 2 | WINDOW SORT PUSHED RANK | | 107 | 9737 | 22 (5)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| DT_ORDERS | 107 | 9737 | 21 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | DT_ORDERS_I1 | 43 | | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("RK"<=5)
2 - filter(RANK() OVER ( PARTITION BY "CUSTOMER_ID","VEHICLE_ID" ORDER BY
INTERNAL_FUNCTION("ORDER_ID") DESC )<=5)
4 - access("O"."CUSTOMER_ID"=TO_NUMBER(:VAR_CUST_ID)) <----
Note
- dynamic sampling used for this statement
Statistics
9 recursive calls
0 db block gets
244 consistent gets
0 physical reads
0 redo size
519 bytes sent via SQL*Net to client
239 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
5 rows processedHTH
David -
SQL Performance issue: Using user defined function with group by
Hi Everyone,
im new here and I really could need some help on a weird performance issue. I hope this is the right topic for SQL performance issues.
Well ok, i create a function for converting a date from timezone GMT to a specified timzeone.
CREATE OR REPLACE FUNCTION I3S_REP_1.fnc_user_rep_date_to_local (date_in IN date, tz_name_in IN VARCHAR2) RETURN date
IS
tz_name VARCHAR2(100);
date_out date;
BEGIN
SELECT
to_date(to_char(cast(from_tz(cast( date_in AS TIMESTAMP),'GMT')AT
TIME ZONE (tz_name_in) AS DATE),'dd-mm-yyyy hh24:mi:ss'),'dd-mm-yyyy hh24:mi:ss')
INTO date_out
FROM dual;
RETURN date_out;
END fnc_user_rep_date_to_local;The following statement is just an example, the real statement is much more complex. So I select some date values from a table and aggregate a little.
select
stp_end_stamp,
count(*) noi
from step
where
stp_end_stamp
BETWEEN
to_date('23-05-2009 00:00:00','dd-mm-yyyy hh24:mi:ss')
AND
to_date('23-07-2009 00:00:00','dd-mm-yyyy hh24:mi:ss')
group by
stp_end_stampThis statement selects ~70000 rows and needs ~ 70ms
If i use the function it selects the same number of rows ;-) and takes ~ 4 sec ...
select
fnc_user_rep_date_to_local(stp_end_stamp,'Europe/Berlin'),
count(*) noi
from step
where
stp_end_stamp
BETWEEN
to_date('23-05-2009 00:00:00','dd-mm-yyyy hh24:mi:ss')
AND
to_date('23-07-2009 00:00:00','dd-mm-yyyy hh24:mi:ss')
group by
fnc_user_rep_date_to_local(stp_end_stamp,'Europe/Berlin')I understand that the DB has to execute the function for each row.
But if I execute the following statement, it takes only ~90ms ...
select
fnc_user_rep_date_to_gmt(stp_end_stamp,'Europe/Berlin','ny21654'),
noi
from
select
stp_end_stamp,
count(*) noi
from step
where
stp_end_stamp
BETWEEN
to_date('23-05-2009 00:00:00','dd-mm-yyyy hh24:mi:ss')
AND
to_date('23-07-2009 00:00:00','dd-mm-yyyy hh24:mi:ss')
group by
stp_end_stamp
)The execution plan for all three statements is EXACTLY the same!!!
Usually i would say, that I use the third statement and the world is in order. BUT I'm working on a BI project with a tool called Business Objects and it generates SQL, so my hands are bound and I can't make this tool to generate the SQL as a subselect.
My questions are:
Why is the second statement sooo much slower than the third?
and
Howcan I force the optimizer to do whatever he is doing to make the third statement so fast?
I would really appreciate some help on this really weird issue.
Thanks in advance,
AndiHi,
The execution plan for all three statements is EXACTLY the same!!!Not exactly. Plans are the same - true. They uses slightly different approach to call function. See:
drop table t cascade constraints purge;
create table t as select mod(rownum,10) id, cast('x' as char(500)) pad from dual connect by level <= 10000;
exec dbms_stats.gather_table_stats(user, 't');
create or replace function test_fnc(p_int number) return number is
begin
return trunc(p_int);
end;
explain plan for select id from t group by id;
select * from table(dbms_xplan.display(null,null,'advanced'));
explain plan for select test_fnc(id) from t group by test_fnc(id);
select * from table(dbms_xplan.display(null,null,'advanced'));
explain plan for select test_fnc(id) from (select id from t group by id);
select * from table(dbms_xplan.display(null,null,'advanced'));Output:
PLAN_TABLE_OUTPUT
Plan hash value: 47235625
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10 | 30 | 162 (3)| 00:00:02 |
| 1 | HASH GROUP BY | | 10 | 30 | 162 (3)| 00:00:02 |
| 2 | TABLE ACCESS FULL| T | 10000 | 30000 | 159 (1)| 00:00:02 |
Query Block Name / Object Alias (identified by operation id):
1 - SEL$1
2 - SEL$1 / T@SEL$1
Outline Data
/*+
BEGIN_OUTLINE_DATA
FULL(@"SEL$1" "T"@"SEL$1")
OUTLINE_LEAF(@"SEL$1")
ALL_ROWS
OPTIMIZER_FEATURES_ENABLE('10.2.0.4')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
Column Projection Information (identified by operation id):
1 - (#keys=1) "ID"[NUMBER,22]
2 - "ID"[NUMBER,22]
34 rows selected.
SQL>
Explained.
SQL>
PLAN_TABLE_OUTPUT
Plan hash value: 47235625
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10 | 30 | 162 (3)| 00:00:02 |
| 1 | HASH GROUP BY | | 10 | 30 | 162 (3)| 00:00:02 |
| 2 | TABLE ACCESS FULL| T | 10000 | 30000 | 159 (1)| 00:00:02 |
Query Block Name / Object Alias (identified by operation id):
1 - SEL$1
2 - SEL$1 / T@SEL$1
Outline Data
/*+
BEGIN_OUTLINE_DATA
FULL(@"SEL$1" "T"@"SEL$1")
OUTLINE_LEAF(@"SEL$1")
ALL_ROWS
OPTIMIZER_FEATURES_ENABLE('10.2.0.4')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
Column Projection Information (identified by operation id):
1 - (#keys=1) "TEST_FNC"("ID")[22]
2 - "ID"[NUMBER,22]
34 rows selected.
SQL>
Explained.
SQL> select * from table(dbms_xplan.display(null,null,'advanced'));
PLAN_TABLE_OUTPUT
Plan hash value: 47235625
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10 | 30 | 162 (3)| 00:00:02 |
| 1 | HASH GROUP BY | | 10 | 30 | 162 (3)| 00:00:02 |
| 2 | TABLE ACCESS FULL| T | 10000 | 30000 | 159 (1)| 00:00:02 |
Query Block Name / Object Alias (identified by operation id):
1 - SEL$F5BB74E1
2 - SEL$F5BB74E1 / T@SEL$2
Outline Data
/*+
BEGIN_OUTLINE_DATA
FULL(@"SEL$F5BB74E1" "T"@"SEL$2")
OUTLINE(@"SEL$2")
OUTLINE(@"SEL$1")
MERGE(@"SEL$2")
OUTLINE_LEAF(@"SEL$F5BB74E1")
ALL_ROWS
OPTIMIZER_FEATURES_ENABLE('10.2.0.4')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
Column Projection Information (identified by operation id):
1 - (#keys=1) "ID"[NUMBER,22]
2 - "ID"[NUMBER,22]
37 rows selected. -
Hello,
We are encountering a problem with Toplink 11.1.1.0.1 when adding a custom sql statement within a ReadAllQuery on a parent class. The same code with the same descriptor works fine with 10.1.3.3 and 9.0.4.7.
ReadAllQuery query = new ReadAllQuery(Person.class);
ExpressionBuilder b = query.getExpressionBuilder();
query.addArgument("instId", Integer.class);
ReportQuery subQuery = new ReportQuery();
subQuery.setReferenceClass(Person.class); // dummy mapped class...
SQLCall selectIdsCall = new SQLCall();
String subSelect = "select inst.ID from PERSON inst where inst.ID = #instId"; // <= re-use bind variable in child query
selectIdsCall.setSQLString(subSelect);
subQuery.setCall(selectIdsCall);
Expression expr = b.get("id").in(subQuery);
query.setSelectionCriteria(expr);
Vector params = new Vector(1);
params.add(new Integer(1));
List res = (List) session.executeQuery(query, params);
SQL statements generated by Toplink 11.1.1.0.1_
SELECT DISTINCT t0.OBJECTTYPE_ID FROM PERSON t0
WHERE t0.ID IN (select inst.ID from PERSON inst where inst.ID = 1)
SELECT t0.ID, t0.OBJECTTYPE_ID, t0.GENDER, t0.AGE, t0.FIRSTNAME, t0.LASTNAME, t0.ADDRESS_ID, t0.TITI_ID, t1.ID, t1.BONUS_ID
FROM PERSON t0, EMPLOYEE t1 WHERE ((t0.ID IN (select inst.ID from PERSON inst where inst.ID = 1)
AND (t1.ID = t0.ID)) AND (t0.OBJECTTYPE_ID = NULL))
SQL statements generated by Toplink 10.1.3.3 and 9.0.4.7_
SELECT DISTINCT t0.OBJECTTYPE_ID FROM PERSON t0
WHERE t0.ID IN (select inst.ID from PERSON inst where inst.ID = 1)
SELECT t0.ID, t0.OBJECTTYPE_ID, t0.GENDER, t0.AGE, t0.FIRSTNAME, t0.LASTNAME, t0.ADDRESS_ID, t0.TITI_ID, t1.ID, t1.BONUS_ID
FROM PERSON t0, EMPLOYEE t1 WHERE ((t0.ID IN (select inst.ID from PERSON inst where inst.ID = 1)
AND (t1.ID = t0.ID)) AND (t0.OBJECTTYPE_ID = 'EM'))It looks like the arguments are shifted. You can see it when using bind variables in 11.1.1.0.1
Exception [TOPLINK-4002] (Oracle TopLink - 11g (11.1.1.0.1) (Build 081030)): oracle.toplink.exceptio
ns.DatabaseException
Internal Exception: java.sql.SQLException: Invalid column index
Error Code: 17003
Call: SELECT t0.ID, t0.OBJECTTYPE_ID, t0.GENDER, t0.AGE, t0.FIRSTNAME, t0.LASTNAME, t0.ADDRESS_ID, t
0.TITI_ID, t1.ID, t1.BONUS_ID FROM PERSON t0, EMPLOYEE t1 WHERE ((t0.ID IN (select inst.ID from PERS
ON inst where inst.ID = ?) AND (t1.ID = t0.ID)) AND (t0.OBJECTTYPE_ID = ?))
bind => [1, null, EM]Has anyone already encountered this problem ?Hello,
We are encountering a problem with Toplink 11.1.1.0.1 when adding a custom sql statement within a ReadAllQuery on a parent class. The same code with the same descriptor works fine with 10.1.3.3 and 9.0.4.7.
ReadAllQuery query = new ReadAllQuery(Person.class);
ExpressionBuilder b = query.getExpressionBuilder();
query.addArgument("instId", Integer.class);
ReportQuery subQuery = new ReportQuery();
subQuery.setReferenceClass(Person.class); // dummy mapped class...
SQLCall selectIdsCall = new SQLCall();
String subSelect = "select inst.ID from PERSON inst where inst.ID = #instId"; // <= re-use bind variable in child query
selectIdsCall.setSQLString(subSelect);
subQuery.setCall(selectIdsCall);
Expression expr = b.get("id").in(subQuery);
query.setSelectionCriteria(expr);
Vector params = new Vector(1);
params.add(new Integer(1));
List res = (List) session.executeQuery(query, params);
SQL statements generated by Toplink 11.1.1.0.1_
SELECT DISTINCT t0.OBJECTTYPE_ID FROM PERSON t0
WHERE t0.ID IN (select inst.ID from PERSON inst where inst.ID = 1)
SELECT t0.ID, t0.OBJECTTYPE_ID, t0.GENDER, t0.AGE, t0.FIRSTNAME, t0.LASTNAME, t0.ADDRESS_ID, t0.TITI_ID, t1.ID, t1.BONUS_ID
FROM PERSON t0, EMPLOYEE t1 WHERE ((t0.ID IN (select inst.ID from PERSON inst where inst.ID = 1)
AND (t1.ID = t0.ID)) AND (t0.OBJECTTYPE_ID = NULL))
SQL statements generated by Toplink 10.1.3.3 and 9.0.4.7_
SELECT DISTINCT t0.OBJECTTYPE_ID FROM PERSON t0
WHERE t0.ID IN (select inst.ID from PERSON inst where inst.ID = 1)
SELECT t0.ID, t0.OBJECTTYPE_ID, t0.GENDER, t0.AGE, t0.FIRSTNAME, t0.LASTNAME, t0.ADDRESS_ID, t0.TITI_ID, t1.ID, t1.BONUS_ID
FROM PERSON t0, EMPLOYEE t1 WHERE ((t0.ID IN (select inst.ID from PERSON inst where inst.ID = 1)
AND (t1.ID = t0.ID)) AND (t0.OBJECTTYPE_ID = 'EM'))It looks like the arguments are shifted. You can see it when using bind variables in 11.1.1.0.1
Exception [TOPLINK-4002] (Oracle TopLink - 11g (11.1.1.0.1) (Build 081030)): oracle.toplink.exceptio
ns.DatabaseException
Internal Exception: java.sql.SQLException: Invalid column index
Error Code: 17003
Call: SELECT t0.ID, t0.OBJECTTYPE_ID, t0.GENDER, t0.AGE, t0.FIRSTNAME, t0.LASTNAME, t0.ADDRESS_ID, t
0.TITI_ID, t1.ID, t1.BONUS_ID FROM PERSON t0, EMPLOYEE t1 WHERE ((t0.ID IN (select inst.ID from PERS
ON inst where inst.ID = ?) AND (t1.ID = t0.ID)) AND (t0.OBJECTTYPE_ID = ?))
bind => [1, null, EM]Has anyone already encountered this problem ? -
PL/SQL CLOB and comma seperated list
Hi,
i´am beginner!
I have a table with a clob field with a comma separeted list. The content can be '', '44' or '44,55...' as an example.
So how can i get the values in clob and search another table?
Something like...
select clob from table1
each clob
select * from table2
where table2.id = (clob value)
... do somtheing further
Thank you,
JochenOk... it depends...
If you know your CLOB is going to hold a list of values that are less than 4000 characters, you can simply treat the CLOB as a VARCHAR2 and perform one of the many techniques for splitting that string to give a varying IN list...
e.g.
SQL> ed
Wrote file afiedt.buf
1 select *
2 from emp
3 where ename in (
4 with t as (select '&input_string' as txt from dual)
5 select REGEXP_SUBSTR (txt, '[^,]+', 1, level)
6 from t
7 connect by level <= length(regexp_replace(txt,'[^,]*'))+1
8* )
SQL> /
Enter value for input_string: SCOTT,JAMES
old 4: with t as (select '&input_string' as txt from dual)
new 4: with t as (select 'SCOTT,JAMES' as txt from dual)
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7788 SCOTT ANALYST 7566 19-04-1987 00:00:00 3000 20
7900 JAMES CLERK 7698 03-12-1981 00:00:00 950 30
SQL>(or alternatively read here: http://tkyte.blogspot.com/2006/06/varying-in-lists.html)
If it's going to exceed the SQL VARCHAR2 limit of 4000 characters then you would most likely need to create a Pipelined function to split your CLOB into it's component values and return each one, thus allowing you to treat the results as a table of their own... e.g.
Note: this example is for a pipelined function that splits a varchar2 string, but you could adapt it to use the DBMS_LOB package to split a CLOB in the same manner...
SQL> CREATE OR REPLACE TYPE split_tbl IS TABLE OF VARCHAR2(4000);
2 /
Type created.
SQL> CREATE OR REPLACE FUNCTION split (p_list VARCHAR2, p_delim VARCHAR2:=' ') RETURN SPLIT_TBL PIPELINED IS
2 l_idx PLS_INTEGER;
3 l_list VARCHAR2(4000) := p_list;
4 l_value VARCHAR2(4000);
5 BEGIN
6 LOOP
7 l_idx := INSTR(l_list, p_delim);
8 IF l_idx > 0 THEN
9 PIPE ROW(SUBSTR(l_list, 1, l_idx-1));
10 l_list := SUBSTR(l_list, l_idx+LENGTH(p_delim));
11 ELSE
12 PIPE ROW(l_list);
13 EXIT;
14 END IF;
15 END LOOP;
16 RETURN;
17 END SPLIT;
18 /
Function created.
SQL> SELECT column_value
2 FROM TABLE(split('FRED,JIM,BOB,TED,MARK',','));
COLUMN_VALUE
FRED
JIM
BOB
TED
MARK
SQL> create table mytable (val VARCHAR2(20));
Table created.
SQL> insert into mytable
2 select column_value
3 from TABLE(split('FRED,JIM,BOB,TED,MARK',','));
5 rows created.
SQL> select * from mytable;
VAL
FRED
JIM
BOB
TED
MARK
SQL>... and once you can treat the values like a table it's just a case of using it like you would any table of values i.e. join on it or use it in an IN statment with a subselect etc. -
Group by with a subselect?
I have a problem when trying to group by the results of a subselect. I keep getting the error ORA-00979: not a GROUP BY expression, though I can't see the problem with the SQL.
I want to count the number of rows in a table having / not having at least one row in another table.
The query is equivalent to:
select c1, count(*) from
(select case when exists
(select * from dual t2
where t1.dummy=t2.dummy)
then 'Y' else 'N' end c1
from dual t1) t
group by c1
This fails on every version of Oracle I've tried, and I get the same error with:
select c1, count(*) from
(select case when t1.dummy in
(select t2.dummy from dual t2)
then 'Y' else 'N' end c1
from dual t1) t
group by c1
Is this a fault with the SQL, or with Oracle?
Thanks in advance,
RexOn 9.2.0.5:
ora9205>select c1, count(*)
2 from (select case
3 when exists
4 (select * from dual t2
5 where t1.dummy = t2.dummy)
6 then 'Y' else 'N'
7 end c1
8 from dual t1) t
9 group by c1;
C COUNT(*)
Y 1
1 row selected.
-- Two approaches with the DEPT and EMP tables
ora9205>select c1, count(*)
2 from (select case
3 when exists
4 (select null
5 from emp e
6 where e.deptno = d.deptno)
7 then 'Y' else 'N'
8 end c1
9 from dept d)
10 group by c1;
C COUNT(*)
N 2
Y 3
2 rows selected.
ora9205>select 'Y', count(*)
2 from dept d
3 where exists (select null
4 from emp e
5 where e.deptno = d.deptno)
6 union all
7 select 'N', count(*)
8 from dept d
9 where not exists (select null
10 from emp e
11 where e.deptno = d.deptno);
' COUNT(*)
Y 3
N 2
2 rows selected. -
Compilation problems using NVL function in Pro*C subselect
I have come across a weird oracle problem. When I execute the following query in SQLPlus it works but when
I include it in Pro*C code in a EXEC SQL statement it gives syntax errors and fails to compile. Any idea what I am doing wrong.
SELECT DISTINCT
A.ID_PERSON,
C.ID_STAGE_PERSON_LINK ,
A.NM_PERSON_FULL,
A.NBR_PERSON_AGE,
A.ADDR_PERSON_ST_LN_1,
A.ADDR_PERSON_CITY,
A.ADDR_PERSON_ZIP,
A.CD_PERSON_STATE,
A.CD_PERSON_COUNTY,
A.NBR_PERSON_PHONE,
C.CD_STAGE_PERS_REL_INT
FROM
PERSON A,
STAGE_PERSON_LINK C
WHERE
C.ID_CASE = 88776721
AND A.IND_INVALID_PERS IS NULL
AND C.CD_STAGE_PERS_TYPE = 'PRN'
AND C.ID_PERSON = A.ID_PERSON
AND C.ID_STAGE_PERSON_LINK =
NVL (
(SELECT MAX(F.ID_STAGE_PERSON_LINK)
FROM STAGE_PERSON_LINK F
WHERE F.ID_PERSON=C.ID_PERSON
AND F.ID_CASE = C.ID_CASE
AND F.CD_STAGE_PERS_TYPE = 'PRN'
AND F.CD_STAGE_PERS_REL_INT IS NOT NULL)
(SELECT MAX(G.ID_STAGE_PERSON_LINK)
FROM STAGE_PERSON_LINK G
WHERE G.ID_PERSON=C.ID_PERSON
AND G.ID_CASE = C.ID_CASE
AND G.CD_STAGE_PERS_TYPE = 'PRN')
AND A.ID_PERSON NOT IN
SELECT S.ID_PERSON
FROM STAGE_PERSON_LINK S,STAGE T
WHERE S.ID_CASE = C.ID_CASE
AND S.ID_CASE = T.ID_CASE
AND S.ID_STAGE = T.ID_STAGE
AND T.CD_STAGE <> 'INT'
MINUS
SELECT H.ID_PERSON
FROM STAGE_PERSON_LINK H, STAGE F
WHERE H.ID_CASE = F.ID_CASE
AND H.ID_STAGE = F.ID_STAGE
AND H.ID_CASE = C.ID_CASE
AND H.CD_STAGE_PERS_ROLE <> 'XE'
AND F.CD_STAGE <> 'INT'
This query returns data when run in sqlplus.When used in a Pro*C C program and compiled the precompiler complains with syntax errors when used with EXEC SQL DECLARE CLSS82D_CURSOR CURSOR FOR < query above >.However removing the NVL function and retaining the subselect clause compiles but that is not what I want to do.
Syntax error at line 262, column 20, file clss82d.pc:
Error at line 262, column 20 in file clss82d.pc
SELECT MAX( F.ID_STAGE_PERSON_LINK )
...................1
PCC-S-02201, Encountered the symbol "MAX" when expecting one of the following:
( ) * + - / . @ | at, day, hour, minute, month, second, year,
The symbol "(" was substituted for "MAX" to continue.
Syntax error at line 263, column 10, file clss82d.pc:
Error at line 263, column 10 in file clss82d.pc
FROM STAGE_PERSON_LINK F
.........1
PCC-S-02201, Encountered the symbol "FROM" when expecting one of the following:
, ) * + - / | at, day, hour, minute, month, second, year,Pro*C works bit differently tha sqlplus. try removing the blank line after
SELECT MAX(G.ID_STAGE_PERSON_LINK)
FROM STAGE_PERSON_LINK G
WHERE G.ID_PERSON=C.ID_PERSON
AND G.ID_CASE = C.ID_CASE
AND G.CD_STAGE_PERS_TYPE = 'PRN')
good luck,
Gauranga -
"SQL Query in HTTP Request" (5474:0)
Hi,
The IDS signature "SQL Query in HTTP Request" (5474:0) does not recognize all malicious SQL selects. Currently, the reg exp looks like [%]20|[=]|[+])[Ss][Ee][Ll][Ee][Cc][Tt]([%]20|[+])[^\r\n\x00-\x19\x7F-\xFF]+([%]20|[+])[Ff][Rr][Oo][Mm]([%]20|[+] . We noticed that subselects does not trigger the signature. For example, "...(select%20something%20from%20somethingmore%20where%20variable%20=%20(select%20....." which could be malicious. Is there any possibility to include "(" in the regexp to detect subselects?
Regards,
/Olahmmm...That should actually match just fine. Let's break it down:
([%]20|[=]|[+]) <--"%20","=",or "+"
[Ss][Ee][Ll][Ee][Cc][Tt] <-- "SELECT"
([%]20|[+]) <--"%20" or "+"
[^\r\n\x00-\x19\x7F-\xFF]+ <-- NOT one or more ascii control or extended chars
([%]20|[+]) <-- "%20" or "+"
[Ff][Rr][Oo][Mm] <-- "FROM"
([%]20|[+]) <-- "%20" or "+"
The only reason I can think that it wouldn't match is if there some funky characters between the first SELECT and the first FROM (i.e. carriage return/line feed, etc). Also remember that a %20 or = or + must precede the SELECT and that a %20 or + must follow the FROM. -
Using the result of a function, inside a subselect
Hi!
I´m wondering if it´s possible to use the result of a function inside a subselect. Let me give you an example of what I´m trying to do here:
select * from t_node where node_pk in (get_node_parents_pk(22345));
The function get_node_parents_pk stands in for the following SELECT-statment:
select node_pk from t_node_child where parent_node_pk = 12345
The statement above would return something like this: 12435,23423,23453,23452
These values represent the node_pk value for the parent nodes.
I want the get_node_parents_pk function to return a result set similar to this so that I might call it inside the IN ( ) statement.
Any clue? =)I created a collection type in the database:
CREATE OR REPLACE TYPE nodes_pk_arr IS TABLE OF INTEGER;
The function get_node_parents_pk () is made to return the collection type above. However, this does not work. I get the following error message:
SELECT *
FROM t_node
WHERE node_pk IN
(SELECT * FROM TABLE (get_node_parents_pk (22345)));
ORA-22905: cannot access rows from a non-nested table item
However, if I insert a nodes_pk_arr collection directly into the SQL-statement, like I do below, it works:
SELECT *
FROM t_node
WHERE node_pk IN
(SELECT * FROM TABLE (nodes_pk_arr(24564,23545,34523));
So, when returning the collection from the function I´m told that the collection is not a nested table, when in fact it is. What gives?
Also, is there no way to return a result set directly from the get_node_parents_pk() function, making it possible to write the statement like that shown below?
SELECT *
FROM t_node
WHERE node_pk IN (get_node_parents_pk (22345));
Your reply is much appreciated!
Kind regards
Robert -
Hello,
i want to write an sql-update statement where a field through a part of another field will be supplemented.
example:
update tabelle set targetDirectiory = ' export/home/VALUE_FROM_FIELD x' where blablabla
This should work as a subselect ?but I do not know how i can merge the strings
Thanks a lot.
LutzIt could have been better if you would have provided some supporting data. Anyway
You can do it like
UPDATE emp e
SET dept_name = 'DEPT-'||(SELECT d.dept_name
FROM dept d
WHERE d.dept_id = e.dept_id
WHERE blahblahblah;Regards
Arun -
SQL statement using result of aggregate min function to fetch a row - how?
Need help trying to get to something seemingly simple. I'll provide a simple example to illustrate the problem.
I'll be using a simple addresses table with 4 fields.
Create the table:
CREATE TABLE "ADDRESSES"
( "OWNER_NAME" VARCHAR2(20 BYTE),
"STREET_NAME" VARCHAR2(20 BYTE),
"STREET_NUMBER" NUMBER
) ;populate with 6 rows
Insert into ADDRESSES (OWNER_NAME,STREET_NAME,STREET_NUMBER) values ('FRED','MAIN',1);
Insert into ADDRESSES (OWNER_NAME,STREET_NAME,STREET_NUMBER) values ('JOAN','MAIN',2);
Insert into ADDRESSES (OWNER_NAME,STREET_NAME,STREET_NUMBER) values ('JEAN','MAIN',3);
Insert into ADDRESSES (OWNER_NAME,STREET_NAME,STREET_NUMBER) values ('JACK','ELM',1);
Insert into ADDRESSES (OWNER_NAME,STREET_NAME,STREET_NUMBER) values ('JANE','ELM',2);
Insert into ADDRESSES (OWNER_NAME,STREET_NAME,STREET_NUMBER) values ('JEFF','ELM',3);We now have this:
Select * from addresses
OWNER_NAME STREET_NAME STREET_NUMBER
FRED MAIN 1
JOAN MAIN 2
JEAN MAIN 3
JACK ELM 1
JANE ELM 2
JEFF ELM 3
6 rows selectedNow i wish to group by StreetName, and get a count of houses. At the same time, i'd like to know the first and last house number
select
street_name,
count(*) "NBR HOUSES",
min(street_number) "First Number",
max(street_number) "Last Number"
from addresses
group by street_name
produces
STREET_NAME NBR HOUSES First Number Last Number
ELM 3 1 3
MAIN 3 1 3
2 rows selectedExcellent. Now for the problem. I wish to also list on each line, the owner that lives at the first and/or last house number. Note again, assume that house number and street name is unique
It would seem i have all that i need. Not sure how to get at it.
I tried:
select
street_name,
count(*) "NBR HOUSES",
min(street_number) "First Number",
max(street_number) "Last Number",
(Select b.owner_name from addresses b where b.street_number = min(street_number) and b.owner_name = owner_name) "First Owner"
from addresses
group by street_nameBut get a sql syntax error, group function not allowed when i add the subselect.
any ideas?
thanks for any help.
Edited by: user6876601 on Nov 19, 2009 7:08 PM
Edited by: user6876601 on Nov 19, 2009 7:30 PMHi,
Welcome to the forum!
Getting the highest and lowest number for each street is a fairly simple concept; simpler to describe, and simple to code.
Now you want the owner_name associated with the highest and lowest number, which is a more complicated concept; a little harder to describe, and, unfortunately, much less simple to code, and much, much harder to explain:
select
street_name,
count (*) "NBR HOUSES",
min (street_number) "First Number",
min (owner_name) KEEP (DENSE_RANK FIRST ORDER BY street_number)
"First Owner",
max (street_number) "Last Number",
min (owner_name) KEEP (DENSE_RANK LAST ORDER BY street_number)
"Last Owner"
from addresses
group by street_name
;Notice that I used min for both "First Owner" and "Last Owner". Why is that?
The important keyword in these funtions is the word FIRST or LAST that comes after DENSE_RANK and before ORDER BY. The function at the beginning is merely a tie-breaker.
That is, MIN in this context only refers to what should happen when there is a tie for the first or last in the group. Even if such a thing is impossibe in your data, the generic functions have to have some mechanism for returning a single owner_name when two or more rows have an equal claim to having the highest street_number. For example, if we change Joan's address to 1 Main, then MIN (street_number) is still 1, obviously, but who is the person associated with the minimum street_number: is it Fred or Joan? Both have an equal claim to being the owner with the lowest address on Main Street, but aggregate functions must return a single value, so we have to have some mechanism for tell the system whether to return 'JOAN' or 'FRED'. In this example, I arbitrarily said that in the een of a tie, the lowest name, in alphabetic order, should be returned. In this case, 'FRED' would be returned, since 'FRED' is earlier than 'JOAN' .
Thanks for including the CREATE TABLE and INSERT statements!
Maybe you are looking for
-
Installing Multiple Operating Systems with grub and Arch Linux
NOTE: Please keep in mind that there are many different ways to achieve this same result using various loop and ramdisk methods, read this with a separate window to jot down your comments and suggestions... this is ongoing for me so any help would be
-
Curve 3G/9300 no longer connects to Nokia CK-7W Handsfree set
I've just updated to OS6 and my BB Curve 9300 no longer connects to the bluetooth handsfree set in my car (Nokia CK-7W). No problems before the update. Presumably this will be a software issue rather than hardware as everything else still connects wi
-
That little blue question mark
I place a hyperlink to 'sending an email' and publish. On the published site a small blue question mark appears however the link is active. Why doesn't the email address show up as on the page in iWeb? Any ideas?
-
I'm on my 3rd Droid in less than 1 year. I guess my memory isn't as good as some because when the 3rd phone came I thought I knew the drill: They send you just the phone so you need your battery and back cover. Then you send the defective phone back
-
How to align buttons using ActionScript in Flex
Hi all, I'm pretty new to Flex and ActionScript but I've created an myAddForm() function in an actionscript class but I can't align the buttons - I've been looking at using a buttonbar but can't figure out how to convert the code in to actionscript f