1 sql best coding practice in peopletools 7.x david kurtz go-faster consultancy ltd....
TRANSCRIPT
1
SQL Best Coding Practice in PeopleTools 7.x
David KurtzGo-Faster Consultancy Ltd.
www.go-faster.co.uk
2
Who are you?
• Familiar with SQL• not necessarily the DBA• Might be
– Application developer
– Team Leader
3
So Where is all the SQL?
• Views• Scrollxxx() PeopleCode• SQLExec() PeopleCode• Mass Change• Application Engine• PS/Query / Crystal• SQR• Stored Statements
4
Views
5
Scrollxxx() PeopleCode
6
SQLExec() PeopleCode
7
Mass Change
8
Application Engine
9
PS/Query / Crystal
10
SQR
11
Stored Statements
12
Simplicity
• As simple as possible• As complicated as necessary
• Data Model• Avoid excessive I/O
13
SQL
• Coding Standard• Implicit Type Conversion• Sorts• Indexes• Sub-queries
14
Coding Standards
• Be explicit– Make it readable
• Indent sub-queries and brackets
– Use table aliases• Lower parse time
• Less unexpected results without error messages
– Avoid implicit type conversion
– Avoid possible Y2K issue• Explicitly specify Y2K compliant date formats
15
Readability
CREATE TABLE PS_GEN_JOB_TBL(...) AS SELECT DISTINCT ...FROM PS_PERSONAL_DATA A, PS_JOB B, PS_PERS_NID ND,
PS_NID_TYPE_TBL NDTWHERE A.EMPLID=B.EMPLIDAND A.EMPLID=ND.EMPLIDAND B.EMPLID=ND.EMPLIDAND ND.NATIONAL_ID_TYPE=NDT.NATIONAL_ID_TYPEAND ( B.EFFDT>=%CURRENTDATEIN
OR ( B.EFFDT=( SELECT MAX(B2.EFFDT)FROM PS_JOB B2WHERE B2.EMPLID=B.EMPLID AND B2.EMPL_RCD#=B.EMPL_RCD# AND B2.EFFDT<=%CURRENTDATEIN)
AND B.EFFSEQ= (SELECT MAX(B3.EFFSEQ) FROM PS_JOB B3 WHERE B3.EMPLID=B.EMPLID AND B3.EMPL_RCD#=B.EMPL_RCD# AND B3.EFFDT=B.EFFDT)))
16
Minimum table aliases
SELECT COUNT(*)FROM PS_JOB BWHERE ( EFFDT=( SELECT MAX(B1.EFFDT)
FROM PS_JOB B1WHERE B.EMPLID=EMPLID AND B.EMPL_RCD#=EMPL_RCD# AND B.EFFDT<=%CURRENTDATEIN)
AND EFFSEQ= (SELECT MAX(B2.EFFSEQ) FROM PS_JOB B2WHERE B.EMPLID=EMPLID AND B.EMPL_RCD#=EMPL_RCD# AND B.EFFDT=EFFDT))
17
Maximum table aliases
SELECT COUNT(*)FROM PS_JOB BWHERE ( B.EFFDT=( SELECT MAX(B1.EFFDT)
FROM PS_JOB B1WHERE B1.EMPLID=B.EMPLID AND B1.EMPL_RCD#=B.EMPL_RCD# AND B1.EFFDT<=%CURRENTDATEIN)
AND B.EFFSEQ= (SELECT MAX(B2.EFFSEQ) FROM PS_JOB B2WHERE B2.EMPLID=B.EMPLID AND B2.EMPL_RCD#=B.EMPL_RCD# AND B2.EFFDT=B.EFFDT))
18
Wrong table alias
SELECT COUNT(*)FROM PS_JOB BWHERE ( EFFDT=( SELECT MAX(B1.EFFDT)
FROM PS_JOB B1WHERE B.EMPLID=EMPLID AND B.EMPL_RCD#=EMPL_RCD# AND B.EFFDT<=%CURRENTDATEIN)
AND EFFSEQ= (SELECT MAX(B2.EFFSEQ) FROM PS_JOB B2WHERE B2.EMPLID=EMPLID AND B2.EMPL_RCD#=EMPL_RCD# AND B2.EFFDT=EFFDT))
19
Implicit Type Conversion
SELECT *FROM PS_JOBWHERE EMPLID=8001
SELECT *FROM PS_JOBWHERE EMPLID=‘8001’
20
Implicit Type Conversion
SELECT *FROM PS_JOBWHERE EMPLID=8001
TABLE ACCESS (FULL) OF 'PS_JOB’
why did this not use the index?
SELECT *FROM PS_JOBWHERE EMPLID=‘8001’
INDEX (RANGE SCAN) OF 'PSAJOB' (NON-UNIQUE)
21
Implicit Type Conversion
SELECT *FROM PS_JOBWHERE EMPLID=8001
TABLE ACCESS (FULL) OF 'PS_JOB’
why did this not use the index?
SELECT *FROM PS_JOBWHERE TO_NUMBER(EMPLID)=8001
SELECT *FROM PS_JOBWHERE EMPLID=‘8001’
INDEX (RANGE SCAN) OF 'PSAJOB' (NON-UNIQUE)
22
Sorts
• Updating indexed columns• Distinct• Order by• Group by• Union -v- Union All
23
Indexes
• >~ 200 rows• <~ 10%
– Very rough guidelines
– Avoid updating indexed columns
– Sometimes, even very small tables, that fit in a single block can benefit from a suitable index.
24
Distinct
• Sorts whole select list• Can drive the join order of the tables• Avoid distinct & order by
– Order one way for the distinct
– Order another way for the order by
25
Distinct
SELECT DISTINCT A,B,C,DFROM tableORDER BY A,B,C
• ‘Order by’ clause is necessary– Update Mar 2009 – Up to Oracle 9i,DISTINCT and GROUP BY used a sort operation, so on non-partitioned tables the rows were returned in that order. In Oracle 10g these commands use a hash operation. If you want the rows in a particular order you should say so!
26
Distinct
• Instead of
SELECT DISTINCT
A,B,C,DFROM tableORDER BY A,C,B
• Do not rely on this
SELECT DISTINCT
A,C,B, DFROM table
27
Group by
• Instead of
SELECT A,B,C,SUM(D)
FROM tableGROUP BY A,B,CORDER BY A,C,B
• Do not rely on this
SELECT A,C,B,
SUM(D)FROM tableGROUP BY A,C,B
28
But if hash operation disabled
• Instead of
SELECT A,B,C,SUM(D)
FROM tableGROUP BY A,B,CORDER BY A,C,B
• Match the group and order clauses
SELECT A,C,B, SUM(D)
FROM tableGROUP BY A,C,BORDER A,C,B
29
Union -v- Union All
• Union– Each query is distinct, and so is sorted
• Hash operation possible in Oracle 10g
– Duplicates are eliminated
• Union All– One query followed by the next
30
Union -v- Union All
SELECT 1FROM dualUNIONSELECT 1FROM dual
• Returns
Dummy-----1
SELECT 1FROM dualUNION ALLSELECT 1FROM dual
• Returns
Dummy-----11
31
Union -v- Union All
SELECT 2FROM dualUNIONSELECT 1FROM dual
• Returns
Dummy-----12
SELECT 2FROM dualUNION ALLSELECT 1FROM dual
• Returns
Dummy-----21
32
Disabling Indexes
• Functions on columns• Index disabled
– TO_CHAR(column,’DD-MM-YYYY’) = :bind
• Index enabled– column = TO_DATE(:bind, ’DD-MM-YYYY’)
• Oracle syntax, generic principle
33
Use all indexed columns
• Specify all indexed columns– Cannot exact scan column unless exact scan all
previous columns
34
Use all indexed columns
SELECT …FROM PS_JOB BWHERE EMPLID = :1AND EFFSEQ = (SELECT MAX(EFFSEQ)
FROM PS_JOB B1WHERE B1.EMPLID = B.EMPLIDAND B1.EFFDT = B.EFFDT)
SELECT …FROM PS_JOB BWHERE EMPLID = :1AND EFFDT = (SELECT MAX(EFFSEQ)
FROM PS_JOB B1WHERE B1.EMPLID = B.EMPLIDAND B1.EMPL_RCD# = B.EMPL_RCD#AND B1.EFFDT = B.EFFDT)
35
High Water Marks (Oracle)
• Oracle specific• Delete -v- Truncate
DELETE FROM table;
TRUNCATE TABLE table;
– Full Scans - HWM
36
Sub-queries
• Correlated– executed once per parent row
– (because PeopleSoft recommend disabling _UNNEST_SUBQUERY from Oracle 9i).
• Not Correlated– executed once in advance
37
Sub-queries
– Correlated
DELETE FROM table1 t1WHERE EXISTS(
SELECT ‘x’FROM table2 t2WHERE t1.keycolumn = t2.keycolumn)
– Non-Correlated
DELETE FROM table1 t1WHERE t1.keycolumn IN(
SELECT t2.keycolumnFROM table2 t2)
38
Sub-queries (Oracle)
• Oracle specific
DELETE FROM table1 t1WHERE (t1.keycolumn1, t1.keycolumn2) IN(SELECT t2.keycolumn1, t2.keycolumn2FROM table2 t2)
39
ROWID (Oracle)
• Oracle specific• physical address of row
40
Sub-queries (Oracle)
• Oracle specific
DELETE FROM table1 t1WHERE t1.rowid IN(SELECT t1b.rowidFROM table1 t1b, table2 t2WHERE t1b.keycolumn1 = t2.keycolumn2AND t1b.keycoulmn2 = t2.keycolumn2)
41
Order of ‘From’ clause (Oracle)
• Oracle specific• Rule Based Optimiser
– backwards
• Cost Based Optimiser– doesn’t matter
• CBO + Ordered Hint– Forwards
– But use LEADING hint from 10g
42
Summary
• Lots of places to write SQL• Code should be
– efficient
– simple
– readable
– explicit
43
SQL Best Coding Practice in PeopleTools 7.x
David KurtzGo-Faster Consultancy Ltd.
www.go-faster.co.uk