在运行存储过程以获取一些行时,首先我要验证查询是否会在发送结果之前返回一行,第二,如果可以验证而不运行相同的相同验证查询两次。
我正在使用光标存储屈服结果,因此我尝试了光标属性%ROWCOUNT
&%NOTFOUND
。但是没有很大的工作。另外,我想在光标上运行循环的情况。
procedure MODULE_LIST_GK(p_module_Id IN MODULE_LIST.MODULE_ID% TYPE,
p_Error_Code out nvarchar2,
p_Error_Msg out nvarchar2,
p_Cursor out sys_refcursor) IS
BEGIN
OPEN p_Cursor FOR
SELECT A.MODULE_ID,
A.MODULE_NM,
A.AUTH_STATUS_ID
FROM MODULE_LIST A
WHERE A.MODULE_ID=p_module_Id;
SELECT COUNT(MODULE_ID)
INTO v_row_num
FROM MODULE_LIST A
WHERE A.MODULE_ID=p_module_Id;
IF v_row_num=0 THEN
p_Error_Code := SQLCODE;
p_Error_Msg := 'Does not Exists';
Return;
end IF;
EXCEPTION
WHEN OTHERS THEN
p_error_code:= SQLCODE;
p_error_msg := SQLERRM;
END MODULE_LIST_GK;
您的实现有几点可以改进的点。
first 如果您希望对很多参数,返回的光标将为空比首先检查空光标,并且仅在此检查打开光标之后。反之亦然。
如何检查光标是否为空?不幸的是,您必须获取第一行才能验证它。
open l_cur for
select id, status from tab where id = p_id;
fetch l_cur into l_id, l_status;
if l_cur%NOTFOUND then
p_Error_Msg := 'Does not Exists';
Return;
end if;
此检查比经常使用count(*)
仅考虑第一个(几个(行而不是在光标中计数所有行更有效。
如果支票失败了,您准备就绪,另一个简单打开光标并将其返回。
open l_cur for
select id, status from tab where id = p_id;
p_Cursor := l_cur;
想到了另外两个想法。
如果数据库非常动态,则应使用Generall方法。当其他会话删除检查和光标的第二个打开之间时,您将如何处理情况?
最终考虑返回异常而不是返回代码。
为了知道光标是否包含行,您必须打开它并获取第一行。一旦完成此操作,返回光标就再也没有意义了,因为收件人将无法获取第一行,因为光标已经超出了它。
因此,您必须选择两次。您要做的是在此处使用ROWNUM
或EXISTS
子句向DBMS展示您对所有行不感兴趣的DBM。这可以极大地加速查询。
PROCEDURE module_list_gk(p_module_id IN MODULE_LIST.MODULE_ID%TYPE,
p_error_code OUT NVARCHAR2,
p_error_msg OUT NVARCHAR2,
p_cursor OUT SYS_REFCURSOR) IS
v_count INTEGER;
BEGIN
SELECT COUNT(*)
INTO v_count
FROM module_list
WHERE module_id = p_module_Id
AND ROWNUM = 1;
IF v_count = 0 THEN
p_error_code := 0; -- Or -1403 for NO DATA FOUND if you like
p_error_msg := 'Does not Exists';
RETURN;
END IF;
OPEN p_Cursor FOR
SELECT module_id, module_nm, auth_status_id
FROM module_list
WHERE module_id = p_module_id;
EXCEPTION WHEN OTHERS THEN
p_error_code:= SQLCODE;
p_error_msg := SQLERRM;
END module_list_gk;
第一个查询的 sqlcode顺便说一句( SELECT COUNT(*)
返回一行,带有发现的记录数 - 因此没有错误(。这就是为什么您应该决定明确返回零或某些错误代码,例如-1403。
EXISTS
相同:
BEGIN
SELECT CASE WHEN EXISTS
(
SELECT NULL
FROM module_list
WHERE module_id = p_module_Id
) THEN 1 ELSE 0 END
INTO v_count
FROM DUAL;
IF v_count = 0 THEN