Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PHP]import danych z .csv
Forum PHP.pl > Forum > Przedszkole
Cromwell
Importuję dane z pliku csv do bazy danych. Skrypt wygląda tak:

  1. //formularz
  2. echo '<form action="dodaj.php" method="get">
  3. <input type="hidden" name="add" value="dodaj" />
  4. <input type="submit" value="dodaj" />
  5. </form>';
  6.  
  7. // jesli add = dodaj, wykonaj skrypt
  8. $add = $_GET['add'];
  9.  
  10. if ($add == 'dodaj')
  11. {
  12.  
  13. //definiowanie atrybutow
  14. $fieldseparator = ";";
  15. $lineseparator = "\n";
  16. $csvfile = "firmy.csv";
  17.  
  18.  
  19. if(!file_exists($csvfile)) {
  20. echo "Plik nie istnieje. Upewnij się, że umieściłeś go w katalogu skryptu.\n";
  21. }
  22.  
  23. $file = fopen($csvfile,"r");
  24. if(!$file) {
  25. echo "Błąd podczas otwierania pliku.\n";
  26. }
  27.  
  28. $size = filesize($csvfile);
  29. if(!$size) {
  30. echo "Plik jest pusty.\n";
  31. }
  32.  
  33. $csvcontent = fread($file,$size);
  34.  
  35. fclose($file);
  36.  
  37. conn();
  38.  
  39. $lines = 0;
  40. $queries = "";
  41. $linearray = array();
  42.  
  43. foreach(split($lineseparator,$csvcontent) as $line) {
  44.  
  45. $lines++;
  46. $line = trim($line," \t");
  47. $line = str_replace("\r","",$line);
  48. $line = str_replace("'","\'",$line);
  49. $linearray = explode($fieldseparator,$line);
  50. $linemysql = implode("','",$linearray);
  51. $query = "insert into firmy values('$linemysql');";
  52. $queries .= $query . "\n";
  53. @mysql_query($query);
  54. }
  55.  
  56. echo "Znaleziono $lines rekordów w pliku CSV. Wszystkie zostały dodane do bazy poprawnie.\n";
  57. }
  58.  
  59. ?>


Skrypt działa bardzo dobrze.
Chciałbym żeby rekordy które wgrywam o jakimś ID zastępowały rekordy które są już w bazie z takim samym ID.
jasin
W takim razie powinno Ci pomóc INSERT ... ON DUPLICATE KEY UPDATE.
Cromwell
Ok, przeczytałem fragment w manualu i albo ja tego nie rozumiem, albo nie o to mi chodzi.
Z tego co wywnioskowałem, dzięki temu poleceniu mogę zmienić określone dane, aby rekordy nie były takie same.
A mi chodzi o to, żeby w przypadku takiego samego ID, nowy rekord nadpisywał stary.

Nie wiem, pewnie coś źle rozumiem.
Zmieniłem w kodzie tak:
  1. $query = "insert into firmy values('$linemysql') ON DUPLICATE KEY UPDATE lp=VALUES(lp);";


I nie działa.
jasin
Ok. Zawsze możesz zrobić zapytanie:
  1. UPDATE ... WHERE id = x
i jeśli to zapytanie zwróci zero zaktualizowanych rekordów to robisz INSERT.
Cromwell
Wprowadziłem zmiany:
  1. $linearray = explode($fieldseparator,$line);
  2. $pierw = $linearray[0];
  3. $linemysql = implode("','",$linearray);
  4.  
  5. $query = "UPDATE firmy SET values('$linemysql') WHERE lp = $pierw;";
  6.  
  7. $queries .= $query . "\n";
  8.  
  9. @mysql_query($query);
  10. if ($query < 1)
  11. { $query = "insert into firmy values('$linemysql');";
  12. @mysql_query($query); }

Jednak efekt jest ten sam - dodaje wszystkie rekordy raz jeszcze..
jasin
Poczytaj o mysql_affected_rows.
Powinno u Ciebie wyglądać to jakoś tak:
  1. $linearray = explode($fieldseparator,$line);
  2.  
  3. $pierw = $linearray[0];
  4.  
  5. $linemysql = implode("','",$linearray);
  6.  
  7. $query = "UPDATE firmy SET values('$linemysql') WHERE lp = $pierw;";
  8.  
  9. $queries .= $query . "\n";
  10.  
  11. @mysql_query($query);
  12.  
  13. if (mysql_affected_rows() == 0)
  14. {
  15. $query = "insert into firmy values('$linemysql');";
  16. @mysql_query($query);
  17. }
Cromwell
Po wprowadzeniu zmian, nic się nie dodaje..
Aby zobaczyć, gdzie jest błąd, zmieniłem na:
  1. $pierw = $linearray[0];
  2.  
  3. $linemysql = implode("','",$linearray);
  4.  
  5. $query = "UPDATE firmy SET values('$linemysql') WHERE lp = '$pierw';";
  6.  
  7. $queries .= $query . "\n";
  8.  
  9. mysql_query($query) or die('1'.mysql_error());
  10.  
  11. if (mysql_affected_rows() == 0)
  12. {
  13. $query = "insert into firmy values('$linemysql');";
  14. mysql_query($query) or die('2'.mysql_error());
  15. }

Teraz dostaję komunikat
Cytat
1You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near

Zastanawia mnie to, ponieważ danych, które są wczytywane nie zmieniałem, tak jak wyglądały tak dalej wyglądają, więc to nie z nimi problem.
Składnia zapytania.. wydaje mi się, że jest dobrze.
Nie wiem w sumie, gdzie teraz jest błąd.
darko
wyprintuj całe zapytanie
Cromwell
Ok, całe zapytanie wygląda tak:
  1. UPDATE firmy SET VALUES('10000001','1','2','3','','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21',22','23','24','25',' 26','27','28','29','','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52', '53','54','55','56') WHERE lp = '10000001';


Zmieniłem w nim wartości na liczby, gdyż po prostu nie mogę ich pokazać publicznie (wewnątrz zapytania po przecinkach dodałem jeszcze dwie spacje, aby się ładnie wyświetliło tutaj). Same wartości na pewno wchodzą do bazy dobrze, gdyż skryptem, który umieściłem w pierwszym poście dodawałem dokładnie te same rekordy.

Zapytanie ma prawo się nie wykonać, jeśli w bazie danych nie ma danego rekordu. Jednak wtedy skrypt powinien zejść niżej i wykonać to drugie. To, które jest identyczne jak to z pierwszego postu.

Może chodzi o to, że jeśli skrypt nie wykona zapytania, to już dalej nie robi tylko raz jeszcze zaczyna od foreach z nową wartością?

EDIT
Jak usunąłem fragment, który informował o błędzie w pierwszym zapytaniu, wtedy skrypt niby cały poszedł, dostałem info, że rekordy zostały dodane poprawnie, jednak w bazie ich nie ma.
darko
Wyrzuć warunek where
Cromwell
Zmieniłem na:
  1. UPDATE firmy SET (lista pól, oddzielona przecinkami) VALUES('10000001','1','2','3','','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21',22','23','24','25',' 26','27','28','29','','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52', '53','54','55','56') WHERE lp = '10000001';

I dalej to samo. Zapytanie nie przechodzi, ale myślę, że to dlatego, bo w bazie danych nie ma rekordu z taką liczbą lp.
Tylko że w takim wypadku skrypt powinien iść dalej, wykonać zapytanie INSERT INTO, a tego nie robi..

@darko, bez warunku WHERE dalej nie idzie..
darko
W moim ostatnim poście napisałem: Wyrzuć warunek where, a widzę, że dalej jest...

Nie myślałeś o tym, żeby użyć REPLACE questionmark.gif W Twoim przypadku bardziej by się sprawdziło.
ziqzaq
Z ciekawości zapytam.
Skąd taka składnia "updatea"? blinksmiley.gif
  1. UPDATE tabela SET (kolumny) VALUES (wartosci);

Mysql update vs. insert.
Cromwell
Zmieniłeś post po tym, jak ja napisałem swój.
Wyrzuciłem i dodałem część postu od "@darko, bez warunku".

A co do REPLACE - szczerze mówiąc, nie wiem jak sensownie zbudować wyrażenie używając REPLACE. Żeby jeśli rekord z takim LP już jest w bazie tylko podmieniało, a jeśli nie ma, to wstawiało nowy.
darko
Cytat
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted


To chyba wszystko mówi, na przykład:

  1. REPLACE INTO nazwa_bazy.nazwa_tabeli VALUES('10000001','1','2','3','','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21',22','23','24','25',' 26','27','28','29','','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52', '53','54','55','56')


to dokładnie spełnia swoją rolę, sprawdziłem na przykładowej tabeli.
Cromwell
Działa idealnie smile.gif

Początkowo nie zrozumiałem dokładnie REPLACE (chociaż używałem go już kiedyś), bo szukałem jeszcze w google dla pewności różnych zastosowań i trafiłem na kilka bardzo rozbudowanych przykładów.

Wielkie, wielkie dzięki smile.gif
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.