【问题标题】:Deleting specific record from nested table Oracle DB从嵌套表 Oracle DB 中删除特定记录
【发布时间】:2013-12-06 12:40:19
【问题描述】:

我在从表 (ORACLE DB) 中删除特定记录时遇到问题。 我有一个表,里面有一个嵌套表。

表结构如下所示:其中 ML - 嵌套表

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

我需要做的是删除 ID 为“L201”的特定记录。

到目前为止我所尝试的:

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

这可以给我所有的 ID。

输出:

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';

抛出错误:

单行子查询返回多行

【问题讨论】:

    标签: oracle nested-table


    【解决方案1】:

    也许这个:

    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;
    

    【讨论】:

    • 我仍然收到子查询行(第 2 行)未正确结束的错误。第 2 行出错:SQL 命令未正确结束。
    • 如果我在删除语句中不包含表名,我会收到这样的错误 - 无法在表达式或嵌套表视图列上执行 DML
    【解决方案2】:

    在阅读了一些文献后,我想我找到了正确的方法。
    通过为您的对象类型定义映射函数,您可以直接比较两个嵌套表。
    示例:

    -- 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');
    

    在此示例中,map-functions 仅返回 brandid 的串联版本,但您可以将其定义为您想要/需要的。

    【讨论】:

    • 第 2 行出现错误:ORA-04127:单行子查询返回多于一行
    • 更新的 SQL 删除了我的所有行。仍然不好:) 现在它的工作原理是这样的——如果有任何 ID 为 L201 的记录,它会删除所有行。如果没有 - 什么都不会发生。
    • 是的,没想到 ;) 很高兴,@Wernfrieds 解决方案对您有用。不要忘记将他的答案标记为已接受。
    猜你喜欢
    • 1970-01-01
    • 2012-04-03
    • 2019-03-08
    • 1970-01-01
    • 2019-11-25
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多