Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [MySQL][PHP]import danych z .csv
Cromwell
post 30.11.2009, 16:11:26
Post #1





Grupa: Zarejestrowani
Postów: 63
Pomógł: 0
Dołączył: 1.09.2009

Ostrzeżenie: (0%)
-----


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.

Ten post edytował Cromwell 30.11.2009, 16:12:11
Go to the top of the page
+Quote Post
jasin
post 30.11.2009, 16:24:17
Post #2





Grupa: Zarejestrowani
Postów: 142
Pomógł: 32
Dołączył: 21.08.2008
Skąd: Toruń

Ostrzeżenie: (0%)
-----


W takim razie powinno Ci pomóc INSERT ... ON DUPLICATE KEY UPDATE.

Ten post edytował jasin 30.11.2009, 16:24:51


--------------------
Go to the top of the page
+Quote Post
Cromwell
post 30.11.2009, 18:26:55
Post #3





Grupa: Zarejestrowani
Postów: 63
Pomógł: 0
Dołączył: 1.09.2009

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
jasin
post 30.11.2009, 18:46:56
Post #4





Grupa: Zarejestrowani
Postów: 142
Pomógł: 32
Dołączył: 21.08.2008
Skąd: Toruń

Ostrzeżenie: (0%)
-----


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.


--------------------
Go to the top of the page
+Quote Post
Cromwell
post 30.11.2009, 19:47:16
Post #5





Grupa: Zarejestrowani
Postów: 63
Pomógł: 0
Dołączył: 1.09.2009

Ostrzeżenie: (0%)
-----


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..
Go to the top of the page
+Quote Post
jasin
post 30.11.2009, 20:04:12
Post #6





Grupa: Zarejestrowani
Postów: 142
Pomógł: 32
Dołączył: 21.08.2008
Skąd: Toruń

Ostrzeżenie: (0%)
-----


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. }


Ten post edytował jasin 30.11.2009, 20:05:10


--------------------
Go to the top of the page
+Quote Post
Cromwell
post 1.12.2009, 11:36:07
Post #7





Grupa: Zarejestrowani
Postów: 63
Pomógł: 0
Dołączył: 1.09.2009

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
darko
post 1.12.2009, 11:40:28
Post #8





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


wyprintuj całe zapytanie


--------------------
Nie pomagam na pw, tylko forum.
Go to the top of the page
+Quote Post
Cromwell
post 1.12.2009, 11:59:13
Post #9





Grupa: Zarejestrowani
Postów: 63
Pomógł: 0
Dołączył: 1.09.2009

Ostrzeżenie: (0%)
-----


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.

Ten post edytował Cromwell 1.12.2009, 12:07:48
Go to the top of the page
+Quote Post
darko
post 1.12.2009, 12:06:51
Post #10





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Wyrzuć warunek where

Ten post edytował darko 1.12.2009, 12:08:53


--------------------
Nie pomagam na pw, tylko forum.
Go to the top of the page
+Quote Post
Cromwell
post 1.12.2009, 12:20:59
Post #11





Grupa: Zarejestrowani
Postów: 63
Pomógł: 0
Dołączył: 1.09.2009

Ostrzeżenie: (0%)
-----


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..

Ten post edytował Cromwell 1.12.2009, 12:29:53
Go to the top of the page
+Quote Post
darko
post 1.12.2009, 12:29:37
Post #12





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


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.


--------------------
Nie pomagam na pw, tylko forum.
Go to the top of the page
+Quote Post
ziqzaq
post 1.12.2009, 12:41:57
Post #13





Grupa: Zarejestrowani
Postów: 428
Pomógł: 128
Dołączył: 17.06.2007

Ostrzeżenie: (0%)
-----


Z ciekawości zapytam.
Skąd taka składnia "updatea"? blinksmiley.gif
  1. UPDATE tabela SET (kolumny) VALUES (wartosci);

Mysql update vs. insert.
Go to the top of the page
+Quote Post
Cromwell
post 1.12.2009, 12:43:55
Post #14





Grupa: Zarejestrowani
Postów: 63
Pomógł: 0
Dołączył: 1.09.2009

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
darko
post 1.12.2009, 12:49:10
Post #15





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


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.


--------------------
Nie pomagam na pw, tylko forum.
Go to the top of the page
+Quote Post
Cromwell
post 1.12.2009, 13:00:43
Post #16





Grupa: Zarejestrowani
Postów: 63
Pomógł: 0
Dołączył: 1.09.2009

Ostrzeżenie: (0%)
-----


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
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 1.07.2025 - 03:55