Inline select statement and SQL optimizatino
Hi everyone,
I am trying to optimze a script but can't get the fulle explainplan in PL/SQL.
The problem is that the select statements in de column defenition is not explained. below are the 2 scripts I want to compare:
SQL1:
Select
z.title
, (select name from members where id =z.id) as name
, z.id
from job z
SQL2
Select
z.title
, d.name
, z.id
from job z
left outer join members d on z.id=d.id
My question is: what is the effect on performance and cost of the 'inline select' statement of name in SQL1
hope to hear form you soon
Harm
Edited by: HALI on 25-nov-2010 1:14
In respons to your question below is the output:
I altered the used names, tablenames etc. according to our privacy pollacy.
A far as I can see the inline statement is not traced.
The query with ansi-join:
xplain plan for
select
id as Interne
, mv.ie_id as Act
, 'H_W' as Rl
from testing i
left outer join resutino m on i.hand=m.id
left outer join vert mv on m.voor || case when m.voeg is not null then ' '|| m.voeg end ||' '||m.naam = mv.source and mv.field = 'employee'
explain plan succeeded.
select * from table(dbms_xplan.display)
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 684 | 47880 | 19 |
| 1 | HASH JOIN OUTER | | 684 | 47880 | 19 |
| 2 | HASH JOIN OUTER | | 684 | 22572 | 15 |
| 3 | TABLE ACCESS FULL | testing | 684 | 5472 | 7 |
| 4 | TABLE ACCESS FULL | resutino | 308 | 7700 | 7 |
| 5 | TABLE ACCESS FULL | VERT | 166 | 6142 | 3 |
Note: cpu costing is off, 'PLAN_TABLE' is old version
13 rows selected
The inline select query:
xplain plan for
SELECT
case when (select ie_id from vert xov where xov.field = 'field' and source in
(select m.voor || case when m.voeg is not null then ' '|| m.voegend ||' '||m.naam from resultino m where i.hand= m.id)) is not null then
'X'||(select ie_id from vert xov where xov.field = 'field' and source in
(select m.voor || case when m.voeg is not null then ' '|| m.voegend ||' '||m.naam from resultino m where i.hand= m.id))
else 'X' || (select ie_id from vert xov where xov.source = 'none' and xov.veld = 'employee')
end as Act,
'ADM' as Rol,
i.id as Interne
FROM testing i
explain plan succeeded.
select * from table(dbms_xplan.display)
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 684 | 5472 | 7 |
| 1 | TABLE ACCESS FULL | testing | 684 | 5472 | 7 |
Note: cpu costing is off, 'PLAN_TABLE' is old version
9 rows selected
Similar Messages
-
Bind Variable in SELECT statement and get the value in PL/SQL block
Hi All,
I would like pass bind variable in SELECT statement and get the value of the column in Dynamic SQL
Please seee below
I want to get the below value
Expected result:
select distinct empno ,pr.dept from emp pr, dept ps where ps.dept like '%IT' and pr.empno =100
100, HR
select distinct ename ,pr.dept from emp pr, dept ps where ps.dept like '%IT' and pr.empno =100
TEST, HR
select distinct loc ,pr.dept from emp pr, dept ps where ps.dept like '%IT' and pr.empno =100
NYC, HR
Using the below block I am getting column names only not the value of the column. I need to pass that value(TEST,NYC..) into l_col_val variable
Please suggest
----- TABLE LIST
CREATE TABLE EMP(
EMPNO NUMBER,
ENAME VARCHAR2(255),
DEPT VARCHAR2(255),
LOC VARCHAR2(255)
INSERT INTO EMP (EMPNO,ENAME,DEPT,LOC) VALUES (100,'TEST','HR','NYC');
INSERT INTO EMP (EMPNO,ENAME,DEPT,LOC) VALUES (200,'TEST1','IT','NYC');
INSERT INTO EMP (EMPNO,ENAME,DEPT,LOC) VALUES (300,'TEST2','MR','NYC');
INSERT INTO EMP (EMPNO,ENAME,DEPT,LOC) VALUES (400,'TEST3','HR','DTR');
INSERT INTO EMP (EMPNO,ENAME,DEPT,LOC) VALUES (500,'TEST4','HR','DAL');
INSERT INTO EMP (EMPNO,ENAME,DEPT,LOC) VALUES (600,'TEST5','IT','ATL');
INSERT INTO EMP (EMPNO,ENAME,DEPT,LOC) VALUES (700,'TEST6','IT','BOS');
INSERT INTO EMP (EMPNO,ENAME,DEPT,LOC) VALUES (800,'TEST7','HR','NYC');
COMMIT;
CREATE TABLE COLUMNAMES(
COLUMNAME VARCHAR2(255)
INSERT INTO COLUMNAMES(COLUMNAME) VALUES ('EMPNO');
INSERT INTO COLUMNAMES(COLUMNAME) VALUES ('ENAME');
INSERT INTO COLUMNAMES(COLUMNAME) VALUES ('DEPT');
INSERT INTO COLUMNAMES(COLUMNAME) VALUES ('LOC');
COMMIT;
CREATE TABLE DEPT(
DEPT VARCHAR2(255),
DNAME VARCHAR2(255)
INSERT INTO DEPT(DEPT,DNAME) VALUES ('IT','INFORMATION TECH');
INSERT INTO DEPT(DEPT,DNAME) VALUES ('HR','HUMAN RESOURCE');
INSERT INTO DEPT(DEPT,DNAME) VALUES ('MR','MARKETING');
INSERT INTO DEPT(DEPT,DNAME) VALUES ('IT','INFORMATION TECH');
COMMIT;
PL/SQL BLOCK
DECLARE
TYPE EMPCurTyp IS REF CURSOR;
v_EMP_cursor EMPCurTyp;
l_col_val EMP.ENAME%type;
l_ENAME_val EMP.ENAME%type;
l_col_ddl varchar2(4000);
l_col_name varchar2(60);
l_tab_name varchar2(60);
l_empno number ;
b_l_col_name VARCHAR2(255);
b_l_empno NUMBER;
begin
for rec00 in (
select EMPNO aa from EMP
loop
l_empno := rec00.aa;
for rec in (select COLUMNAME as column_name from columnames
loop
l_col_name := rec.column_name;
begin
l_col_val :=null;
l_col_ddl := 'select distinct :b_l_col_name ,pr.dept ' ||' from emp pr, dept ps where ps.dept like ''%IT'' '||' and pr.empno =:b_l_empno';
dbms_output.put_line('DDL ...'||l_col_ddl);
OPEN v_EMP_cursor FOR l_col_ddl USING l_col_name, l_empno;
LOOP
l_col_val :=null;
FETCH v_EMP_cursor INTO l_col_val,l_ename_val;
EXIT WHEN v_EMP_cursor%NOTFOUND;
dbms_output.put_line('l_col_name='||l_col_name ||' empno ='||l_empno);
END LOOP;
CLOSE v_EMP_cursor;
END;
END LOOP;
END LOOP;
END;user1758353 wrote:
Thanks Billy, Would you be able to suggest any other faster method to load the data into table. Thanks,
As Mark responded - it all depends on the actual data to load, structure and source/origin. On my busiest database, I am loading on average 30,000 rows every second from data in external files.
However, the data structures are just that - structured. Logical.
Having a data structure with 100's of fields (columns in a SQL table), raise all kinds of questions about how sane that structure is, and what impact it will have on a physical data model implementation.
There is a gross misunderstanding by many when it comes to performance and scalability. The prime factor that determines performance is not how well you code, what tools/language you use, the h/w your c ode runs on, or anything like that. The prime factor that determines perform is the design of the data model - as it determines the complexity/ease to use the data model, and the amount of I/O (the slowest of all db operations) needed to effectively use the data model. -
Concat java variable to a MySql select statement and exeucte
Hi,
I am trying to append a variable to a MySql select statement.
Overview: I need to retrieve data from a MySql database with a java variable as a reference and select the data in the database based on that variable.
CODE THAT I CURRENTLY HAVE:
// Declare variables
Connection conn = null;
Statement st = null;
Resultset rs2 = null;
String st2 = null;
String keyid = null;
// Connect to database
try {
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
conn = DriverManager.getConnection("jdbc:mysql://" + mysql_host + ":3306/" + mysql_database, mysql_login, mysql_password);
st = conn.createStatement();
// Select data in Database with hanging equal sign
st2 = ("SELECT * FROM table WHERE keyid= ");
// Append keyid to hanging equal sign of select statement
rs2 = st.executeQuery(st2 + keyid);
}This is not working when I try to display the data.What is not working about it? Is there an error message? Stack Trace?
Where do you get the value of keyId from?
I would suggest that you use a prepared statement rather than building up a sql string like this. It prevents sql injection attacks
// Declare variables
Connection conn = null;
PreparedStatement stmt = null;
Resultset rs2 = null;
String sql= null;
String keyid = null;
// Connect to database
try {
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
conn = DriverManager.getConnection("jdbc:mysql://" + mysql_host + ":3306/" + mysql_database, mysql_login, mysql_password);
// Select data in Database with place holder for parameter
sql = "SELECT * FROM table WHERE keyid= ?";
// prepare the statement
stmt = conn.prepareStatement(sql);
// set the value of key id to use with the query
stmt.setString(1, keyId);
// run the query
rs2 = st.executeQuery();
catch (Exception e){
System.out.println("An error occurred " + e.getMessage());
e.printStackTrace();
finally{
if (rs2 != null) try { rs2.close(); } catch(SQLException ex){}
if (stmt != null) try { stmt.close(); } catch(SQLException ex){}
if (conn != null) try { con.close(); } catch(SQLException ex){}
} -
Long running select statement and v$session_longops
Oracle Version: 10.2.0.4
I've a long running sql query that takes the estimated 6 minutes to complete and return the result.
While it's running I'd like to observe it into the view v$session_longops.
I altered the session that runs the query with
ALTER SESSION SET timed_statistics=TRUE;The tables it queries have gathered statistics on them.
However I don't see any rows in the view v$session_longops for the respective SID and serial#. Why is that? What am I missing?
Thank you!Hi,
Now I understand what you all meant by "loops" here .. Yes, the query does nested loops as one can see from the execution plan. So it could be the reason
SELECT STATEMENT, GOAL = ALL_ROWS
SORT GROUP BY
CONCATENATION
TABLE ACCESS BY LOCAL INDEX ROWID TABLE_1
NESTED LOOPS
NESTED LOOPS
TABLE ACCESS BY GLOBAL INDEX ROWID TABLE_2
INDEX RANGE SCAN IPK_t2_CDATE
TABLE ACCESS BY INDEX ROWID TABLE_3
INDEX RANGE SCAN IPK_T3
PARTITION RANGE ALL
INDEX RANGE SCAN IRGP_REGCODE
TABLE ACCESS BY LOCAL INDEX ROWID TABLE_1
NESTED LOOPS
NESTED LOOPS
TABLE ACCESS BY GLOBAL INDEX ROWID TABLE_2
INDEX RANGE SCAN IPK_t2_STATUS
TABLE ACCESS BY INDEX ROWID TABLE_3
INDEX RANGE SCAN IPK_T3
PARTITION RANGE SINGLE
INDEX RANGE SCAN IRGP_REGCODE -
Select Statement (pl/sql) in ADF
Hi,
I am new in ADF.
Please give any idea or sample code about how to write Select Statement in ADF and how can i catch value.
ThanksThanks for reply
But i don't want to use View Object.
Is there another way like below insert code
public void insertTable() {
//System.out.println("OK");
DBTransaction trans = getDBTransaction();
CallableStatement statement = null;
String plsql =
"DECLARE "
+ "PRAGMA AUTONOMOUS_TRANSACTION; "
+"BEGIN "
+ "INSERT INTO test_check "
+ "(id,name) "
+ "VALUES (?,?); "
+ "COMMIT; "
+"END;";
statement = trans.createCallableStatement(plsql,DBTransaction.DEFAULT);
try {
statement.setInt(1,"001");
statement.setString(2, "user10892984");
int rows = statement.executeUpdate();
} catch (SQLException e) {
throw new JboException(e);
} finally {
try {
if (statement != null)
statement.close();
} catch (SQLException e) {System.out.println("Not Insert.......");
} -
Usage of Xopen SQL states and SQL Exception?
Hi
Is there way to make full use of SQL Exceptions?
Has anybody used sql states from sql exception?
It is specified in the API reference that an sql exception object contains an xopen sql state which is a string. But the states in specs are defined as class, subclass.
The question is how can i make use of these java strings to interpret what exactly happened at the database? Are they really useful? If they are, any utilities which converts these strings to a meaningful message? Any pointers on these question would also help me.
Thanx in adv.
GiridharSQLException has inherited a method getMessage() which seems to be quite useful.
For situations where you want to check on a specific one of several possible (or expected) states (like: maybe the table is not yet created ...), I think you can quite fine use getSQLState() and also getErorCode(). Try out in tests, which information is returned by which constellation, then you can use it for making decisions in your program logic.
But be aware, that all these informations probably are DBMS specific! -
In Oracle SQL, cannot use column in select statement and order by
Hi,
Is there a work around for this.
Thanks in advance
Pablo.Hi,
943981 wrote:
Hi All,
This is the error I get:
ORA-00960: ambiguous column naming in select list
00960. 00000 - "ambiguous column naming in select list"
*Cause: A column name in the order-by list matches more than one select
list columns.
*Action: Remove duplicate column naming in select list.
Error at Line: 6 Column: 17That error message looks pretty clear to me. What don't you understand?
Either
(a) use aliases, so each column has a unique name, or
(b) remove duplicate columns from the SELECT clause.
Post your query. It's hard to say exactly what you're doing wrong when we don't know exactly what you're doing.
For best results, post a complete test script (including CREATE TABLE and INSERT statements, if necessary) that people can to re-create the problem and test their ideas.
See the forum FAQ {message:id=9360002} -
How to processing the results from the select statement in SQL query?
Hi
This might be too simple, but my knowledge of the SQL is very limited...
I have table where I do have details from calls (Lync QoE).
I can take all calls from the table, but I would like to count the concurrent calls on the table. This is how I got it work on the Excel to work (but I would like to do that on the SQL statement to get it more dynamic use):
Table have these line and this is what I get out from the Select):
[callid],[start],[end]
1ABC,1.1.2014 01:00:15, 1.1.2014 01:01:00
5DEF,1.1.2014 01:00:45, 1.1.2014 01:05:00
FDE2,1.1.2014 01:03:15, 1.1.2014 01:04:00
KDJ8,1.1.2014 01:04:15, 1.1.2014 01:06:00
FDJ8,2.1.2014 01:04:15, 2.1.2014 01:06:00
KDSE,3.1.2014 01:04:15, 3.1.2014 01:06:00
The information I would like to get, is what is the maximum amount of the concurrent calls per day.
On the excel I basically count line by line how many concurrent calls each line have had, and then pickup the highest one. On above example the calls 5DEF, FDE2 and FDE2 have been active at the same time which gives 3 for the first day.
The table is ordered by the start. So let say the code is on the third line (FDE2). I need to count calls from before which end time is after the start time (of FDE2), but also I need to count calls after (FDE2) which are started before the current
call has ended.
PetriUnfortunately your post is off topic as it's not specific to SQL Server Samples and Community Projects.
This is a standard response I’ve written in advance to help the many people who post their question in this forum in error, but please don’t ignore it. The links I provide below will help you determine the right forum to ask your question in.
For technical issues with Microsoft products that you would run into as an end user, please visit the Microsoft Answers forum ( http://answers.microsoft.com ) which has sections for Windows, Hotmail,
Office, IE, and other products.
For Technical issues with Microsoft products that you might have as an IT professional (like technical installation issues, or other IT issues), please head to the TechNet Discussion forums at http://social.technet.microsoft.com/forums/en-us, and
search for your product name.
For issues with products you might have as a Developer (like how to talk to APIs, what version of software do what, or other developer issues), please head to the MSDN discussion forums at http://social.msdn.microsoft.com/forums/en-us, and
search for your product or issue.
If you’re asking a question particularly about one of the Microsoft Dynamics products, a great place to start is here: http://community.dynamics.com/
If you think your issue is related to SQL Server Samples and Community Projects and I've flagged it as Off-topic, I apologise. Please repost your question and include as much detail as possible about your problem so that someone can assist you further.
If you really have no idea where to post your question please visit the Where is the forum for…? forum http://social.msdn.microsoft.com/forums/en-us/whatforum/
When you see answers and helpful posts, please click Vote As Helpful,
Propose As Answer, and/or Mark As Answer
Jeff Wharton
MSysDev (C.Sturt), MDbDsgnMgt (C.Sturt), MCT, MCPD, MCSD, MCSA, MCITP, MCDBA
Blog: Mr. Wharty's Ramblings
Twitter: @Mr_Wharty
MC ID:
Microsoft Transcript -
Discrepancy between Select Expert and SQL Query
Greetings. I am having an issue with a report, but I think it's more cosmetic and may not be causing a functional issue...
When I go into the Report...Select Expert...Record, I see that my criteria for the report is .AND. logic.
When I go into the SQL Query view, it shows .OR. logic...
After I verify the database, the SQL query still does not get updated. Saving and re-opening the report still does not update.
Is there any reason this will never match? Thanks in advance.Sorry. I am on Crystal 12. Database is SQL 2005.
I didn't think the detail mattered much, but the select expert shows:
isnull({NONCONFORMANCE.CLOSED_DATE}) and
not isnull({NONCONFORMANCE.PRODUCT_ID}) and
not({NONCONFORMANCE.PRODUCT_ID}= '') and
not({NONCONFORMANCE.PRODUCT_ID}= ' ')
SELECT N.NCM_ID, N.NCM_DATE, N.PRODUCT_ID, N.CLOSED_DATE, N.ENTITY_ID
FROM NONCONFORMANCE N
WHERE N.CLOSED_DATE IS NULL AND N.PRODUCT_ID IS NOT NULL AND NOT (N.PRODUCT_ID='' OR N.PRODUCT_ID=' ') AND N.ENTITY_ID='CHI'
Now that I look at how the SQL is generated (after cleaning up the statement), it's the negatives that got me. I originally had a problem with the report that was pulling back blanks and spaces. I made changes and I didn't pay close enough attention to what exactly changed in the SQL... It appears to be the way the logic in the Select Expert is converted to SQL.
I just need to start using Command more often and write my own SQL instead of using the Select Expert!!! -
Oracle 11g stats and SQL plan mgt
Oracle 11.0.1.7:
- According to what I have read so far in the various documents it looks like when dbms gather stats run and if that results in new sql plan oracle will not automatically start using that plan until it's verified by sql tuning advisor or is evolved. Is that correct? Is that the default behaviour?
- I just upgraded from 10g to 11g so I am not sure how stats is behaving currently. I am really concerned and want to understand how it's behaving.
- How can I tell what's going on currently in the system in terms of stats gathering and if the new better plan is being used or not.You have the default setting for the two parameters in place. That means, that if SQL Plan Baselines exist, they will be used, thereby preventing new execution plans from getting used without evolvement
optimizer_use_sql_plan_baselines=true does that.
But by default, there are no SQL Plan Baselines as long as you don't create them - for example with the setting of
optimizer_capture_sql_plan_baselines=trueYou can check whether SQL Plan Baselines exist with
select * from dba_sql_plan_baselines;It should return no rows. -
PL/SQL cursors vs. SQL*plus Select statement
Hi folks, hope you're doing well,
Here is a question that kept me wondering:
Why would I use cursors when i can achieve the same thing with a SQL+ Select statement which is much easier to formulate than a cursor (e.g. you need no declaration, loops etc)?.
Thanks so much,
-aThere is no such thing as a SQL*Plus SELECT statement. The SELECT command is part of the SQL Language - not part of the SQL*Plus (very limited small vocabulary) macro language.
All SQL SELECTs (from client languages) winds up in the SQL Engine as SQL cursors. A SQL Cursor is basically the:
- SQL source code
- SQL "compiled" code (instructions on how to fetch the rows)
On the client side, client cursors (not to be confused with SQL cursors) are used. A client cursor is created in the client language when it makes SQL calls via the database client driver (called the OCI/Oracle Call Interface for Oracle clients).
Typically this is what a client does. It makes a connection to the database and gets a database handler in return. The database handler is the "communication channel" from the client to the db. In Oracle, the database handler in the client refers to the Oracle session (for that client) on db server.
A SQL statement (source code) is used by the client. This can be a SELECT statement you type in at the SQL*Plus command line. It can be a SELECT statement for the PL/SQL cursor command in a stored procedure.
The client creates a SQL handle for this SQL statement, by calling the Oracle client driver. Note that this SQL handle is a client handle - a client cursor for that SQL statement.
E.g.
a) sqlHandle = CreateSQL( databaseHandle, 'SELECT ... FROM ...')
b) sqlHandle.Parse
c) sqlHandle.Execute
After the SQL handle (client cursor) has been executed, the client can fetch rows from it.
This is what SQL*Plus does automatically for you, without you having to write the code to do it. SQL*Plus CONNECT command create a database connection handle. You enter a SELECT statement and SQL*Plus creates a SQL handle (client cursor), executes it, fetches from it, displays the rows, and closes the SQL handle when done.
The same applies to PL/SQL. You can use a SELECT statement just like that in PL/SQL. E.g.
declare
i integer;
begin
select count(*) into i from emp where deptid = 123;
end;This is called an implicit cursor. PL/SQL creates (just like SQL*Plus) an implicit client cursor. It creates and disposes of that client SQL handle for you - you do not need to do it.
Or, you can create an explicit cursor. E.g. declare
cursor c is select count(*) from emp where deptid = 123;
i integer;
begin
open c;
fetch c into i;
close c;
end;The question as to when to use implicit (client) cursors versus explicit (client) cursors depends on your requirements. Do you need to cycle through the results of the SQL? Etc.
And keep in mind that in either case, the SQL Engine creates a SQL cursor anyway on its side. -
SQL column as select statement to be referenced into a group by
Is there a notation or solution to be able to reference a column that is a inline select statement within a group by as detailed below? The group by will not accept the alias. I also tried to make the SQL a MAX to remove the need for the group by reference and this returned invalid expression.
SELECT DISTINCT hdr.BUSINESS_UNIT,
hdr.SESSN_ID,
hdr.STREAM_ROOT_ID,
hdr.SESSN_STS_CD,
hdr.SESSN_CRE_DTTM,
CASE
WHEN C.OPRID <> ' ' THEN C.OPRID
ELSE S.OPERATOR
END OPRID,
strm.QS_APP_CONTEXT,
RECV.QTY_SH_RECVD Quantity_Received,
CASE
WHEN hdr.BUSINESS_UNIT = 'MFG01' THEN MAX(G.MFDS_SGRP_SIZE)
ELSE MAX(S.SESSN_SGRP_SIZE)
END Quantity_Inspected,
MAX(S.QS_VALUEREADING_1) Defect_Count,
CASE
WHEN MAX(S.QS_VALUEREADING_1) = 0 THEN ' '
ELSE MAX(G.MFDS_NAME)
END Characteristic,
MAX(CMNT.QS_COMMENT2) COMMENTS,
strm.INV_ITEM_ID,
itm.DESCR,
strm.WORK_CENTER_CODE,
strm.VENDOR_ID,
*(SELECT V.NAME1 FROM PS_VENDOR V WHERE strm.VENDOR_ID = V.VENDOR_ID AND V.SETID = (SELECT SETID FROM PS_SET_CNTRL_REC*
WHERE RECNAME = 'VENDOR'
AND SETCNTRLVALUE = strm.BUSINESS_UNIT)) VENDOR_NAME,
strm.PRDN_AREA_CODE,
strm.COMPL_OP_SEQ,
strm.PRODUCTION_TYPE,
C.RECEIVER_ID,
C.RECV_LN_NBR,
RECV.PO_ID,
RECV.LINE_NBR,
RECV.SCHED_NBR,
C.PRODUCTION_ID,
C.SERIAL_ID,
C.INV_LOT_ID
FROM PS_QS_SESSN_HDR8 hdr
LEFT OUTER JOIN PS_QS_SESSN_TRACE8 C
ON hdr.BUSINESS_UNIT = C.BUSINESS_UNIT
AND hdr.SESSN_ID = C.SESSN_ID
LEFT OUTER JOIN PS_RECV_INSPDTL_VW RECV
ON C.BUSINESS_UNIT = RECV.BUSINESS_UNIT
AND C.RECEIVER_ID = RECV.RECEIVER_ID
AND C.RECV_LN_NBR = RECV.RECV_LN_NBR
LEFT OUTER JOIN PS_QS_STREAM_ROOT strm
ON hdr.STREAM_ROOT_ID = strm.STREAM_ROOT_ID
AND hdr.BUSINESS_UNIT = strm.BUSINESS_UNIT
LEFT OUTER JOIN PS_QS_STREAM8_VW G
ON strm.STREAM_ROOT_ID = G.STREAM_ROOT_ID
AND strm.BUSINESS_UNIT = G.BUSINESS_UNIT
LEFT OUTER JOIN PS_QS_SUBGROUP S
ON hdr.BUSINESS_UNIT = S.BUSINESS_UNIT
AND hdr.SESSN_ID = S.SESSN_ID
AND S.STREAM_ID = G.STREAM_ID
LEFT OUTER JOIN PS_QS_SESSN_COMM8 CMNT
ON S.BUSINESS_UNIT = CMNT.BUSINESS_UNIT
AND S.SESSN_ID = CMNT.SESSN_ID
AND S.STREAM_ID = CMNT.STREAM_ID
AND C.SAMPLE = CMNT.SAMPLE
LEFT OUTER JOIN PS_MASTER_ITEM_TBL itm
ON itm.INV_ITEM_ID = strm.INV_ITEM_ID
LEFT OUTER JOIN PS_SET_CNTRL_REC cntrl
ON itm.SETID = cntrl.SETID
AND cntrl.RECNAME = 'MASTER_ITEM_TBL'
AND cntrl.SETCNTRLVALUE = strm.BUSINESS_UNIT
WHERE S.QS_VALUEREADING_1 = (SELECT MAX(S2.QS_VALUEREADING_1)
FROM PS_QS_SUBGROUP S2
WHERE S2.BUSINESS_UNIT = S.BUSINESS_UNIT
AND S2.SESSN_ID = S.SESSN_ID
AND S2.STREAM_ID = S.STREAM_ID)
GROUP BY hdr.BUSINESS_UNIT,
hdr.SESSN_ID,
hdr.STREAM_ROOT_ID,
hdr.SESSN_STS_CD,
hdr.SESSN_CRE_DTTM,
C.OPRID,
S.OPERATOR,
strm.QS_APP_CONTEXT,
RECV.QTY_SH_RECVD,
strm.INV_ITEM_ID,
itm.DESCR,
strm.WORK_CENTER_CODE,
strm.VENDOR_ID,
VENDOR_NAME,
strm.PRDN_AREA_CODE,
strm.COMPL_OP_SEQ,
strm.PRODUCTION_TYPE,
C.RECEIVER_ID,
C.RECV_LN_NBR,
RECV.PO_ID,
RECV.LINE_NBR,
RECV.SCHED_NBR,
C.PRODUCTION_ID,
C.SERIAL_ID,
C.INV_LOT_IDHi,
Assign the alias in a sub-query. Then you'll be able to use it wherever you want to, and how many times you want to, in a super-query.
For example:
WITH got_vendor AS
SELECT hdr.business_unit
SELECT v.name1
FROM ps_vendor v
WHERE strm.vendor_id = v.vendor_id
AND v.setid = (
SELECT setid
FROM ps_set_cntrl_rec
WHERE recname = 'VENDOR'
AND setcntrlvalue = strm.business_unit
) AS vendor_name
FROM ps_qs_sessn_hdr8 hdr
SELECT business_unit -- NOTE: no hdr.; all columns are from got_vendor now
, vendor
FROM got_vendor
GROUP BY business_unit
, vendor
;When you define an alias (such as vendor) in a query, you can use that alias in the ORDER BY clause of that same query, but that's the only place in that same query where you can use it. If you want to use the alias anywhere else (e.g., in the GROUP BY clause, as in your example, the WHERE clause, or elsewhere in the SELECT clause), then you probably want to compute it in a sub-query, as shown above.
There's probably a better way to compute vendor, but that's a separate problem.
Edited by: Frank Kulash on Jan 3, 2012 10:37 AM
Added example -
Hint in Update or Select Statement in an inline query ??
Hi ,
I had an update statement that will get the data from the inline select statement,now where can i can keep the hint ,either in update statement or in Select statement...
Please let me know if my sample script is wrong or any better way to approach...Please assume that Salary table had millions of employee's salary records.
update emp
set salary = salary + (select /*+ full(a) parallel(a,4) */ salary from Salary
where experience > 5 and empno = 55 )
where empno = 85Thanks
RedeYou would put the hint in the select statement as you have it, but it won't work until you alias your table name to "a" since that is how you are referencing it in the hint:
update emp
set salary = salary + (select /*+ full(a) parallel(a,4) */ salary from Salary a
where experience > 5 and empno = 55 )
where empno = 85
NOTE I added the "a" right after the Salary table name AND you can only do parallel updates on partitioned table, but the select will run in parallel to at least get the data for you quickly.
To answer your other question about syntax, it is incorrect and there are a lot of ways to write it but a straight forward way would be to use the merge statement
merge into emp e
using (select /*+ full(s) parallel(s,4) */ s.salary from salary s where s.experience > 5) s
on (e.empno = s.empno)
when matched then update
set salary = s.salary; -
How to generate mutiple Results for multiple SQL SELECT statements
I just downloaded SQL Developer 1.5 and play around with it.
On a daily basis, I need run 4 different SELECT statements and dump the output of each SELECT into an CSV file and send to some users. In SQL Navigator, I can select all 4 SELECT statements and execute them at same time. Once all complete, I will see 4 tabs, each represent the output for each SELECT statement. Then I can export output from each tab into a CSV file.
It seems that SQL Developer 1.5 still can't run mutiple SELECT statements and display the output of each statement into a separate "Results" tab so that I can export the data into multiple CSV files easily.
Right now, I have to hightlight each SELECT statement and press F9, then export the output data into CSV.
I wish I can execute 4 SELECT statements all in once on SQL Developer and get all the output data and export 4 times into 4 CSV files.
Thanks!
KevinHow about doing it as a set of tabs within the Resuls Tab?
So you would have your Top row of tabs:
Results, Script Output, Explain, AutoTrace, DBMS Output and OWA Output
Then When you have the Results tab selected you could have a row of tabs beneath the Top row with one tab for each result set. Switching between result sets should switch which section of SQL is highlighted as the "Current SQL".
A similar mechinism could be employed for each of the top level tabs where it makes sense to have multiple output tabs.
A further refinement of this feature might be to allow the result tabs to be dockable within the parent tab so that multiple result tabs can be viewed simultaneously. This way 2 or more explain plans (for example) could be visually compared without requiring the code to exist in two separate code panes. -
PL/SQL 101 : Cursors and SQL Projection
PL/SQL 101 : Cursors and SQL Projection
This is not a question, it's a forum article, in reponse to the number of questions we get regarding a "dynamic number of columns" or "rows to columns"
There are two integral parts to an SQL Select statement that relate to what data is selected. One is Projection and the other is Selection:-
Selection is the one that we always recognise and use as it forms the WHERE clause of the select statement, and hence selects which rows of data are queried.
The other, SQL Projection is the one that is less understood, and the one that this article will help to explain.
In short, SQL Projection is the collective name for the columns that are Selected and returned from a query.
So what? Big deal eh? Why do we need to know this?
The reason for knowing this is that many people are not aware of when SQL projection comes into play when you issue a select statement. So let's take a basic query...
First create some test data...
create table proj_test as
select 1 as id, 1 as rn, 'Fred' as nm from dual union all
select 1,2,'Bloggs' from dual union all
select 2,1,'Scott' from dual union all
select 2,2,'Smith' from dual union all
select 3,1,'Jim' from dual union all
select 3,2,'Jones' from dual
... and now query that data...
SQL> select * from proj_test;
ID RN NM
1 1 Fred
1 2 Bloggs
2 1 Scott
2 2 Smith
3 1 Jim
3 2 Jones
6 rows selected.
OK, so what is that query actually doing?
To know that we need to consider that all queries are cursors and all cursors are processed in a set manner, roughly speaking...
1. The cursor is opened
2. The query is parsed
3. The query is described to know the projection (what columns are going to be returned, names, datatypes etc.)
4. Bind variables are bound in
5. The query is executed to apply the selection and identify the data to be retrieved
6. A row of data is fetched
7. The data values from the columns within that row are extracted into the known projection
8. Step 6 and 7 are repeated until there is no more data or another condition ceases the fetching
9. The cursor is closed
The purpose of the projection being determined is so that the internal processing of the cursor can allocate memory etc. ready to fetch the data into. We won't get to see that memory allocation happening easily, but we can see the same query being executed in these steps if we do it programatically using the dbms_sql package...
CREATE OR REPLACE PROCEDURE process_cursor (p_query in varchar2) IS
v_sql varchar2(32767) := p_query;
v_cursor number; -- A cursor is a handle (numeric identifier) to the query
col_cnt integer;
v_n_val number; -- numeric type to fetch data into
v_v_val varchar2(20); -- varchar type to fetch data into
v_d_val date; -- date type to fetch data into
rec_tab dbms_sql.desc_tab; -- table structure to hold sql projection info
dummy number;
v_ret number; -- number of rows returned
v_finaltxt varchar2(100);
col_num number;
BEGIN
-- 1. Open the cursor
dbms_output.put_line('1 - Opening Cursor');
v_cursor := dbms_sql.open_cursor;
-- 2. Parse the cursor
dbms_output.put_line('2 - Parsing the query');
dbms_sql.parse(v_cursor, v_sql, dbms_sql.NATIVE);
-- 3. Describe the query
-- Note: The query has been described internally when it was parsed, but we can look at
-- that description...
-- Fetch the description into a structure we can read, returning the count of columns that has been projected
dbms_output.put_line('3 - Describing the query');
dbms_sql.describe_columns(v_cursor, col_cnt, rec_tab);
-- Use that description to define local datatypes into which we want to fetch our values
-- Note: This only defines the types, it doesn't fetch any data and whilst we can also
-- determine the size of the columns we'll just use some fixed sizes for this example
dbms_output.put_line(chr(10)||'3a - SQL Projection:-');
for j in 1..col_cnt
loop
v_finaltxt := 'Column Name: '||rpad(upper(rec_tab(j).col_name),30,' ');
case rec_tab(j).col_type
-- if the type of column is varchar2, bind that to our varchar2 variable
when 1 then
dbms_sql.define_column(v_cursor,j,v_v_val,20);
v_finaltxt := v_finaltxt||' Datatype: Varchar2';
-- if the type of the column is number, bind that to our number variable
when 2 then
dbms_sql.define_column(v_cursor,j,v_n_val);
v_finaltxt := v_finaltxt||' Datatype: Number';
-- if the type of the column is date, bind that to our date variable
when 12 then
dbms_sql.define_column(v_cursor,j,v_d_val);
v_finaltxt := v_finaltxt||' Datatype: Date';
-- ...Other types can be added as necessary...
else
-- All other types we'll assume are varchar2 compatible (implicitly converted)
dbms_sql.DEFINE_COLUMN(v_cursor,j,v_v_val,2000);
v_finaltxt := v_finaltxt||' Datatype: Varchar2 (implicit)';
end case;
dbms_output.put_line(v_finaltxt);
end loop;
-- 4. Bind variables
dbms_output.put_line(chr(10)||'4 - Binding in values');
null; -- we have no values to bind in for our test
-- 5. Execute the query to make it identify the data on the database (Selection)
-- Note: This doesn't fetch any data, it just identifies what data is required.
dbms_output.put_line('5 - Executing the query');
dummy := dbms_sql.execute(v_cursor);
-- 6.,7.,8. Fetch the rows of data...
dbms_output.put_line(chr(10)||'6,7 and 8 Fetching Data:-');
loop
-- 6. Fetch next row of data
v_ret := dbms_sql.fetch_rows(v_cursor);
-- If the fetch returned no row then exit the loop
exit when v_ret = 0;
-- 7. Extract the values from the row
v_finaltxt := null;
-- loop through each of the Projected columns
for j in 1..col_cnt
loop
case rec_tab(j).col_type
-- if it's a varchar2 column
when 1 then
-- read the value into our varchar2 variable
dbms_sql.column_value(v_cursor,j,v_v_val);
v_finaltxt := ltrim(v_finaltxt||','||rpad(v_v_val,20,' '),',');
-- if it's a number column
when 2 then
-- read the value into our number variable
dbms_sql.column_value(v_cursor,j,v_n_val);
v_finaltxt := ltrim(v_finaltxt||','||to_char(v_n_val,'fm999999'),',');
-- if it's a date column
when 12 then
-- read the value into our date variable
dbms_sql.column_value(v_cursor,j,v_d_val);
v_finaltxt := ltrim(v_finaltxt||','||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'),',');
else
-- read the value into our varchar2 variable (assumes it can be implicitly converted)
dbms_sql.column_value(v_cursor,j,v_v_val);
v_finaltxt := ltrim(v_finaltxt||',"'||rpad(v_v_val,20,' ')||'"',',');
end case;
end loop;
dbms_output.put_line(v_finaltxt);
-- 8. Loop to fetch next row
end loop;
-- 9. Close the cursor
dbms_output.put_line(chr(10)||'9 - Closing the cursor');
dbms_sql.close_cursor(v_cursor);
END;
SQL> exec process_cursor('select * from proj_test');
1 - Opening Cursor
2 - Parsing the query
3 - Describing the query
3a - SQL Projection:-
Column Name: ID Datatype: Number
Column Name: RN Datatype: Number
Column Name: NM Datatype: Varchar2
4 - Binding in values
5 - Executing the query
6,7 and 8 Fetching Data:-
1 ,1 ,Fred
1 ,2 ,Bloggs
2 ,1 ,Scott
2 ,2 ,Smith
3 ,1 ,Jim
3 ,2 ,Jones
1 ,3 ,Freddy
1 ,4 ,Fud
9 - Closing the cursor
PL/SQL procedure successfully completed.
So, what's really the point in knowing when SQL Projection occurs in a query?
Well, we get many questions asking "How do I convert rows to columns?" (otherwise known as a pivot) or questions like "How can I get the data back from a dynamic query with different columns?"
Let's look at a regular pivot. We would normally do something like...
SQL> select id
2 ,max(decode(rn,1,nm)) as nm_1
3 ,max(decode(rn,2,nm)) as nm_2
4 from proj_test
5 group by id
6 /
ID NM_1 NM_2
1 Fred Bloggs
2 Scott Smith
3 Jim Jones
(or, in 11g, use the new PIVOT statement)
but many of these questioners don't understand it when they say their issue is that, they have an unknown number of rows and don't know how many columns it will have, and they are told that you can't do that in a single SQL statement. e.g.
SQL> insert into proj_test (id, rn, nm) values (1,3,'Freddy');
1 row created.
SQL> select id
2 ,max(decode(rn,1,nm)) as nm_1
3 ,max(decode(rn,2,nm)) as nm_2
4 from proj_test
5 group by id
6 /
ID NM_1 NM_2
1 Fred Bloggs
2 Scott Smith
3 Jim Jones
... it's not giving us this 3rd entry as a new column and we can only get that by writing the expected columns into the query, but then what if more columns are added after that etc.
If we look back at the steps of a cursor we see again that the description and projection of what columns are returned by a query happens before any data is fetched back.
Because of this, it's not possible to have the query return back a number of columns that are based on the data itself, as no data has been fetched at the point the projection is required.
So, what is the answer to getting an unknown number of columns in the output?
1) The most obvious answer is, don't use SQL to try and pivot your data. Pivoting of data is more of a reporting requirement and most reporting tools include the ability to pivot data either as part of the initial report generation or on-the-fly at the users request. The main point about using the reporting tools is that they query the data first and then the pivoting is simply a case of manipulating the display of those results, which can be dynamically determined by the reporting tool based on what data there is.
2) The other answer is to write dynamic SQL. Because you're not going to know the number of columns, this isn't just a simple case of building up a SQL query as a string and passing it to the EXECUTE IMMEDIATE command within PL/SQL, because you won't have a suitable structure to read the results back into as those structures must have a known number of variables for each of the columns at design time, before the data is know. As such, inside PL/SQL code, you would have to use the DBMS_SQL package, just like in the code above that showed the workings of a cursor, as the columns there are referenced by position rather than name, and you have to deal with each column seperately. What you do with each column is up to you... store them in an array/collection, process them as you get them, or whatever. They key thing though with doing this is that, just like the reporting tools, you would need to process the data first to determine what your SQL projection is, before you execute the query to fetch the data in the format you want e.g.
create or replace procedure dyn_pivot is
v_sql varchar2(32767);
-- cursor to find out the maximum number of projected columns required
-- by looking at the data
cursor cur_proj_test is
select distinct rn
from proj_test
order by rn;
begin
v_sql := 'select id';
for i in cur_proj_test
loop
-- dynamically add to the projection for the query
v_sql := v_sql||',max(decode(rn,'||i.rn||',nm)) as nm_'||i.rn;
end loop;
v_sql := v_sql||' from proj_test group by id order by id';
dbms_output.put_line('Dynamic SQL Statement:-'||chr(10)||v_sql||chr(10)||chr(10));
-- call our DBMS_SQL procedure to process the query with it's dynamic projection
process_cursor(v_sql);
end;
SQL> exec dyn_pivot;
Dynamic SQL Statement:-
select id,max(decode(rn,1,nm)) as nm_1,max(decode(rn,2,nm)) as nm_2,max(decode(rn,3,nm)) as nm_3 from proj_test group by id order by id
1 - Opening Cursor
2 - Parsing the query
3 - Describing the query
3a - SQL Projection:-
Column Name: ID Datatype: Number
Column Name: NM_1 Datatype: Varchar2
Column Name: NM_2 Datatype: Varchar2
Column Name: NM_3 Datatype: Varchar2
4 - Binding in values
5 - Executing the query
6,7 and 8 Fetching Data:-
1 ,Fred ,Bloggs ,Freddy
2 ,Scott ,Smith ,
3 ,Jim ,Jones ,
9 - Closing the cursor
PL/SQL procedure successfully completed.
... and if more data is added ...
SQL> insert into proj_test (id, rn, nm) values (1,4,'Fud');
1 row created.
SQL> exec dyn_pivot;
Dynamic SQL Statement:-
select id,max(decode(rn,1,nm)) as nm_1,max(decode(rn,2,nm)) as nm_2,max(decode(rn,3,nm)) as nm_3,max(decode(rn,4,nm)) as nm_4 from proj_test group by id order by id
1 - Opening Cursor
2 - Parsing the query
3 - Describing the query
3a - SQL Projection:-
Column Name: ID Datatype: Number
Column Name: NM_1 Datatype: Varchar2
Column Name: NM_2 Datatype: Varchar2
Column Name: NM_3 Datatype: Varchar2
Column Name: NM_4 Datatype: Varchar2
4 - Binding in values
5 - Executing the query
6,7 and 8 Fetching Data:-
1 ,Fred ,Bloggs ,Freddy ,Fud
2 ,Scott ,Smith , ,
3 ,Jim ,Jones , ,
9 - Closing the cursor
PL/SQL procedure successfully completed.
Of course there are other methods, using dynamically generated scripts etc. (see Re: 4. How do I convert rows to columns?), but the above simply demonstrates that:-
a) having a dynamic projection requires two passes of the data; one to dynamically generate the query and another to actually query the data,
b) it is not a good idea in most cases as it requires code to handle the results dynamically rather than being able to simply query directly into a known structure or variables, and
c) a simple SQL statement cannot have a dynamic projection.
Most importantly, dynamic queries prevent validation of your queries at the time your code is compiled, so the compiler can't check that the column names are correct or the tables names, or that the actual syntax of the generated query is correct. This only happens at run-time, and depending upon the complexity of your dynamic query, some problems may only be experienced under certain conditions. In effect you are writing queries that are harder to validate and could potentially have bugs in them that would are not apparent until they get to a run time environment. Dynamic queries can also introduce the possibility of SQL injection (a potential security risk), especially if a user is supplying a string value into the query from an interface.
To summarise:-
The projection of an SQL statement must be known by the SQL engine before any data is fetched, so don't expect SQL to magically create columns on-the-fly based on the data it's retrieving back; and, if you find yourself thinking of using dynamic SQL to get around it, just take a step back and see if what you are trying to achieve may be better done elsewhere, such as in a reporting tool or the user interface.
Other articles in the PL/SQL 101 series:-
PL/SQL 101 : Understanding Ref Cursors
PL/SQL 101 : Exception Handlingexcellent article. However there is one thing which is slightly erroneous. You don't need a type to be declared in the database to fetch the data, but you do need to declare a type;
here is one of my unit test scripts that does just that.
DECLARE
PN_CARDAPPL_ID NUMBER;
v_Return Cci_Standard.ref_cursor;
type getcardapplattrval_recordtype
Is record
(cardappl_id ci_cardapplattrvalue.cardappl_ID%TYPE,
tag ci_cardapplattrvalue.tag%TYPE,
value ci_cardapplattrvalue.value%TYPE
getcardapplattrvalue_record getcardapplattrval_recordtype;
BEGIN
PN_CARDAPPL_ID := 1; --value must be supplied
v_Return := CCI_GETCUSTCARD.GETCARDAPPLATTRVALUE(
PN_CARDAPPL_ID => PN_CARDAPPL_ID
loop
fetch v_return
into getcardapplattrvalue_record;
dbms_output.put_line('Cardappl_id=>'||getcardapplattrvalue_record.cardappl_id);
dbms_output.put_line('Tag =>'||getcardapplattrvalue_record.tag);
dbms_output.put_line('Value =>'||getcardapplattrvalue_record.value);
exit when v_Return%NOTFOUND;
end loop;
END;
Maybe you are looking for
-
Help with getting a node xpath from within the rules engine
I'm new here and to BizTalk. In the rule composer I've setup my vocabularies and have started implementing rules. When a rule is evaluated to false I have a custom function called AddValidationError which is attached to the Action section. This me
-
HT4972 how do i update my iphone on my laptop?
How do I update my iPhone on my laptop?
-
Why aren't my adobe webfonts showing correctly in Chrome version 37?
I am running Windows 7 and using Chrome version 37. My muse sites with adobe webfonts are not displaying the nice fonts. They are jagged and looks crappy. On the other hand, Internet Explorer is displaying them just fine. web sites in trouble are www
-
PFD files not loading correctly into iTunes Library
I have just upgraded to Mavericks. Now when I try to to "Load to Library" the PDF files are placed in the music section of iTunes, not the book section. Any help would be appreciated.
-
Livecycle/Dataservices 2.6.1 [Transient] property
Hi Guys and Girls I am using livecyle 2.6.1 with AIR 2.0.2 and a java backend, with the flex 3.4 SDK. I have a managed collection with a property that has a [Transient] variable set which is used as a flag for products that have been ordered.This v