如何查询批量收藏?如果我有
select name
bulk collect into namesValues
from table1
其中namesValues为dbms_sql.varchar2_table
。
现在,我有另一个包含
的表格XYZ name is_valid
v
h
如果name在table1中,则我想将is_valid更新为'Y',否则为'N'。表1有1000万行。批量收集后我想执行
update xyz
set is_valid ='Y'
where name in namesValue.
如何查询namesValue?或者还有另一种选择。表1没有索引。 请帮忙。
答案 0 :(得分:5)
正如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;
/
根据您的回滚段大小等,您可能希望在批量收集循环中发出临时提交,但请注意,您将无法回滚这些更改。我故意没有为此添加任何COMMIT,因此您可以选择将它们放在适合您系统的位置。
您可能还想根据可用的资源更改c_bulk_limit常量的大小。
如果xyz表很大且名称列上没有索引,您的更新仍会导致问题。
希望它有所帮助...
答案 1 :(得分:4)
“Table1没有索引。”
那里有你的问题。为什么不?在TABLE1.NAME上放置一个索引,并使用普通的SQL UPDATE来修改XYZ中的数据。
尝试使用批量收集解决此问题不是正确的方法。