如何在sqlplus(Oracle)中完成CREATE TYPE的输入?

Ale*_*lex 3 sql oracle sqlplus user-defined-types

我正在尝试在终端输入一个CREATE TYPE,我无法弄清楚如何完成它.这是我的具体查询:

CREATE TYPE testtype AS OBJECT (
    id int
);
/
Run Code Online (Sandbox Code Playgroud)

然后它拒绝执行任何操作,而是等待更多输入.我可以毫不费力地输入几乎所有其他查询类型.到底是怎么回事?我需要做一些最终确定的步骤来完成它吗?

Luk*_*ard 5

当你说它"等待更多输入"时,你是说SQL*Plus要求另一行输入,或者数据库显然没有响应?

换句话说,你得到这个:

SQL> create type testtype (
  2     id int
  3  );
  4  /
  5

(5表明SQL*Plus认为还有更多内容),或者你得到这样的东西:

SQL> create type testtype (
  2     id int
  3  );
  4  /


^Ccreate type testtype (
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-01013: user requested cancel of current operation

(我在没有成功完成的情况下运行了几秒后就打断了它.)

对于这个答案的其余部分,我将假设后者.我不能诚实地相信SQL*Plus会无法识别输入的结束.单独/在一行上(即使在其中一侧或两侧都有空格)被解释为输入的明确结束,即使输入不是有效的SQL.

请注意,如果您使用的是shell,例如bash,即使您正在运行的程序当前没有请求用户输入,也可以键入文本.例如:

SQL> create type testtype as object (
  2     id int
  3  );
  4  /

hello
is anybody there?
^Ccreate type testtype as object (
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-01013: user requested cancel of current operation

在这种情况下,SQL*Plus会忽略这些行hello,is anybody there?因为当我输入它时它很忙.(它可能选择稍后读入它们 - 它们可以从标准输入中读取 - 但在这种情况下它选择了不要.)

要使create type语句运行几秒钟而不是完成,我创建了以下(适当命名的)触发器:

CREATE OR REPLACE TRIGGER utterly_stupid
  BEFORE CREATE ON SCHEMA
BEGIN
  IF UPPER(ora_dict_obj_name) = 'TESTTYPE' THEN
    LOOP
      NULL;
    END LOOP;
  END IF;
END;
/
Run Code Online (Sandbox Code Playgroud)

如果您尝试创建名为"TESTTYPE"的对象,则此触发器会导致无限循环.

我并不是说你的数据库中有一个像你这样愚蠢的触发器,但你可能想看看数据库中的任何触发器BEFORE CREATEAFTER CREATE触发器.

另一种可能性可能是AFTER SERVERERROR ON DATABASE触发器.也许您的create type语句会触发错误,并导致其中一个触发器触发.你的数据库中有没有这些?

似乎挂起的会话通常是由锁定引起的.如果另一个用户对您尝试更新的行或表有锁定,则会话将阻塞,直到他们释放锁定为止.但很难看出什么可以阻止一个create type声明本身,这就是为什么我建议触发器.您还可以尝试阅读有关Oracle中锁定和阻止的文章.

我无法相信问题是由于已存在的类型或您无权创建类型.在这两种情况下,您都应该立即得到错误.