Oracle数据库中关键字

来源:互联网 发布:php幸运大转盘源码 编辑:程序博客网 时间:2024/04/28 02:16
 在Oracle数据库 中有一些单词具有特定的意思,也许不是提供给你的,但是使用它们你就可以不必解析、执行和获取你所编写的代码。为了更准确,在第一句话中的“一些单词”可以归类为保留字和关键字。在关键字的分类中,上下文起到了作用,因为一个单词不总是保留字。例如,单词COMMIT 本身可以触发很多事件,所以你可能要假设COMMIT 是Oracle密切使用的一个关键字。从Oracle 的角度看,就是只有它可以使用这个单词。但结果是,COMMIT 并没有如它希望的那样。如果你想的话你可以创建一个叫做COMMIT 的表,因为COMMIT 是一个关键字,这比保留字的级别要低。

   

 SQL> create table commit (id number);

Table  create.

SQL>

    保留字是被锁定的,而关键字在某些条件下可以使用。审查是一个有用的工具或功能,那么如果你想创建你自己的审查表,你是否可以使用“create table audit (...)”语句呢?

   

 SQL>  create table audit (id number);
create table audit (id number);
             *
ERROR at line 1:
ORA-00903:invalid table name


SQL>

    至少在SQL中是不行的,你不能通过这种方法使用“audit”。既然你不想使用这些特殊单词,那么你怎样能知道(或者你能从哪找到)特殊单词有哪些呢?在文档库(在一个索引中)中的几个指导包括了这个列表,但是权威的和一站式的来源是V$RESERVED_WORDS 数据字典视图。

  视图的名称表示这只是关于保留字的;但是描述视图的时候,重要的主键列被称为KEYWORD。这使得当我要了解关键字和保留字的区别时把我搞糊涂了。它使得视图中的第二列也很重要:RESERVED。因此V$RESERVED_WORDS 的解码环如下所示:

   

RESERVED值

意思

Y

是保留字

N

不是保留字

 
    
    数据库参考指导在对V$RESERVED_WORDS的描述中准确地表达了这个意思。视图有其它几个字段,而它们所显示出来的(或没有)很有意思。拿LENGTH举例。这个字段如它的名字所显示的,表示了关键字的长度。这带来两个问题。首先,为什么这个长度重要呢?其次,这个值既然很容易得到,那为什么不把它存储为一个属性呢?(是哪个正规化作出这个例外的?)

  在Oracle 10g 中,有27个关键字长度是1,有29个关键字长度为1或为空。这些长度为1或为空的关键字有哪些呢(而且它们的保留状态是什么)?我正在思考长度为1的关键字,因为它们通常包括符号。也可以包括关键字“>>”,但是这样的话要考虑的关键字的数量就超出了在这里所需要考虑的。

   

关键字(保留的)

关键字(不保留的)

|
:
-
[
<
]
!
*
>
(
=
.
@
^
/
,
)
+
&


E
A
G
M
K
U
 
P
T

  

  
    在非保留关键字字段中有两个值为空的例子。它们显示为一个空格、或为空或其它的什么吗?这个问题很难回答,因为它们都没有ASCII 值。如果其中一个表现为一个或多个空格的形式,那么可能backspace、tab、新行或者空格的值就对应地变成了8、9、10或32。

   


    
    让我们更深一层地研究视图定义,并看看这些值是从哪来的。使用Toad 深入到GV_$RESERVED_WORDS 脚本(在SYS schema下面,VIEWS)中,我们看到下面的内容:

   

  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;
    
    在格式化一些字段并按类型排序之后(只针对长度小于等于1的),输出下面的内容:
    
   ADDR           INDX    INST_ID KEYWORD  LENGTH   TYPE
-------- ---------- ---------- ------- ------- ------
607DE010       1140          1               0      1
607DD48C       1073          1 E             1      1
607DC8B0       1004          1 A             1      1
607D6818        442          1 G             1      1
607D3B3C        181          1 M             1      1
607DC070        956          1 K             1      1
607DA230        780          1 U             1      1
607DE03C       1141          1               0      1
607D37A0        160          1 P             1      1
607DC40C        977          1 T             1      1
607D8E14        663          1 |             1      2
607D8FF8        674          1 :             1      2
607DA364        787          1 -             1      2
607DAA70        828          1 [             1      2
607DADE0        848          1 <             1      2
607DBB74        927          1 ]             1      2
607DBE8C        945          1 !             1      2
607DC82C       1001          1 *             1      2
607D8BAC        649          1 >             1      2
607D7D10        564          1 (             1      2
607D7108        494          1 =             1      2
607D6CBC        469          1 .             1      2
607D6978        450          1 @             1      2
607D4FDC        301          1 ^             1      2
607D45B8        242          1 /             1      2
607D3A34        175          1 ,             1      2
607D2B6C         89          1 )             1      2
607D1F38         18          1 +             1      2
607D2300         40          1 &             1      2

 
    
    TYPE 字段用作分组。全部的类型数量如下所示:

   

SQL> select type, count(*)
  2  from x$kwddef
  3  group by type
  4  order by 1;
      TYPE   COUNT(*)
---------- ----------
         1        998
         2         95
         9          2
        16         29
        33         14
        34          4

    
    将类型的值作为一个指示器,将一个单词指定为具有重复的意思,使它具有一个足够高的类型值(大于32),以便分割的截断大于1。这18个具有重复值的单词是:

   

关键字
---------------------
PRIVILEGE
NOPARALLEL_INDEX
NESTED_TABLE_SET_REFS
INTEGER
NOREWRITE
REFERENCING
NO_FILTERING
SB4
UB2
INDEX_RS
SMALLINT
NOCPU_COSTING
PARALLEL
ROLES
MAXARCHLOGS
CONSTRAINTS
DECIMAL
CHAR

 
    
    这些单词真的与其它关键字具有同一个意思吗?通过计算,答案是否定的。直接的单词数(1140)和总的单词数(1142)间只有两个数的差距。这是否是和单词的目的或功能有某种关联呢?就是说是否CHAR是(大致是)和VARCHAR2一个意思呢?如果是这样的话,那么VARCHAR(或VARCHAR2,选一个)也应该是相同的。那么这个相同的意思就有点神秘了。

  让我们来看一个从Oracle 公司的展望而来的问题。在OTN论坛上的一个技术作者在创建新的关键字一栏里发表了一篇文章叫做认识到的一个关键问题。许多的(如果不是所有的),有记录的优化器hint是某种形式的关键字。假设你创建一个叫做GO_FAST 的存储过程,但是在下一个版本的关系数据库管理系统中,就有一个新的(假设我们愿意等这么久!)叫做GO_FAST 的hint 供你使用。你就可以开始想象当已创建的对象名称为了不和新版本中的保留字冲突而要改名时接收到的客户的海量抱怨。

  但是,已记录的单词数从8.1.7.4版本中的660增加到了10.2.0.3中的1142个。减少两个视图的结果就是10g 有487个关键字在8i 中找不到,而8i 有两个(不算空白的话)在10g 中找不到。许多新的单词是和优化器hint有关的。

  作为一个开发人员,你需要能够开发一个用户无权使用的scheme。可以在你的关系数据库管理系统产品的开始建立一个scheme,这个scheme不只要阻止与它不一致的用户,还要只允许一些选定的用户能够首先看到它。X$表就是用于这个的。

  我试着解释在X$表名称背后所隐藏的意思。几个来源定义了许多X$表;一个相当广泛的来源是MetaLink 的注解175982.1。即使有了这个列表,“kwddef”的意思也还没有表示出来。我们知道开头“k”是核心的意思,我曾经猜测“wddef”可能是与单词定义有关。

  关键是在SYS中所命名的避免了冲突,但是在SYS中所显示出来的(通过视图,作为一种方式)可能会与你的代码或命名scheme 冲突。你肯定已经做过这样的事情。在Oracle 中,在某些等级上一个对象有且只有一个名称。用户A和用户B可以各有一个叫做EMP的表,但是最多只能有一个具有和EMP相同名称的公共同义字。假设一个用户叫做A:

   

SQL> create table a.emp as select * from scott.emp;
Table created.
SQL> create public synonym emp for scott.emp;
Synonym created.
SQL> create public synonym emp for a.emp;
create public synonym emp for a.emp
                      *
ERROR at line 1:
ORA-00955: name is already used by an existing object

 


    
    结束语

  建立一个命名规范,特别是对于关键字,这使我想起了在骑士保护圣杯时看到的(在“圣战奇兵”中的情景)当Donovan (Jones的敌人)选了错误的酒杯后可怕的死状:“他选了。。。可怜的。”一旦选好了关键字并且产品发布给了用户,那么再要添加更多的关键字(或要将一个非保留字改变为一个保留字)就很困难了。在早期所做的表面上看起来没什么关系的选择或决定可能限制你将来的选择。尽管允许某些单词可以重新定义看起来好像你具有了很大的灵活性,但是你可能只是使这条路越来越混乱。

  而使得情况更加复杂的是,Oracle 的一些关键字同时还是ANSI保留字。此外,如果使用不同的系统,那么在系统A中的关键字可能在系统B中不是关键字。在电影的后面部分,在Indiana 选中了正确的酒杯之后,骑士说道:“你选对了。”当给出了许多单词来选择时这可能很难做到。现在选择你所需要的,并且如果可能的话,设置一些保留状态的保留字以防万一。在将来将它们删除要比试着要求它们要来得容易。