无法使用oracle中的游标在表中插入记录
Posted
技术标签:
【中文标题】无法使用oracle中的游标在表中插入记录【英文标题】:Not able to insert the records in table using cursor in oracle 【发布时间】:2020-04-16 17:34:08 【问题描述】:我想使用cursor
将记录插入到表中。所以下面是相同的查询。
CREATE OR REPLACE PROCEDURE FIBER_TRANSM_VALID_DATA
AS
BEGIN
DECLARE
SPANID NVARCHAR2(50);
MZONENAME NVARCHAR2(50);
CURSOR CR_SPAN_VALID_DATA IS
SELECT RJ_SPAN_ID, RJ_MAINTENANCE_ZONE_NAME
FROM APP_FTTX.transmedia@SAT
WHERE LENGTH(RJ_SPAN_ID) = 21
AND INVENTORY_STATUS_CODE = 'IPL'
AND REGEXP_LIKE(rj_span_id, 'SP(N|Q|R|S).*_(BU|MP)$')
AND RJ_MAINTENANCE_ZONE_CODE IN ('INMUNVMB01')
AND ROWNUM < 11;
BEGIN
OPEN CR_SPAN_VALID_DATA;
LOOP
FETCH CR_SPAN_VALID_DATA INTO SPANID, MZONENAME;
EXIT WHEN CR_SPAN_VALID_DATA%NOTFOUND;
IF SPANID > 0
THEN
BEGIN
INSERT INTO TBL_FIBER_VALID_TRANS_DATA (RJ_SPAN_ID, RJ_MAINTENANCE_ZONE_NAME)
VALUES (SPANID, MZONENAME);
END;
END IF;
COMMIT;
END LOOP;
CLOSE CR_SPAN_VALID_DATA;
END;
END FIBER_TRANSM_VALID_DATA;
但我收到错误
错误(36,13): PL/SQL: SQL 语句被忽略 错误(36,65):PL/SQL:ORA-00904:“RJ_MAINTENANCE_ZONE_NAME”:标识符无效
更新
表结构如下
SPAN_ID NVARCHAR2(50)
MAINTENANCE_ZONE_NAME NVARCHAR2(50)
MAINTENANCE_ZONE_CODE NVARCHAR2(50)
R4G_STATE_NAME NVARCHAR2(50)
STATE_NAME NVARCHAR2(50)
NETWORK_CATEGORY NVARCHAR2(100)
NETWORK_TYPE NVARCHAR2(100)
CONSTRUCTION_METHODOLOGY NVARCHAR2(50)
INVENTORY_STATUS_CODE NVARCHAR2(20)
OWNERSHIP_TYPE_CODE NVARCHAR2(20)
ROUTE_NAME NVARCHAR2(100)
INTRACITY_LINK_ID NVARCHAR2(100)
CALCULATED_LENGTH NUMBER(38,8)
LAST_UPDATED_BY NVARCHAR2(100)
LAST_UPDATED_DATE DATE
【问题讨论】:
当 SQL> desc TBL_FIBER_VALID_TRANS_DATA 发出时你会得到什么。 @BarbarosÖzhan:表格的结构,由其他几列组成 我的意思是表中是否包含名为RJ_MAINTENANCE_ZONE_NAME
的列,您确定表中存在该列吗?
@BarbarosÖzhan 让我再次检查并在此处发布表结构
@BarbarosÖzhan:很抱歉这是我的专栏错误
【参考方案1】:
如果它必须是游标循环,请参见另一种方法 - 游标FOR
循环。它更容易编写和维护,因为 Oracle 为您做了大部分事情,即您不必显式声明游标和游标变量,打开它,从中获取,注意何时退出循环,关闭光标。所有肮脏的工作都是为你完成的。
您所要担心的是,您编写的select
实际上返回了一些行,因为我已经看到您写的评论 - 尽管过程已编译,但它没有插入任何行。由于我们没有您的数据,因此我们无能为力。
给你(假设表和列确实存在):
create or replace procedure fiber_transm_valid_data as
begin
for cur_r in (select rj_span_id,
rj_maintenance_zone_name
from app_fttx.transmedia@sat
where length(rj_span_id) = 21
and inventory_status_code = 'IPL'
and regexp_like(rj_span_id, 'SP(N|Q|R|S).*_(BU|MP)$')
and rj_maintenance_zone_code in ('INMUNVMB01')
)
loop
if cur_r.rj_span_id > '0' then
insert into tbl_fiber_valid_trans_data
(span_id, maintenance_zone_name)
values (cur_r.rj_span_id, cur_r.rj_maintenance_zone_name);
end if;
end loop;
end fiber_transm_valid_data;
还有一些注意事项:不要在循环中使用COMMIT
,因为它会导致问题(例如 snapshot too old 错误)。考虑将其完全移出过程,让调用者决定是否提交。
你真的执行了这个过程吗?您确实创建了它,但是 - 如果您从未调用过它,这可能是您看不到插入任何行的原因。所以:
begin
fiber_transm_valid_data ;
end;
/
【讨论】:
感谢 littlefoot 的回答。我一定会尝试您的代码并测试它是否相应地工作。给我一些时间,我会相应地更新你 我在运行它时遇到了这个错误ORA-06502: PL/SQL: numeric or value error: character to number conversion error ORA-06512: at "APP_FIBERINV.FIBER_TRANSM_VALID_DATA", line 12 ORA-06512: at line 2
是因为这行:if cur_r.rj_span_id > 0
。 RJ_SPAN_ID 似乎是 VARCHAR2(字符串),因此您无法将其与 0(零,数字)进行比较。将其修改为 if cur_r.rj_span_id > '0'
(将 0 括在单引号中)可修复 this 错误,但是 - 我不知道这是否是您真正想要做的事情。
是的,这就是原因,现在错误消失了,所以在运行后我测试了表,仍然没有插入记录,我应该删除那个 if 条件并检查吗?
您确保select
返回任何结果吗?【参考方案2】:
您的整个 PL/SQL 代码可以用简单的INSERT INTO..SELECT
编写。无需遍历游标中的每条记录,只需在普通 SQL 中执行即可:
INSERT INTO TBL_FIBER_VALID_TRANS_DATA
(SPAN_ID, MAINTENANCE_ZONE_NAME)
SELECT RJ_SPAN_ID, RJ_MAINTENANCE_ZONE_NAME
FROM APP_FTTX.transmedia@SAT
WHERE LENGTH(RJ_SPAN_ID) = 21
AND INVENTORY_STATUS_CODE = 'IPL'
AND REGEXP_LIKE(rj_span_id, 'SP(N|Q|R|S).*_(BU|MP)$')
AND RJ_MAINTENANCE_ZONE_CODE IN ('INMUNVMB01')
AND ROWNUM < 11
AND SPAN_ID > 0; --> This is the check you are using in your PL/SQL code
AND ROWNUM
我希望您知道ROWNUM
只会为您提供它获取的随机行,除非您特别提及ORDER BY
,否则它不会按任何特定顺序排列,然后在其上应用rownum。在您的代码中,您将获得10
随机行。要了解更多信息,请参阅How ROWNUM works。
【讨论】:
感谢 lalit 的回答,但我想用光标来做,可以吗?我快完成了。我想是因为当我删除 ROWNUM 部分时,你回答的方式花费了太多时间 @nkb SQL 总是比 PL/SQL 快。如果您仍想使用游标在 PL/SQL 中逐行执行,也就是逐行缓慢,请使用FORALL
语句查看 BULK COLLECT
。关于ROWNUM
,看我给的链接。以上是关于无法使用oracle中的游标在表中插入记录的主要内容,如果未能解决你的问题,请参考以下文章