Showing posts with label SQL. Show all posts
Showing posts with label SQL. Show all posts

Making Oracle Case sensitive, again

This article is a continuation on Making Oracle Case Insensitive. Read that first to understand the context discussed here.


Oracle is always Case Sensitive while querying data. Now we have learned how to make Oracle Case Insensitive for queries. Let us ask some questions to get going.

What is the purpose of making Oracle Case Insensitive?
By making Oracle Case Insensitive, you need not any more use Case mixed words. For example Test, TEST, tESt are all same once you have made Oracle Case Insensitive. Its use could be in Data warehousing applications.

How to make Oracle Case Sensitive back again after this?
You have to alter two session paramaters NLS_COMP and NLS_SORT.

First set NLS_COMP to binary.

ALTER SESSION SET nls_comp=binary;

Secondly set NLS_SORT to generic.

ALTER SESSION SET nls_sort=GENERIC_M_CI;

Once these variables are altered Oracle is back in business as case sensitive.

How to rename a table in Oracle?

There are two ways of renaming a table in Oracle:

Method 1: Simple

rename {old_table_name} to {new_table_name}

Example:

rename CUSTOMER to CUSTOMER_BACKUP

Method 2: Not so Complex

alter table {old_table_name} rename to {new_table_name};

Example:

alter table CUSTOMER rename to CUSTOMER_BACKUP;

The minimum version that supports table renaming is Oracle 8i. All the dependencies of the table will automatically updated. No need of updating them after wards.

Deleting duplicate rows from Oracle Table

Tip Courtesy: Oracle Tips by Burleson Consulting (dba-oracle)

Removing duplicate rows from Oracle tables with SQL can be very tricky, and there are several techniques. This post shows some examples of using SQL to delete duplicate table rows using an SQL sub query to identify duplicate rows, manually specifying the join columns:

DELETE FROM
   table_name A
WHERE
  a.rowid >
   ANY (
     SELECT
        B.rowid
     FROM
        table_name B
     WHERE
        A.col1 = B.col1
     AND
        A.col2 = B.col2
        );


For a script that does not uses ROWID concept, read this post.

Deleting/Listing duplicate records without ROWID

Script for getting Oracle table size

There is no oracle defined function for getting size of a table. After all if it is easy with one simple query who will require a function. Isn't it?

Anyway you can choose to save this query as a function for easy retrieval.

select

segment_name table_name,
sum(bytes)/(1024*1024) table_size_meg
from user_extents
where segment_type='TABLE'
and segment_name = '&table_name'
group by segment_name;

Read more on what all to remember while getting the size of a table. Click here

Create your own function for the purpose:

CREATE OR REPLACE FUNCTION get_table_size
(t_table_name VARCHAR2)RETURN NUMBER IS

l_size NUMBER;
BEGIN
SELECT sum(bytes)/(1024*1024)
INTO l_size
FROM
user_extents
WHERE
segment_type='TABLE'
AND segment_name = t_table_name;

RETURN l_size;
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END;

/

Example:
SELECT get_table_size('EMP') Table_Size from dual;

Result:
Table_Size
0.0625

How to enter a single quotation mark in Oracle

Q: How to enter a single quotation mark in Oracle?

Ans: Although this may be a undervalued question, I got many a search for my blog with this question. This is where I wanted to address this question elaborately or rather in multiple ways.

Method 1
The most simple and most used way is to use a single quotation mark with two single quotation marks in both sides.

SELECT 'test single quote''' from dual;

The output of the above statement would be:
test single quote'

Simply stating you require an additional single quote character to print a single quote character. That is if you put two single quote characters Oracle will print one. The first one acts like an escape character.

This is the simplest way to print single quotation marks in Oracle. But it will get complex when you have to print a set of quotation marks instead of just one. In this situation the following method works fine. But it requires some more typing labour.

Method 2
I like this method personally because it is easy to read and less complex to understand. I append a single quote character either from a variable or use the CHR() function to insert the single quote character.

The same example inside PL/SQL I will use like following:

DECLARE
l_single_quote CHAR(1) := '''';
l_output VARCHAR2(20);
BEGIN
SELECT 'test single quote'||l_single_quote
INTO l_output FROM dual;

DBMS_OUTPUT.PUT_LINE(l_single_quote);
END;

The output above is same as the Method 1.

Now my favourite while in SQL is CHR(39) function. This is what I would have used personally:

SELECT 'test single quote'||CHR(39) FROM dual;

The output is same in all the cases.

Now don't ask me any other methods, when I come to know of any other methods I will share here.

Multitable Inserts using INSERT ALL

Multitable inserts allow a single INSERT INTO .. SELECT statement to conditionally, or non-conditionally, insert into multiple tables. This statement reduces table scans and PL/SQL code necessary for performing multiple conditional inserts compared to previous versions. It's main use is for the ETL process in data warehouses where it can be parallelized and/or convert non-relational data into a relational format.
--Unconditional Insert into all tables
INSERT ALL
INTO ap_cust VALUES (customer_id, program_id, delivered_date)
INTO ap_orders VALUES (order_date, program_id)
SELECT program_id, delivered_date, customer_id, order_dateFROM airplanes;
-- Pivoting insert to split non-relational data
INSERT ALL
INTO Sales_info VALUES (employee_id,week_id,sales_MON)
INTO Sales_info VALUES (employee_id,week_id,sales_TUE)
INTO Sales_info VALUES (employee_id,week_id,sales_WED)
INTO Sales_info VALUES (employee_id,week_id,sales_THUR)
INTO Sales_info VALUES (employee_id,week_id, sales_FRI)
SELECT EMPLOYEE_ID, week_id, sales_MON, sales_TUE,
sales_WED, sales_THUR,sales_FRI FROM Sales_source_data;
-- Conditionally insert into ALL tables
INSERT ALL
WHEN SAL>10000 THEN INTO sal_history VALUES(EMPID,HIREDATE,SAL)
WHEN MGR>200 THEN INTO mgr_history VALUES(EMPID,MGR,SYSDATE)
SELECT employee_id EMPID, hire_date HIREDATE, salary SAL, manager_id MGR
FROM employees WHERE employee_id > 200;

-- Insert into the FIRST table with a matching condition
INSERT FIRST
WHEN SAL > 25000 THEN INTO special_sal VALUES(DEPTID,SAL)
WHEN HIREDATE like ('%') THEN INTO hiredate_history_00 VALUES(DEPTID,HIREDATE)
WHEN HIREDATE like ('%99%') THEN INTO hiredate_history_99 VALUES(DEPTID,HIREDATE)
ELSE INTO hiredate_history VALUES(DEPTID, HIREDATE)
SELECT department_id DEPTID, SUM(salary) SAL, MAX(hire_date) HIREDATE
FROM employees GROUP BY department_id;

Deleting/Listing duplicate records without ROWID

I was hunting for an article when my friend came up and asked me this question.

How to list/delete duplicate records without using ROWID?

I never asked why he do not want to use ROWID, because I was caught in some thinking.

I done some googling, and derived the method, but first the ROWID method

First how to delete records with ROWID, and why?

ROWID is the unique record identifier within Oracle, and it is easy to get the minimum of the ROWID for the duplicating criteria and delete the rest of them.

We will take the example of EMP table for simplicity. Assume that there is no primary key in the Employee_Id column due to some data migration requirements. Once the data migration is over I need to check the existense of duplicate records. This is how traditionally we used to achieve this:

Suppose the data after migration stands like this:
Employee_Id Employee_Name
10          Scott
11          Tiger
10          Amanda
10          Nagpal
20          Rawat

It is clear from this data that there are duplicate records, but in a normal data migration there will be millions of records from which identifying the duplicate records will be a nightmare. This is where the following query will save our day:

SELECT Employee_Id, Employee_Name
FROM   Employee e
WHERE  ROWID NOT IN (SELECT MIN(ROWID)
                     FROM   Employee f
                     WHERE  e.Employee_Id = f.Employee_Id);

The above query will list the following duplicate records:
Employee_Id Employee_Name
10          Amanda
10          Nagpal

We will not get into the decision of what to do with the duplicate records as it is not our discussion topic.

Now what does the MIN(ROWID) implies in the query? It implies that the first record inserted cannot be a duplicate record, and the rest of the data are. Simple isn't it?

Now how to select the same data without ROWID?

Consider the following select statement:

SELECT Employee_Id, Employee_Name,
  decode(row_number() over( PARTITION BY employee_id ORDER BY employee_id),1,'Not duplicate','Dupilcate') Dupicate_Criteria
FROM employee;

The following is the data from the query:

EMPLOYEE_ID    EMPLOYEE_NAME   DUPICATE_CRITERIA
10             Scott           Not duplicate
10             Amanda          Dupilcate
10             Nagpal          Dupilcate
11             Tiger           Not duplicate
20             Rawat           Not duplicate

In this, you can see the usage of row_number() function with over() clause. In the over() clause we are partitioning the data on basis of the duplicate criteria, that is the Employee_Id. The Order By clause is mandatory so we will use the same Employee_Id. Now the row_number() function assigns running numbers for each Employee_Id. If there are any duplicate records, the row_number() function will return any value greater than 1 (in the running order).

So it is very easy for us to identify the usage of row_number() function and to find an alternative method of getting duplicate rows without using ROWID in our query. Now it is in your hands to do more research and find out more usages.

Thanks for Subesh Kumar who prompted me for a short research in this topic, and hence this article.

Oracle Index and Like clause

Topic: Beginners Level

From time immemorial there has been debate over the usage of like clause and its association (or rather non-association with index). What is the fuzz all about? Let's check here.

Like clause allows you to use wildcard character searches over data stored in oracle database. By this means we can do pattern searching over the existing data.

For example:
You have a daily meeting calendar in which the attendees names are stored in comma seperated values in a VARCHAR2(2000) field. You want to search on what days a particular attendee say for instance Rose has attended the meeting.

table: meeting_schedule
fields:
meeting_date date
meeting_place varchar2(200)
meeting_attendees varchar2(2000)

In such a case of searching, without the usage of wildcard characters such as % will not yeild appropriate results.

The query for such a situation would be:

SELECT meeting_date, meeting_place
FROM meeting_schedule
WHERE meeting_attendees like '%Rose%';

Now the above query will list the meeting_date and meeting_place where Rose has attended. Of course this is a simple usage of LIKE clause.

The Like clause is valid to be used in any DML statement such as SELECT, INSERT, UPDATE and DELETE.

Now what is that links LIKE clause so much with the indexes in Oracle?
Indexes as you may know are like indexes in the book where it points to a page in the book. The same way Oracle indexes point to a data location. Both Indexes and Tables contain two different copies of data, but Indexes contain far less data compared to the tables. Think of Indexes as containing distinct values of a row in a table. So if there are more and more repetitive rows in a row, then accessing Index will prove to be lot faster than accessing the table.

So by this you must have understood where an Index would help. An Index should be used only in such cases, so that it can improve performance. If otherwise used in all places it will degrade the performance.

How can an Index degrade the performance?
By using an index side-by-side of a table, we are agreeing that it has some extra work to do. Like at every insert, update or delete to the table, the index also needs to be updated. This extra work can prove fatal if there are lot of rows in the index.

So as a simple way to know where to use index, if each row of a table is different from that of other row and there are no distinct values do not use indexes. Only use indexes if atleast there are 25% distinct rows available in the table.

Of course there is no such hard core rule as to when to use Index and when not to use. It just depends upon the situation.

Switch to another Oracle User and back

Sometimes, the DBA needs to log into a user's account to make a change, such as to grant a privilege on a user's table to another user, but, may not know what the user's password is, or, may need to make changes to a set of users from a script, but, doesn't want to include their passwords in the script itself.  Oracle provides an undocumented "identified by values" clause in the "alter user" command that can be used for this purpose. 

Since the dba_users table contains the encoded password for each user, this value can be used to generate an "alter user" command to reset the user's password back to its original value.  Then, from user system or another DBA user, you can alter the user's password to a known value (such as "whatever"), log into the user's account using "connect userid/whatever", make the changes that are needed, connect back to the system account, and run the generated "alter user" command to put the original password back.

The following SQL generates a password change script (setpw.sql) to set all users to a known password ("whatever"), and, another script (resetpw.sql) to set all users back to their original passwords.  This would be used as part of another script to generate the password change scripts, run setpw.sql, log in and make the changes that are needed, and immediately run resetpw.sql to put the passwords back.  Note that the users won't be able to log in during that time, since their passwords are not valid while you are running the script.

spool setpw.sql
select 'alter user ' || username || ' identified by whatever;' from dba_users;
spool off

spool resetpw.sql
select 'alter user ' || username || ' identified by values ''' || password || ''';' from dba_users;
spool off

Generated Script setpw.sql

alter user SYS identified by whatever;
alter user SYSTEM identified by whatever;
alter user DES identified by whatever;
alter user ELAN identified by whatever;

Generated Script resetpw.sql

alter user SYS identified by values '5638228DAF52805F';
alter user SYSTEM identified by values 'D4DF7931AB130E37';
alter user DES identified by values 'ABFEC5AC2274E54D';
alter user ELAN identified by values 'B53CE8493EC6FB92';

Source & Credits: www.akadia.com

How to switch Oracle in Single User-Multi Session Mode

During a migration it may be important, that nobody can connect to the database. You may have two possibilities to achieve this

On Table Level using LOCK TABLE

On Database Level using RESTRICTED SESSION

Exclusive Table Locks (X)

An exclusive table lock is the most restrictive mode of table lock, allowing the transaction that holds the lock exclusive write access to the table. An exclusive table lock is acquired for a table as follows:

$ sqlplus scott/tiger

SQL> GRANT ALL ON emp TO PUBLIC;
SQL> LOCK TABLE emo IN EXCLUSIVE MODE;

$ sqlplus test/test

SQL> SELECT * FROM scott.emp; (This works)
SQL> DELETE FROM scott.emp WHERE empno = 7369; (Waiting ...)

Permitted Operations

Only one transaction can obtain an exclusive table lock for a table. An exclusive table lock permits other transactions only to query the table.

Prohibited Operations

An exclusive table lock held by a transaction prohibits other transactions from performing any type of DML statement or placing any type of lock on the table.

Lock Duration

Oracle releases all locks acquired by the statements within a transaction when you either commit or roll back the transaction. Oracle also releases locks acquired after a savepoint when rolling back to the savepoint. However, only transactions not waiting for the previously locked resources can acquire locks on the now available resources. Waiting transactions will continue to wait until after the original transaction commits or rolls back completely.

Oracle in Single User Mode

You may use the RESTRICTED SESSION system privilege to switch the database in single user mode for migrations.

RESTRICTED SESSION - Specifies whether logon to Oracle is restricted

ENABLE - Allows only users with RESTRICTED SESSION system privilege to log on to Oracle. Existing sessions are not terminated.

DISABLE - Reverses the effect of the ENABLE RESTRICTED SESSION clause, allowing all users with CREATE SESSION system privilege to log on to Oracle. This is the default.

You can use this clause regardless of whether your instance has the database dismounted or mounted, open or closed.

In a first step (before the migration), you shutdown the database an start it again to be sure that all users are disconnected. Now revoke the RESTRICTED SESSION system privilege from most users, this system privilege is normally not used.

$ svrmgrl
svrmgr> CONNECT SYS AS sysdba;
svrmgr> SHUTDOWN IMMEDIATE;
svrmgr> STARTUP;
svrmgr> SPOOL revoke_restricted_session;
svrmgr> SELECT 'REVOKE restricted session FROM '
username ';' FROM dba_users
WHERE username NOT IN ('SYS','SYSTEM');
svrmgr> SPOOL OFF;
svrmgr> @revoke_restricted_session.log;
svrmgr> ALTER SYSTEM ENABLE RESTRICTED SESSION;

As user SYS you can now perform the migration. If an ordinary user tries to connect, he will get the following error messge:

sqlplus scott/tiger

ERROR: ORA-01035: ORACLE only available to users
with RESTRICTED SESSION privilege

After the migration to not to forget, to disable the RESTRICTED SESSION system privilege

svrmgr> ALTER SYSTEM DISABLE RESTRICTED SESSION;

Source: www dot akadia dot com

Automatically Calculating Percentages in Queries

Starting with Release 7.1 of Oracle, users have had access to a feature called an inline view. An inline view is a view within a query. Using this feature, you can easily accomplish your task.

Example: Show percentage of salaries for each department

Every row in the report must have access to the total sum of sal. You can simply divide sum (sal) by that total, and you'll have a number that represents the percentage of the total.

column percentage format 99.9

select deptno, sum(sal),sum(sal)/tot_sal*100 "PERCENTAGE"
from emp, (select sum(sal) tot_sal from emp)
group by deptno, tot_sal;


With Oracle8i Release 2 (8.1.6 and higher), you can calculate percentages by using the new analytic functions as well. The query using an analytic function might look like this:

column percentage format 99.9

select deptno, sum(sal), (ratio_to_report(sum(sal)) over())*100 "PERCENTAGE"
from emp
group by deptno;

The query produces the same answer—but it does so more efficiently, because it does not have to make two passes over the data to arrive at the answer. Because the analytic functions are built-in, queries that use them will find the answer more rapidly than the "pure" SQL-based approach.

Source: www dot akadia dot com

Query to find out queries running in database

To find out which queries are running in database, login as SYS and issue the following query:
 
SELECT
a.USERNAME, a.STATUS, b.sql_text
FROM V$SESSION a INNER JOIN V$SQLAREA b
ON a.SQL_ADDRESS= b.ADDRESS;
 
V$SESSION view lists session information for each current session.
 
To see field-wise description for V$SESSION follow the link below:

V$SQLAREA lists statistics on shared SQL area and contains one row per SQL string. It provides statistics on SQL statements that are in memory, parsed, and ready for execution.

To see field-wise description for V$SQLAREA follow the link below:

Simultaneous execution of PLSQL programs

Test Your PL/SQL Knowledge

This puzzler has come from Steven Feuerstein for the month of January 2008. So I thought to reproduce the puzzler with its answer:

Answer the following multiple choice question to see how well you understand the nuances of PL/SQL:

Which of the following do not help you execute multiple PL/SQL programs simultaneously?

  1. Oracle Advanced Queuing
  2. DBMS_JOB
  3. DBMS_SQL
  4. Pipelined Functions

Now for the answer scroll down:

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

Answer: (c) DBMS_SQL. Both Advanced Queuing and DBMS_JOB provide mechanisms for communicating with other sessions, thereby allowing you to "kick off" multiple PL/SQL programs at the same time. Pipelined functions are a special type of table functions: functions that can be called in the FROM clause of a query. If you include the PARALLEL_ENABLE clause in the header of a pipelined function, then the Parallel Query engine will be able to run multiple instances of that same function simultaneously on different processors.

DBMS_SQL, on the other hand, simply allows you to execute SQL statements that are constructed dynamically, at run-time. It does not contain any parallelization or process-spawning capabilities.

Sounds Interesting???

Steven Feuerstein is considered one of the world's leading experts on the Oracle PL/SQL language, having written ten books on PL/SQL all published by O'Reilly Media, including Oracle PL/SQL Programming and Oracle PL/SQL Best Practices (all from O'Reilly Media).

Steven has been developing software since 1980, spent five years with Oracle (1987-1992), and serves as a PL/SQL Evangelist to Quest Software.  

He publishes puzzlers every month and here is where you can see all of them.

 

Questions on SQL Part2

Part 2 – Questions on SQL and SQL *Plus

 

1. A user is setting up a join operation between tables EMP and DEPT. There are some employees in the EMP table that the user wants returned by the query, but the employees are not assigned to departments yet. Which SELECT statement is most appropriate for this user?

 

A.      select e.empid, d.head from emp e, dept d;

B.      select e.empid, d.head from emp e, dept d where e.dept# = d.dept#;

C.      select e.empid, d.head from emp e, dept d where e.dept# = d.dept# (+);

D.     select e.empid, d.head from emp e, dept d where e.dept# (+) = d.dept#;

 

2. Developer ANJU executes the following statement: CREATE TABLE animals AS SELECT * from MASTER.ANIMALS; What is the effect of this statement?

 

A.      A table named ANIMALS will be created in the MASTER schema with the same data as the ANIMALS table owned by ANJU.

B.      A table named ANJU will be created in the ANIMALS schema with the same data as the ANIMALS table owned by MASTER.

C.      A table named ANIMALS will be created in the ANJU schema with the same data as the ANIMALS table owned by MASTER.

D.     A table named MASTER will be created in the ANIMALS schema with the same data as the ANJU table owned by ANIMALS.

 

3. User JANKO would like to insert a row into the EMPLOYEE table. The table has three columns: EMPID, LASTNAME, and SALARY. The user would like to enter data for EMPID 59694, LASTNAME Harris, but no salary. Which statement would work best?

 

A.      INSERT INTO employee VALUES (59694,'HARRIS', NULL);

B.      INSERT INTO employee VALUES (59694,'HARRIS');

C.      INSERT INTO employee (EMPID, LASTNAME, SALARY) VALUES (59694,'HARRIS');

D.     INSERT INTO employee (SELECT 59694 FROM 'HARRIS');

 

4. Which three of the following are valid database datatypes in Oracle? (Choose three.)

 

A.      CHAR

B.      VARCHAR2

C.      BOOLEAN

D.     NUMBER

 

5. Omitting the WHERE clause from a DELETE statement has which of the following effects?

 

A.      The delete statement will fail because there are no records to delete.

B.      The delete statement will prompt the user to enter criteria for the deletion

C.      The delete statement will fail because of syntax error.

D.     The delete statement will remove all records from the table.

 

6. Dropping a table has which of the following effects on a nonunique index created for the table?

 

A.      No effect.

B.      The index will be dropped.

C.      The index will be rendered invalid.

D.     The index will contain NULL values.

 

7. To increase the number of null-able columns for a table,

 

A.      Use the alter table statement.

B.      Ensure that all column values are NULL for all rows.

C.      First increase the size of adjacent column datatypes, then add the column.

D.    Add the column, populate the column, then add the NOT NULL constraint.

 

8. Which line of the following statement will produce an error?

 

A.      CREATE TABLE goods

B.      (good_no NUMBER,

C.      good_name VARCHAR2 check(good_name in (SELECT name FROM avail_goods)),

D.     CONSTRAINT pk_goods_01

E.      PRIMARY KEY (goodno));

F.      There are no errors in this statement.

 

9. MAXVALUE is a valid parameter for sequence creation.

 

A.      A. TRUE

B.      B. FALSE

 

10. Which function below can best be categorized as similar in function to an IF-THEN-ELSE statement?

 

A.      SQRT

B.      DECODE

C.      NEW_TIME

D.     ROWIDTOCHAR

 

 

 

Answers:

  1. Option D
  2. Option C
  3. Option A
  4. Option A, B and D
  5. Option D
  6. Option B
  7. Option A
  8. Option C
  9. Option A
  10. Option B

 

End of Part 2

Questions on SQL Part1

Part 1 – Questions on SQL and SQL *Plus

 

1. Which of the following statements contains an error?

 

A. SELECT * FROM emp WHERE empid = 493945;

B. SELECT empid FROM emp WHERE empid= 493945;

C. SELECT empid FROM emp;

D. SELECT empid WHERE empid = 56949 AND lastname = 'SMITH';

 

2. Which of the following correctly describes how to specify a column alias?

 

A. Place the alias at the beginning of the statement to describe the table.

B. Place the alias after each column, separated by white space, to describe the column.

C. Place the alias after each column, separated by a comma, to describe the column.

D. Place the alias at the end of the statement to describe the table.

 

3. The NVL function

A. Assists in the distribution of output across multiple columns.

B. Allows the user to specify alternate output for non-null column values.

C. Allows the user to specify alternate output for null column values.

D. Nullifies the value of the column output.

 

4. Output from a table called PLAYS with two columns, PLAY_NAME and AUTHOR, is shown below.

Which of the following SQL statements produced it?

 

PLAY_TABLE
-------------------------------------
"Midsummer Night's Dream", SHAKESPEARE
"Waiting For Godot", BECKETT
"The Glass Menagerie", WILLIAMS

 

A. SELECT play_name || author FROM plays;

B. SELECT play_name, author FROM plays;

C. SELECT play_name||', ' || author FROM plays;

D. SELECT play_name||', ' || author PLAY_TABLE FROM plays;

 

5. Issuing the DEFINE_EDITOR="emacs" will produce which outcome?

 

A. The emacs editor will become the SQL*Plus default text editor.

B. The emacs editor will start running immediately.

C. The emacs editor will no longer be used by SQL*Plus as the default text editor.

D. The emacs editor will be deleted from the system.

 

6. The user issues the following statement. What will be displayed if the EMPID selected is 60494?

 

SELECT DECODE(empid,38475, ‘Terminated’,60494, ‘LOA’, ‘ACTIVE’)

FROM  emp;

 

A. 60494

B. LOA

C. Terminated

D. ACTIVE

 

7. SELECT (TO_CHAR(NVL(SQRT(59483), ‘INVALID’)) FROM DUAL is a valid SQL statement.

 

A. TRUE

B. FALSE

 

8. The appropriate table to use when performing arithmetic calculations on values defined within the SELECT statement (not pulled from a table column) is

 

A. EMP

B. The table containing the column values

C. DUAL

D. An Oracle-defined table

 

9. Which of the following is not a group function?

 

A. avg( )

B. sqrt( )

C. sum( )

D. max( )

 

10. The default character for specifying runtime variables in SELECT statements is

 

A. Ampersand

B. Ellipses

C. Quotation marks

D. Asterisk

 

Answers:

  1. Option D
  2. Option B
  3. Option C
  4. Option D
  5. Option A
  6. Option B
  7. Option B
  8. Option C
  9. Option B
  10. Option A

 

 

To view explanations for the answers of questions go here.

 

Don’t miss the explanations for the answers.

 

End of Part 1

Q-quote operator introduced in Oracle 10g

-----------------------------------------------------------------------

-- Document: Q-quoting mechanism

-- Created On: 17-Dec-07

-- Author: Amar Kumar Padhi

-- Email: amar.padhi@gmail.com

-- Purpose: Q-quote operator introduced in Oracle 10g.

-----------------------------------------------------------------------

 

We make use of single quotation mark in SQL and PL/SQL to identify sting literals. If the literal itself contains a single quote, we need to add one more quote next to it. This additional quote acts as an escape character and removes conflict with the outside quotes that are enclosing the string.

 

Oracle realises that long complex strings having lot of single quotes can turn out to become cumbersome and prone to errors that may not be caught during testing.

 

Release 10g onwards, a new quoting mechanism is provided in the form of "q". This new quote operator allows us to choose our own quotation mark delimiter.

 

Here are some examples -

SQL> select 'amar's web blog. It's personal..' str from dual;

select 'amar's web blog. It's personal..' str from dual

*

ERROR at line 1:

ORA-00923: FROM keyword not found where expected

 

What we normally do:-

SQL> select 'amar''s web blog. It''s personal..' str from dual;

STR

--------------------------------

amar's web blog. It's personal..

1 row selected.

 

Here is use of Q - quote operator. The above statement can also be represented as any one of the below.

 

select q'(amar's web blog. It's personal.)' str from dual;

select q'[amar's web blog. It's personal.]' str from dual;

select q'Aamar's web blog. It's personal.A' str from dual;

select q'/amar's web blog. It's personal./' str from dual;

select q'Zamar's web blog. It's personal.Z' str from dual;

select q'|amar's web blog. It's personal.|' str from dual;

select q'+amar's web blog. It's personal.+' str from dual;

 

(New added)

select q'zamar's web blog. It's personal.z' str from dual;

 

And so on. After the Q-quote is specified, provide the single quote along with a unique character at the beginning of the string. To close the string, provide the same character followed by the single quote. The single and the provided character form the two character string enclosure.

 

If you decide to use braces, Oracle expects matching enclosures, i.e., Open brackets should be represented by closed brackets at the end of the string. Other characters can be represented as they are at both ends.

 

All we need to take care of is that the last two character delimiter does not show up in the string itself. For instance the below will throw error as the closing characters get repeated within the string.

 

SQL> select q'aamar's web blog. Ita's personal.a' str from dual;

ERROR:

ORA-01756: quoted string not properly terminated

 

The same can be used in PL/SQL also.

SQL> declare

2 l_str varchar2(100) := q'[amar's web blog. Ita's personal.]';

3 begin

4 dbms_output.put_line(l_str);

5 end;

6 /

amar's web blog. Ita's personal.

PL/SQL procedure successfully completed.

 

I recently came across a program that framed dynamic INSERT statement to copy data from one database to another. Unfortunately, one of the record columns had a single quote embedded in the string and this resulted in the program unit to fail in production. This happened in release 9i and the only alternative available was to remove/double the single quotes from the string literal. From release 10g, Q-quote could also be used to prevent this problem. I will simulate the same scenario and try this out.

 

SQL> create table am100(col1 number, col2 varchar2(100));

Table created.

SQL> create table am102(col1 number, col2 varchar2(100));

Table created.

SQL> insert into am100 values(1, q'[amar's web blog. It's personal]');

1 row created.

SQL> insert into am100 values(2, q'[this is a simple string]');

1 row created.

SQL> insert into am100 values(3, q'[this is just another string]');

1 row created.

SQL> select * from am100;

COL1 COL2

---------- ----------------------------------

1 amar's web blog. It's personal

2 this is a simple string

3 this is just another string

3 rows selected.

SQL> commit;

Commit complete.

 

Now I will call a simple routine that will read the data and generate dynamic SQL for inserting into another table.

 

declare

l_str varchar2(4000);

begin

for rec in (select col1, col2 from am100) loop

l_str := 'insert into am102(col1, col2) values (' || rec.col1 ||',''' ||

rec.col2 || ''')';

dbms_output.put_line(l_str);

execute immediate l_str;

end loop;

end;

/

 

The unit errors out as below, because of the single quote mismatch.

insert into am102(col1, col2) values (1,'amar's web blog. It's personal');

begin

*

ERROR at line 1:

ORA-00917: missing comma

ORA-06512: at line 4

 

I will now modify the program unit to add Q-quote. We can also use the REPLACE function to remove or double-up single quote in strings, both options are given below.

 

[] With REPLACE function (doubling the single quote);

declare

l_str varchar2(4000);

begin

for rec in (select col1, replace(col2, '''', '''''') col2 from am100) loop

l_str := 'insert into am102(col1, col2) values ('

|| rec.col1 ||',''' || rec.col2 || ''')';

dbms_output.put_line(l_str);

execute immediate l_str;

end loop;

end;

/

 

Output generated:-

insert into am102(col1, col2) values (1,'amar''s web blog. It''s personal')

insert into am102(col1, col2) values (2,'this is a simple string')

insert into am102(col1, col2) values (3,'this is just another string')

 

[] With Q-quote

declare

l_str varchar2(4000);

Begin

for rec in (select col1, 'q''[' || col2 || ']''' col2 from am100) loop

l_str := 'insert into am102(col1, col2) values ('

|| rec.col1 ||',' || rec.col2 || ')';

dbms_output.put_line( l_str );

execute immediate l_str;

end loop;

end;

/

 

Output generated:-

insert into am102(col1, col2) values (1,q'[amar's web blog. It's personal]')

insert into am102(col1, col2) values (2,q'[this is a simple string]')

insert into am102(col1, col2) values (3,q'[this is just another string]')

 

Q-quote will be a handy option when we deal with huge text literals.