fac*_*ook 2 oracle plsql oracle11g
如何查询批量收藏?如果我有
select name
bulk collect into namesValues
from table1
Run Code Online (Sandbox Code Playgroud)
其中namesValues是dbms_sql.varchar2_table.
现在,我有另一个包含XYZ的表格
name is_valid
v
h
Run Code Online (Sandbox Code Playgroud)
如果name在table1中,则我想将is_valid更新为'Y',否则为'N'.表1有1000万行.批量收集后我想执行
update xyz
set is_valid ='Y'
where name in namesValue.
Run Code Online (Sandbox Code Playgroud)
如何查询namesValue?或者还有另一种选择.表1没有索引.请帮忙.
正如Tom Kyte(甲骨文公司副总裁)所说:
我非常感谢你的口头禅是:
如果可能的话,您应该在单个SQL语句中执行此操作.
如果您无法在单个SQL语句中执行此操作,请在PL/SQL中执行此操作.
如果您无法在PL/SQL中执行此操作,请尝试Java存储过程.
如果您不能在Java中执行此操作,请在C外部过程中执行此操作.
如果你不能在C外部程序中做到这一点,你可能需要认真思考为什么你需要这样做...
想一想......
学习所有有关SQL的知识......
如果可以,您应该在SQL中执行更新.如果您需要添加索引来执行此操作,那么循环使用BULK COLLECT填充的集合可能更为可取.
但是,如果这是某种分配....你应该这样指定它,但这是你将如何做到这一点.
我假设你的数据库服务器没有能力在内存中容纳1000万条记录,所以不是BULK一次性收集所有1000万条记录,而是将BULK COLLECT放入循环中以减少内存开销.如果不是这种情况,那么您可以省略批量收集循环.
DECLARE
c_bulk_limit CONSTANT PLS_INTEGER := 500000;
--
CURSOR names_cur
IS
SELECT name
FROM table1;
--
TYPE namesValuesType IS TABLE OF table1.name%TYPE
INDEX BY PLS_INTEGER;
namesValues namesValuesType;
BEGIN
-- Populate the collection
OPEN name_cur;
LOOP
-- Fetch the records in a loop limiting them
-- to the c_bulk_limit amount at a time
FETCH name_cur BULK COLLECT INTO namesValues
LIMIT c_bulk_limit;
-- Process the records in your collection
FORALL x IN INDICES OF namesValues
UPDATE xyz
SET is_valid ='Y'
WHERE name = namesValue(x)
AND is_valid != 'Y';
-- Set up loop exit criteria
EXIT WHEN namesValues.COUNT < c_bulk_limit;
END LOOP;
CLOSE name_cur;
-- You want to update all remaining rows to 'N'
UPDATE xyz
SET is_valid ='N'
WHERE is_valid IS NULL;
EXCEPTION
WHEN others
THEN
IF name_cur%ISOPEN
THEN
CLOSE name_cur;
END IF;
-- Re-raise the exception;
RAISE;
END;
/
Run Code Online (Sandbox Code Playgroud)
根据您的回滚段大小等,您可能希望在批量收集循环中发出临时提交,但请注意,您将无法回滚这些更改.我故意没有为此添加任何COMMIT,因此您可以选择将它们放在适合您的系统的位置.
您还可能希望根据可用资源更改c_bulk_limit常量的大小.
如果xyz表很大并且名称列上没有索引,则更新仍会导致问题.
希望能帮助到你...
| 归档时间: |
|
| 查看次数: |
4770 次 |
| 最近记录: |