2011-12-02 16 views
7

Próbuję użyć odpowiedzi staticsan w this question dla przygotowanych wyciągów. Weźmy ten przykład:Jak wstawić wiele wierszy w bazie danych mysql jednocześnie z przygotowanymi instrukcjami?

$stmt = $mysqli->prepare("INSERT INTO something (userid, time, title) VALUES (?, ?, ?)"); 
$stmt->bind_param('iis', $userid, time(), $title); 
$stmt->execute(); 

W odpowiedzi staticsan's implozji tablica jest dodanie wszystkich wartości w rachunku mysql tak, że w końcu możemy wstawić wiele danych do bazy danych za pomocą jednego rachunku. Jak to zrobić w moim przykładzie?

+0

Twój przykład ma stałą liczbę parametrów, tak to już rozwiązany. Czy możesz rozwinąć swój problem nieco bardziej? Czego spróbowałeś do tej pory? Powinien zasadniczo działać tak samo, ale dodać więcej parametrów, np. w pętli foreach. – hakre

+0

Możesz przygotować przygotowane oświadczenie przy użyciu kodu, jak wspomniano tutaj, http://stackoverflow.com/questions/1176352/pdo-prepared-inserts-multiple-rows-in-single-query –

Odpowiedz

5

To jest całkowicie poprawny:

$stmt = $mysqli->prepare("INSERT INTO something (userid, time, title) VALUES (?, ?, ?)"); 

$stmt->bind_param('iis', $userid, time(), $title); 
$stmt->execute(); 

$stmt->bind_param('iis', $userid, time(), $title); 
$stmt->execute(); 

$stmt->bind_param('iis', $userid, time(), $title); 
$stmt->execute(); 

$stmt->bind_param('iis', $userid, time(), $title); 
$stmt->execute(); 

Można foreach nad tablicę wartości do wstawienia i wiążą i wykonanie za każdym razem. To nie będzie tak szybkie, jak wkładka zbiorcza w przyklejonym przykładzie, ale będzie bezpieczniejsze.

+1

Dzięki, to działa. Ale wykonanie execute() zostanie wykonane dla każdego elementu tablicy, więc każdy wiersz zostanie wstawiony do bazy danych oddzielnie, a nie wszystkie jednocześnie. Czy mam rację? Miałem nadzieję, że zobaczę rozwiązanie, w którym najpierw bind_param wszystkie wartości i na samym końcu wykonaj go raz. – phpheini

+0

Tak, to prawda, ale główną zaletą jest wzrost prędkości zapewniany przez przygotowane oświadczenie - przygotowanie wyciągu raz i wiele razy działa znacznie szybciej niż przygotowanie za każdym razem. –

+0

To nadal jest tona wolniejsza niż stare, dobre, statyczne zapytanie 'INSERT', prawda? Mam na myśli, że wykonywanie zapytań w pętli tworzy opóźnienie ~ 2ms pomiędzy każdym zapytaniem. Z dużymi tablicami zajęłoby to na zawsze, nie? – NoobishPro

-2

Kwerenda wygląda następująco:

INSERT INTO people (name, age) 
    VALUES 
    ('Helen', 24), 
    ('Katrina', 21), 
    ('Samia', 22), 
    ('Hui Ling', 25), 
    ('Yumie', 29) 
+4

tak, ale nie dla przygotowanych oświadczeń. Pytanie brzmi, czy muszę napisać: '$ mysqli-> prepare (" INSERT INTO something (identyfikator użytkownika, czas, tytuł) VALUES (?,?,?), (?,?,?), (?,? ,?) ");' , a następnie 'bind_param ('iisiisiis', $ userid [0], time(), $ title, $ userid [0], time(), $ title [0], $ userid [1], time(), $ title [1], $ userid [2], time(), $ title [2]); ' – phpheini

2

Można budować przygotowane oświadczenie przy użyciu kodu jak wspomniano tutaj,

PDO Prepared Inserts multiple rows in single query

PHP logika będzie coś w rodzaju,

/** 
* Insert With Ignore duplicates in Mysql DB. 
* 
* @param string $date Date. 
*/ 
public static function insertWithIgnore($em, $container, $tableName, $fields, $rows) 
{ 
    $query = "INSERT IGNORE INTO $tableName (`" . implode('`,`', $fields) . "`) VALUES "; 
    $placeHolr = array_fill(0, count($fields), "?"); 
    $qPart = array_fill(0, count($rows), "(" . implode(',', $placeHolr) . ")"); 
    $query .= implode(",", $qPart); 

    $pdo = self::getPDOFromEm($em, $container); 
    $stmt = $pdo->prepare($query); 
    $i = 1; 
    foreach ($rows as $row) { 
     $row['created_at'] = date("Y-m-d H:i:s"); 
     foreach ($fields as $f) { 
      if (!isset($row[$f])) { 
       $row[$f] = null; 
      } 
      $stmt->bindValue($i++, $row[$f]); 
     } 
    } 

    $result = $stmt->execute(); 

    if ($result == false) { 
     $str = print_r($stmt->errorInfo(), true); 
     throw new \Exception($str); 
    } 

    $stmt->closeCursor(); 
    $pdo = null; 
} 

/** 
* Replace old rows in Mysql DB. 
* 
* @param string $date Date. 
*/ 
public static function replace($em, $container, $tableName, $fields, $rows, $extraFieldValues = null) 
{ 
    if ($extraFieldValues != null) { 
     $fields = array_unique(array_merge($fields, array_keys($extraFieldValues))); 
    } 

    $query = "REPLACE INTO $tableName (`" . implode('`,`', $fields) . "`) VALUES "; 
    $placeHolr = array_fill(0, count($fields), "?"); 
    $qPart = array_fill(0, count($rows), "(" . implode(',', $placeHolr) . ")"); 
    $query .= implode(",", $qPart); 

    $pdo = self::getPDOFromEm($em, $container); 
    $stmt = $pdo->prepare($query); 
    $i = 1; 
    foreach ($rows as $row) {    
     if ($extraFieldValues != null) { 
      $row = array_merge($row, $extraFieldValues); 
     } 
     foreach ($fields as $f) { 
      $stmt->bindValue($i++, $row[$f]); 
     }       
    } 
    $stmt->execute(); 
    if (!$stmt) { 
     throw new \Exception("PDO::errorInfo():" . print_r($stmt->errorInfo(), true)); 
    } 
    $stmt->closeCursor(); 
    $pdo = null; 
} 
Powiązane problemy