【问题标题】:PLSQL execute immediate ORA-00955 name is already used by an existing objectPLSQL 立即执行 ORA-00955 名称已被现有对象使用
【发布时间】:2018-07-25 16:34:05
【问题描述】:

我制作了一个 PL/SQL 块,如果它不存在,它会创建一个表。如果它存在,那么它会截断表。当我执行脚本时,我收到以下错误:

ORA-00955 name is already used by an existing object

你能帮我解决这个错误吗?

脚本

DECLARE
nCount NUMBER;
vSqlStatement LONG;
BEGIN
    SELECT count(1) into nCount FROM all_tables where table_name = 'CHANGES'; 
    IF(nCount <= 0)
    THEN
       dbms_output.put_line (' Greather or equal to 0: ' || nCount);     
       vSqlStatement:='
       CREATE TABLE ADMRAPPORT.CHANGES
       (
            "ID" NUMBER(10),
            "VersionName" VARCHAR2(255),
            "VersionNumber" NUMBER(10),
            "Version_ID" NUMBER(10),
            "VersionFlag" VARCHAR2(255)
        )';
      execute immediate vSqlStatement;    
    END IF;
    IF(nCount > 0)
    THEN
        dbms_output.put_line (' Smaller then 0');
        vSqlStatement:='TRUNCATE TABLE ADMRAPPORT.CHANGES';
        execute immediate vSqlStatement;
    END IF;
END;

【问题讨论】:

  • 提示:ADMRAPPORT.
  • 您没有在数据字典中测试 changes 表的名称 - 因此,具有此名称的对象很可能位于 admrapport 中。注意:文本输出与您的条件不匹配
  • 嗨,戈登,我不明白你的评论,你能解释一下吗?
  • 嗨,collapser,我改进了这个问题,但我仍然遇到同样的错误!
  • 你从“SELECT * FROM all_tables where table_name = 'CHANGES'”得到什么?

标签: sql oracle plsql


【解决方案1】:

如果可以以ADMRAPPORT 用户身份运行脚本并删除对架构名称的引用,这一切都会简单得多。

目前,您检查 ALL_TABLES 是否有任何名为 CHANGES 的表属于任何模式。 ALL_TABLES 仅显示您有权访问的表,这意味着已授予您或您拥有的角色的表。这可能会出错的两种方式:

  1. 其他一些架构(不是ADMRAPPORT)有一个名为CHANGES 的表并授予您访问它的权限。您的计数结果将为 1,因此您的代码将停止而不创建 ADMRAPPORT.CHANGES

  2. ADMRAPPORT.CHANGES 确实存在,但未授予您,因此您的计数结果为 0,因为该表未显示在 ALL_TABLES 中。然后代码继续并尝试创建它,但失败了。也许这就是这里发生的事情。

如果您可以以ADMRAPPORT 用户身份调用脚本,请尝试以下简化版本:

declare
    object_already_exists exception;
    pragma exception_init(object_already_exists, -955);

    vsqlstatement long :=
       'create table changes
       ( id            number(10)
       , versionname   varchar2(255)
       , versionnumber number(10)
       , version_id    number(10)
       , versionflag   varchar2(255) )';

begin
    execute immediate vsqlstatement;
    dbms_output.put_line('Table created');
exception
    when object_already_exists then
        execute immediate 'truncate table changes';
        dbms_output.put_line('Table truncated.');
end;

我还会添加一些约束(ID 是主键吗?任何列都应该是 NOT NULL 吗?等等),并考虑授权和同义词。

请注意,我已从您的列名中删除了双引号,因为它们只会在以后造成混乱和错误。

【讨论】:

    【解决方案2】:

    尝试使用 DBA_OBJECTS 而不是 ALL_TABLES。如果您无权访问此表,则必须按照 William 的建议处理异常

    【讨论】:

      【解决方案3】:

      您是否正确复制/粘贴脚本?例如,您有:

      IF(nCount <= 0)
          THEN
             dbms_output.put_line (' Greather or equal to 0: ' || nCount);
      

      以后

      IF(nCount > 0)
          THEN
              dbms_output.put_line (' Smaller then 0');
      

      【讨论】:

      • 不是我,但这并不能真正回答问题,即使你是对的,cmets 是错误的(并且拼写错误)。
      • 感谢@WilliamRobertson,如果执行的实际代码将条件块反转(如 cmets 建议的那样),它实际上可以解释这种情况,这意味着 create table 语句位于计数所在的块中大于 0。无论如何,有时我想知道我为什么还要打扰 ;-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-22
      相关资源
      最近更新 更多