Удаление определенной записи из вложенной таблицы Oracle DB

У меня проблемы с удалением определенной записи из таблицы (БД ORACLE). У меня есть таблица с вложенной таблицей внутри нее.

Структура таблицы выглядит так: где ML - вложенная таблица

Name, City, ML(Brand, Model, ID, Year, Price)

Что мне нужно сделать, так это удалить конкретную запись с идентификатором «L201».

Что я пробовал до сих пор:

SELECT B.ID FROM TABLE Dock A, Table(A.ML) B;

Это работает, давая мне все идентификаторы.

Выход:

ID
____
B201
S196
L201

Это не работает при попытке удалить запись:

DELETE FROM Dock
(SELECT B.ID FROM Dock A, Table(A.ML) B) C
WHERE C.ID = 'L201';

Получение ошибки:

Строка 2: команда SQL завершилась неправильно;

DELETE FROM TABLE
(SELECT D.ML FROM Dock D) E
WHERE E.ID = 'L201';

Выдает ошибку:

однострочный подзапрос возвращает более одной строки


person user3074445    schedule 06.12.2013    source источник


Ответы (2)


Может быть, этот:

DELETE FROM 
   (SELECT A.Name, A.City, d.Brand, d.Model, d.ID, d.Year, d.Price 
   FROM Dock A, TABLE(ML) d)
WHERE ID = 'L201';

Обновление: еще одна пробная версия, прежде чем мы сделаем ее более продвинутой:

DELETE FROM Dock
WHERE ROWID =ANY (SELECT a.ROWID FROM Dock a, TABLE(ML) b WHERE b.ID = 'L201');

Обновление 2. Если вы предпочитаете более объектно-ориентированный подход, этот тоже должен работать. По крайней мере, я не получил никакой ошибки.

CREATE OR REPLACE TYPE ML_TYPE AS OBJECT (
  brand VARCHAR2(100),
  ID VARCHAR2(20),
  MODEL VARCHAR2(20), 
  YEAR NUMBER, 
  Price NUMBER,
MAP MEMBER FUNCTION getID RETURN VARCHAR2,
CONSTRUCTOR FUNCTION ML_TYPE(ID IN VARCHAR2) RETURN SELF AS RESULT);


CREATE OR REPLACE TYPE BODY ML_TYPE IS   

CONSTRUCTOR FUNCTION ML_TYPE(ID IN VARCHAR2) RETURN SELF AS RESULT IS
-- Constructor to create dummy ML-Object which contains just an ID,
-- used for comparison
BEGIN
    SELF.ID := ID;
    RETURN;
END ML_TYPE;

MAP MEMBER FUNCTION getID RETURN VARCHAR2 IS
BEGIN
    RETURN SELF.ID;
END getID;
END;
/

CREATE OR REPLACE TYPE ML_TABLE_TYPE IS TABLE OF ML_TYPE;

CREATE TABLE Dock (Name VARCHAR2(20), City  VARCHAR2(20), ML ML_TABLE_TYPE) 
NESTED TABLE ML STORE AS ML_NT;

insert into Dock values ('A', 'NY', ML_TABLE_TYPE(
  ML_TYPE('brand1','L301','Model 2',2013, 1000),
  ML_TYPE('brand2','L101','Model 3',2013, 1000)));

insert into Dock values ('B', 'NY', ML_TABLE_TYPE(
  ML_TYPE('brand3','K301','Model 4',2014, 3000),
  ML_TYPE('brand4','K101','Model 5',2014, 3000)));

insert into Dock values ('A', 'NY', ML_TABLE_TYPE(
  ML_TYPE('brand5','K301','Model 8',2012, 2000),
  ML_TYPE('brand6','L201','Model 9',2012, 2000)));


DELETE FROM Dock WHERE ML_TYPE('L201') MEMBER OF ML;
person Wernfried Domscheit    schedule 06.12.2013
comment
Я все еще получаю сообщение об ошибке, что строка подзапроса (строка 2) не завершена должным образом. Ошибка в строке 2: команда SQL завершилась неправильно. - person user3074445; 06.12.2013
comment
Если я не включаю имя таблицы в оператор удаления, я получаю сообщение об ошибке: Невозможно выполнить DML для выражения или столбца представления вложенной таблицы. - person user3074445; 06.12.2013

Прочитав некоторую литературу, я думаю, что нашел правильный способ сделать это.
Определив функцию сопоставления для вашего типа объекта, вы можете напрямую сравнивать две вложенные таблицы.
Пример:

-- creating the custom object type
create or replace type ml_type as object (
  brand varchar2(100),
  id varchar2(20),
  map member function sort_key return varchar2
);
-- creating the object type body and defining the map-function
create or replace type body ml_type as
    map member function sort_key return varchar2 is
    begin
        return self.brand || '|' || self.id;
    end;
end;
/
-- creating the nested table of custom type
create or replace type ml_tab as table of ml_type;

-- deleting from your table by comparing the nested-table elements
delete from dock where ml = (select ml from dock a, table(a.ml) b where b.id = 'L201');

В этом примере функции карты просто возвращают конкатенированную версию brand и id, но вы можете определить ее так, как вам нужно/нужно.

person Armunin    schedule 06.12.2013
comment
ОШИБКА в строке 2: ORA-04127: однострочный подзапрос возвращает более одной строки - person user3074445; 06.12.2013
comment
Обновленный SQL удалил все мои строки. Все равно нехорошо :) Сейчас это работает так - если есть какая-то запись с ID L201, она удаляет все строки. Если их нет - ничего не происходит. - person user3074445; 06.12.2013
comment
Да, не ожидал;) Рад, что решение @Wernfrieds сработало для вас. Не забудьте отметить его ответ как принятый. - person Armunin; 06.12.2013