2012-04-28 27 views
7

這裏是我的SQL請求:PHP的MySQL,Pdo和查詢:爲什麼多個'查詢'不起作用(在這種情況下)?

$sql 
    = 'CREATE TEMPORARY TABLE tmp ' 
    . 'SELECT * FROM '.$table.' ' 
    . 'WHERE id=:id; ' 
    . 'ALTER TABLE tmp drop ID; ' 
    . 'INSERT INTO '.$table.' ' 
    . 'SELECT 0,tmp.* FROM tmp; ' 
    . 'SET @last=LAST_INSERT_ID(); ' 
    . 'DROP TABLE tmp;' 
    . 'SELECT @last; '; 
    $stmt = $this->bd->execQuery($sql, array(':id'=>101)); 
    echo "1 -> = "; var_export($stmt); echo "\n"; 
    $stmt = $stmt->fetch(PDO::FETCH_OBJ); 
    echo "2 -> = "; var_export($stmt); echo "\n"; 

轉儲談話本身:在查詢的工作(我檢查)。

sql = 
'CREATE TEMPORARY TABLE tmp SELECT * FROM categorie WHERE id=:id; ALTER TABLE tmp drop ID; INSERT INTO categorie SELECT 0,tmp.* FROM tmp; SET @last=LAST_INSERT_ID(); DROP TABLE tmp;SELECT @last; ' 
params = array (
    ':id' => 101, 
) 
1 -> = PDOStatement::__set_state(array(
    'queryString' => 'CREATE TEMPORARY TABLE tmp SELECT * FROM categorie WHERE id=:id; ALTER TABLE tmp drop ID; INSERT INTO categorie SELECT 0,tmp.* FROM tmp; SET @last=LAST_INSERT_ID(); DROP TABLE tmp;SELECT @last; ', 
)) 
2 -> = false 

如果我做「手」上的控制檯線它也能工作(對不起代碼looong線):

mysql> CREATE TEMPORARY TABLE tmp SELECT * FROM categorie WHERE id=101; ALTER TABLE tmp drop ID; INSERT INTO categorie SELECT 0,tmp.* FROM tmp; SET @last=LAST_INSERT_ID(); DROP TABLE tmp;SELECT @last; 
Query OK, 1 row affected (0.00 sec) 
Records: 1 Duplicates: 0 Warnings: 0 

Query OK, 1 row affected (0.00 sec) 
Records: 1 Duplicates: 0 Warnings: 0 

Query OK, 1 row affected (0.07 sec) 
Records: 1 Duplicates: 0 Warnings: 0 

Query OK, 0 rows affected (0.00 sec) 

Query OK, 0 rows affected (0.00 sec) 

+-------+ 
| @last | 
+-------+ 
| 141 | 
+-------+ 
1 row in set (0.00 sec) 

mysql> 

這裏是我的代碼正在執行。

public function execQuery($sql, $tab=array()) 
{ 
    $stmt = self::$_pdo->prepare($sql); 
    if ($stmt===false) { 
        throw new Exception(
            'Erreur prepare '.$sql. 
            ' = '.var_export(self::$_pdo->errorInfo(), true) 
       ); 
    } 
    foreach ($tab as $key=>$valeur) { 
        $stmt->bindValue($key, $valeur); 
    } 
    if ($stmt->execute()===false) { 
        throw new Exception(
            "Erreur execution de la requete :\n\"".$sql."\"\n". 
            "Paramètres de la requete :\n\"".var_export($tab, true)."\"\n". 
            "Details de l'erreur : \n".var_export(self::$_pdo->errorInfo(), true) 
       ); 
    } 
    return $stmt; 
} 

我該怎麼做才能在一次拍攝中獲得最後插入的值(=使我所做的工作)?

+3

我相信PHP的mysql接口只允許每個函數調用一個查詢 - 大概是它正確地獲取結果。 – 2012-04-28 17:31:23

+2

不是檢查false,而是設置'$ pdo-> setAttribute(ATTR_ERRMODE,ERRMODE_EXCEPTION)'讓PDO在發生任何錯誤時拋出'PDOException's。這將保證你得到一個特定的錯誤,並知道你做錯了什麼。 – 2012-04-28 17:34:03

+0

不回答這個問題,但你總是可以把你的SQL存儲過程中... – eggyal 2012-04-28 17:55:46

回答

1

正如我在上面的評論中所提到的,儘管它沒有回答你如何在PHP的一個查詢中發出多個SQL命令的問題,但一種解決方法是使用預準備語句將SQL存儲在存儲過程中:

DELIMITER ;; 

CREATE PROCEDURE copyRecord(TableName VARCHAR(20), id INT) BEGIN 
    -- prevent SQL injection 
    SET TableName = CONCAT('`', REPLACE(TableName, '`', '``'), '`'); 
    SET @id = id; 

    SET @sql = CONCAT(' 
    CREATE TEMPORARY TABLE tmp SELECT * FROM ', TableName, ' WHERE id = ? 
    '); 
    PREPARE stmt FROM @sql; 
    EXECUTE stmt USING @id; 
    DEALLOCATE PREPARE stmt; 

    ALTER TABLE tmp drop ID; 

    SET @sql = CONCAT(' 
    INSERT INTO ', TableName, ' SELECT 0,tmp.* FROM tmp 
    '); 
    PREPARE stmt FROM @sql; 
    EXECUTE stmt; 
    DEALLOCATE PREPARE stmt; 

    DROP TABLE tmp; 

    SET @sql = NULL; 
    SET @id = NULL; 
    SELECT LAST_INSERT_ID(); 
END;; 

DELIMITER ; 

從PHP中,您只需調用SQL命令CALL copyRecord('categorie', 101)即可。

+0

是否有可能做類似'CREATE TEMPORARY TABLE tmp SELECT * FROM? WHERE id = ?;'? – 2012-04-30 08:15:59

+0

@ OlivierPons:可悲的是,人們只能提供值作爲參數 - 而不是標識符。 – eggyal 2012-04-30 08:16:47

+0

第3行中的錯誤1064(42000):您的SQL語法中有錯誤;檢查與您的MySQL服務器版本相對應的手冊,以便在'sql TEXT;'/ mysql Ver 14.14 Distrib 5.1.62附近使用正確的語法,用於使用readline 6的debian-linux-gnu(x86_64)。1 – 2012-04-30 08:50:32

相關問題