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 中的所有表行?