Oracle SQL Toolkit (Cheatsheet)

Context: FIT2094_MOC, FIT3003_MOC Β· the ONE pre-lab/pre-exam re-read β€” every clause, predicate and function the two units teach, in one place Β· depth lives in the linked pattern notes Read protocol: scan anatomy β†’ scan tables β†’ attempt all three practice items from a blank editor β†’ follow links only where you failed.

Quick Revision

  • 🎯 Objective: assemble any query from the fixed skeleton βž” SELECT β†’ FROM(+JOIN) β†’ WHERE β†’ GROUP BY β†’ HAVING β†’ ORDER BY.
  • ⚑ Key Constraint: logical execution order β‰  writing order: FROM β†’ WHERE β†’ GROUP BY β†’ HAVING β†’ SELECT β†’ ORDER BY β€” explains why aliases work in ORDER BY but not GROUP BY/WHERE.
  • ⚠ Unit divergence: FIT2094 bans implicit joins; FIT3003 lectures and labs use them. Everything else is shared.

🧩 Statement Anatomy (execution order)

SELECT   dt_code, AVG(drone_flight_time) AS avg_flight     -- 5. project + alias
FROM     drone.drone                                        -- 1. source (+ JOINs)
WHERE    to_char(drone_pur_date,'yyyy') = '2021'            -- 2. filter ROWS (pre-group)
GROUP BY dt_code                                            -- 3. form groups (no aliases here!)
HAVING   AVG(drone_flight_time) > 50                        -- 4. filter GROUPS (may use aggregates)
ORDER BY dt_code;                                           -- 6. sort (aliases OK, NULLS LAST OK)

πŸ— DDL β€” Build & Inspect the Schema

(βž” DDL Table Creation Β· Altering and Dropping Tables Β· Oracle Data Types)

ToolMicro-syntaxJob / gotcha
createCREATE TABLE car (carID NUMBER(5) NOT NULL, …, PRIMARY KEY (carID), FOREIGN KEY (carID) REFERENCES car(carID));FIT3003 declares PK/FK inline; FIT2094 requires named constraints via ALTER
typesVARCHAR2(30) Β· CHAR(2) Β· NUMBER(4) Β· NUMBER(8,2) Β· DATECHAR is blank-padded fixed width; NUMBER(p,s) = precision, scale
DATE defaultsformat DD-MON-YYYY; range 1/1/4712 BC – 12/31/4712 ADno time given ⟹ 12:00:00 A.M.; no date given ⟹ first day of current month
copy a tableCREATE TABLE car AS SELECT * FROM dtaniar.car;copies rows only β€” PK/FK are NOT copied βž” Populating Tables from Queries (INSERT-SELECT, CTAS)
list my tablesSELECT * FROM TAB;returns TNAME / TABTYPE / CLUSTERID β€” the data-dictionary view of your account
show structureDESCRIBE car; / DESC car;column, nullability, type β€” use after every ALTER to confirm
add columnALTER TABLE student ADD (Suburb VARCHAR2(40));new column is NULL in all existing rows
retype columnALTER TABLE car MODIFY (transmission CHAR(30));one verb per statement β€” cannot ADD and DROP in one ALTER
drop columnALTER TABLE car DROP COLUMN transmission; / DROP (CiTTy)data destroyed, DDL auto-commits ⟹ irreversible
drop tableDROP TABLE car;fails while another table holds an FK to it β€” drop the child (carsales) first

✏️ DML & Transactions

(βž” DML INSERT (Oracle) Β· DML UPDATE and DELETE (Oracle) Β· Database Transaction)

ToolMicro-syntaxJob / gotcha
insert all colsINSERT INTO car VALUES (1,'Holden','Cruze',2015,'Black',25780);positional, every column in table order
insert some colsINSERT INTO car (carID, make) VALUES (16,'Audi');column list mandatory for partial inserts; all NOT NULL columns must appear
insert a dateINSERT INTO carsales VALUES (1,4,TO_DATE('04/Feb/2015','DD/MON/YYYY'),25780,824.96);a bare '04-FEB-2015' is a string, not a DATE
insert manyINSERT ALL INTO car VALUES (…) INTO car VALUES (…) SELECT * FROM DUAL;one statement, all-or-nothing; use single inserts when rows depend on each other
updateUPDATE car SET colour='Grey' WHERE carID=5;one table at a time; several columns OK; omitting WHERE updates every row
deleteDELETE FROM car WHERE carID=5;omitting WHERE deletes every row; deleting a referenced PK raises ORA-02292: integrity constraint violated - child record found
commitCOMMIT;until then changes sit in the local buffer only β€” commit regularly and exit the client properly
DUALSELECT TO_CHAR(SYSDATE,'DD-MON-YYYY HH24:MI') FROM DUAL;Oracle’s one-row dummy table for evaluating an expression with no real source

πŸ”Ž Predicates (WHERE) β€” SQL SELECT and WHERE

PredicateMicro-syntaxGotcha
comparisonprice > 2000, <><> is not-equal
rangeprice BETWEEN 3000 AND 5300inclusive both ends ≑ >=3000 AND <=5300
setemp_no IN (3, 8) Β· colour NOT IN ('Black','White')negate: β€œnot 3 nor 8” = <>3 AND <>8 β€” OR is always-true trap
patternname LIKE 'D%' / '_JI%'% any run, _ one char
null testrent_in_dt IS NULL / IS NOT NULL= NULL is always UNKNOWN β€” never matches
date rangesalesdate BETWEEN TO_DATE('01-JAN-2014','DD-MON-YYYY') AND TO_DATE('31-DEC-2015','DD-MON-YYYY')alternative: compare TO_CHAR(salesdate,'YYYYMMDD') > '20140101' as sortable strings
logicNOT β†’ AND β†’ OR precedence3-valued logic: NULL = UNKNOWN; only TRUE rows returned β€” bracket everything

πŸ›  Row Functions & Output Shaping

ToolMicro-syntaxJob / gotcha
NVLNVL(col, 'Still out')replace NULL; types must match βž” wrap date first: NVL(TO_CHAR(dt,'dd-Mon-yyyy'),'Still out')
TO_CHARTO_CHAR(dt,'dd-Mon-yyyy'), TO_CHAR(n,'$9,999')date/number β†’ display string; also extracts parts: TO_CHAR(dt,'yyyy')
TO_DATETO_DATE('01-Mar-2021','dd-Mon-yyyy')string β†’ date for comparing/inserting β€” never compare raw strings
format masksDD-MON-YYYY Β· MM/DD/YYYY Β· HH:MI AM Β· MONTH DAY, YYYY Β· DD-MON-YYYY HH24:MIthe same masks serve TO_DATE (in) and TO_CHAR (out)
concatcust_fname || ' ' || cust_lnameOracle concatenation is ||
case-blindUPPER(manuf_name) = UPPER('DJI...')normalise both sides β€” string values are case-sensitive, identifiers are not
DISTINCTSELECT DISTINCT make, yearde-dupes at record level, not per attribute β€” make may still repeat
aliasAS avg_flight Β· (purchasedPrice+stampDuty) AS TotalPriceusable in ORDER BY only (see execution order); also names computed columns
sortORDER BY t DESC, id Β· NULLS LAST/FIRSTmandatory whenever >1 row possible β€” tuples have no order
conditionalCASE/DECODEβž” SQL Conditional Expressions (CASE, DECODE)

πŸ“¦ Aggregates & Grouping β€” SQL Aggregate Functions and GROUP BY

  • Five aggregates βž” COUNT / SUM / AVG / MIN / MAX; COUNT(*) counts rows incl. NULLs, COUNT(col) non-null only, COUNT(DISTINCT col) distinct non-null only.
  • GROUP BY rule βž” every non-aggregate SELECT column MUST appear in GROUP BY; column aliases are illegal in GROUP BY (not yet computed) β€” repeat the expression: GROUP BY to_char(ct_date_start,'yyyy').
  • WHERE vs HAVING βž” WHERE filters rows before grouping; HAVING filters groups after, and may contain aggregates: HAVING COUNT(DISTINCT model) > 1.
  • Aggregate over a join βž” join condition goes in WHERE/ON and runs first; group on the surviving columns.

πŸ”— Joins β€” SQL Joins (ANSI) Β· SQL Self Join and Outer Join

FormSyntaxWhen
JOIN … ONFROM a JOIN b ON a.id = b.idthe general form β€” default choice, always works
JOIN … USINGJOIN b USING (manuf_id)identical column names both sides
NATURAL JOINa NATURAL JOIN ball common columns match β€” ⚠ no common column β‡’ Cartesian product
self joinFROM emp e1 JOIN emp e2 ON e1.mgrno = e2.empnorecursive FK (employee→manager); distinct aliases required
outer joinLEFT / RIGHT / FULL OUTER JOIN … ON …keep unmatched rows (INNER drops them)
implicit / old-styleFROM customer ct, carsales cs, car c WHERE ct.customerID = cs.customerID AND c.carID = cs.carIDbanned in FIT2094 (marked wrong) Β· βœ… standard in FIT3003 β€” tables need conditions

Missing join condition = PRODUCT. FIT3003 warns that a comma-list FROM with no matching WHERE condition returns the Cartesian product, exhausts your Oracle quota, and locks your account. Count your ANDs before running.

πŸͺ† Subqueries β€” SQL Subquery (Nested SELECT) Β· SQL Subquery Approaches (Nested, Correlated, Inline)

  • Single value βž” compare with =, <, >: WHERE price < (SELECT AVG(price) FROM …).
  • List of values βž” IN / NOT IN: WHERE carID NOT IN (SELECT carID FROM carsales) β€” the anti-join β€œwhich cars are unsold” shape.
  • ANY / ALL βž” > ANY (beats at least one βž” nearly all rows), > ALL (beats every one βž” few rows) β€” classic MCQ discriminator.
  • Multi-column pairs βž” WHERE (dt_code, price) IN (SELECT dt_code, MAX(price) … GROUP BY dt_code) β€” per-group max pattern.
  • In DML βž” subquery sets the target set: UPDATE … SET cost = cost*1.2 WHERE manuf_id = (SELECT …); see Populating Tables from Queries (INSERT-SELECT, CTAS).

βž• Advanced SQL (FIT2094 Topic 10)

ToolMicro-syntaxJob / gotcha
CASECASE WHEN cond THEN 'r' ELSE 'd' END / CASE col WHEN v THEN …if/else in SELECT; searched form allows ranges
DECODEDECODE(emp_type,'F','Full','C','Casual')equality-only legacy of CASE β€” βž” SQL Conditional Expressions (CASE, DECODE)
set opsq1 UNION / UNION ALL / INTERSECT / MINUS q2union-compatible (same cols + types); one final ORDER BY; names from q1 β€” βž” SQL Set Operators
subquery placementnested (once) Β· correlated (per-row) Β· inline view (FROM (SELECT …) alias) Β· scalar-in-SELECTβž” SQL Subquery Approaches (Nested, Correlated, Inline)
populate tableINSERT INTO t (SELECT …) Β· CREATE TABLE t AS (SELECT …)CTAS copies data, NOT constraints β€” re-add PK/FK after
viewCREATE OR REPLACE VIEW v AS SELECT … Β· DROP VIEW vvirtual table (stored query); banned in FIT2094 Assignment 2 β€” use a subquery
date part / formatEXTRACT(YEAR FROM d) (number) Β· TO_CHAR(d,'yyyy') (string)filter/group by a date part
text alignLPAD/RPAD(s,n,'*') Β· LTRIM/TRIM(s)monospace-only bar charts

🏭 Warehouse ETL Clauses (FIT3003 W2)

(βž” Building Dimension Tables Β· Building Fact Tables Β· Fact Measure Aggregation Rules)

ToolMicro-syntaxJob / gotcha
dimension by copycreate table AgentDim as select * from Agent;route 1 of 3; rows only, no PK/FK
dimension by projectioncreate table CourseDim as select CourseCode, CourseName from Course;route 2 β€” drop columns no analysis question needs
dimension by de-dupcreate table CountryDim as select distinct Country from Student;mandatory distinct when the source is a transaction table
dimension by handcreate table TimeDim (Quarter number(1), Description varchar2(20)); + insert into … values (1,'Jan-Mar');route 3 β€” members are business knowledge, membership is fixed and known
manufactured keyCountry || City as LocationID Β· set QuarterID = Year || Quarterbuilds an ID the operational DB never stored
time keyto_char(DownloadDate,'YYYYMM') as TimeID Β· 'MM' Β· 'YYYY' Β· 'Month''Month' yields the name; masks are the dimension’s attributes
staging tablecreate table TempFact as select … from a, b where …;the joined, unaggregated row set; grain preserved for one later group by
add derived columnalter table TempFact add (Quarter number(1)); then update … set Quarter = 1 where …the chapter’s banding idiom β€” one update per band, not CASE
null-band catch-allupdate TempFact set Quarter = '4' where Quarter is null;last band by exclusion instead of a range test
fact by aggregationcreate table SalesFact as select Quarter, BranchID, sum(TotalPrice) as Total_Sales from TempFact group by Quarter, BranchID;group by list the fact’s composite PK; build from operational/temp tables, never from the dimensions
two populationsfrom Opening O left outer join Placement P on O.OpenNo = P.OpenNo + count(OpenNo) / count(CandNo)outer join keeps unmatched rows; count(col) skips the NULLs β€” count(*) would equalise both measures
latest-per-entityrank() over (partition by E.EmpNo order by D.GraduationDate desc) as Rank in an inline view, then where T.Rank = 1pre-processes the operational side; without it the join multiplies rows per entity
never storeavg(x) as a fact measureaverage of averages β‰  average β€” store Total_x and Number_of_y, recover with sum(Total_x)/sum(Number_of_y)

🧹 Data Exploration & Cleaning Clauses (FIT3003 W3)

(βž” Data Exploration (Warehouse Validation) Β· Data Cleaning (Dirty Data) Β· Multi-Role Facts)

ToolMicro-syntaxJob / gotcha
baseline countselect count(*) from dw.uselog;run on every source table before building anything β€” the prediction all later numbers are judged against
duplicate PK probeselect PK, count(*) from t group by PK having count(*) > 1;the standard dirty-data detector; empty result that key is clean
duplicate row probegroup by log_time, log_date, student_id, act having count(*) > 1when there is no single-column PK, group on the full composite
orphan FK probeselect * from t1 where FK not in (select PK from t2);anti-join; a NULL inside the subquery makes not in return nothing at all
formatted sampleselect log_date, to_char(log_time,'HH24:MI'), student_id from t order by …;order by puts duplicates adjacent so they are visible in a big table
de-dup at the joincreate table tempfact2 as select distinct U.…, S.… from … where …;kills join fan-out and true source duplicates in one clause; only removes rows identical across the projected columns
de-dup a copycreate table student_clean as select distinct * from dw.student;when the defect survives projection; CTAS brings no PK/FK
contradiction checkselect * from contract where starttime > endtime;inconsistent-value type β€” two attributes disagreeing
domain checkselect * from charter where char_distance < 0;incorrect-value type β€” outside the legal range
null checkselect * from major where major_name is null;= NULL never matches; only IS NULL
simplest repairdelete from t where <<the same predicate>>;always select first β€” the count is the evidence the repair worked
merge two role factsselect … sum(x) from ( select * from f1 union select * from f2 ) group by emp_num;union alone leaves two rows per member; the outer group by is what merges β€” legal only for individually-owned measures
label vs keygroup by F.CourseCode, D1.CourseNamekeep the key in the grouping list; grouping on the description alone merges members that share it

✍️ Integration Practice

⚠️ Common Mistakes

  • πŸ’‘ = NULL never matches βž” 3-valued logic makes it UNKNOWN; only IS NULL works.
  • πŸ’‘ β€œnot A or B” trap βž” emp_no <> 3 OR emp_no <> 8 is TRUE for every row; exclusion needs AND.
  • πŸ’‘ Alias in GROUP BY βž” illegal (GROUP BY runs before SELECT); repeat the full expression.
  • πŸ’‘ Forgetting COMMIT βž” your inserts exist only in the session buffer; close the client badly and the work is gone.
  • πŸ’‘ Word’s curly quotes βž” SQL pasted from a .docx lab sheet carries ' instead of '; Oracle rejects it β€” retype the quote.
  • πŸ’‘ Building a FIT3003 fact from the dimension tables βž” dimensions were created with select distinct and hold no measures; aggregate from the operational (or Temp) tables.
  • πŸ’‘ Staging a fact without counting first βž” correct SQL over dirty sources produces a correctly-shaped fact with inflated measures; predict the join cardinality before trusting anything βž” Data Exploration (Warehouse Validation).
  • πŸ’‘ select … as X while group by still names the old column βž” ORA-00979; change the projection and the grouping list together.