pl/sql 过程中的排序表失败

Posted

技术标签:

【中文标题】pl/sql 过程中的排序表失败【英文标题】:Sorting table in pl/sql procedure fails 【发布时间】:2015-04-17 09:54:42 【问题描述】:

这是一个 pl/sql 的家庭作业练习。我必须对表中每一行中的值进行排序,其列应从 user_tab_columns 中检索。 我是 pl/sql 的初学者。我用不同的方法尝试了好几个小时,但没有正确解决。

下面的代码可能看起来很愚蠢,但是请你帮帮我吗?

 CREATE TABLE notat(Id Number, Col1 Number, Col2 Number, Col3 Number,   Col4 Number, Col5 Number, Col6 Number, Col7 Number);
 INSERT INTO notat VALUES(1,6,3,8,4,7,8,4);
 INSERT INTO notat VALUES(2,5,7,9,2,1,7,8);
 INSERT INTO notat VALUES(3,2,7,4,8,1,5,9);
 INSERT INTO notat VALUES(4,8,4,7,9,4,1,4);
 INSERT INTO notat VALUES(5,7,5,2,5,2,6,4);

 create or replace procedure sp1_fy_marks is
    v_colname  varchar2(10);
    v2_colname varchar2(10);
    tmp        number;
    tmp2       number;

 begin

 for row in (select * from notat)
 loop

 for x in (select column_name
            from user_tab_columns
           where table_name = 'NOTAT')
 loop

  v_colname := x.column_name;

  execute immediate 'Select ' || v_colname || ' from   NOTAT where Id='  || row.Id into tmp;

  for y in (select column_name
              from user_tab_columns
             where table_name = 'NOTAT')
  loop

    v2_colname := y.column_name;

    execute immediate 'Select ' || v2_colname || ' from NOTAT where Id=' || row.Id into tmp2;

    if tmp > tmp2 then
      execute immediate 'UPDATE NOTAT SET ' || v_colname || '=' || tmp2 || '  WHERE Id=' || row.Id;
      execute immediate 'UPDATE NOTAT SET ' || v2_colname || '=' || tmp || '  WHERE Id=' || row.Id;
    end if;

  end loop;
  end loop;
  end loop;
  end sp1_fy_marks;
  execute sp1_fy_marks;

【问题讨论】:

能否请我解释清楚...没有得到你真正想做的事情 我正在尝试对位于同一行的不同列中的值进行排序。 如果你问我,这是一件非常愚蠢的事情。你确定这就是练习的真正目的吗? 我很确定,但我知道这听起来很傻...... 【参考方案1】:

正如我所说,这似乎是一个愚蠢的要求 - 我已经使用 db 35 年了,甚至从未想过要做这样的事情。

但是,您的代码看起来是正确的方法。不是最新的 PL/SQL(自从我上次使用它以来已经有几年了)我没有检查语法或任何东西,但如果我不得不这样做,我认为我会采用这种方法。

但是,如果我确实必须这样做,我实际上会争辩说数据库设计不正确。列应包含不同类型的数据,因此不可比较。如果它们在逻辑上具有可比性,那么您将中断 3NF - 您有一个重复组。正确的设计会将列拆分为不同设计表中的行。排序是一个微不足道的练习。你正在做的就是你提出的解决方案。

所以我会说:是的,在这种情况下,你做了一件非常愚蠢的事情!

【讨论】:

【参考方案2】:

请...,格式化您的代码,许多简单的问题很容易发现和修复 如果代码被格式化。作为旁注,我强烈建议 你养成了在表名前加上模式的习惯,尤其是 在引用所有者架构之外的表时,我建议使用 sys.user_tab_columns,即使技术上没有必要。

create or replace procedure sp1_fy_marks is
  v_colname  varchar2(10);
  v2_colname varchar2(10);
  tmp        number;
  tmp2       number;
begin
  for row in (select * from notat)
  loop

    for x in (select column_name
                from user_tab_columns
               where table_name = 'NOTAT')
    loop

      v_colname := x.column_name;

      execute immediate 'Select ' || v_colname || ' from   NOTAT where Id=' || row.Id into tmp;

      for y in (select column_name
                  from user_tab_columns
                 where table_name = 'NOTAT')
      loop

        v2_colname := y.column_name;

        execute immediate 'Select ' || v2_colname || ' from NOTAT where Id=' || row.Id into tmp2;

        if tmp > tmp2 then
          execute immediate 'UPDATE NOTAT SET ' || v_colname || '=' || tmp2 || '  WHERE Id=' || row.Id;
          execute immediate 'UPDATE NOTAT SET ' || v2_colname || '=' || tmp || '  WHERE Id=' || row.Id;
        end if;

      end loop;
    end loop;
  end loop;
end sp1_fy_marks;
execute sp1_fy_marks;

其次,每张表都像一个桶,数据被倒入其中,而 在桶中没有强加命令。的选择 桶外的数据强加了一个顺序。这包括选择 来自 sys.user_tab_columns 的数据。您有两个来自 sys.user_tab_columns 的选择,无法保证包含列名的行的顺序完全一样。

第三,您假设列的顺序,可能是顺序 如果您有列 a b c,则会发生 select * from notat 在 notat 中,您可以“从 notat 中选择 b c a”或“从 notat 中选择 c a b” 此外,select * from sys.user_tab_columns 与一些强加的顺序不 确保select * from notat的顺序相同

【讨论】:

以上是关于pl/sql 过程中的排序表失败的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 PL/SQL 过程和表名作为变量打印动态 SQL 中的所有表行?

匿名 pl/sql 块中的声明顺序

为啥 PL/SQL 会失败

将 XML 数据存储在表中的 PL/SQL 过程抛出错误(23,102):PL/SQL:ORA-00907:缺少右括号

PL/SQL 存储过程填充事实表

检查架构中的 IF 表 EXISTS 时发生 Oracle PL/SQL 过程错误 [重复]