Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle PL/SQL:如何删除一行,然后使用管道将其输出?_Sql_Oracle_Plsql_Dml - Fatal编程技术网

Oracle PL/SQL:如何删除一行,然后使用管道将其输出?

Oracle PL/SQL:如何删除一行,然后使用管道将其输出?,sql,oracle,plsql,dml,Sql,Oracle,Plsql,Dml,我有一个包裹: CREATE OR REPLACE PACKAGE pkg_location IS TYPE dep_row IS RECORD (id departments.department_id%TYPE, name departments.department_name%TYPE); TYPE dep_table IS TABLE OF dep_row; FUNCTION drop_departments (v_city_title IN VARCHAR2)

我有一个包裹:

CREATE OR REPLACE PACKAGE pkg_location IS
    TYPE dep_row IS RECORD (id departments.department_id%TYPE, name departments.department_name%TYPE);
    TYPE dep_table IS TABLE OF dep_row;
    FUNCTION drop_departments (v_city_title IN VARCHAR2) RETURN dep_table PIPELINED;
END pkg_location; 
我需要实现
drop\u departments
功能,该功能通过
city
departments
表中删除行,并使用管道输出删除的部门数据

但我真的不知道从哪里开始。你能帮帮我吗

表结构:

DEPARTMENTS: DEPARTMENT_ID (NUMBER) | DEPARTMENT_NAME (VARCHAR 40) | LOCATION_ID (NUMBER)
LOCATIONS:   LOCATION_ID (NUMBER)   | CITY (VARCHAR 40)
您需要3个步骤:

  • 将要删除的所有记录保存到与函数类型相同的本地表中
  • 删除记录
  • 返回您保存的集合(不必使用管道连接)
管道函数存在问题-在选择过程中,无法从表中选择*(my_pipe_函数)并在函数内部执行删除(DML)操作

为了避免删除内部函数的问题,您需要更改逻辑,不使用管道,或者需要在
自治事务中删除记录

参见下面的3个示例

insert into departments(id , department_id , department_name , city_title ) values(1, 1, '1', 'City-1');
insert into departments(id , department_id , department_name , city_title )  values(2, 2, '2', 'City-1');
insert into departments(id , department_id , department_name , city_title )  values(3, 2, '3', 'City-2');
带有
管道的示例1

    CREATE OR REPLACE PACKAGE BODY pkg_location IS
    FUNCTION drop_departments (v_city_title IN VARCHAR2) RETURN dep_table PIPELINED
    is
      tblResult dep_table;
    begin

      --delete the records and save deleted records
      delete from departments 
              where city_title = v_city_title
      RETURNING department_id, department_name 
      BULK COLLECT INTO tblResult;

      --return list of deleted records        
      for i in tblResult.FIRST .. tblResult.LAST loop
        pipe row (tblResult(i));
      end loop;
    end;
END pkg_location;
但是你不能像这样使用smth
从表中选择*(包装位置。放置部门('City-1'))

样本2-我已移除管道

CREATE OR REPLACE PACKAGE BODY pkg_location IS
    FUNCTION drop_departments (v_city_title IN VARCHAR2) RETURN dep_table 
    is
      tblResult dep_table;
    begin

      --delete the records and save deleted records
      delete from departments 
              where city_title = v_city_title
        RETURNING department_id, department_name 
        BULK COLLECT INTO tblResult;

      --return list of deleted records        
      return tblResult;
  end;      
END pkg_location;
现在您可以这样使用该函数:

declare
  tbl pkg_location.dep_table;
begin
  tbl := pkg_location.drop_departments('City-1');

  for i in tbl.first .. tbl.last loop
    dbms_output.put_line(tbl(i).name);
  end loop;
end;
输出将为1和2

示例3-使用
自主交易

CREATE OR REPLACE PACKAGE BODY pkg_location IS

    FUNCTION drop_departments (v_city_title IN VARCHAR2) RETURN dep_table PIPELINED    
    is
    --it let you use the function in select * from table(f)
    PRAGMA AUTONOMOUS_TRANSACTION;
      tblResult dep_table;
    begin
      --delete the records and save deleted records
      delete from departments 
              where city_title = v_city_title
       returning department_id, department_name 
      bulk collect into tblResult;

      --you must do the commit before pipe row ()
      commit;

      --return list of deleted records        
      for i in tblResult.FIRST .. tblResult.LAST loop
        pipe row (tblResult(i));
      end loop;
    end;
END pkg_location;
现在你可以使用

select * from table(pkg_location.drop_departments('City-1'))
结果将是:

1   1   1
2   2   2

删除之前的选择是不必要的,并且可能存在并发问题。您可以使用
DELETE departments WHERE city\u title=v\u city\u title RETURNING department\u id,department\u name BULK COLLECT to tblResult将删除的记录输出到集合中流水线版本没有问题,它也可以使用自治事务。您只需要在管道行之前发出commit,因为这会生成一个值,并将函数保留到需要下一条记录为止,并且必须在保留函数作用域之前提交/回滚自治事务。但在这种情况下,返回集合的非管道方法是最好的。这是最少的代码量,您可以为所有已删除的记录分配内存,因此迭代并生成固定集合是没有意义的。