Sql Oracle正在使用另一个集合更新一个集合中的值
我有一个使用for循环的解决方案,但这种方法效率低,性能差。我刚开始使用收藏,但在互联网上还找不到我的答案。谁能给我指出正确的方向吗? 这是我试图实现的目标的简化版本Sql Oracle正在使用另一个集合更新一个集合中的值,sql,oracle,join,plsql,collections,Sql,Oracle,Join,Plsql,Collections,我有一个使用for循环的解决方案,但这种方法效率低,性能差。我刚开始使用收藏,但在互联网上还找不到我的答案。谁能给我指出正确的方向吗? 这是我试图实现的目标的简化版本 DECLARE TYPE rec_numbers IS RECORD ( DIGIT NUMBER, ENGLISH VARCHAR2 (10), FRENCH VARCHAR2(10), ITALIAN VARCHAR2(10) ); TYPE tab_numbers IS TABLE OF rec_number
DECLARE
TYPE rec_numbers IS RECORD
(
DIGIT NUMBER,
ENGLISH VARCHAR2 (10),
FRENCH VARCHAR2(10),
ITALIAN VARCHAR2(10)
);
TYPE tab_numbers IS TABLE OF rec_numbers;
blk_num tab_numbers;
blk_num2 tab_numbers;
BEGIN
SELECT 1 DIGIT, 'ONE' ENGLISH, NULL FRENCH, NULL ITALIAN
BULK COLLECT INTO blk_num
FROM DUAL;
SELECT 1 DIGIT, NULL ENGLISH, 'UN' FRENCH, 'UNO' ITALIAN
BULK COLLECT INTO blk_num2
FROM DUAL;
FOR i IN blk_num.FIRST .. blk_num.LAST LOOP
FOR j IN blk_num2.FIRST .. blk_num2.LAST LOOP
IF blk_num(i).digit = blk_num2(j).digit THEN
blk_num(i).french := blk_num2(j).french;
blk_num(i).italian := blk_num2(j).italian;
END IF;
END LOOP;
END LOOP;
END;
嵌套循环可能很慢。如果blk_num和blk_num2每个都有1000条记录,那么您正在进行1000x1000=一百万次迭代。这是^2的性能 加载blk_num2后,您可以花时间将其转换为关联数组,从而实现这一点。然后,不必循环遍历blk_num2中的所有条目,只需通过其索引值请求即可找到您要查找的条目 以下是我的意思的一个例子:
DECLARE
TYPE rec_numbers IS RECORD
(
DIGIT NUMBER,
ENGLISH VARCHAR2 (10),
FRENCH VARCHAR2(10),
ITALIAN VARCHAR2(10)
);
TYPE tab_numbers IS TABLE OF rec_numbers;
blk_num tab_numbers;
blk_num2 tab_numbers;
-- Define an associative array to copy blk_num2 into.
-- Note: I did not INDEX BY PLS_INTEGER because I do not know how big DIGIT can be.
-- if DIGIT will always fit into a PLS_INTEGER, you can use that instead.
TYPE assoc_numbers IS TABLE OF rec_numbers INDEX BY VARCHAR2(30);
blk_num2_aa assoc_numbers;
BEGIN
SELECT 1 DIGIT, 'ONE' ENGLISH, NULL FRENCH, NULL ITALIAN
BULK COLLECT INTO blk_num
FROM DUAL;
SELECT 1 DIGIT, NULL ENGLISH, 'UN' FRENCH, 'UNO' ITALIAN
BULK COLLECT INTO blk_num2
FROM DUAL;
-- Copy blk_num2 into blk_num2_aa
FOR i in blk_num2.FIRST..blk_num2.LAST LOOP
blk_num2_aa(to_char(blk_num2(i).digit)) := blk_num2(i);
END LOOP;
FOR i IN blk_num.FIRST .. blk_num.LAST LOOP
-- Find the match based on the associative array's index value
IF blk_num2_aa.exists(to_char(blk_num(i).digit)) THEN
blk_num(i).french := blk_num2_aa(to_char(blk_num(i).digit)).french;
blk_num(i).italian := blk_num2_aa(to_char(blk_num(i).digit)).italian;
END IF;
END LOOP;
END;
你没有提到为什么你需要在这里收藏。如果将类型和集合定义为模式对象,则可以使用表函数执行简单的联接查询,以完全实现for循环的功能
CREATE OR REPLACE
TYPE rec_numbers AS OBJECT
( digit NUMBER,
english VARCHAR2(10),
french VARCHAR2(10),
italian VARCHAR2(10) );
/
CREATE OR REPLACE TYPE tab_numbers AS
TABLE OF rec_numbers;
/
代码
输出
1,ONE,UN,UNO
PL/SQL procedure successfully completed.
这个怎么样
update (select * from table(blk_num )) a
set (FRENCH, ITALIAN) =
(select FRENCH, ITALIAN
from table(blk_num2) b
where a.DIGIT = b.DIGIT);
你到底为什么要在这里使用集合?您的版本似乎表明您的用户首先将表中的数据加载到集合中并进行一些比较。为什么所有这些都不是纯SQL呢?在任何集合中添加第二个值,您将看到它不起作用。工作一演示@RavshanAbdulaev:你说它不工作是什么意思?检查第二个值。另外,您的解决方案在或12c中不起作用。此外,对于外部联接,您使用的是过时的+语法,而不是ANSI标准的显式联接。看到我的错误了,正如你所说。我无法重现我得到意外结果的例子。无法理解我的解决方案在Oracle 11g或12c中的错误,您能解释一下吗?
update (select * from table(blk_num )) a
set (FRENCH, ITALIAN) =
(select FRENCH, ITALIAN
from table(blk_num2) b
where a.DIGIT = b.DIGIT);