Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]PDO - Dodanie wielu wierszy w jednym zapytaniu
Forum PHP.pl > Forum > Przedszkole
@rtur
Mam taką tablice:
  1. $tablica = array(
  2. 0=> array (
  3. 'artist'=> 'Opus',
  4. 'songtitle'=> 'Life Is Life',
  5. ),
  6. 1=> array (
  7. 'artist'=> 'Smookie',
  8. 'title'=> 'Needles And Pins',
  9. ),
  10. 2=> array (
  11. 'artist'=>'George Harrison',
  12. 'title'=>'Got My Mind Set On You',
  13. ),
  14. 3=> array (
  15. 'artist'=> 'Smookie',
  16. 'title'=> 'I`ll Mett You At Midnight',
  17. ),
  18. )

Chciałbym dodać dane z tej tablicy do tabeli w bazie danych jednym zapytaniem insert za pomocą PDO
W przypadku jednego rekordu zrobiłbym tak:
  1. $stmt = $pdo -> prepare('INSERT INTO `songs` (`artist`, `title`) VALUES(:artysta,:tytul)');
  2. $stmt -> bindValue(':artysta', $artysta, PDO::PARAM_STR);
  3. $stmt -> bindValue(':tytul', $tytul, PDO::PARAM_STR);
  4. $exec = $stmt -> execute();

Jak wygląda składnia zapytania insert dla wielu rekordów z bindowaniem danych z tablicy w PDO?
viking
Jeżeli masz przygotowane zapytanie (prepare) możesz je wykonywać dowolną ilość razy.
http://php.net/manual/en/pdo.prepare.php (przykłady) Execute przyjmuje tablicę danych.
@rtur
hmm coś takiego?

  1. $artysta=array();
  2. $tytul=array();
  3. foreach ($tablica as $tab){
  4. $artysta[] .= $tab['artist'];
  5. $tytul[] .= $tab['title'];
  6. }
  7.  
  8. $stmt = $pdo -> prepare('INSERT INTO `songs` (`artist`, `title`) VALUES(:artysta,:tytul)');
  9. $stmt -> bindValue(':artysta', $artysta, PDO::PARAM_STR);
  10. $stmt -> bindValue(':tytul', $tytul, PDO::PARAM_STR);
  11. $exec = $stmt -> execute();
viking
A czy coś takiego jest w przykładach? Parametry muszą się zgadzać też czyli nie raz songtitle, innym razem title.

  1. try {
  2. $dbh = new PDO('pgsql:host=localhost;port=5432;dbname=db;user=user;password=pass');
  3. $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  4. $dbh->exec("SET NAMES 'UTF8';");
  5.  
  6. $tablica = array(
  7. 0 => array(
  8. 'artist' => 'Opus',
  9. 'title' => 'Life Is Life',
  10. ),
  11. 1 => array(
  12. 'artist' => 'Smookie',
  13. 'title' => 'Needles And Pins',
  14. ),
  15. 2 => array(
  16. 'artist' => 'George Harrison',
  17. 'title' => 'Got My Mind Set On You',
  18. ),
  19. 3 => array(
  20. 'artist' => 'Smookie',
  21. 'title' => 'I`ll Mett You At Midnight',
  22. ),
  23. );
  24.  
  25. $stmt = $dbh->prepare('INSERT INTO song (artist, songtitle) VALUES(:artist,:title)');
  26.  
  27. foreach ($tablica as $value) {
  28. $exec = $stmt->execute($value);
  29. }
  30. } catch (PDOException $e) {
  31. echo 'Klasa PDO zwróciła wyjątek: ' . $e->getMessage();
  32. }


http://wwwgo.pl/article/10/php_data_object...luge_baz_danych
@rtur
Dzięki, oczywiście będzie title w parametrach, moja pomyłka pisarska.

W wyniku tego execute() x4 (tyle jest elementów w tablicy) wykona się 4x zapytanie
  1. INSERT INTO song (artist, songtitle) VALUES(:artist,:title)
tylko za każdym razem z innymi parametrami, czyli mamy 4 zapytania do bazy?

Przy zwykłym mysql_query jest coś takiego
  1. INSERT INTO song (artist, songtitle) VALUES ('Opus','Life Is Life'),('Smookie','Needles And Pins'),('George Harrison','Got My Mind Set On You'),('Smookie','I`ll Mett You At Midnight')
i tu mam jedno zapytanie do bazy.

Przepraszam, do tej pory używałem głównie mysql_ a teraz dopiero zaczynam swoją przygodę z PDO
@rtur
Dzięki, czy w PDO moje zapytanie może mieć taką konstrukcję?
  1. $sth = $dbh->prepare('INSERT INTO song (artist, title) VALUES(:artysta1,:tytul1),(:artysta2,:tytul2), ... (:artysta10,:tytul10)');
  2. $sth->bindValue(':artysta1',$artysta[1]);
  3. $sth->bindValue(':tytul1',$tytul[1]);
  4. $sth->bindValue(':artysta2',$artysta[2]);
  5. $sth->bindValue(':tytul2',$tytul[2]);
  6. ...
  7. $sth->bindValue(':artysta10',$artysta[10]);
  8. $sth->bindValue(':tytul10',$tytul[10]);
  9. $sth->execute();
Turson
Może. Kod można uprościć pętlą
@rtur
Oczywiście zrobię go pętlą for, chodziło mi tylko o konstrukcję zapytania. Dzięki za pomoc smile.gif
viking
Jeżeli naprawdę chcesz zyskać na wydajności to https://dev.mysql.com/doc/refman/5.6/en/load-data.html
Dopóki nie robisz tysięcy rekordów nie warto sobie głowy zawracać. Zwłaszcza że te dane nie wyglądają na zmienne.
@rtur
Nie wiem czy jest sens to będzie co 20 minut 20 rekordów próbowało wrzucić... to chyba nie dużo...

Korzystam z tej klasy https://github.com/indieteq/PHP-MySQL-PDO-Database-Class i o ile udało mi się zrobić pętlę Values (:artysta1,:tytul1),....(:artysta20,:tytul20) do zapytania insert dla wielu to nie mogę sobie podpięciem parametrów...
  1. $i=0;
  2. $numItems=20;
  3. foreach($data as $d){
  4. if($i === $numItems) {
  5. $val .= '(:artysta'.$i.',:tytul'.$i.')';
  6. }
  7. else{
  8. $val .= '(:artysta'.$i.',:tytul'.$i.'), ';
  9. }
  10. }
  11. $sqlQuery = 'INSERT INTO song (artist,title) VALUES '.$val;
  12. // Przy pojedynczym rekordzie dane dodałbym tak;
  13. $db->query($sqlQuery,array('artysta1'=>$dane[0][1],'tytul1'=>$dane[0][2]));

W jaki sposób do zmiennej $tablicaDlaWieluParametrow przypisać coś takiego:
  1. $tablicaDlaWieluParametrow = array('artysta1'=>$dane[0][1],'tytul1'=>$dane[0][2],....'artysta20'=>$dane[19][1],'tytul20'=>$dane[19][2]);

aby zadziałało tak:
  1. $db->query($sqlQuery,$tablicaDlaWieluParametrow);

domyślam się że pętlą ale nie chce mi wyjść coś co zadziała jako drugi parametr w funkcji $db->query();
viking
Skoro jest to 20 rekordów co 20 minut to nie ma sensu nawet nad tym myśleć. Dla bazy to nic. Gdybyś tam miliony wkładał mogła by coś taka optymalizacja przynieść.
@rtur
no tak w sumie masz rację, teraz nie będą to miliony rekordów ale nie wykluczam że w niedalekiej przyszłości może być 20, 50 lub więcej razy 20 rekordów co 20 minut, nie są to jedyne rekordy jakie będą się dodawały w tym skrypcie, dlatego zawczasu chcę myśleć o optymalizacji zapytań, i np. co się da wrzucić jednym zapytaniem...
viking
Poczytaj https://dev.mysql.com/doc/refman/5.0/en/insert-speed.html
Masz kilka możliwości przyśpeiszenia choćby INSERT DELAYED. Pamiętaj o wyłączeniu autocommit czy jak to się zwało w mysql. I odpowiedź Turson pokazała jak zrobić w jednym wywyołaniu.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.