2011-11-24 20 views
4

我正在寫一個簡單的MySQL存儲過程:如何防止存儲過程的用戶傳遞null?

DELIMITER $ 
DROP PROCEDURE IF EXISTS GetUserByCaseId $ 
CREATE DEFINER = 'DEV_Organization'@'localhost' 
PROCEDURE GetUserByCaseId (IN searchedForId VARCHAR(8)) 
    LANGUAGE SQL NOT DETERMINISTIC READS SQL DATA SQL SECURITY DEFINER 
BEGIN 
    SELECT 
    CaseIdAuthenticator.sid AS sid, 
    CaseIdAuthenticator.caseId AS caseId, 
    User.firstName AS firstName, 
    User.lastName AS lastName, 
    User.position AS position, 
    User.email AS email 
    FROM CaseIdAuthenticator 
    INNER JOIN User ON User.sid = CaseIdAuthenticator.sid 
    WHERE CaseIdAuthenticator.caseId = searchedForId 
    LIMIT 1; 
END 
$ 

這工作:

mysql> CALL DEV_Organization.GetUserByCaseId("bro4"); 
+------+--------+-----------+----------+----------+----------------------+ 
| sid | caseId | firstName | lastName | position | email    | 
+------+--------+-----------+----------+----------+----------------------+ 
| 3773 | bro4 | Billy  | O'Neal |   | [email protected] | 
+------+--------+-----------+----------+----------+----------------------+ 
1 row in set (0.00 sec) 

但不幸的是允許客戶端與傳遞null逃脫:

mysql> CALL DEV_Organization.GetUserByCaseId(NULL); 
Empty set (0.00 sec) 

我會相反,這會拋出一個錯誤。我怎樣才能做到這一點? (只需設置一個類型的VARCHAR(8) NOT NULL導致MySQL拋出一個錯誤,在創建過程時......)

編輯:評論者問我理由。我有一個數據庫API工作早在PHP土地,看起來像這樣:

/** 
* Inside function which is used to implement other procedure functions. 
* 
* @param string $suffix The database schema suffix. 
* @param string $procedure The name of the procedure that should be executed. 
* @param array $arguments A set of arguments which should be passed to the stored procedure. 
* @return PDOStatement The PDOStatement generated by sending the query to the MySQL Server. 
*/ 
private function ProcedureInner($suffix, $procedure, $arguments = array()) 
{ 
    $suffix = (string)$suffix; 
    $procedure = (string)$procedure; 
    $questionMarks = ''; 
    $args = count($arguments); 
    if ($args > 0) 
    { 
    $questionMarks = '?'; 
    for ($idx = 1; $idx < $args; ++$idx) 
    { 
     $questionMarks .= ', ?'; 
    } 
    } 
    $stmt = $this->pdo->prepare("CALL `{$this->mode}_{$suffix}`.`{$procedure}` ({$questionMarks})"); 
    $stmt->execute($arguments); 
    return $stmt; 
} 

/** 
* Executes a stored procedure which returns a single value in a single row. 
* 
* @param string $schema The suffix of the schema where the procedure is located. 
* @param string $procedure The name of the procedure to call. 
* @param array $arguments Arguments to supply to the procedure, if any. 
* @return mixed The content of the value. 
*/ 
public function ProcedureScalar($schema, $procedure, $arguments = array()) 
{ 
    $result = $this->ProcedureInner($schema, $procedure, $arguments); 
    $answer = $result->fetchColumn(0); 
    $result->closeCursor(); 
    return $answer; 
} 

注意到它是如何方便客戶忘記來傳遞參數數組中的參數。然而,這是數據庫抽象的低級別部分,我不想在這裏設置約束條件來尋找特定的參數。

+1

任何理由,你爲什麼不會在您的客戶端(APP)執行此檢查? – Devraj

+0

@Devraj:這裏的目標是防止應用程序中的錯誤。如果MySQL拋出一個錯誤,它會自動翻譯成客戶端上的異常或錯誤代碼,而不管客戶端是什麼。我需要那樣做。我會用更多的信息更新這個問題... –

+0

@Devraj:好的,更新。 –

回答

4

的MySQL 5.5及更高版本只是爲此提供SIGNAL(提高用戶程序任意例外):

.... 
BEGIN 
    IF searchedForId IS NULL THEN 
    SIGNAL SQLSTATE '45000' -- unhandled user-defined exception 
     SET MESSAGE_TEXT = 'Parameter may not be NULL'; 
    END IF; 
    SELECT 
    CaseIdAuthenticator.sid AS sid, 
.... 
相關問題