1) comparing dates. How do I compare dates in Oracle?
char VS char
select dateaniv from test2 where to_char(dateaniv,'dd/mm/yyyy')='12/06/1977';
date VS date (better)
select dateaniv from test2 where dateaniv=to_date('12/06/1977','dd/mm/yyyy')
Comparing dates the wrong way
These Oracle date comparisons works, but no index cannot be used because date2 is invalidated with the trunc function (unless you create a function-based index on trunc(date2,'YYYY:MM').
where to_char(DATE1,'YYYY:MM') >= to_char(DATE2,'YYYY:MM')
where trunc(date1,'mm') >= trunc(date2,'mm');
2) UNION and UNION ALL
There are exhaustive notes on how the Oracle SQL UNION operator is used to merge separate SQL queries, but there is an important difference between UNION and UNION ALL.
The Oracle SQL UNION differs from the Oracle UNION ALL primarily because it does not filter out duplicate rows.
The UNION SQL operator returns only the unique rows that appear in either result, while the UNION ALL operator returns all rows in both queries, including duplicate rows.
3) WITH Clause : Subquery Factoring in Oracle
Using the SCOTT schema, for each employee we want to know how many other people are in their department. Using an inline view we might do the following.
-- Non-ANSI Syntax
SELECT e.ename AS employee_name,
dc.dept_count AS emp_dept_count
FROM emp e,
(SELECT deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno) dc
WHERE e.deptno = dc.deptno;
-- ANSI Syntax
SELECT e.ename AS employee_name,
dc.dept_count AS emp_dept_count
FROM emp e
JOIN (SELECT deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno) dc
ON e.deptno = dc.deptno;
Using a WITH clause this would look like the following.
-- Non-ANSI Syntax
WITH dept_count AS (
SELECT deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno)
SELECT e.ename AS employee_name,
dc.dept_count AS emp_dept_count
FROM emp e,
dept_count dc
WHERE e.deptno = dc.deptno;
-- ANSI Syntax
WITH dept_count AS (
SELECT deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno)
SELECT e.ename AS employee_name,
dc.dept_count AS emp_dept_count
FROM emp e
JOIN dept_count dc ON e.deptno = dc.deptno;
The difference seems rather insignificant here.
What if we also want to pull back each employees manager name and the number of people in the managers department? Using the inline view it now looks like this.
-- Non-ANSI Syntax
SELECT e.ename AS employee_name,
dc1.dept_count AS emp_dept_count,
m.ename AS manager_name,
dc2.dept_count AS mgr_dept_count
FROM emp e,
(SELECT deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno) dc1,
emp m,
(SELECT deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno) dc2
WHERE e.deptno = dc1.deptno
AND e.mgr = m.empno
AND m.deptno = dc2.deptno;
-- ANSI Syntax
SELECT e.ename AS employee_name,
dc1.dept_count AS emp_dept_count,
m.ename AS manager_name,
dc2.dept_count AS mgr_dept_count
FROM emp e
JOIN (SELECT deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno) dc1
ON e.deptno = dc1.deptno
JOIN emp m ON e.mgr = m.empno
JOIN (SELECT deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno) dc2
ON m.deptno = dc2.deptno;
Using the WITH clause this would look like the following.
-- Non-ANSI Syntax
WITH dept_count AS (
SELECT deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno)
SELECT e.ename AS employee_name,
dc1.dept_count AS emp_dept_count,
m.ename AS manager_name,
dc2.dept_count AS mgr_dept_count
FROM emp e,
dept_count dc1,
emp m,
dept_count dc2
WHERE e.deptno = dc1.deptno
AND e.mgr = m.empno
AND m.deptno = dc2.deptno;
-- ANSI Syntax
WITH dept_count AS (
SELECT deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno)
SELECT e.ename AS employee_name,
dc1.dept_count AS emp_dept_count,
m.ename AS manager_name,
dc2.dept_count AS mgr_dept_count
FROM emp e
JOIN dept_count dc1 ON e.deptno = dc1.deptno
JOIN emp m ON e.mgr = m.empno
JOIN dept_count dc2 ON m.deptno = dc2.deptno;
So we don't need to redefine the same subquery multiple times. Instead we just use the query name defined in the WITH clause, making the query much easier to read.
If the contents of the WITH clause is sufficiently complex, Oracle may decide to resolve the result of the subquery into a global temporary table. This can make multiple references to the subquery more efficient.
The MATERIALIZE and INLINE optimizer hints can be used to influence the decision.
The undocumented MATERIALIZE hint tells the optimizer to resolve the subquery as a global temporary table, while the INLINE hint tells it to process the query inline.
WITH dept_count AS (
SELECT /*+ MATERIALIZE */ deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno)
SELECT ...
WITH dept_count AS (
SELECT /*+ INLINE */ deptno, COUNT(*) AS dept_count
FROM emp
GROUP BY deptno)
SELECT ...
Even when there is no repetition of SQL, the WITH clause can simplify complex queries, like the following example that lists those departments with above average wages.
WITH
dept_costs AS (
SELECT dname, SUM(sal) dept_total
FROM emp e, dept d
WHERE e.deptno = d.deptno
GROUP BY dname),
avg_cost AS (
SELECT SUM(dept_total)/COUNT(*) avg
FROM dept_costs)
SELECT *
FROM dept_costs
WHERE dept_total > (SELECT avg FROM avg_cost)
ORDER BY dname;
In the previous example, the main body of the query is very simple, with the complexity hidden in the WITH clause.
4)
inner join or cross join?
cross join= cartesian product
inner join or join (regular join)
5) GROUP BY WITH VARCHAR COLUMN
select dateaniv,sum(to_number(num_users)) from test2
2 group by dateaniv;
6) differences between CROSS JOIN AND INNER JOIN
cross join = cartesian product
inner join = join
inner join uses ON + where
cross join uses WHERE
7) fake join
SQL> select * from dept d, test2 a
2 where d.deptno=to_number(num_users||'0');
DEPTNO DNAME LOC DATEANIV DATEANIV2 NUM_USERS
---------- -------------- ------------- ---------- ---------- ----------
10 ACCOUNTING NEW YORK 12/06/1977 01/02/1977 1
10 ACCOUNTING NEW YORK 01/01/1977 01/02/1977 1
10 ACCOUNTING NEW YORK 01/01/1978 1
10 ACCOUNTING NEW YORK 01/12/1977 01/02/1977 1
10 ACCOUNTING NEW YORK 01/10/1977 01/02/1977 1
10 ACCOUNTING NEW YORK 01/01/1977 01/01/1977 1
10 ACCOUNTING NEW YORK 01/01/1977 01/01/1977 1
7 rows selected.
8) null handling
SQL> select * from test2
2 where dateaniv2 is null;
DATEANIV DATEANIV2 NUM_USERS
---------- ---------- ----------
01/01/1978 1
SQL> select * from test2
2 where dateaniv2 is not null;
DATEANIV DATEANIV2 NUM_USERS
---------- ---------- ----------
12/06/1977 01/02/1977 1
01/01/1977 01/02/1977 1
01/12/1977 01/02/1977 1
01/10/1977 01/02/1977 1
01/01/1977 01/01/1977 1
01/01/1977 01/01/1977 1
6 rows selected.
SQL> select nvl(dateaniv2,'01/01/1900') from test2
2 where dateaniv2 is null;
NVL(DATEAN
----------
01/01/1900
SQL> select DECODE(dateaniv2,NULL,'01/01/1900') from test2
2 /
DECODE(DAT
----------
01/01/1900
7 rows selected.
SQL> select nvl2(dateaniv2,dateaniv2,'01/01/1900') from test2
2 /
NVL2(DATEA
----------
01/02/1977
01/02/1977
01/01/1900
01/02/1977
01/02/1977
01/01/1977
01/01/1977
7 rows selected.
The LNNVL function has been available since at least Oracle 9i, but was undocumented until Oracle 11g. It is used in a where clause to evaluate a condition. If this condition evaluates to false or unknown, it returns true. If the condition evaluates to true, it returns false.
SQL> SELECT id, col3 FROM null_test_tab WHERE LNNVL(col1 IS NULL) ORDER BY id;
ID COL3
---------- ----------
1 THREE
1 row selected.
SQL> SELECT id, col3 FROM null_test_tab WHERE LNNVL(col2 = 'TWO') ORDER BY id;
ID COL3
---------- ----------
3 THREE
4 THREE
2 rows selected.
SQL> SELECT id, col3 FROM null_test_tab WHERE LNNVL(col2 != 'TWO') ORDER BY id;
ID COL3
---------- ----------
1 THREE
2 THREE
3 THREE
4 THREE
4 rows selected.
NULLIF
The NULLIF function was introduced in Oracle 9i. It accepts two parameters and returns null if both parameters are equal. If they are not equal, the first parameter value is returned.
In our test table the values of COL3 and COL4 are equal in row 4, so we would only expect null returned for that row using the following query.
SQL> SELECT id, NULLIF(col3, col4) AS output FROM null_test_tab ORDER BY id;
ID OUTPUT
---------- ----------
1 THREE
2 THREE
3 THREE
4
4 rows selected.
SQL>
9)after creating a user, we need to grant roles:
GRANT CONNECT, RESOURCE, DBA TO books_admin;
GRANT UNLIMITED TABLESPACE TO books_admin;
GRANT CREATE SESSION GRANT ANY PRIVILEGE TO books_admin;
GRANT
SELECT,
INSERT,
UPDATE,
DELETE
ON
schema.books
TO
books_admin;
10) system tables
all tablespaces, all users, dba_x
select table_name, tablespace_name from sys.all_tables;
lundi 19 octobre 2020
10 oracle tips part2
Inscription à :
Publier les commentaires (Atom)

Aucun commentaire:
Enregistrer un commentaire