SQL Faq: What Is SQL and Where Does It Come From?
SQL Faq: What Is SQL and Where Does It Come From?
2 What are the difference between DDL, DML and DCL commands?
4 How does one escape special characters when writing SQL queries?
7 How does one get the time difference between two date columns?
12 How can one dump/ examine the exact content of a database column?
SQL> COMMIT;
Commit complete.
TRUNCATE removes all rows from a table. The operation cannot be rolled back
and no triggers will be fired. As such, TRUNCATE is faster and doesn't use as much
undo space as a DELETE.
COUNT(*)
----------
0
The DROP command removes a table from the database. All the tables' rows,
indexes and privileges will also be removed. No DML triggers will be fired. The
operation cannot be rolled back.
DROP and TRUNCATE are DDL commands, whereas DELETE is a DML command.
Therefore DELETE operations can be rolled back (undone), while DROP and
TRUNCATE operations cannot be rolled back.
From Oracle 10g a table can be "undropped". Example:
SQL> FLASHBACK TABLE emp TO BEFORE DROP;
Flashback complete.
PS: DELETE will not free up used space within a table. This means that repeated
DELETE commands will severely fragment the table and queries will have to
navigate this "free space" in order to retrieve rows.
SET DEFINE ~
SELECT 'Laurel & Hardy' FROM dual;
Other methods:
Define an escape character:
Another way to escape the & would be to use concatenation, which would not
require any SET commands -
Syntax
q'[QUOTE_CHAR]Text[QUOTE_CHAR]'
Make sure that the QUOTE_CHAR doesnt exist in the text.
SELECT q'{This is Orafaq's 'quoted' text field}' FROM DUAL;
In the above example, Oracle is instructed to randomly return 10% of the rows in the
table.
This example will sample 5% of all formatted database blocks instead of rows.
This clause only works for single table queries on local tables. If you include the
SAMPLE clause within a multi-table or remote query, you will get a parse error or
"ORA-30561: SAMPLE option not allowed in statement with multiple table
references". One way around this is to create an inline view on the driving table of
the query with the SAMPLE clause. Example:
If you examine the execution plan of a "Sample Table Scan", you should see a step
like this:
ORDER BY dbms_random.value()
This method orders the data by a random column number. Example:
Method 2:
This method is usually faster. However, remember to recreate all indexes,
constraints, triggers, etc. on the table when done.
Method 3:
Note: One can eliminate N^2 unnecessary operations by creating an index on the
joined fields in the inner loop (no need to loop through the entire table on each pass
by a record). This will speed-up the deletion process.
Note 2: If you are comparing NULL columns, use the NVL function. Remember that
NULL is not equal to NULL. This should not be a problem as all key columns should
be NOT NULL by definition.
Method 4:
This method collects the first row (order by rowid) for each key values and delete the
rows that are not in this set:
Solution 1
SQL> SELECT floor(((date1-date2)*24*60*60)/3600)
2 || ' HOURS ' ||
3 floor((((date1-date2)*24*60*60) -
4 floor(((date1-date2)*24*60*60)/3600)*3600)/60)
5 || ' MINUTES ' ||
6 round((((date1-date2)*24*60*60) -
7 floor(((date1-date2)*24*60*60)/3600)*3600 -
8 (floor((((date1-date2)*24*60*60) -
9 floor(((date1-date2)*24*60*60)/3600)*3600)/60)*60) ))
10 || ' SECS ' time_difference
11 FROM dates;
TIME_DIFFERENCE
------------------------------------------------------------------------------
--
24 HOURS 0 MINUTES 0 SECS
1 HOURS 0 MINUTES 0 SECS
0 HOURS 1 MINUTES 0 SECS
Solution 2
If you don't want to go through the floor and ceiling maths, try this method
(contributed by Erik Wile):
Solution 3
Here is a simpler method (contributed by Aniruddha Jathar):
SELECT *
FROM (SELECT job,
sum(decode(deptno,10,sal)) DEPT10,
sum(decode(deptno,20,sal)) DEPT20,
sum(decode(deptno,30,sal)) DEPT30,
sum(decode(deptno,40,sal)) DEPT40
FROM scott.emp
GROUP BY job)
ORDER BY 1;
JOB DEPT10 DEPT20 DEPT30 DEPT40
--------- ---------- ---------- ---------- ----------
ANALYST 6000
CLERK 1300 1900 950
MANAGER 2450 2975 2850
PRESIDENT 5000
SALESMAN 5600
Here is the same query with some fancy headers and totals:
SELECT * FROM (
SELECT ename, rownum rn
FROM emp WHERE rownum < 101
) WHERE RN between 91 and 100 ;
Note: the 101 is just one greater than the maximum row of the required rows (means
x= 90, y=100, so the inner values is y+1).
Ravi Pachalla provided this solution:
SELECT rownum, f1 FROM t1
GROUP BY rownum, f1 HAVING rownum BETWEEN 2 AND 4;
Another solution is to use the MINUS operation. For example, to display rows 5 to 7,
construct a query like this:
SELECT *
FROM tableX
WHERE rowid in (
SELECT rowid FROM tableX
WHERE rownum <= 7
MINUS
SELECT rowid FROM tableX
WHERE rownum < 5);
Youssef Youssef provided this solution: "this one was faster for me and allowed for
sorting before filtering by rownum. The inner query (table A) can be a series of
tables joined together with any operation before the filtering by rownum is applied."
SELECT *
FROM (SELECT a.*, rownum RN
FROM (SELECT *
FROM t1 ORDER BY key_column) a
WHERE rownum <=7)
WHERE rn >=5;
Please note, there is no explicit row order in a relational database. However, this
query is quite fun and may even help in the odd situation.
Praveena Konkimalla provided this solution:
The generic solution to get full information of rows between x and y
SELECT * FROM emp WHERE empno in (SELECT empno FROM emp GROUP BY
rownum,empno HAVING rownum BETWEEN &x AND &y);
[edit] Can one retrieve only the Nth row from a table?
Rupak Mohan provided this solution to select the Nth row from a table:
SELECT * FROM t1 a
WHERE n = (SELECT COUNT(rowid)
FROM t1 b
WHERE a.rowid >= b.rowid);
SELECT * FROM (
SELECT ENAME,ROWNUM RN FROM EMP WHERE ROWNUM < 101 )
WHERE RN = 100;
Note: In this first query we select one more than the required row number, then we
select the required one. Its far better than using a MINUS operation.
Ravi Pachalla provided these solutions:
SELECT f1 FROM t1
WHERE rowid = (
SELECT rowid FROM t1
WHERE rownum <= 10
MINUS
SELECT rowid FROM t1
WHERE rownum < 10);
SELECT rownum,empno FROM scott.emp a
GROUP BY rownum,empno HAVING rownum = 4;
Alternatively...
Please note, there is no explicit row order in a relational database. However, this
query is quite fun and may even help in the odd situation.
For this example, type=96 is indicating a CHAR column. The last byte in the column
is 32, which is the ASCII code for a space. This tells us that this column is blank-
padded.
Oracle does not support this syntax. However, it doesn't mean that it cannot be
done.
Workarounds:
1. Create a new table and copy the data across.
SQL> CREATE TABLE tab1 AS SELECT 0 AS col1, col1 AS col2 FROM tab1_old;
Table created.
One can produce an indented report by using the level number to substring or lpad()
a series of spaces, and concatenate that to the string. Look at this example:
Use the "start with" clause to specify the start of the tree. More than one record can
match the starting condition. One disadvantage of having a "connect by prior" clause
is that you cannot perform a join to other tables. The "connect by prior" clause is
rarely implemented in the other database offerings. Trying to do this
programmatically is difficult as one has to do the top level query first, then, for each
of the records open a cursor to look for child nodes.
One way of working around this is to use PL/SQL, open the driving cursor with the
"connect by prior" statement, and the select matching records from other tables on a
row-by-row basis, inserting the results into a temporary table for later retrieval.
NOTE: Tree-structured queries are definitely non-relational (enough to kill Codd and
make him roll in his grave). Also, this feature is not often found in other database
offerings.
Rename a column
From Oracle 9i one can RENAME a column from a table. Look at this example:
create table t2 >column list with new name> as select * from t1;
drop table t1;
rename t2 to t1;
Execution Plan
--------------------------------------------- ----- --------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=3)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'T' (Cost=2 Card=1 Bytes=3)
Execution Plan
--------------------------------------------- ----- --------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=41)
1 0 TABLE ACCESS (FULL) OF 'T' (Cost=2 Card=1 Bytes=41)
Execution Plan
--------------------------------------------- ----- --------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=3)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'T' (Cost=2 Card=1 Bytes=3)
Execution Plan
--------------------------------------------- ----- --------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=3)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'T' (Cost=2 Card=1 Bytes=3)
[edit] How does one select EVERY Nth row from a table?
One can easily select all even, odd, or Nth rows from a table using SQL queries like
this:
Method 1: Using a subquery
SELECT *
FROM emp
WHERE (ROWID,0) IN (SELECT ROWID, MOD(ROWNUM,4)
FROM emp);
SELECT *
FROM ( SELECT rownum rn, empno, ename
FROM emp
) temp
WHERE MOD(temp.ROWNUM,4) = 0;
Please note, there is no explicit row order in a relational database. However, these
queries are quite fun and may even help in the odd situation.
For Oracle 8i and above, one can get the bottom N rows using an inner-query with
an ORDER BY clause:
SELECT *
FROM (SELECT * FROM my_table ORDER BY col_name_1)
WHERE ROWNUM < 10;
SELECT *
FROM my_table a
WHERE 10 >= (SELECT COUNT(DISTINCT maxcol)
FROM my_table b
WHERE b.maxcol <= a.maxcol)
ORDER BY maxcol;
[edit] How does one select the TOP N rows from a table?
From Oracle 9i onwards, the RANK() and DENSE_RANK() functions can be used to
determine the TOP N rows. Examples:
Get the top 10 employees based on their salary
For Oracle 8i and above, one can get the Top N rows using an inner-query with an
ORDER BY clause:
SELECT *
FROM (SELECT * FROM my_table ORDER BY col_name_1 DESC)
WHERE ROWNUM < 10;
SELECT *
FROM my_table a
WHERE 10 >= (SELECT COUNT(DISTINCT maxcol)
FROM my_table b
WHERE b.maxcol >= a.maxcol)
ORDER BY maxcol DESC;
Sample output:
Department Graph
-------------- --------------------------------------------------
ACCOUNTING +++
RESEARCH +++++
SALES ++++++
In the above example, the value returned by COUNT(*) is used to control the
number of "*" characters to return for each department. We simply pass COUNT(*)
as an argument to the string function LPAD (or RPAD) to return the desired number
of *'s.
This function returns a string result with the concatenated non-NULL values from a
SQL statement. It returns NULL if there are no non-NULL values.
Here is an example of how to map several rows to a single concatenated column:
VARCHAR2
VARCHAR2 is used to store variable length character strings. The string value's
length will be stored on disk with the value itself.