आपको FOR LOOP
की आवश्यकता नहीं है , केवल एक अद्यतन कार्य करता है:
UPDATE emp
SET comm = extra
WHERE comm IS NULL AND extra IS NOT NULL;
यहाँ एक डेमो है:http://www.sqlfiddle.com/#!4/ aacc3/1
--- संपादित करें ----
मैंने ध्यान नहीं दिया, कि अपेक्षित आउटपुट में deptno 10 को 20 में अपडेट किया गया था,
deptno
को अपडेट करने के लिए एक अन्य प्रश्न की आवश्यकता है:
UPDATE emp
SET deptno = 20
WHERE deptno = 10;
---- संपादित करें -----
यदि आप अन्य तालिका में परिवर्तित मान सम्मिलित करना चाहते हैं, तो RETURNING..बल्क संग्रह और फ़ोरॉल के साथ एक प्रक्रिया आज़माएं:
CREATE OR REPLACE PROCEDURE pro_cedure( p_dept_id number )
IS
TYPE changed_table_type IS TABLE OF changed%ROWTYPE;
changed_buff changed_table_type;
BEGIN
SELECT deptno, comm, extra BULK COLLECT INTO changed_buff
FROM emp
WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id
FOR UPDATE;
UPDATE emp
SET comm = extra
WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id;
FORALL i IN 1 .. changed_buff.count
INSERT INTO changed VALUES changed_buff( i );
END;
/
यदि आप एक कॉल (1000 से अधिक ... या अधिकतम कुछ हजारों) में बड़ी संख्या में रिकॉर्ड संसाधित नहीं करने जा रहे हैं तो प्रक्रिया को काम करना चाहिए। अगर एक dept_id
इसमें दस हजार या अधिक पंक्तियां हो सकती हैं, तो यह प्रक्रिया धीमी हो सकती है, क्योंकि यह पीजीए मेमोरी की एक बड़ी मात्रा का उपभोग करेगी। ऐसे मामले में, थोक संग्रह के साथ एक और दृष्टिकोण की आवश्यकता होती है।
- संपादित करें --- अनुक्रम मानों को कैसे संग्रहीत करें --------
मुझे लगता है कि तालिका changed
इस तरह 4 कॉलम हैं:
CREATE TABLE "TEST"."CHANGED"
( "DEPTNO" NUMBER,
"OLDVAL" NUMBER,
"NEWVAL" NUMBER,
"SEQ_NEXTVAL" NUMBER
) ;
और हम अनुक्रम मानों को seq_nextval
. में संग्रहीत करेंगे कॉलम।
ऐसी स्थिति में प्रक्रिया कुछ इस तरह दिख सकती है:
create or replace
PROCEDURE pro_cedure( p_dept_id number )
IS
TYPE changed_table_type IS TABLE OF changed%ROWTYPE;
changed_buff changed_table_type;
BEGIN
SELECT deptno, comm, extra, sequence_name.nextval
BULK COLLECT INTO changed_buff
FROM emp
WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id
FOR UPDATE;
UPDATE emp
SET comm = extra
WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id;
FORALL i IN 1 .. changed_buff.count
INSERT INTO changed VALUES changed_buff( i );
END;
-- संपादित करें --- डेटा के छोटे सेट के लिए कर्सर के साथ संस्करण -----
हां, डेटा के छोटे सेट के लिए बल्क संग्रहण गति में उल्लेखनीय वृद्धि नहीं देता है, और ऐसे मामले में for..loop वाला सादा कर्सर पर्याप्त है।
नीचे एक उदाहरण दिया गया है आप अपडेट के साथ कर्सर का उपयोग कैसे करते हैं, FOR UPDATE
पर ध्यान दें क्लॉज, यह तब आवश्यक होता है जब हम WHERE CURRENT OF
का उपयोग करके कर्सर से प्राप्त रिकॉर्ड को अपडेट करने की योजना बनाते हैं खंड।
इस बार INSERT कथन के भीतर एक अनुक्रम मान का मूल्यांकन किया जाता है।
create or replace
PROCEDURE pro_cedure( p_dept_id number )
IS
CURSOR mycursor IS
SELECT deptno, comm, extra
FROM emp
WHERE comm IS NULL AND extra IS NOT NULL
AND deptno = p_dept_id
FOR UPDATE;
BEGIN
FOR emp_rec IN mycursor
LOOP
UPDATE emp
SET comm = extra
WHERE CURRENT OF mycursor;
INSERT INTO changed( deptno, oldval, newval, seq_nextval)
VALUES( emp_rec.deptno, emp_rec.comm,
emp_rec.extra, sequence_name.nextval );
END LOOP;
END;