Recently, I came across the view v$reserved_words. I wanted to know more about this view, so I did a little research and the result was the following list of questions and answers.
What information does v$reserved_words give?
Up to Oracle database version 10g Release 1 (10.1), the definition of this view was:
This view gives a list of all the keywords that are used by the PL/SQL compiler. This view helps developers to determine whether a word is already being used as a keyword in the language.
Starting with Oracle database version 10g Release 2 (10.2), the definition has changed:
This view gives a list of all SQL keywords. To determine whether a particular keyword is reserved in any way, check the RESERVED, RES_TYPE, RES_ATTR, and RES_SEMI columns.
What is the difference between a reserved word and a keyword?
Contrary to keywords, reserved words can never be used as identifiers or as names to user-defined database objects.
Does v$reserved_words contain only reserved words?
No. The view v$reserved_words has a misleading name. It contains ALL keywords used in the Oracle code, not just reserved words. The v$reserved_words.reserved column (10gR2 and above) indicates whether the keyword is actually reserved or not.
What is the definition of the view v$reserved_words in the database (10gR2 and above)?
Query v$fixed_view_definition:
SELECT view_definition FROM v$fixed_view_definition
WHERE view_name='GV$RESERVED_WORDS'
to get the definition of the view:
SELECT inst_id,
keyword,
LENGTH,
decode(MOD(TRUNC(type / 2), 2), 0, 'N', 1, 'Y', '?') reserved,
decode(MOD(TRUNC(type / 4), 2), 0, 'N', 1, 'Y', '?') res_type,
decode(MOD(TRUNC(type / 8), 2), 0, 'N', 1, 'Y', '?') res_attr,
decode(MOD(TRUNC(type / 16), 2), 0, 'N', 1, 'Y', '?') res_semi,
decode(MOD(TRUNC(type / 32), 2), 0, 'N', 1, 'Y', '?') duplicate
FROM x$kwddef
What is the meaning of each column in the view v$reserved_words (10gR2 and above)?
How can I list the keywords that I CANNOT use as identifiers in my PL/SQL program?
The output of the following PL/SQL code gives you the list of keywords that you cannot declare as identifiers (Connected to Oracle 10gR2 Express Edition):
BEGIN
FOR rec IN
(SELECT keyword,
reserved
FROM v$reserved_words
ORDER BY keyword)
LOOP
BEGIN
EXECUTE IMMEDIATE 'declare ' || rec.keyword || ' number;
begin
null;
end;';
EXCEPTION
WHEN others THEN
IF rec.reserved = 'Y' THEN
DBMS_OUTPUT.PUT_LINE(rec.keyword || ' - RESERVED');
ELSE
DBMS_OUTPUT.PUT_LINE(rec.keyword);
END IF;
END;
END LOOP;
END;
Output:
! - RESERVED
& - RESERVED
( - RESERVED
) - RESERVED
* - RESERVED
+ - RESERVED
, - RESERVED
- - RESERVED
. - RESERVED
/ - RESERVED
: - RESERVED
< - RESERVED
<<
= - RESERVED
> - RESERVED
@ - RESERVED
ALL - RESERVED
ALTER - RESERVED
AND - RESERVED
ANY - RESERVED
AS - RESERVED
ASC - RESERVED
AT
BEGIN
BETWEEN - RESERVED
BY - RESERVED
CASE
...
But, don’t you observe something weird here?
Yes, I do. There are keywords that are NOT reserved, yet they CANNOT be used as identifiers, like BEGIN and TYPE for example.
Are there any RESERVED keywords that CAN BE used as identifiers?
Yes.
BEGIN
FOR rec IN
(SELECT keyword,
reserved
FROM v$reserved_words
WHERE reserved = 'Y'
ORDER BY keyword)
LOOP
BEGIN
EXECUTE IMMEDIATE 'declare ' || rec.keyword || ' number;
begin
null;
end;';
DBMS_OUTPUT.PUT_LINE(rec.keyword || ' - RESERVED');
EXCEPTION
WHEN others THEN
NULL;
END;
END LOOP;
END;
Output:
CHAR - RESERVED
DATE - RESERVED
DECIMAL - RESERVED
FLOAT - RESERVED
INTEGER - RESERVED
LONG - RESERVED
PCTFREE - RESERVED
RAW - RESERVED
RENAME - RESERVED
SET - RESERVED
SMALLINT - RESERVED
SYNONYM - RESERVED
TRIGGER - RESERVED
VARCHAR - RESERVED
VARCHAR2 - RESERVED
So, for example, you can declare something like this without generating an error:
DECLARE
char NUMBER;
date VARCHAR2(1);
integer VARCHAR2(1);
BEGIN
char := 1;
date := 'e';
integer := 'r';
END;
But why would you use keywords, reserved or not, as identifiers?!
Now, I’ve lost my confidence in RESERVED. What does RESERVED = ‘Y’ really mean?
Let me know when you find the answer to this question.
Is there any way to use a SQL reserved word as a name for a database object?
Again, why would you want to do that? but to answer your question, just enclose the reserved word with quotation marks:
EDDIE@XE> create table create (x number);
create table create (x number)
*
ERROR at line 1:
ORA-00903: invalid table name
EDDIE@XE> create table "create" (x number);
Table created.
EDDIE@XE> desc create;
ERROR:
ORA-00931: missing identifier
EDDIE@XE> desc "create";
Name Null? Type
----------------------------------------- -------- ------
X NUMBER
Sources and resources:
Documentation:
SQL and PL/SQL reserved words:
Metalink:
Related articles:
> But why would you use keywords, reserved or not, as identifiers?!
Presumably the idea is to help you avoid using them, especially since each release of Oracle adds more. Otherwise you would never know that the list now includes GUARANTEED, VERSION, INFORMATIONAL, WALLET, WELLFORMED and M. (Not to mention LENGTH, which is rather bizarrely used as a column name by the view itself.)
It also seems to include a selection of what appear to be optimizer hints such as USE_HASH and FULL. I can’t see what naming conflict could ever arise in practice with those.
A good practice would be to always use a certain prefix or suffix in your PL/SQL identifiers as a way to avoid using reserved words. For example, prefix local identifiers with
l_and global identifiers withg_. So, even though “begin” cannot be used as an identifier, “l_begin” can.