新手求助各位老师,一个ORACLE 存储过程写法,不大明白为什么老报语法错误

TS败类 2018-10-15 11:07:09
求助一下各位老师,新手在学习过程中遇到一个小功能想自己实现一下 功能:删除父文件情况下子文件行一并删除,因此设计了一个存储过程迭代。不明白为什么老是报语法错误,之前是按mysql写的,后来觉得会不会是mysql 8版本的改动问题,因此重新按ORACLE写了一次,还是出错。希望各位老师能帮忙看一下哪里错了。手边能查的资料全部查过了,实在是走投无路了,谢谢各位老师了。
大体思路如图父过程创建一张临时表,子过程每次执行都将自己本行的名字写入临时表,父过程在调用子过程迭代完成后删除临时表里面所有内容就完成了功能



CREATE OR REPLACE PROCEDURE delete_folder(folder_name_to_delete IN VARCHAR(50))
IS
DECLARE done BOOLEAN DEFAULT 0;
next_delete VARCHAR(50);
CURSOR temp_list_cursor IS
SELECT folder_name
FROM
temp_middle_list;
BEGIN
CREATE TEMPORARY TABLE temp_middle_list(folder_name VARCHAR(50));
EXECUTE findChildList(folder_name_to_delete);
OPEN temp_list_cursor;
LOOP
FETCH temp_list_cursor INTO next_delete;
DELETE FROM folder_delete WHERE folder_delete.file_name = temp_middle_list.folder_name;
EXIT WHEN temp_list_cursor%notfound;
END LOOP;
close temp_list_cursor;
END delete_folder;


CREATE OR REPLACE PROCEDURE findChildList(folder_name_to_delete IN VARCHAR(50))
IS
DECLARE out INT DEFAULT 0;
iterator_element VARCHAR(50);
CURSOR list_cursor IS
SELECT file_name
FROM
folder_delete
WHERE
parent_name = folder_name_to_delete;
BEGIN
INSERT INTO temp_middle_list VALUES(folder_name_to_delete);
OPEN list_cursor;
LOOP
FETCH list_cursor INTO iterator_element;
EXECUTE findChildList(iterator_element);
EXIT WHEN list_curso%notfound;
END LOOP;
CLOSE list_cursor;
END findChildList;
...全文
361 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
卖水果的net 2018-10-20
  • 打赏
  • 举报
回复
10楼的回复,就是解决死循环的。你跑一下没有问题的。
TS败类 2018-10-19
  • 打赏
  • 举报
回复
引用 9 楼 wmxcn2000 的回复:

CREATE OR REPLACE PROCEDURE findChildList(folder_name_to_delete IN VARCHAR) IS
iterator_element VARCHAR(50);
CURSOR list_cursor is
SELECT file_name
FROM folder_delete
WHERE parent_name = folder_name_to_delete;
BEGIN
INSERT INTO temp_middle_list VALUES (folder_name_to_delete);
OPEN list_cursor;
LOOP
FETCH list_cursor INTO iterator_element;
EXIT WHEN list_cursor%notfound; -- 这两行交换了一下
findChildList(iterator_element); -- 这两行交换了一下
END LOOP;
CLOSE list_cursor;
END findChildList;
/


非常感谢老师的解答,我忘了说了,我昨天就一经发现那个会进入无限循环,已经改过了WHILE循环,后面会贴出子过程,但是无论是自己的还是老师今天给出的代码还是无法按预期删掉所有行数据,调试中任然没有跳到子过程,临时表任然没有数据,后来我试过在临时表中手动装填数据,按照会话级临时表的意思应该就算不调用子过程任然能删除所有数据,但是还是没有删除,不大明白为什么,辛苦老师了,这个问题困扰我好多天了,如果老师能给出解决方案真的非常感谢

CREATE OR REPLACE PROCEDURE findChildList(folder_name_to_delete IN VARCHAR) IS
iterator_element VARCHAR(50);
CURSOR list_cursor is
SELECT file_name
FROM folder_delete
WHERE parent_name = folder_name_to_delete;
BEGIN
dbms_output.put_line('准备添加到临时表中:'||folder_name_to_delete);
INSERT INTO temp_middle_list VALUES (folder_name_to_delete);
dbms_output.put_line('添加完成:'||folder_name_to_delete);
OPEN list_cursor;
WHILE list_cursor%found LOOP--我这里用的是while 游标存在
FETCH list_cursor
INTO iterator_element;
findChildList(iterator_element);
END LOOP;--这里结束循环,应该也是OK的
CLOSE list_cursor;
END findChildList;
/
卖水果的net 2018-10-19
  • 打赏
  • 举报
回复
1、你需要学习一下 SQL 和 PLSQL 的基础知识 2、把你的数据贴上来。 要 create table 和 insert 的,不要发文本或图片。
卖水果的net 2018-10-19
  • 打赏
  • 举报
回复

CREATE OR REPLACE PROCEDURE findChildList(folder_name_to_delete IN VARCHAR) IS
  iterator_element VARCHAR(50);
  CURSOR list_cursor is
    SELECT file_name
      FROM folder_delete
     WHERE parent_name = folder_name_to_delete;
BEGIN
  INSERT INTO temp_middle_list VALUES (folder_name_to_delete);
  OPEN list_cursor;
  LOOP
    FETCH list_cursor INTO iterator_element;
    EXIT WHEN list_cursor%notfound; -- 这两行交换了一下
    findChildList(iterator_element); -- 这两行交换了一下
  END LOOP;
  CLOSE list_cursor;
END findChildList;
/

TS败类 2018-10-19
  • 打赏
  • 举报
回复
引用 7 楼 wmxcn2000 的回复:
1、你需要学习一下 SQL 和 PLSQL 的基础知识
2、把你的数据贴上来。 要 create table 和 insert 的,不要发文本或图片。

再次感谢老师的耐心解答,我会去好好看一下基础的,我把建表插入表和建临时表的语句贴上来,辛苦老师了

CREATE TABLE IF NOT EXISTS folder_delete
(
file_id int NOT NULL PRIMARY KEY,
file_name varchar(50) NOT NULL,
file_type int NOT NULL,
parent_name varchar(50)
);

INSERT ALL INTO folder_delete
VALUES
('1','A','1','C')
INTO folder_delete
VALUES
('2','B','1','NULL')
INTO folder_delete
VALUES
('3','C','1','B')
INTO folder_delete
VALUES
('4','D','0','A')
INTO folder_delete
VALUES
('5','E','0','A')
select 1 from dual;

下面是临时表
CREATE GLOBAL TEMPORARY TABLE temp_middle_list (folder_name VARCHAR(50)) ON PRESERVE DELETE ROWS;
TS败类 2018-10-18
  • 打赏
  • 举报
回复
引用 5 楼 wmxcn2000 的回复:
你的问题太多了,我给你改了。你参考一下。
-- 先创建 findChildList ,再创建 delete_folder
-
CREATE OR REPLACE PROCEDURE findChildList(folder_name_to_delete IN VARCHAR) IS
iterator_element VARCHAR(50);
CURSOR list_cursor is
SELECT file_name
FROM folder_delete
WHERE parent_name = folder_name_to_delete;
BEGIN
INSERT INTO temp_middle_list VALUES (folder_name_to_delete);
OPEN list_cursor;
LOOP
FETCH list_cursor
INTO iterator_element;
findChildList(iterator_element);
EXIT WHEN list_cursor%notfound;
END LOOP;
CLOSE list_cursor;
END findChildList;
/

CREATE OR REPLACE PROCEDURE delete_folder(folder_name_to_delete IN VARCHAR) IS
-- done BOOLEAN := 0;
next_delete VARCHAR(50);
BEGIN
findChildList(folder_name_to_delete);
DELETE FROM folder_delete
WHERE folder_delete.file_name in
(select folder_name from temp_middle_list);
END delete_folder;
/

首先再次感谢老师给我的解答,我反复测试了找出了所有引起报错的问题,目前还有几个疑惑
1.为什么变量直接声明就可以用了,加上DECLARE反而报错呢,这个写法我看很多书上,网页上都在这么写我照猫画虎画下来的,不大理解为啥这里不可以
2.调用另外一个存储过程为什么不可以EXECUTE 过程名或者CALL 过程名而可以直接写过程名调用呢
3.我在测试这个过程的时候发现正常结束,但是没有按照预计功能删除我的测试数据,单步调试时候发现并不能跳转到另外一个程序去,而且临时表我后来就算改成了会话级别(按道理应该里面会有内容,就是删除的目标),里面还是空表,所以我觉得可能是这个过程没有成功调用另一个子过程,可是我现在并不知道为什么,麻烦老师能给一些指点吗

下面附上我的测试
卖水果的net 2018-10-18
  • 打赏
  • 举报
回复
你的问题太多了,我给你改了。你参考一下。 -- 先创建 findChildList ,再创建 delete_folder - CREATE OR REPLACE PROCEDURE findChildList(folder_name_to_delete IN VARCHAR) IS iterator_element VARCHAR(50); CURSOR list_cursor is SELECT file_name FROM folder_delete WHERE parent_name = folder_name_to_delete; BEGIN INSERT INTO temp_middle_list VALUES (folder_name_to_delete); OPEN list_cursor; LOOP FETCH list_cursor INTO iterator_element; findChildList(iterator_element); EXIT WHEN list_cursor%notfound; END LOOP; CLOSE list_cursor; END findChildList; / CREATE OR REPLACE PROCEDURE delete_folder(folder_name_to_delete IN VARCHAR) IS -- done BOOLEAN := 0; next_delete VARCHAR(50); BEGIN findChildList(folder_name_to_delete); DELETE FROM folder_delete WHERE folder_delete.file_name in (select folder_name from temp_middle_list); END delete_folder; /
TS败类 2018-10-17
  • 打赏
  • 举报
回复
引用 2 楼 minsic78 的回复:
过程中的DDL语句需要用动态SQL来执行他们~

老师好,谢谢老师能回复,这两天太忙了,才有空再动手试一下但是我还是没太查到应该怎么理解,能说的具体一点吗,谢谢老师了
TS败类 2018-10-17
  • 打赏
  • 举报
回复
引用 1 楼 wmxcn2000 的回复:
CREATE TEMPORARY TABLE temp_middle_list(folder_name VARCHAR(50));

创建临时表,不能在存储过程中这样定义。 要先把这张表创建好,存储过程直接调用就可以了,和正常的表操作是一样的。


老师好,谢谢老师能回复,这两天忙实习,早就看到了,晚上才找了个机会按照老师说的方法实践了一下,创建了一个事务级别的临时表,成功了。但是发现过程还是报错,又检查了一下并没有发现明显错误,还请老师指点,非常感谢!!。下面会贴上截图和代码
先建一张事务级别临时表


CREATE GLOBAL TEMPORARY TABLE temp_middle_list (folder_name VARCHAR(50)) ON COMMIT DELETE ROWS;

下面是主过程的(我发现主过程并不需要游标,于是去掉了)

CREATE OR REPLACE PROCEDURE delete_folder(folder_name_to_delete IN VARCHAR(50))
IS
DECLARE done BOOLEAN DEFAULT 0;
next_delete VARCHAR(50);
BEGIN
EXECUTE findChildList(folder_name_to_delete);
DELETE FROM folder_delete WHERE folder_delete.file_name = temp_middle_list.folder_name;
END delete_folder;

下面是子过程的

CREATE OR REPLACE PROCEDURE findChildList(folder_name_to_delete IN VARCHAR(50))
IS
DECLARE out INT DEFAULT 0;
iterator_element VARCHAR(50);
CURSOR list_cursor IS
SELECT file_name
FROM
folder_delete
WHERE
parent_name = folder_name_to_delete;
BEGIN
INSERT INTO temp_middle_list VALUES(folder_name_to_delete);
OPEN list_cursor;
LOOP
FETCH list_cursor INTO iterator_element;
EXECUTE findChildList(iterator_element);
EXIT WHEN list_curso%notfound;
END LOOP;
CLOSE list_cursor;
END findChildList;
卖水果的net 2018-10-16
  • 打赏
  • 举报
回复
CREATE TEMPORARY TABLE temp_middle_list(folder_name VARCHAR(50)); 创建临时表,不能在存储过程中这样定义。 要先把这张表创建好,存储过程直接调用就可以了,和正常的表操作是一样的。
minsic78 2018-10-16
  • 打赏
  • 举报
回复
过程中的DDL语句需要用动态SQL来执行他们~

17,086

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧