Anda di halaman 1dari 42

1. To see current user name Sql> show user; 2.

Change SQL prompt name SQL> set sqlprompt Manimara > Manimara > Manimara > 3. Switch to DOS prompt SQL> host 4. How do I eliminate the duplicate rows ? SQL> delete from table_name where rowid not in (select max(rowid) from table group by duplicate_values_field_name); or SQL> delete duplicate_values_field_name dv from table_name ta where rowid <(select min(rowid) from table_name tb where ta.dv=tb.dv); Example. Table Emp Empno Ename 101 Scott 102 Jiyo 103 Millor 104 Jiyo 105 Smith delete ename from emp a where rowid < ( select min(rowid) from emp b where a.ename = b.ename); The output like, Empno Ename 101 Scott 102 Millor 103 Jiyo 104 Smith 5. How do I display row number with records? To achive this use rownum pseudocolumn with query, like SQL> SQL> select rownum, ename from emp; Output: 1 Scott 2 Millor 3 Jiyo 4 Smith 6. Display the records between two range select rownum, empno, ename from emp where rowid in (select rowid from emp where rownum <=&upto

minus select rowid from emp where rownum<&Start); Enter value for upto: 10 Enter value for Start: 7 ROWNUM EMPNO ENAME --------- --------- ---------1 7782 CLARK 2 7788 SCOTT 3 7839 KING 4 7844 TURNER 7. I know the nvl function only allows the same data type(ie. number or char or date Nvl(comm, 0)), if commission is null then the text Not Applicable want to display, instead of blank space. How do I write the query? SQL> select nvl(to_char(comm.),'NA') from emp; Output : NVL(TO_CHAR(COMM),'NA') ----------------------NA 300 500 NA 1400 NA NA 8. Oracle cursor : Implicit & Explicit cursors Oracle uses work areas called private SQL areas to create SQL statements. PL/SQL construct to identify each and every work are used, is called as Cursor. For SQL queries returning a single row, PL/SQL declares all implicit cursors. For queries that returning more than one row, the cursor needs to be explicitly declared. 9. Explicit Cursor attributes There are four cursor attributes used in Oracle cursor_name%Found, cursor_name%NOTFOUND, cursor_name%ROWCOUNT, cursor_name%ISOPEN 10. Implicit Cursor attributes Same as explicit cursor but prefixed by the word SQL SQL%Found, SQL%NOTFOUND, SQL%ROWCOUNT, SQL%ISOPEN

Tips : 1. Here SQL%ISOPEN is false, because oracle automatically closed the implicit cursor after executing SQL statements. : 2. All are Boolean attributes. 11. Find out nth highest salary from emp table SELECT DISTINCT (a.sal) FROM EMP A WHERE &N = (SELECT COUNT (DISTINCT (b.sal)) FROM EMP B WHERE a.sal<=b.sal); Enter value for n: 2 SAL --------3700 12. To view installed Oracle version information SQL> select banner from v$version; 13. Display the number value in Words SQL> select sal, (to_char(to_date(sal,'j'), 'jsp')) from emp; the output like, SAL (TO_CHAR(TO_DATE(SAL,'J'),'JSP')) --------- ----------------------------------------------------800 eight hundred 1600 one thousand six hundred 1250 one thousand two hundred fifty If you want to add some text like, Rs. Three Thousand only. SQL> select sal "Salary ", (' Rs. '|| (to_char(to_date(sal,'j'), 'Jsp'))|| ' only.')) "Sal in Words" from emp / Salary Sal in Words ------- -----------------------------------------------------800 Rs. Eight Hundred only. 1600 Rs. One Thousand Six Hundred only. 1250 Rs. One Thousand Two Hundred Fifty only. 14. Display Odd/ Even number of records Odd number of records: select * from emp where (rowid,1) in (select rowid, mod(rownum,2) from emp); 1 3 5 Even number of records: select * from emp where (rowid,0) in (select rowid, mod(rownum,2) from emp)

2 4 6 15. Which date function returns number value? months_between 16. Any three PL/SQL Exceptions? Too_many_rows, No_Data_Found, Value_Error, Zero_Error, Others 17. What are PL/SQL Cursor Exceptions? Cursor_Already_Open, Invalid_Cursor 18. Other way to replace query result null value with a text SQL> Set NULL N/A to reset SQL> Set NULL 19. What are the more common pseudo-columns? SYSDATE, USER , UID, CURVAL, NEXTVAL, ROWID, ROWNUM 20. What is the output of SIGN function? 1 for positive value, 0 for Zero, -1 for Negative value. 21. What is the maximum number of triggers, can apply to a single table? 12 triggers.

What is SQL and where does it come from?


Structured Query Language (SQL) is a language that provides an interface to relational database systems. SQL was developed by IBM in the 1970s for use in System R, and is a de facto standard, as well as an ISO and ANSI standard. SQL is often pronounced SEQUEL. In common usage SQL also encompasses DML (Data Manipulation Language), for INSERTs, UPDATEs, DELETEs and DDL (Data Definition Language), used for creating and modifying tables and other database structures. The development of SQL is governed by standards. A major revision to the SQL standard was completed in 1992, called SQL2. SQL3 support object extensions and are (partially?) implemented in Oracle8 and 9.

Back to top of file

What are the difference between DDL, DML and DCL commands?
DDL is Data Definition Language statements. Some examples:
CREATE - to create objects in the database ALTER - alters the structure of the database DROP - delete objects from the database TRUNCATE - remove all records from a table, including all spaces allocated for the records are removed COMMENT - add comments to the data dictionary GRANT - gives user's access privileges to database REVOKE - withdraw access privileges given with the GRANT command

DML is Data Manipulation Language statements. Some examples:


SELECT - retrieve data from the a database INSERT - insert data into a table UPDATE - updates existing data within a table DELETE - deletes all records from a table, the space for the records remain CALL - call a PL/SQL or Java subprogram EXPLAIN PLAN - explain access path to data LOCK TABLE - control concurrency

DCL is Data Control Language statements. Some examples:


COMMIT - save work done SAVEPOINT - identify a point in a transaction to which you can later roll back ROLLBACK - restore database to original since the last COMMIT SET TRANSACTION - Change transaction options like what rollback segment to use

Back to top of file

How does one escape special characters when building SQL queries?
The LIKE keyword allows for string searches. The '_' wild card character is used to match exactly one character, '%' is used to match zero or more occurrences of any characters. These characters can be escaped in SQL. Example:
SELECT name FROM emp WHERE id LIKE '%\_%' ESCAPE '\';

Use two quotes for every one displayed. Example:

SELECT 'Franks''s Oracle site' FROM DUAL; SELECT 'A ''quoted'' word.' FROM DUAL; SELECT 'A ''''double quoted'''' word.' FROM DUAL;

Back to top of file

How does one eliminate duplicates rows from a table?


Choose one of the following queries to identify or remove duplicate rows from a table leaving only unique records in the table: Method 1:
SQL> DELETE FROM table_name A WHERE ROWID > ( 2 3 SELECT min(rowid) FROM table_name B WHERE A.key_values = B.key_values);

Method 2:
SQL> create table table_name2 as select distinct * from table_name1; SQL> drop table_name1; SQL> rename table_name2 to table_name1; SQL> -- Remember to recreate all indexes, constraints, triggers, etc on table...

Method 3: (thanks to Dennis Gurnick)


SQL> delete from my_table t1 SQL> where SQL> SQL> SQL> exists (select 'x' from my_table t2 where t2.key_value1 = t1.key_value1 and t2.key_value2 = t1.key_value2 and t2.rowid > t1.rowid);

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 speedup the deletion process. Note 2: If you are comparing NOT-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. Back to top of file

How does one generate primary key values for a table?

Create your table with a NOT NULL column (say SEQNO). This column can now be populated with unique values:
SQL> UPDATE table_name SET seqno = ROWNUM;

or use a sequences generator:


SQL> CREATE SEQUENCE sequence_name START WITH 1 INCREMENT BY 1; SQL> UPDATE table_name SET seqno = sequence_name.NEXTVAL;

Finally, create a unique index on this column. Back to top of file

How does one get the time difference between two date columns?
Look at this example query:
select floor(((date1-date2)*24*60*60)/3600) || ' HOURS ' || floor((((date1-date2)*24*60*60) floor(((date1-date2)*24*60*60)/3600)*3600)/60) || ' MINUTES ' || round((((date1-date2)*24*60*60) floor(((date1-date2)*24*60*60)/3600)*3600 (floor((((date1-date2)*24*60*60) floor(((date1-date2)*24*60*60)/3600)*3600)/60)*60))) || ' SECS ' time_difference from ...

If you don't want to go through the floor and ceiling math, try this method (contributed by Erik Wile):
select to_char(to_date('00:00:00','HH24:MI:SS') + (date1 - date2), 'HH24:MI:SS') time_difference from ...

Note that this query only uses the time portion of the date and ignores the date itself. It will thus never return a value bigger than 23:59:59. Back to top of file

How does one add a day/hour/minute/second to a date value?


The SYSDATE pseudo-column shows the current system date and time. Adding 1 to SYSDATE will advance the date by 1 day. Use fractions to add hours, minutes or seconds to the date. Look at these examples:
SQL> select sysdate, sysdate+1/24, sysdate +1/1440, sysdate + 1/86400 from dual;

SYSDATE SYSDATE+1/86400

SYSDATE+1/24

SYSDATE+1/1440

-------------------- -------------------- --------------------------------------03-Jul-2002 08:32:12 03-Jul-2002 09:32:12 03-Jul-2002 08:33:12 03Jul-2002 08:32:13

The following format is frequently used with Oracle Replication:


select sysdate NOW, sysdate+30/(24*60*60) NOW_PLUS_30_SECS from dual;

NOW

NOW_PLUS_30_SECS

-------------------- -------------------03-JUL-2002 16:47:23 03-JUL-2002 16:47:53

Here are a couple of examples:


Description Date Expression

Now Tomorow/ next day Seven days from now One hour from now Three hours from now An half hour from now 10 minutes from now 30 seconds from now Tomorrow at 12 midnight Tomorrow at 8 AM Next Monday at 12:00 noon

SYSDATE SYSDATE + 1 SYSDATE + 7 SYSDATE + 1/24 SYSDATE + 3/24 SYSDATE + 1/48 SYSDATE + 10/1440 SYSDATE + 30/86400 TRUNC(SYSDATE + 1) TRUNC(SYSDATE + 1) + 8/24 NEXT_DAY(TRUNC(SYSDATE), 'MONDAY') + 12/24

First day of next month at TRUNC(LAST_DAY(SYSDATE ) + 1) 12 midnight First day of the current month TRUNC(LAST_DAY(ADD_MONTHS(SYSDATE,-1))) + 1

The next Monday, TRUNC(LEAST(NEXT_DAY(sysdate,''MONDAY'' ),NEXT_DAY(sysdate,''WEDNE Wednesday or Friday at 9 SDAY''), NEXT_DAY(sysdate,''FRIDAY'' ))) + (9/24)

a.m

Back to top of file

How does one count different data values in a column?


Use this simple query to count the number of data values in a column:
select my_table_column, count(*) from group my_table by my_table_column;

A more sophisticated example...


select dept, sum( sum( decode(sex,'M',1,0)) MALE, decode(sex,'F',1,0)) FEMALE,

count(decode(sex,'M',1,'F',1)) TOTAL from group my_emp_table by dept;

Back to top of file

How does one count/sum RANGES of data values in a column?


A value x will be between values y and z if GREATEST(x, y) = LEAST(x, z). Look at this example:
select f2, sum(decode(greatest(f1,59), least(f1,100), 1, 0)) "Range 60100", sum(decode(greatest(f1,30), least(f1, 59), 1, 0)) "Range 3059", sum(decode(greatest(f1, 0), least(f1, 29), 1, 0)) "Range 0029" from group my_table by f2;

For equal size ranges it might be easier to calculate it with DECODE(TRUNC(value/range), 0, rate_0, 1, rate_1, ...). Eg.
select ename "Name", sal "Salary", decode( trunc(f2/1000, 0), 0, 0.0, 1, 0.1, 2, 0.2,

3, 0.31) "Tax rate" from my_table;

Back to top of file

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); Shaik Khaleel provided this solution: 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 MINUS SELECT rowid FROM t1 WHERE rownum < 10); rownum <= 10

SELECT rownum,empno FROM scott.emp a GROUP BY rownum,empno HAVING rownum = 4;

Alternatively...
SELECT * FROM emp WHERE rownum=1 AND rowid NOT IN (SELECT rowid FROM emp WHERE rownum < 10);

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.

10

Back to top of file

Can one retrieve only rows X to Y from a table?


Shaik Khaleel provided this solution to the problem: 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 WHERE tableX rowid in (

SELECT rowid FROM tableX WHERE rownum <= 7 MINUS SELECT rowid FROM tableX WHERE rownum < 5); Youssef Youssef provided this soluton: "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.

11

Back to top of file

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 WHERE emp (ROWID,0) IN (SELECT ROWID, MOD(ROWNUM,4) FROM emp);

Method 2: Use dynamic views (available from Oracle7.2):


SELECT * FROM ( SELECT rownum rn, empno, ename FROM emp ) temp WHERE MOD(temp.ROWNUM,4) = 0;

Method 3: Using GROUP BY and HAVING - provided by Ravi Pachalla


SELECT rownum, f1 FROM t1 GROUP BY rownum, f1 HAVING MOD(rownum,n) = 0 OR rownum = 2-n

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. Back to top of file

How does one select the TOP N rows from a table?


Form Oracle8i one can have an inner-query with an ORDER BY clause. Look at this example:
SELECT * FROM WHERE (SELECT * FROM my_table ORDER BY col_name_1 DESC) ROWNUM < 10;

Use this workaround with prior releases:


SELECT * FROM my_table a WHERE 10 >= (SELECT COUNT(DISTINCT maxcol)

12

FROM my_table b WHERE b.maxcol >= a.maxcol) ORDER BY maxcol DESC;

Back to top of file

How does one code a tree-structured query?


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. The SCOTT/TIGER database schema contains a table EMP with a self-referencing relation (EMPNO and MGR columns). This table is perfect for tesing and demonstrating tree-structured queries as the MGR column contains the employee number of the "current" employee's boss. The LEVEL pseudo-column is an indication of how deep in the tree one is. Oracle can handle queries with a depth of up to 255 levels. Look at this example:
select from LEVEL, EMPNO, ENAME, MGR EMP

connect by prior EMPNO = MGR start with MGR is NULL;

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:
select lpad(' ', LEVEL * 2) || ENAME ........

One uses 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. Back to top of file

How does one code a matrix report in SQL?


Look at this example query with sample output:
SELECT FROM * (SELECT job, sum(decode(deptno,10,sal)) DEPT10,

13

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 CLERK MANAGER PRESIDENT SALESMAN 1300 2450 5000 5600 6000 1900 2975 950 2850

Back to top of file

How does one implement IF-THEN-ELSE in a select statement?


The Oracle decode function acts like a procedural statement inside an SQL statement to return different values or columns based on the values of other columns in the select statement. Some examples:
select decode(sex, 'M', 'Male', 'F', 'Female', 'Unknown') from employees;

select a, b, decode( abs(a-b), a-b, 'a > b', 0, 'a = b', 'a < b') from tableX;

select decode( GREATEST(A,B), A, 'A is greater OR EQUAL than B', 'B is greater than A')...

select decode( GREATEST(A,B), A, decode(A, B, 'A NOT GREATER THAN B', 'A GREATER THAN B'),

14

'A NOT GREATER THAN B')...

Note: The decode function is not ANSI SQL and is rarely implemented in other RDBMS offerings. It is one of the good things about Oracle, but use it sparingly if portability is required. From Oracle 8i one can also use CASE statements in SQL. Look at this example:
SELECT ename, CASE WHEN sal>1000 THEN 'Over paid' ELSE 'Under paid' END FROM emp;

Back to top of file

How can one dump/ examine the exact content of a database column?
SELECT DUMP(col1) FROM tab1 WHERE cond1 = val1;

DUMP(COL1) ------------------------------------Typ=96 Len=4: 65,66,67,32

For this example the type is 96, indicating CHAR, and 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. Back to top of file

Can one drop a column from a table?


From Oracle8i one can DROP a column from a table. Look at this sample script, demonstrating the ALTER TABLE table_name DROP COLUMN column_name; command. Other workarounds:
1. SQL> update t1 set column_to_drop = NULL; SQL> rename t1 to t1_base; SQL> create view t1 as select <specific columns> from t1_base;

2. SQL> create table t2 as select <specific columns> from t1; SQL> drop table t1;

15

SQL> rename t2 to t1;

Back to top of file

Can one rename a column in a table?


From Oracle9i one can RENAME a column from a table. Look at this example:
ALTER TABLE tablename RENAME COLUMN oldcolumn TO newcolumn;

Other workarounds:
1. -- Use a view with correct column names... rename t1 to t1_base; create view t1 <column list with new name> as select * from t1_base;

2. -- Recreate the table with correct column names... create table t2 <column list with new name> as select * from t1; drop table t1; rename t2 to t1;

3. -- Add a column with a new name and drop an old column... alter table t1 add ( newcolame datatype ); update t1 set newcolname=oldcolname; alter table t1 drop column oldcolname;

Back to top of file

How can I change my Oracle password?


Issue the following SQL command: ALTER USER <username> IDENTIFIED BY <new_password> / From Oracle8 you can just type "password" from SQL*Plus, or if you need to change another user's password, type "password user_name". Back to top of file

How does one find the next value of a sequence?

16

Perform an "ALTER SEQUENCE ... NOCACHE" to unload the unused cached sequence numbers from the Oracle library cache. This way, no cached numbers will be lost. If you then select from the USER_SEQUENCES dictionary view, you will see the correct high water mark value that would be returned for the next NEXTVALL call. Afterwards, perform an "ALTER SEQUENCE ... CACHE" to restore caching. You can use the above technique to prevent sequence number loss before a SHUTDOWN ABORT, or any other operation that would cause gaps in sequence values. Back to top of file

Workaround for snapshots on tables with LONG columns


You can use the SQL*Plus COPY command instead of snapshots if you need to copy LONG and LONG RAW variables from one location to another. Eg:
COPY TO SCOTT/TIGER@REMOTE CREATE IMAGE_TABLE USING SELECT IMAGE_NO, IMAGE FROM IMAGES; -

Note: If you run Oracle8, convert your LONGs to LOBs, as it can be replicated.

1.

A PL/SQL package to generate random numbers

What if you want a random number in the where clause, like, so you can choose 1/10 of the rows at random? Use a hash instead.
select * from emp where dbms_utility.get_hash_value(dump(rowid),0,100)<10;

2. The biggest difference between Oracle and everyone else is the locking mechanism. Everyone else gets share locks on data when they query it. That means other queries can also see the data, but queries block writes and writes block queries. (Update: the default for everyone else, for for example for DB2, is for queries not to block writes. Instead they show any data committed at the time the query internally fetches the data. This means each query result can be internally inconsistent, but it allows greater concurrency.) Oracle doesn't have share locks. Instead it uses snapshots, which are points in time. A query looks at the data as of some point in time. If someone changes the data later, that's OK, the query still sees the old version of the data. Each query result is internally consistent, but consecutive queries may not be consistent with one another. Queries don't block writes and writes don't block queries. Writes still block writes. Both share locks and

17

snapshots are reasonable concurrency models, but they aren't the same. It's wrong to think in terms of one when working with the other. 3. Derived tables (from-clause subqueries, inline views):
4. 5. 6. select * from (select * from emp); insert into (select deptno from dept) select trunc(a) from (select sum(empno)/5000 a from emp);

This has the same effect as if you used a view. It is useful for queries that have a repeated complex expression; for example
select x from (select avg(sin(empno)) x from emp group by deptno) where x > 0;

It's also useful when you want to use one of the values found by a subquery, for example when deleting all outdated entries from a log:
delete from log where rowid in (select rowid from log minus select a.rowid from log a, (select id, max(time) mtime from log group by id) b where a.id = b.id and a.time = b.mtime);

As of 9i, inline views can also be expressed with a "WITH clause", for example
with sub1 as (select deptno, avg(sin(empno)) x from emp group by deptno) select a.deptno, a.x, b.x from sub1 a, sub1 b where a.deptno > b.deptno;

7. When should varchar2 be used instead of char? Always. Varchar2 is always faster, more space efficient, less buggy, and its comparison rules are more likely to be what you expect. 8. Is SQL case sensitive? No. Can I give tables case-sensitive names with weird characters in them? Yes. Quote them, like so:
9. create table "Table" ("My column is KEWL!!!" int);

10. How do I insert data into an nvarchar2 column? From 9i onwards, just like any other character column, and the character set is guaranteed to hold the Unicode repertoire and measure characters using UCS2 codepoints. There is implicit conversion between char and nchar. Before 9i, avoid nvarchar2. If you really must use it, you insert like so: "insert into nemp (ename) values (n'SCOTT')". 11. Building a big bogus table:
12. 13. create table a (a1 number, a2 varchar2(50)); begin

18

14. for i in 1..10000 loop 15. insert into a values (i, 'I am a unique and extraordinary individual'); 16. end loop; 17. commit; 18. end; 19. / 20. alter table a add constraint apk primary key (a1); 21. select count(*) from a; -- 10000 rows

22. Like the making of sausage and politics, it is best not to understand the making of Oracle data types.
23. select dump(1), dump(-1), dump(sysdate) from dual;

Ouch! Ouch! You're twisting my arm. I'll explain, for Oracle numbers at least. 1. All data on disk looks like <length><stuff> 2. All data on disk is byte-sortable (other than the lengths). 3. Digits are base 100, and the first byte is the (base-100) exponent. For example, the number 1 has exponent 193, 10 also has 193, 100 has 194, 0.01 has 192. 4. Negative numbers complement the exponent. 62 for -1, 63 for -.01, 61 for -100. 5. Why? Because the exponent has to be byte-sortable. 6. Digits. Positive digits are 1..100. Negative digits are 101..2. Again, to be byte-sortable. Base-100 digits use about 7 out of 8 bits of each byte, so this is a reasonably efficient way of storing numbers. 7. Negative numbers have a trailing byte of value 102, unless the maximum number of digit bytes (20) are used. To make things byte sortable. -1 > -1.01, right? But (62,100) < (62,100,100). The trailing 102 corrects that: (62,100,102) > (62,100,100,102). 8. But why isn't the exponent for 1 192, for -1 63, and why are the digits 1..100 and 101..2 instead of 0..99 and 99..0? Because, way back in prehistory, Oracle used 0 as a null terminator, so you couldn't store 0 on disk for any other purpose. So 1 was added to everything. There's no reason not to store 0 on disk anymore because all values store their lengths separately, but the number format hasn't changed. 9. My guess is that negative infinity was originally (1,1), pushing the negative numbers out to 101..2 instead of 100..1. That's not what negative infinity is now, and SQL doesn't expose the infinities anyhow. 24. To find out how a query is executed, create a plan table with UTLXPLAN.SQL, fill the table with
25. explain plan for select ... ;

and then look at the results with a connect-by script, something like this:
select substrb(to_char(cost),1,6) cost, substrb(to_char(cardinality),1,6) card,

19

substrb(substr(' operation,1,20) type,

',1,level) ||

substrb(options,1,15) subtype, substrb(object_owner,1,5) owner, substrb(object_name,1,5) name, substrb(object_node,1,5) link from plan_table connect by parent_id = prior id start with id = 0; delete from plan_table;

26. Insert and update with check option:


27. 28. 29. 30. 31. 32. insert into (select * from emp where deptno = 10 with check option) values (...); update (select * from (select sal, empno from emp, dept where emp.deptno=dept.deptno and loc='AKRON') where sal > 100000 with check option) set sal = :1 where empno = :2;

33. Mutating/Constraining errors. Before 8i: o o o You only get these when you modify a table being read or you read a table being modified. Foreign key constraints read some tables implicitly. A table that might be deleted from due to delete cascade counts as modifying. You only get these errors from per-row triggers, not from after statement or before statement triggers (unless they are under per-row triggers). Delete cascade enforcement fires statement triggers every time it delete cascades a row, so all those statement triggers are subject to mutating errors too.

When you get the error, use your per-row trigger to fill a PL/SQL table instead. Then use an after-statement trigger to apply the changes based on that PL/SQL table. There are generic packages out there for generating the triggers, PL/SQL tables, and so forth needed to implement update cascade. Often you need more PL/SQL variables to keep track of whether you are already under a trigger, to avoid recursion. After 8i: Half the mutating errors go away. Specifically, it is still illegal to read or modify a mutating table, but modifying a table that is being read is fine. This allows the obvious before-row trigger implementation of update cascade, for example. The problem of delete cascade firing statement triggers under row triggers is fixed in Oracle8i too.
2.

How to enable constraints without locking tables for hours on end (using Oracle8 or later). First put all constraints in the ENABLE NOVALIDATE mode, then

20

ENABLE (or VALIDATE) them individually. The ENABLE NOVALIDATE modifies only metadata. The VALIDATE hold no locks, can run in parallel, and many such enables can be run concurrently. 3. How to store data case sensitive but to index it case insensitive (from 8i on): Set compatible=8.1.0.0.0, query_rewrite_integrity=trusted, and query_rewrite_enabled=true.
4. 5. 6.
create table a (a1 varchar2(10)); create index ai on a (upper(a1)); analyze table a compute statistics;

This will use the cost-based optimizer. From what I've heard, that's OK. As of Oracle8i the cost-based optimizer is a good thing, and it can use several access methods the rule-based optimizer doesn't know about.

21

1.GROUP BY, ORDER BY can be used in WHERE clause. A. B. true false

ans:B

2.select empname from employess empname like 'jack%'; what are the values given below can be returned by the query? 1.jackson and sonjack 2.jackson 3.sonjack 4.none fo the above ans :2 3)Column alias name can be used for where clause ? 1.true 2.false ans :2 )where clause can not appear after group by clause? 1.true 2.false ans:1 5).How many joins required to avod cartesian product? ans: n-1 joins for n tables 6).Which of these are set operators? A. B. C. D. E. union union all intersect minus all of the above

ans :E 7).A single row subquery may return many values. A. B. true false

ans :B 8).select regionid,regioname as region from regions order by 1,regions group by regionid; Will the above statement successfully execute?

A. B.

true false

ans:B 9).Which statement resists the high water mark?

22

Oracle Tips SQL Tips


This section contains tips on standard SQL (Structured Query Language) statements in Oracle.

SELECT * and more


Last Updated: 6/6/1999 Applies to: Oracle 7.3, 8 (and probably earlier versions) To select all columns of a table:
select * from table

However, to select all real columns, plus a pseudocolumn like "user":


select table.*, user from table

The following does not work:


select *, user from table

--Fred

Materialized View
Last Updated: 1/7/2002 Applies to: Oracle 8+ Oracle 8i introduced a new feature called a "materialized view". You define it just like any other view, except that you add the keyword MATERIALIZED:
CREATE MATERIALIZED VIEW view_name

23

A materialized view is like a combination of a table and a view. Like a view, it is defined as a logical view into the data of one or more tables. When you update the tables, subsequent queries of the view see the updated data. However, like a table, its data is stored in the database. Also, like a table, it is faster if you define indexes for it. A regular view is stored as a mapping of data from tables. When you modify the data in the tables, the view is completely ignored. When you access the view, it joins the data currently in the tables, and returns the data you requested. A materialized view is stored as such a mapping along with a copy of the actual data from the tables. When you modify the data in the tables, the view's copy of the data is also updated. When you access the view, the data is drawn directly from the copy. Thus a materialized view makes table updates a little slower, but makes view queries much faster. It also consumes additional space in the database. You could accomplish the same effect by defining an additional table instead of the view, and using triggers on the component tables to update it each time they are changed. However, using a materialized view is more convenient, more efficient, and clearer to the next person who has to maintain your database. Thanks to Andy Glick for sending me a sample of a materialized view from his application! --Fred

Search Source Code of Stored Procedures


Original Version: 1/7/2006 Last Updated: 1/20/2006 Applies to: Oracle 7.3+ Since the source code of all Oracle stored procedures, functions, and packages is stored as data in the database, you can do queries against it like any other 24

data. For example, you can find all references to a given table in all stored procedures, functions, and packages with the following query:
SELECT * FROM WHERE all_source LOWER(text) LIKE '%table_name%'

If you don't have SELECT access to the all_source table, you can try user_source or dba_source instead. Thanks to Chris Boos, the most knowledgeable Oracle guru I know, for this and many other tips! Tip within a tip: To prevent the LIKE clause from treating underscore as a wildcard, use the ESCAPE clause, as:
SELECT * FROM WHERE all_source LOWER(text) LIKE '%table\_name%' ESCAPE '\

Turbocharge SQL with advanced Oracle indexing


Oracle Tips by Burleson Consulting
March 26, 2002 - Updated June 28, 2007

For complete details on Oracle indexing for high performance, see my book "Oracle Tuning: The Definitive Reference". Oracle includes numerous data structures to improve the speed of Oracle SQL queries. Taking advantage of the low cost of disk storage, Oracle includes many new indexing algorithms that dramatically increase the speed with which Oracle queries are serviced. This article explores the internals of Oracle indexing; reviews the standard b-tree index, bitmap indexes, function-based indexes, and index-only tables (IOTs); and demonstrates how these indexes may dramatically increase the speed of Oracle SQL queries. Oracle uses indexes to avoid the need for large-table, full-table scans and disk sorts, which are required when the SQL optimizer cannot find an efficient way to service the SQL query. I begin our look at Oracle indexing with a review of standard Oracle b-tree index methodologies.

The Oracle b-tree index


The oldest and most popular type of Oracle indexing is a standard b-tree index, which excels at

25

servicing simple queries. The b-tree index was introduced in the earliest releases of Oracle and remains widely used with Oracle. B-tree indexes are used to avoid large sorting operations. For example, a SQL query requiring 10,000 rows to be presented in sorted order will often use a b-tree index to avoid the very large sort required to deliver the data to the end user.

An Oracle b-tree index


Oracle offers several options when creating an index using the default b-tree structure. It allows you to index on multiple columns (concatenated indexes) to improve access speeds. Also, it allows for individual columns to be sorted in different orders. For example, we could create a btree index on a column called last_name in ascending order and have a second column within the index that displays the salary column in descending order.
create index name_salary_idx on person ( last_name asc, salary desc);

While b-tree indexes are great for simple queries, they are not very good for the following situations:

Low-cardinality columnscolumns with less than 200 distinct values do not have the selectivity required in order to benefit from standard b-tree index structures. No support for SQL functionsB-tree indexes are not able to support SQL queries using Oracle's built-in functions. Oracle9i provides a variety of built-in functions that allow SQL statements to query on a piece of an indexed column or on any one of a number of transformations against the indexed column.

26

Prior to Oracle9i, the Oracle SQL optimizer had to perform time-consuming long-table, full-table scans due to these shortcomings. Consequently, it was no surprise when Oracle introduced more robust types of indexing structures.

Bitmapped indexes
Oracle bitmap indexes are very different from standard b-tree indexes. In bitmap structures, a two-dimensional array is created with one column for every row in the table being indexed. Each column represents a distinct value within the bitmapped index. This two-dimensional array represents each value within the index multiplied by the number of rows in the table. At row retrieval time, Oracle decompresses the bitmap into the RAM data buffers so it can be rapidly scanned for matching values. These matching values are delivered to Oracle in the form of a Row-ID list, and these Row-ID values may directly access the required information. The real benefit of bitmapped indexing occurs when one table includes multiple bitmapped indexes. Each individual column may have low cardinality. The creation of multiple bitmapped indexes provides a very powerful method for rapidly answering difficult SQL queries. For example, assume there is a motor vehicle database with numerous low-cardinality columns such as car_color, car_make, car_model, and car_year. Each column contains less than 100 distinct values by themselves, and a b-tree index would be fairly useless in a database of 20 million vehicles. However, combining these indexes together in a query can provide blistering response times a lot faster than the traditional method of reading each one of the 20 million rows in the base table. For example, assume we wanted to find old blue Toyota Corollas manufactured in 1981:
select license_plat_nbr from vehicle where color = blue and make = toyota and year = 1981;

Oracle uses a specialized optimizer method called a bitmapped index merge to service this query. In a bitmapped index merge, each Row-ID, or RID, list is built independently by using the bitmaps, and a special merge routine is used in order to compare the RID lists and find the intersecting values. Using this methodology, Oracle can provide sub-second response time when working against multiple low-cardinality columns:

27

Oracle bitmap merge join

Function-based indexes
One of the most important advances in Oracle indexing is the introduction of function-based indexing. Function-based indexes allow creation of indexes on expressions, internal functions, and user-written functions in PL/SQL and Java. Function-based indexes ensure that the Oracle designer is able to use an index for its query. Prior to Oracle8, the use of a built-in function would not be able to match the performance of an index. Consequently, Oracle would perform the dreaded full-table scan. Examples of SQL with function-based queries might include the following:
Select Select Select Select * * * * from from from from customer customer customer customer where where where where substr(cust_name,1,4) = BURL; to_char(order_date,MM) = 01; upper(cust_name) = JONES; initcap(first_name) = Mike;

In Oracle, Oracle always interrogates the where clause of the SQL statement to see if a matching index exists. By using function-based indexes, the Oracle designer can create a matching index that exactly matches the predicates within the SQL where clause. This ensures that the query is retrieved with a minimal amount of disk I/O and the fastest possible speed.

Index-only tables
Beginning with Oracle8, Oracle recognized that a table with an index on every column did not require table rows. In other words, Oracle recognized that by using a special table-access method called an index fast full scan, the index could be queried without actually touching the data itself. Oracle codified this idea with its use of index-only table (IOT) structure. When using an IOT, Oracle does not create the actual table but instead keeps all of the required information inside the Oracle index. At query time, the Oracle SQL optimizer recognizes that all of the values necessary to service the query exist within the index tree, at which time the Oracle cost-based optimizer has a choice of either reading through the index tree nodes to pull the information in sorted order or invoke an index fast full scan, which will read the table in the same fashion as a full table scan, using sequential prefetch (as defined by the db_file_multiblock_read_count parameter). The

28

multiblock read facility allows Oracle to very quickly scan index blocks in linear order, quickly reading every block within the index tablespace. Here is an example of the syntax to create an IOT.
CREATE TABLE emp_iot ( emp_id number, ename varchar2(20), sal number(9,2), deptno number, CONSTRAINT pk_emp_iot_index PRIMARY KEY (emp_id) ) ORGANIZATION index TABLESPACE spc_demo_ts_01 PCTHRESHOLD 20 INCLUDING ename;

Index performance
Oracle indexes can greatly improve query performance but there are some important indexing concepts to understand.

Index clustering Index blocksizes

Indexes and blocksize Indexes that experience lots of index range scans of index fast full scans (as evidence by multiblock reads) will greatly benefit from residing in a 32k blocksize. Today, most Oracle tuning experts utilize the multiple blocksize feature of Oracle because it provides buffer segregation and the ability to place objects with the most appropriate blocksize to reduce buffer waste. Some of the world record Oracle benchmarks use very large data buffers and multiple blocksizes. According to an article by Christopher Foot, author of the OCP Instructors Guide for Oracle DBA Certification, larger block sizes can help in certain situations: "A bigger block size means more space for key storage in the branch nodes of B-tree indexes, which reduces index height and improves the performance of indexed queries." In any case, there appears to be evidence that block size affects the tree structure, which supports the argument that data blocks affect the structure of the tree. Indexes and clustering The CBO's decision to perform a full-table vs. an index range scan is influenced by the clustering_factor (located inside the dba_indexes view), db_block_size, and avg_row_len. It is important to understand how the CBO uses these statistics to determine the fastest way to deliver the desired rows. Conversely, a high clustering_factor, where the value approaches the number of rows in the table (num_rows), indicates that the rows are not in the same sequence as the index, and additional I/O will be required for index range scans. As the clustering_factor approaches the number of rows in the table, the rows are out of sync with the index.

29

Oracle Metalink Note:223117.1 has some great advice for tuning-down db file sequential read waits by table reorganization in row-order: - If Index Range scans are involved, more blocks than necessary could be being visited if the index is unselective: by forcing or enabling the use of a more selective index, we can access the same table data by visiting fewer index blocks (and doing fewer physical I/Os). - If the index being used has a large Clustering Factor, then more table data blocks have to be visited in order to get the rows in each Index block: by rebuilding the table with its rows sorted by the particular index columns we can reduce the Clustering Factor and hence the number of table data blocks that we have to visit for each index block. This validates the assertion that the physical ordering of table rows can reduce I/O (and stress on the database) for many SQL queries.

Also see: Oracle SQL clustering_factor tuning index access Oracle SQL clustering_factor The importance of clustering_factor in multi-block I/O Oracle index rebuilding - indexes rebuild script Oracle table index rebuilding benefits

Conclusion
Oracle dominates the market for relational database technology, so Oracle designers must be aware of the specialized index structures and fully understand how they can be used to improve the performance of all Oracle SQL queries. Many of these techniques are discussed my book "Oracle Tuning: The Definitive Reference". This text details the process of creating all of Oracle's index tree structures and offers specialized tips and techniques for ensuring SQL queries are serviced using the fastest and most efficient indexing structure.

30

Convert Numbers to Words


by Brian Membrey, The PaperBag Software Company Pty Ltd I guess a mundane exercise that most programmers cop at some stage is having to convert a number (123) into a text equivalent (ONE HUNDRED AND TWENTY THREE) - for cheques, group certificates, etc. Probably the code involved a loop stripping out the numerals and then applying a value according to the relative position within the overall value. Although it winds a strange path via date functions, SQL*Plus actually provides a mechanism for automating much of this process. Executing the following :
SELECT TO_CHAR ( TO_DATE ( TO_CHAR ( 103465, '99999999999') , 'J'), 'JSP') FROM dual;

returns a value of ONE HUNDRED THREE THOUSAND FOUR HUNDRED SIXTYFIVE If we break the statement into each component function, then what happens is :

the inner TO_CHAR simply converts the number (which would probably be a numeric variable in practice) to CHAR so some magic can happen ... the TO_DATE converts the CHAR using the J (Julian day) format. (the Julian day is the number of days since January 1, 4712BC, which is when SQL*Plus was invented), having established the date value, we then convert that date back to a Julian day. Because the TO_CHAR in this case is used in DATE context, we can use the J mask to duplicate the original value, and append the SP (spell) format mask. 'Spell" does exactly that - it converts the number to words, hence the string value above.

SP can be used in a number of situations. For example, if SYSDATE is 26-AUG-98, then :


SELECT TO_CHAR ( SYSDATE, 'DdSp') FROM dual; as Twenty-Six, -- spells the day

and
SELECT TO_CHAR ( SYSDATE, 'DDSPTH') FROM dual; SIXTH --returns TWENTY-

Some simple manipulations can be included with the base conversion to cover floating numbers or currencies (email brianm@lt.com.au for source), eg. 103465.27 becomes ONE HUNDRED AND THREE THOUSAND FOUR HUNDRED AND SIXTY-FIVE DOLLARS AND TWENTY-SEVEN CENTS. One covenant however : if in your mad appreciation of this trivia you want to send me a cheque for more than $5,373,484.00, then you'll have to write it manually, or send more than one cheque! 31

SQL*Plus restricts Julian days to between 1 and 5373484, which won't be a problem for most applications, but should be borne in mind before using the technique in anger. 5373484 represents 31-Dec-9999, so this may be Oracle's way of introducing us to a Year 10K problem! Column Count in Oracle Table
11/4/2002 By ITtoolbox Popular Q&A Team for ITtoolbox as adapted from ORACLE-DEV-L discussion group Summary: How do you count the number of columns in a database table? Full Article: Disclaimer: Contents are not reviewed for correctness and are not endorsed or recommended by ITtoolbox or any vendor. Popular Q&A contents include summarized information from Oracle-Dev-L discussion unless otherwise noted.
1) Adapted from response by Dragan Pavlovic on Thursday, October 31, 2002

select COUNT(COLUMN_NAME) from dba_tab_columns where table_name = 'NAME_OF_THE_TABLE_CAPITALS' AND OWNER='SCHEMA_NAME_CAPITALS'


2) Adapted from response by Scott Tolbert on Thursday, October 31, 2002

select COUNT(*) from dba_tab_columns where table_name = YourTableNameHere

List Table Names, Rows, and Created Date This tip comes from Pasupuleti Sailaja, in Hyderabad, Andhra Pradesh, India.

Description: -- Aim rows existed in table

To display table names, number of

-and table created date in current login user for any ORACLE version -- Usage : filename DIR.SQL Step 1) All lines from given program save with

-Step 2) Run the file DIR.SQL by giving START DIR (or) @ DIR at SQL *Plus prompt --- Author 500072, India. : i.e. SQL> @ DIR Pasupuleti Sailaja, ORACLE favorite, Hyderabad-

32

-- E-mail

SAILAJAMAIL@YAHOO.COM

-- Program :

set serveroutput on size 100000 feedback off

declare rs cur rp trs n un begin dbms_output.put_line(rpad('Table Name',40)||' Number of Rows Created Date'); dbms_output.put_line(rpad('-',73,'-')); cur:= dbms_sql.open_cursor; for t in (select object_name, created from user_objects where object_type='TABLE') loop dbms_sql.parse(cur,'select count(*) from ' || t.object_name, dbms_sql.v7); dbms_sql.define_column(cur, 1, rs); rp:= dbms_sql.execute(cur); n:=dbms_sql.fetch_rows(cur); dbms_sql.column_value(cur, 1, rs); dbms_output.put_line(rpad(t.object_name,48,'.')|| rpad(rs,15,'.')||t.created); end loop; dbms_sql.close_cursor(cur); select select count(*) user into into un n from tab where tabtype='TABLE'; integer; integer; integer; integer; integer; varchar2(30);

from

dual;

dbms_output.put_line(rpad('-',73,'-')); dbms_output.put_line(un||' User contain '||n||' Table(s)'); end;

33

set

serveroutput off

feedback

on

feedback 6

-- Example Output:
Table Name Created Date Number of Rows

-----------------------------------------------------------------------ACCTS...........................................5.............. 29-JUN-03 ACCT_ADDRS......................................5.............. 29-JUN-03 BONUS...........................................0.............. 09-AUG-00 CHESS_SAVE......................................0.............. 29-JUN-03 CHESS_SAVE_BOARDSTATE...........................0.............. 29-JUN-03 CHESS_SAVE_CAPTURED.............................0.............. 29-JUN-03 CHESS_SAVE_PLAYER...............................0.............. 29-JUN-03 CITIES..........................................205............ 29-JUN-03 COMPANY_SUMMARY.................................3.............. 29-JUN-03 CUSTOMER........................................9.............. 09-AUG-00 CUSTOMERS.......................................14............. 29-JUN-03 DEMOKIT_CLASSES.................................9.............. 29-JUN-03 DEMOKIT_DEMOS...................................23............. 29-JUN-03 DEMOKIT_DEMO_SCRIPTS............................14............. 29-JUN-03

34

DEMOKIT_INSTALLED_SCRIPTS.......................5.............. 29-JUN-03 DEMOKIT_SCRIPTS.................................10............. 29-JUN-03 DEPT............................................4.............. 09-AUG-00 DUMMY...........................................1.............. 09-AUG-00 DUPEMP..........................................7168........... 12-AUG-00 EMP.............................................14............. 09-AUG-00 FFI$FUNCTION....................................2.............. 29-JUN-03 FFI$FUNCTIONARGS................................10............. 29-JUN-03 FFI$LIBRARY.....................................1.............. 29-JUN-03 FFI$TYPEDEF.....................................14............. 29-JUN-03 FUNDS...........................................5.............. 29-JUN-03 FUND_CONTRIB....................................16............. 29-JUN-03 FUND_XACT.......................................45............. 29-JUN-03 F_EMPCOMP.......................................2.............. 29-JUN-03 F_XACT_TYPE.....................................7.............. 29-JUN-03 GAME_SEMAPHORE..................................0.............. 29-JUN-03 INDCAT..........................................11............. 29-JUN-03 INVINFO.........................................5.............. 29-JUN-03 INVREQUEST......................................12............. 29-JUN-03

35

ITEM............................................0.............. 09-AUG-00 MENU_CAT........................................7.............. 29-JUN-03 MENU_ITM........................................35............. 29-JUN-03 MODE_BUTTON.....................................9.............. 29-JUN-03 ORD.............................................21............. 09-AUG-00 ORDER_HISTORY...................................5.............. 29-JUN-03 ORDPICT.........................................21............. 29-JUN-03 PORTFOLIO.......................................39............. 29-JUN-03 PRICE...........................................17............. 09-AUG-00 PRODUCT.........................................10............. 09-AUG-00 RCL_CLASSIFICATIONS.............................6.............. 29-JUN-03 RCL_COMPONENTS..................................7.............. 29-JUN-03 RCL_COMPONENT_DEPENDANCIES......................6.............. 29-JUN-03 RCL_FRAGMENTS...................................31............. 29-JUN-03 RCL_INSTRUCTIONS................................57............. 29-JUN-03 RCL_INSTRUCTIONS_TEXT...........................520............ 29-JUN-03 RCL_MODULES.....................................31............. 29-JUN-03 SALES_REVENUE...................................16............. 29-JUN-03 SALGRADE........................................5.............. 09-AUG-00

36

STOCKS..........................................328............ 29-JUN-03 STOCK_HISTORY...................................11............. 29-JUN-03 TABLE_CONFIG....................................11............. 29-JUN-03 USA.............................................50............. 29-JUN-03 -----------------------------------------------------------------------SCOTT User contain 56 Table(s)

How to Obtain Oracle Dumps


Occasionally I find it useful to obtain dumps of various Oracle structures to understand how Oracle changes behind the scenes from release to release. Very little information is available on how to interpret such dumps but occasionally Oracle Support will ask you to obtain them and it can speed up response times if you can provide them when you raise a TAR in the first place. These commands will place a trace file in USER_DUMP_DEST. Data block dumps are by far the most useful of these dumps. For example, if you suspect concurrency is a problem, then dumping table segment blocks near to the high water water mark will give a fair idea whether or not there are enough transaction entries defined for the table.

Data block - Oracle7


First, obtain the datablock address (DBA) for the block. For example to obtain a block dump for file 1 block 12: variable x varchar2; exec :x := dbms_utility.make_data_block_address(1,12); print x; 50360894 alter session set events 'immediate trace name blockdump level 50360894'; Note that this will not work for file_ids greater than 32 due to bug number 822057 (fixed in 8.0).

Data block - Oracle8 onwards


alter system dump datafile 1 block 12;

37

Control file contents


alter session set events 'immediate trace name CONTROLF level 10';

Data file headers


alter session set events 'immediate trace name FILE_HDRS level 10';

Redo log headers


alter session set events 'immediate trace name REDOHDR level 10';

System state
This is useful for determining the cause of database hangs. Take 3 successive system state dumps at 10 minute intervals. alter session set events 'immediate trace name SYSTEMSTATE level 10';

Process state
alter session set events 'immediate trace name PROCESSSTATE level 10';

Library cache
alter session set events 'immediate trace name library_cache level 10';

Copy and Rename an Oracle Database - (without export/import)


by Jeff Hunter, Sr. Database Administrator You may find it necessary to duplicate (clone) an Oracle database. One method is to use import/export. This method can work fine, but what if your database is too big? Another method is to make a copy of the current database and rename it. This month I will present an article that explains the steps necessary to copy and rename a database. This article will

38

assume that the original database is called PROD and you want to create a TEST duplicate database. 1.) Copy production database files and init.ora The first step is to locate and copy all database files to their new location. You can use the view V$DATAFILE in the PROD database to locate these files. Before running the query from V$DATAFILE, ensure that you are connected to the PROD database by selecting from V$DATABASE:
SQL> select name from v$database; NAME --------------------------------------PROD SQL> select name from v$datafile; NAME --------------------------------------/u08/app/oradata/PROD/system01.dbf /u06/app/oradata/PROD/rbs01.dbf /u07/app/oradata/PROD/temp01.dbf /u10/app/oradata/PROD/userd01.dbf /u09/app/oradata/PROD/userx01.dbf

After recording these files, shutdown the PROD database and perform an operating system copy of all database files to another location and/or machine. In my example, I will copy all datafiles to a new location as shown in the following table: Old Location New Location
/u08/app/oradata/PROD/system01.dbf /u08/app/oradata/TEST/system01.dbf /u06/app/oradata/PROD/rbs01.dbf /u07/app/oradata/PROD/temp01.dbf /u10/app/oradata/PROD/userd01.dbf /u09/app/oradata/PROD/userx01.dbf /u06/app/oradata/TEST/rbs01.dbf /u07/app/oradata/TEST/temp01.dbf /u10/app/oradata/TEST/userd01.dbf /u09/app/oradata/TEST/userx01.dbf

After copying all files to their new location, startup the PROD database. From the production database, get a copy of the initPROD.ora file and copy it to initTEST.ora. In the initTEST.ora file, change the value of "db_name" from PROD to TEST. Keep in mind that you may also need to change:

audit_file_dest background_dump_dest control_files core_dump_dest log_archive_dest user_dump_dest

39

If the TEST database is going to be on a different machine, copy the initTEST.ora file to that machine in the proper directory. 2.) Create the script that will re-create the controlfile Using SVRMGR on the PROD database, create a script that will be able to re-create the controlfile for the database.
PROD on testdb: svrmgrl SVRMGR> connect internal Connected. SVRMGR> alter database backup controlfile to trace; Statement processed.

The above statement will put a text copy of the controlfile in the USER_DUMP_DEST directory. You will need to search for the newest trace file in this directory. In UNIX you can use the "ls -lt" command. Once you find the correct trace file, rename it to cr_control.sql and edit it as follows: Remove everything up to the "START NOMOUNT" statement and everything after the semicolon at the end of the "CREATE CONTROLFILE" statement. Edit the line starting with "CREATE CONTROLFILE" and replace the word "REUSE" with the word "SET" right before the keyword DATABASE. On the same line, modify the database name changing it from PROD to TEST. On the same line, change the keyword NORESETLOGS to RESETLOGS.

Your script should now read: Edited file cr_control.sql


STARTUP NOMOUNT CREATE CONTROLFILE SET DATABASE "TEST" RESETLOGS NOARCHIVELOG MAXLOGFILES 32 MAXLOGMEMBERS 5 MAXDATAFILES 600 MAXINSTANCES 10 MAXLOGHISTORY 1000 LOGFILE GROUP 1 ( '/u03/app/oradata/TEST/redo_g01a.log', '/u04/app/oradata/TEST/redo_g01b.log', '/u05/app/oradata/TEST/redo_g01c.log' ) SIZE 200K, GROUP 2 ( '/u03/app/oradata/TEST/redo_g02a.log', '/u04/app/oradata/TEST/redo_g02b.log', '/u05/app/oradata/TEST/redo_g02c.log' ) SIZE 200K, GROUP 3 ( '/u03/app/oradata/TEST/redo_g03a.log',

40

'/u04/app/oradata/TEST/redo_g03b.log', '/u05/app/oradata/TEST/redo_g03c.log' ) SIZE 200K DATAFILE '/u08/app/oradata/TEST/system01.dbf', '/u06/app/oradata/TEST/rbs01.dbf', '/u07/app/oradata/TEST/temp01.dbf', '/u10/app/oradata/TEST/userd01.dbf', '/u09/app/oradata/TEST/userx01.dbf' ;

If the TEST database is on a different machine move this file to that machine. 3.) Create the new controlfile for TEST Make sure that your Oracle environment variable "ORACLE_SID" is set to TEST. (i.e. export ORACLE_SID=TEST). Now use SVRMGR and the CREATE CONTROLFILE script (cr_control.sql) to create your controlfile for TEST:
TEST on testdb: svrmgrl SVRMGR> connect internal Connected to an idle instance. SVRMGR> @cr_control ORACLE instance started. Total System Global Area 32798752 Fixed Size 39816 Variable Size 22600856 Database Buffers 9994240 Redo Buffers 163840 Statement processed. SVRMGR>

bytes bytes bytes bytes bytes

NOTE: Stay logged into SVRMGR and proceed to the next step. 4.) Open the TEST database Before opening the TEST database, you will need to perform incomplete recovery. After recovery you can open the database using the RESETLOGS option as show below:
SVRMGR> alter database recover database until cancel using backup controlfile; SVRMGR> alter database recover cancel; Statement processed. SVRMGR> alter database open resetlogs; Statement processed. SVRMGR>

You can verify that the database was renamed to TEST by querying from V$DATABASE:
SVRMGR> select name from v$database; NAME --------TEST 1 row selected.

41

SVRMGR>

42

Anda mungkin juga menyukai