最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

oracle database - What happens if you delete an element from a Nested Table? - Stack Overflow

programmeradmin0浏览0评论

While learning about Nested Tables, I came across a statement that even if you delete a value from a Nested Table, the index still exists but is assigned with NULL. Is this true?

This below code does not give exact output when run on SQL Developer. Instead of giving this output : Index 3 exists but no value assigned. it gives me : Index 3 does not exist. I am not convinced - how come it is not matching with above statement which it says.

DECLARE
   TYPE nt_type IS TABLE OF NUMBER;
   nt nt_type := nt_type(10, 20, 30, 40, 50);
BEGIN
   DBMS_OUTPUT.PUT_LINE('Before DELETE: Count = ' || nt.COUNT); -- Output: 5

   nt.DELETE(3);  -- Deletes the 3rd element (value 30)

   DBMS_OUTPUT.PUT_LINE('After DELETE: Count = ' || nt.COUNT); -- Output: 4

   IF nt.EXISTS(3) THEN
      DBMS_OUTPUT.PUT_LINE('Index 3 exists but no value assigned.');
   ELSE  
      DBMS_OUTPUT.PUT_LINE('Index 3 does not exist.');
   END IF;
   
   -- Display all elements including sparse indexes
   FOR i IN 1..nt.LAST LOOP
      IF nt.EXISTS(i) THEN
         DBMS_OUTPUT.PUT_LINE('Element at index ' || i || ' = ' || COALESCE(TO_CHAR(nt(i)), 'NULL'));
      END IF;
   END LOOP;
END;
/

Expected Output :

Before DELETE: Count = 5  
After DELETE: Count = 4  
Index 3 exists but no value assigned.  
Element at index 1 = 10  
Element at index 2 = 20  
Element at index 3 = NULL  
Element at index 4 = 40  
Element at index 5 = 50  

My SQL Developer output

Before DELETE: Count = 5
After DELETE: Count = 4
Index 3 does not exist.
Element at index 1 = 10
Element at index 2 = 20
Element at index 4 = 40
Element at index 5 = 50

While learning about Nested Tables, I came across a statement that even if you delete a value from a Nested Table, the index still exists but is assigned with NULL. Is this true?

This below code does not give exact output when run on SQL Developer. Instead of giving this output : Index 3 exists but no value assigned. it gives me : Index 3 does not exist. I am not convinced - how come it is not matching with above statement which it says.

DECLARE
   TYPE nt_type IS TABLE OF NUMBER;
   nt nt_type := nt_type(10, 20, 30, 40, 50);
BEGIN
   DBMS_OUTPUT.PUT_LINE('Before DELETE: Count = ' || nt.COUNT); -- Output: 5

   nt.DELETE(3);  -- Deletes the 3rd element (value 30)

   DBMS_OUTPUT.PUT_LINE('After DELETE: Count = ' || nt.COUNT); -- Output: 4

   IF nt.EXISTS(3) THEN
      DBMS_OUTPUT.PUT_LINE('Index 3 exists but no value assigned.');
   ELSE  
      DBMS_OUTPUT.PUT_LINE('Index 3 does not exist.');
   END IF;
   
   -- Display all elements including sparse indexes
   FOR i IN 1..nt.LAST LOOP
      IF nt.EXISTS(i) THEN
         DBMS_OUTPUT.PUT_LINE('Element at index ' || i || ' = ' || COALESCE(TO_CHAR(nt(i)), 'NULL'));
      END IF;
   END LOOP;
END;
/

Expected Output :

Before DELETE: Count = 5  
After DELETE: Count = 4  
Index 3 exists but no value assigned.  
Element at index 1 = 10  
Element at index 2 = 20  
Element at index 3 = NULL  
Element at index 4 = 40  
Element at index 5 = 50  

My SQL Developer output

Before DELETE: Count = 5
After DELETE: Count = 4
Index 3 does not exist.
Element at index 1 = 10
Element at index 2 = 20
Element at index 4 = 40
Element at index 5 = 50
Share Improve this question edited Feb 1 at 16:46 Jon Heller 36.9k6 gold badges81 silver badges143 bronze badges asked Feb 1 at 9:01 codeholic24codeholic24 99511 silver badges24 bronze badges 1
  • Your testing shows what happens, and that matches what the documentation says. You haven't said where you found the statement so we can't say why that disagreed or if you just misinterpreted it. – Alex Poole Commented Feb 1 at 19:54
Add a comment  | 

2 Answers 2

Reset to default 1

When you delete an element from a nested table collection, it marks that position as "non-existent" (which is not the same as existing but holding a NULL value), but does not internally deallocate the memory. Thus, you can reassign a value to that same position without first calling the .extend method, assuming you deleted off the end of the collection. But once you get to a position that had never been allocated at all, you cannot assign to it without first .extending the collection, as that's what assigns the memory.

Note that these are all different:

DECLARE
   TYPE nt_type IS TABLE OF NUMBER;
   nt nt_type := nt_type(10, NULL, 30);
BEGIN
   nt.delete(3); -- delete the 3rd element
   
   dbms_output.put_line(nt(1)); -- 10
   dbms_output.put_line(nt(2)); -- NULL
   
   begin
     dbms_output.put_line(nt(3)); -- raises ORA-01403: no data found
   exception
     when others then
       dbms_output.put_line(sqlerrm);
   end;

   begin
     dbms_output.put_line(nt(4)); -- raises ORA-06533: Subscript beyond count
   exception
     when others then
       dbms_output.put_line(sqlerrm);
   end;

   
   nt.extend(1); -- now add a 4th element. this does not replace the deleted 3 but creates a new 4th
   
   dbms_output.put_line(nt(4)); -- NULL
END;
/

The example above shows that deleting doesn't result in a valid element with a NULL value, but the ORA-01403 exception. Adding another element will increase the collection size without reusing the deleted element's space.

While learning about Nested Tables, I came across a statement that even if you delete a value from a Nested Table, the index still exists but is assigned with NULL. Is this true?

No, the index does not exist.

If you are going to iterate through a sparse array then do not use a FOR loop. Instead use FIRST, NEXT and LAST (as then: you do not need to know what the minimum index is; nor do you have to check whether indexes exist; and it will work on associative arrays where the indexes are not numeric):

DECLARE
  TYPE nt_type IS TABLE OF NUMBER;
  nt  nt_type := nt_type();
  idx PLS_INTEGER;
BEGIN
  nt.EXTEND(5);

  DBMS_OUTPUT.PUT_LINE('Before DELETE: Count = ' || nt.COUNT);

  nt(1) := 10;
  nt(2) := 20;
  nt.DELETE(3);  -- Delete the 3rd element.
  -- Leave the 4th element as its default value.
  nt(5) := 50;

  DBMS_OUTPUT.PUT_LINE('After DELETE: Count = ' || nt.COUNT);

  IF nt.EXISTS(3) THEN
    DBMS_OUTPUT.PUT_LINE('Index 3 exists.');
  ELSE  
    DBMS_OUTPUT.PUT_LINE('Index 3 does not exist.');
  END IF;

  IF nt.EXISTS(4) THEN
    DBMS_OUTPUT.PUT_LINE('Index 4 exists.');
  ELSE  
    DBMS_OUTPUT.PUT_LINE('Index 4 does not exist.');
  END IF;

  -- Display all elements
  idx := nt.FIRST;
  WHILE idx IS NOT NULL LOOP
    DBMS_OUTPUT.PUT_LINE(
      'Element at index ' || idx || ' = ' || COALESCE(TO_CHAR(nt(idx)), 'NULL')
    );
    idx := nt.NEXT(idx);
  END LOOP;
END;
/

Which outputs:

Before DELETE: Count = 5
After DELETE: Count = 4
Index 3 does not exist.
Index 4 exists.
Element at index 1 = 10
Element at index 2 = 20
Element at index 4 = NULL
Element at index 5 = 50

fiddle

发布评论

评论列表(0)

  1. 暂无评论