【问题标题】:ORA-01403: No Data found WHY?ORA-01403: 未找到数据 为什么?
【发布时间】:2017-01-20 10:24:38
【问题描述】:

我已经声明了以下程序:

 CREATE OR REPLACE PROCEDURE MODIFY_NOT_NULL(
      v_tbName       IN VARCHAR2,
      v_cName        IN VARCHAR2,
      v_defaultValue IN VARCHAR2 )
   IS
      v_is_null VARCHAR2(1);
   BEGIN

      SELECT nullable INTO v_is_null 
      FROM USER_TAB_COLUMNS 
      WHERE TABLE_NAME = v_tbName 
      AND COLUMN_NAME  = v_cName;

      IF  v_is_null   = 'Y' THEN
          EXECUTE IMMEDIATE ('ALTER TABLE ' || v_tbName 
               || ' MODIFY (' || v_cName 
               || ' DEFAULT ' || v_defaultValue 
               || '  NOT NULL )');
      END IF;
   END;

但是当我执行我的代码时:

BEGIN
   modify_not_null('TABLE_NAME', 'COLUMN_NAME ' ,'0');
END;
/ 

我得到了一个

"ORA-01403: No Data Found"

如果“SELECT INTO”语句没有返回任何值,通常会抛出这个异常,但是当我执行这个时我总是会得到一个值:

Select nullable 
from USER_TAB_COLUMNS 
WHERE table_name = 'TABLE_NAME' 
AND column_name  = 'COLUMN_NAME';

当我执行上面的代码时,我得到“N”或“Y”作为结果。所以我总是得到一个结果。不知道为什么会抛出这个异常

【问题讨论】:

  • 为什么数据被选入v_is_null,而IF条件是l_nullable?可能是 l_nullable 是声明的局部变量,但已初始化。
  • 非常抱歉,我的帖子又是一个错字...不幸的是,这不是错误,但非常感谢您的提示
  • 您是否正在执行来自不同用户的查询和 PL SQL 块?如果用户 ID 不同,则 USER_TAB_COLUMNS 中的数据会发生变化。最好的调试方法是在代码的每一行之后放置一个 dbms_output 以了解异常的来源。
  • 不,我只使用一个用户执行。
  • 你的子程序调用参数中多了一个空格:'COLUMN_NAME '

标签: oracle plsql database-metadata execute-immediate


【解决方案1】:

您的通话包含一个尾随空格:

modify_not_null('TABLE_NAME', 'COLUMN_NAME ' ,'0');
                                          ^

所以 proc 抛出 no data found 因为'COLUMN_NAME ' != 'COLUMN_NAME'

使用upper(trim(v_cName)) 防止拼写错误导致错误。应用于所有参数。

【讨论】:

    【解决方案2】:

    您正在将 v_defaultValue 参数传递给列名。

    更改程序为

    SELECT nullable INTO v_is_null 
    FROM USER_TAB_COLUMNS 
    WHERE TABLE_NAME = v_tbName AND COLUMN_NAME  = v_cName ;
    

    【讨论】:

      【解决方案3】:

      在您的SELECT .... INTO 之前,您必须确保有可供选择的内容。因为根据你是什么用户,给什么参数,你的表中可能没有数据。

      一个简单的方法是在SELECT之前的开头有一个COUNT

       CREATE OR REPLACE PROCEDURE MODIFY_NOT_NULL(
            v_tbName       IN VARCHAR2,
            v_cName        IN VARCHAR2,
            v_defaultValue IN VARCHAR2 )
         IS
            v_is_null VARCHAR2(1);
            v_count number;
         BEGIN
            -- added select count
            SELECT count(1) INTO v_count FROM USER_TAB_COLUMNS WHERE TABLE_NAME = trim(v_tbName) AND COLUMN_NAME  = trim(v_cName);
            -- added if v_count=1
            if v_count = 1 then
              SELECT nullable INTO v_is_null FROM USER_TAB_COLUMNS WHERE TABLE_NAME = trim(v_tbName) AND COLUMN_NAME  = trim(v_cName);
      
              IF  v_is_null   = 'Y' THEN
               EXECUTE IMMEDIATE ('ALTER TABLE ' || v_tbName || ' MODIFY (' || v_cName || ' DEFAULT ' || v_defaultValue || '  NOT NULL )');
              END IF;
            -- added
            end if;
         END;
      /
      

      分享和享受

      【讨论】:

      • @APC,是的,是的,我的错误。我测试了,但错误的 ':/ ...我恢复到我的第一个答案。
      【解决方案4】:

      保持优雅:)

      create or replace procedure modify_not_null(v_tbName       in varchar2,
                                                  v_cName        in varchar2,
                                                  v_defaultValue in varchar2) is
        cursor c_tbl(cp_tbname in varchar2, 
                     cp_cname in varchar2) is
          select nullable
            from user_tab_columns
           where table_name  = upper(cp_tbname)
             and column_name = upper(cp_cname);
      
        l_tbl c_tbl%rowtype;
      begin
      
        open c_tbl(cp_tbname => v_tbName,
                   cp_cname => v_cName);
        fetch c_tbl into l_tbl;
        close c_tbl;
      
        if l_tbl.nullable = 'Y' then
          execute immediate 'alter table ' || v_tbName || ' modify (' || v_cName ||
                            ' default ' || v_defaultValue  || '  not null )';
        end if;
      exception
        when others then
          raise_application_error(-20000, dbms_utility.format_error_stack);
      end modify_not_null;
      

      【讨论】:

      • 看起来 OP 的错误是由于参数中的尾随空格造成的,而您所有的额外代码实际上并没有解决这个问题。
      • 这如何解决 OP 的问题?如果原始代码引发 ORA-01403,此代码将遇到完全相同的问题(除了隐藏发生异常的真实位置)。
      • 什么是 OP 问题?如果找不到表,它不会引发任何错误。
      • 不会受到ORA-01403的影响,在说不明智的话之前先试试吧。
      • 抑制错误信息与修复问题不同。
      猜你喜欢
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 2013-12-27
      • 2011-11-06
      • 1970-01-01
      • 1970-01-01
      • 2019-10-22
      • 1970-01-01
      相关资源
      最近更新 更多