2012-11-15 28 views
5

下面的代碼可能會返回多行。 sql%rowcount會返回取得的行數嗎?是否有可能使用sql%rowcount進行SELECT?

select * from emp where empname = 'Justin' and dept='IT' 
if sql%rowcount>0 
    ... 

這是我的樣品過程;我是否正確使用sql%rowcount

CREATE PROCEDURE Procn(in_Hid IN VARCHAR2,outInststatus OUT VARCHAR2,outSockid IN NUMBER,outport OUT VARCHAR2,outIP OUT VARCHAR2,outretvalue OUT NUMBER) 
AS 
BEGIN 
select INST_STATUS into outInststatus from TINST_child where INST_ID = in_Hid and INST_STATUS = 'Y'; 
if outInststatus = 'Y' then 
    select PORT_NUMBER,STATIC_IP into outport,outIP from TINST where INST_ID = in_Hid and IP_PORT_STATUS = 'Y'; 
    if sql%rowcount >= 1 then 
     select SOCK_ID into outSockid from TINST where PORT_NUMBER = outport AND STATIC_IP = outIP; 
     outretvalue := 0; 
    else 
     outretvalue := -12; 
    end if; 
    EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
    outretvalue := -13; 
end if; 
END; 
+1

如果它是作爲標記,那麼你必須選擇到的東西,在這種情況下,你會得到一個'no_data_found'異常,如果行計數爲零,或者'太多rows'如果是大於1的PL/SQL ,所以你可以使用異常處理來處理這個問題;或者使用明確的遊標。我認爲需要更多的背景。 –

+0

@alex我hav更新了我的代碼我發佈了一個示例代碼,我正確使用sql%計數? – user1

+0

否; 'select ... into'(除非你按照Codo的建議批量收集)將總是返回一行,或者拋出異常。想象一下,有兩個匹配的行; 'static_ip'的兩個值中的哪一個會在'outIP'中?只要有一行,你的代碼就會工作,但沒有時會失敗。它是否有效?因爲有多行,如果有的話會發生什麼? –

回答

1

基於您的評論

如果第二個「選擇」查詢返回多行我想利用第一個和它的處理

......這應該工作,但可能不像你期望的那樣,因爲你還沒有定義'第一個'的含義。

CREATE PROCEDURE Procn(in_Hid IN VARCHAR2, outInststatus OUT VARCHAR2, 
    outSockid IN NUMBER, outport OUT VARCHAR2, outIP OUT VARCHAR2, 
    outretvalue OUT NUMBER) 
AS 
BEGIN 
    select INST_STATUS into outInststatus 
    from TINST_child 
    where INST_ID = in_Hid and INST_STATUS = 'Y'; 

    -- no need to check if outInstatus is Y, that's all it can be here 

    -- restricting with `rownum` means you'll get at most one row, so you will 
    -- not get too_many_rows. But it will be an arbitrary row - you have no 
    -- criteria to determine which of the multiple rows you want. And you can 
    -- still get no_data_found which will go to the same exception and set -12 
    select PORT_NUMBER, STATIC_IP into outport, outIP 
    from TINST 
    where INST_ID = in_Hid and IP_PORT_STATUS = 'Y' 
    and rownum < 2; 

    -- no need to check sql%rowcount; it can only be 1 here 

    -- not clear if this can return multiple rows too, and what should happen 
    -- if it can; could use rownum restriction but with the same caveats 
    select SOCK_ID into outSockid 
    from TINST 
    where PORT_NUMBER = outport AND STATIC_IP = outIP; 

    outretvalue := 0; 
EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
     outretvalue := -12; 
END; 

exception處理器適用於整個block。如果任何select語句沒有找到行時,no_data_found例外將由塊進行處理,並將爲outretvalue-12

如果你想爲每個select不同outretvalue那麼你可以用他們的子塊,每一個都有自己的異常處理部分:

CREATE PROCEDURE Procn(in_Hid IN VARCHAR2, outInststatus OUT VARCHAR2, 
    outSockid IN NUMBER, outport OUT VARCHAR2, outIP OUT VARCHAR2, 
    outretvalue OUT NUMBER) 
AS 
BEGIN 
    BEGIN 
     select INST_STATUS into outInststatus 
     from TINST_child 
     where INST_ID = in_Hid and INST_STATUS = 'Y'; 
    EXCEPTION 
     WHEN NO_DATA_FOUND THEN 
      outretvalue := -12; 
    END; 

    BEGIN 
     select PORT_NUMBER, STATIC_IP into outport, outIP 
     from TINST 
     where INST_ID = in_Hid and IP_PORT_STATUS = 'Y' 
     and rownum < 2; 
    EXCEPTION 
     WHEN NO_DATA_FOUND THEN 
      outretvalue := -13; 
    END; 

    BEGIN 
     select SOCK_ID into outSockid 
     from TINST 
     where PORT_NUMBER = outport AND STATIC_IP = outIP; 
    EXCEPTION 
     WHEN NO_DATA_FOUND THEN 
      outretvalue := -14; 
    END; 

    outretvalue := 0; 
END; 

你只需要做的是,如果來電者需要知道這select失敗,如果你從來沒有真正指望其中的任何失敗了,它可能更常見不趕在所有的異常,並讓調用者看到原始no_data_found並決定該怎麼做。取決於異常情況對您和您的應用程序意味着什麼。

+0

但我的要求,從笏完全不同ü解釋1.im檢查是否outInstatus爲Y怎麼我需要允許OLY下一步如果「Y」,它也可能返回「N」 2.我不能用ROWNUM堂妹爲限制我需要多行將進入第二個SELECT QUERY,我需要在結果集中隨機選擇第一行,無需根據任何條件進行選擇。 – user1

+0

@ user1 - 1)由於where子句,它只能是'Y'; 'INST_STATUS'不能同時是'Y'和'N'。 2)我不害怕; '需要多行'和'隨機選擇第一行'(這是的)是矛盾的? –

+0

先生,我的問題是在我上面的代碼,如果第一個SELECT查詢返回的「Y」,則沒有PBLM ITLL過程中,如果stmnt.If返回「無數據」它會去exception.If返回「N」其中,LL條件LL根據proc我worte去下? – user1

6

是的,你可以使用SQL%ROWCOUNT。它在PL/SQL中有效。

但是,在PL/SQL中,查詢的結果需要放在某處到PL/SQL表中。 PL/SQL永遠不會將結果發送到輸出(終端,窗口等)。所以SELECT * FROM將無法​​正常工作。

您的代碼看起來是這樣的:

DECLARE 
    TYPE emp_t ...; 
    emp_tab emp_t; 

BEGIN 
    SELECT * 
    BULK COLLECT INTO emp_tab 
    FROM emp 
    WHERE empname = 'Justin' AND dept='IT'; 

    IF sql%rowcount > 0 THEN 
    .. do something ... 
    END IF; 
END; 
/

更新

更新的問題,建議您正在尋找別的東西。

選項1:使用例外

如果有0行或大於1行,這些情況分別處理(如錯誤):

BEGIN 
    select PORT_NUMBER,STATIC_IP into outport, outIP 
    from TINST 
    where INST_ID = in_Hid AND IP_PORT_STATUS = 'Y'; 

EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
    outretvalue := -12; 
    RETURN; 

    WHEN TOO_MANY_ROWS THEN 
    outretvalue := -13; 
    RETURN; 
END; 

選項2:使用聚合

使用聚合,查詢將始終返回一行。如果現在源行匹配WHERE子句,那麼兩個結果值都將爲NULL。如果WHERE子句匹配多個行,則會取最大值。

請注意,此查詢可能會返回最初不在同一行上的端口號和IP地址。

select MAX(PORT_NUMBER), MAX(STATIC_IP) into outport, outIP 
from TINST 
where INST_ID = in_Hid AND IP_PORT_STATUS = 'Y'; 

IF outport IS NULL OR outIP IS NULL THEN 
    outretvalue := -12; 
    RETURN; 
END IF; 

選項3:使用ROWNUM

該查詢返回最多一行。如果沒有行匹配WHERE子句,拋出一個異常,需要進行處理:

BEGIN 
    select PORT_NUMBER, STATIC_IP into outport, outIP 
    from TINST 
    where INST_ID = in_Hid AND IP_PORT_STATUS = 'Y' 
    AND ROWNUM = 1; 

EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
    outretvalue := -12; 
    RETURN; 

END; 
+0

會的sql%的行數收益> 1。你不會從這裏得到'too_many_rows'或'no_data_found'。當你進行批量收集時,'sql%rowcount'將具有行數;儘管我通常會引用'emp_tab.count'來查看包含的數量 - 因爲'sql%count'引用了最後一個查詢,它只會短暫有用,而'emp_tab.count'將保持正確。 – user1

+1

@ user1的 –

相關問題