2016-01-11 103 views
0

我有以下存儲過程:MySQL的存儲過程只返回一個選擇查詢

CREATE PROCEDURE `Get_Events_And_Deadlines_By_User`(IN `intervalStart` INT, IN `intervalEnd` INT) 
    BEGIN 
     IF (intervalStart != 0 AND intervalEnd != 0) THEN 
      SELECT 1 AS `test`; 
     ELSEIF (intervalStart != 0 AND intervalEnd = 0) THEN 
      BEGIN 
       SELECT 2 AS `test`; 
       IF ((SELECT FOUND_ROWS())=1) THEN 
        SELECT 3 AS `test`; 
       END IF; 
      END; 
     ELSE 
      SELECT 4 AS `test`; 
     END IF; 
    END 

當我運行call Get_Events_And_Deadlines_By_User(1,0)我只能獲得結果是該選擇查詢,選擇裏面的if語句從未返回。看起來在存儲過程返回之前,只有遇到的第一個選擇查詢正在執行。爲什麼是這樣?我能做些什麼來解決這個問題?我希望if語句中的select查詢是if語句的唯一結果。

+0

你可以發佈你的PHP代碼嗎?該過程返回多個結果集在2個選擇和你的代碼需要環通不僅記錄每個結果集,但通的多個結果 – vmachan

+0

@vmachan我實際上沒有任何PHP代碼,現在,我只去過在phpmyadmin中進行測試,並從第一個查詢(在'if'語句之前)只獲取一個結果集。 –

+0

更改:IF((SELECT FOUND_ROWS())== 1)THEN' by IF((SELECT FOUND_ROWS())= 1)THEN'。 – wchiquito

回答

0

您的過程返回多個resulsets。
PDO:

<?php 
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'localonly', 'localonly', array(
    PDO::ATTR_EMULATE_PREPARES=>false, 
    PDO::MYSQL_ATTR_DIRECT_QUERY=>false, 
    PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION 
)); 

$result = $pdo->query('Call Get_Events_And_Deadlines_By_User(1,0)'); 
do { 
    foreach($result as $row) { 
     echo join(', ', $row), "\r\n"; 
    } 
    echo "-----\r\n"; 
} while($result->nextRowset()); 
+0

@VolkerV謝謝你的回答!有沒有什麼辦法可以從存儲過程中返回第二個查詢? –

+0

是的,只是跳過第一個。 – VolkerK

+0

什麼是實際查詢來代替'SELECT 2 AS \'test \';'?你可能更容易使用'SELECT Count(*)INTO @nmrows FROM tablename WHERE ....',然後檢查@nmrows – VolkerK

0

我的測試:

mysql> DELIMITER $$ 

mysql> DROP PROCEDURE IF EXISTS `Get_Events_And_Deadlines_By_User`$$ 
Query OK, 0 rows affected, 1 warning (0,00 sec) 

mysql> CREATE PROCEDURE `Get_Events_And_Deadlines_By_User`(
    ->  IN `intervalStart` INT, 
    ->  IN `intervalEnd` INT 
    ->) 
    -> BEGIN 
    ->  IF (intervalStart != 0 AND intervalEnd != 0) THEN 
    ->   SELECT 1 AS `test`; 
    ->  ELSEIF (intervalStart != 0 AND intervalEnd = 0) THEN 
    ->   SELECT 2 AS `test`; 
    ->   IF ((SELECT FOUND_ROWS())=1) THEN 
    ->    SELECT 3 AS `test`; 
    ->   END IF; 
    ->  ELSE 
    ->   SELECT 4 AS `test`; 
    ->  END IF; 
    -> END$$ 
Query OK, 0 rows affected (0,00 sec) 

mysql> DELIMITER ; 

mysql> CALL `Get_Events_And_Deadlines_By_User`(1, 0); 
+------+ 
| test | 
+------+ 
| 2 | 
+------+ 
1 row in set (0,00 sec) 

+------+ 
| test | 
+------+ 
| 3 | 
+------+ 
1 row in set (0,00 sec) 

Query OK, 0 rows affected (0,00 sec) 

後:Retrieving Multiple Result sets with stored procedure in php/mysqli

0

問:我只得到2的select查詢作爲結果,if語句內的select從不返回。看起來在存儲過程返回之前,只有遇到的第一個選擇查詢正在執行。爲什麼是這樣?

答:第二個結果集被程序返回。客戶端負責請求第二個(和後續)結果集。 (在PHP中,這將需要調用的mysqli mysqli_next_result,或PDO nextRowset功能,這取決於你所使用的接口庫

但是,這似乎並沒有成爲你真正的問題

Q值。:我能做些什麼來解決這個

?答:。這真的取決於你想要達到什麼樣的行爲,這是可能的一個過程返回多個結果,併爲客戶處理他們

問:我希望選擇查詢INSIDE if語句是當if成立時的唯一結果。

答:你想運行一個查詢(在SELECT 2的例子程序查詢),但你不想程序返回的,作爲一個結果。您只想知道查詢返回的行數,並根據返回的行數有條件地控制存儲程序中的流量。

有幾種結構可以用來實現這一點。可以在沒有的程序內運行查詢,該查詢具有作爲結果集返回的該查詢的結果。


測試「大於零」行與SELECT EXISTS (subquery)

我懷疑你真的不希望使用FOUND_ROWS功能;我懷疑你不想測試發現的行數是否完全等於1.

如果你試圖實現的是確定一個特定的查詢是否會返回一個或多個行,你可以使用像這樣的模式:

 IF (SELECT EXISTS (SELECT 2 AS `test`)) THEN 
     SELECT 2 AS `test`; 
     ELSE 
     SELECT 3 AS `test`; 
     END IF; 

鑑於在示例代碼的查詢,保證你正在努力實現什麼恰好返回一個行,我只是猜測。

如果您有查詢,並且您想查看該查詢是否返回一行,則可以將其包裝在條件中,該條件將返回布爾值。

EXISTS(subquery)如果子查詢返回至少一行,則返回值1;如果子查詢沒有返回行,則返回0。

該構造可以在IF內用於控制存儲程序內的邏輯流程。

IF (SELECT EXISTS(subquery)) THEN 
     -- subquery returned at least one row, so do something 
    ELSE 
     -- subquery didn't return any rows, so do something else 
    END IF; 

獲得與SELECT COUNT(1) INTO FROM (subquery) q

行的確切數量。如果從一個子查詢測試行的「存在」是不夠的;如果出於某種原因需要獲取子查詢返回的行數確切的,則可以使用COUNT()聚合。例如:

SELECT COUNT(1) FROM (subquery) q 

爲了避免從該查詢從過程一個結果返回結果,可以分配由返回到過程變量或用戶定義的變量的值。假設您已經聲明在程序頂部的過程變量,像這樣:

DECLARE myrowcount INT; 

你可以做這樣的事情:

SELECT COUNT(1) INTO myrowcount FROM (subquery) q 
    IF (myrowcount = 1) THEN 
     -- subquery returned exactly one row 
    ELSE 
     -- subquery either returned zero rows, or returned more than one row 
    END IF; 

用戶定義的變量來代替使用的程序變量。我的首選是使用一個過程變量,如果沒有必要在執行該過程之後保留那些行數。

(使用用戶定義變量的最大缺點是它引入了不必要的模糊性,稍後有人閱讀代碼時會想知道在過程結束後實際是否需要存儲在用戶定義變量中的值。他們不知道這是程序的有意的,故意的副作用,還有別的依賴。在我看來,避免含糊不清是使用程序變量的充分理由。)

0

根據您提到的內容在目前爲止的評論中,我認爲你正在尋找下面的東西。我所做的只是增加一個新的參數爲輸出到你的過程和,而不是使用SELECT填寫測試值,我用一個變量發送從外到你的函數,並從外部接收更新的價值和使用SELECT @test獲得你的價值和它將只有一個值,而不是兩個。

如果您有關於我離開的程序註釋的問題,我建議你閱讀更多關於FOUND_ROWS() usage

DELIMITER $$ 
DROP PROCEDURE IF EXISTS `Get_Events_And_Deadlines_By_User` $$ 

CREATE PROCEDURE `Get_Events_And_Deadlines_By_User`(
     IN `intervalStart` INT, 
     IN `intervalEnd` INT, 
     OUT `test` INT 
    ) 
    BEGIN 
     IF (intervalStart != 0 AND intervalEnd != 0) THEN 
      SET test = 1; 
     ELSEIF (intervalStart != 0 AND intervalEnd = 0) THEN 
      BEGIN 
       SET test = 2; 
       # include your select query here, 
       # as you need if for FOUND_ROWS(), or 
       # it will always return 1 cause there is no successful 
       # SELECT query before it and it will be always 1. 
       SELECT * FROM someTable; 
       IF ((SELECT FOUND_ROWS())=1) THEN 
        SET test = 3; 
       END IF; 
      END; 
     ELSE 
      SET test = 4; 
     END IF; 
    END$$ 
DELIMITER ; 

CALL Get_Events_And_Deadlines_By_User(1,0,@test); 
SELECT @test; 

我希望它有幫助。