Import danych z CSV do MySQL - jak rozwiązać problem brakujących kluczy?

0

Witam,

Mam problem z impotem danych z pliku CSV do bazy MySQL

Plik CSV ma strukture:
nazwa|typ|numer|nazwa|nr_h

Dane chce wstawić do tabel:

grupa: id_grupy, nazwa, typ, numer
czesc: id_czesci, nazwa, nr_h
czesc_grupa: id_czesci, id_grupy

Nie wiem jak rozwiązać fakt żeby przy imporcie dodawało do bazy wszystkie wartości, ponieważ w pliku CSV nie ma pól id_grupy oraz id_czesci. W bazach są one wartościami auto increment.

Nie wiem jak wstawić 2 pierwsze kolumny do tabeli grupa następnie pobrać id wstawionego rekordu aby dodać z 3 ostatnich pól plus id_grupy do tabeli czesc oraz na sam koniec dodać wartość id_grupy i id_czesc do tabeli czesc_grupa.

Problem jest taki że pierwsze 2 kolumny pliku CSV są tylko w jednym wierszu a 3 pozostałe kolumny mogą mieć więcej wierszy.

Jest takie coś ogólnie możliwe?

Licze na jakakolwiek pomoc

0

Skoro nie ma w csv żadnych id to jak to jest ze sobą związane?

Opis jest tak zagmatwany, że po 3 razach dalej niewiele z tego wiem. Może przedstaw tu przykładowe dane z CSV?

0

W pliku nie potrzebuje tych id, chodzi zeby przy imporcie dodawalo do istniejacej bazy nowe rekordy z nowym id i to id wstawialo do innych tabel.

w zalaczniku plik csv

0

Aha, taki myk, plik CSV jest jeden.

Dlaczego nie wiążesz id_grupy bezpośrednio w czesc - ze struktury CSV nie wynika, żeby jedna część miała należeć do wielu grup.

Generalnie temat jest prosty, lecisz po wszystkich wierszach, jak masz uzupełnioną nazwę grupy to dodajesz grupę, zapisujesz nowododane ID, do tego dopisujesz część i wiążesz to zapisanym ID grupy. Jeżeli nie ma nazwy grupy to dodajesz tylko część i wiążesz z zapisanym cześniej ID grupy.
Tyle.

0

To jest dodatek do systemu ten import, tutaj bedzie wklejane zestawienie i zeby z automatu to dodalo. Z poziomu systemu mozna dodac czesc do wielu grup.

$file = $_FILES[csv][tmp_name];
    $handle = fopen($file,"r");
    
    //loop through the csv file and insert into database
    do {
        if ($data[0]) {
            mysql_query("INSERT INTO contacts_tmp (contact_first, contact_last, contact_email) VALUES
                (
                    '".addslashes($data[0])."',
                    '".addslashes($data[1])."',
                    '".addslashes($data[2])."'
                )
            ");
        }
    } while ($data = fgetcsv($handle,1000,",","'")); 

Znalazłem taki kod do posiłkowania się, nada się do przerobienia?

Czyli tak lecimy po wierszach jeżeli pierwsze dwa pola insert grupa, po tym mysqli_insert_id, insert czesc, mysqli_insert_id i insert czesc_grupa.

Ale jeżeli w kolejnym wierszu nie ma grupy i tak potrzebuje id_grupy z poprzedniego wiersza, a z tego co napisales rozumiem ze sprawdzi czy jest grupa jesli nie to wartosc bedzie null i nie doda mi id do czesci tylko null. Problem pojawi sie rowniez przy czesc_grupa bo tam tez kazda czesc z danym id_grupy musi byc dodana.

Może ja tego nie rozumiem do końca.

Nigdy nie importowałem z plików i dlatego wydaje mi się to problematyczne dość mocno.

1

ale nie "przerabiaj" kodów, szczególnie długich na całe 10 linii, bo zaczynasz od czegoś, czego nie rozumiesz i brniesz w to dalej, błądząc jak dziecko we mgle.

rozgryź problem od podstaw, rozrysuj sobie algorytm na kartce, bo inaczej nic nie zrobisz, albo wyprodukujesz (za przeproszeniem) g**no na gównianej podstawie (bo niestety kod powyżej nadaje się do "śmiechu warte", a nie do używania na serwerze produkcyjnym)

Nigdy nie importowałem z plików i dlatego wydaje mi się to problematyczne dość mocno.

a co już robiłeś? mam wrażenie, że niewiele, nawet Ci podałem algorytm, a Ty zupełnie nie próbujesz tematu pojąć, tylko jak najszybciej mieć go z głowy

pseudokod:

$plik_csv = pobierz_csv_skadstam();
$id_ostatniej_grupy = null;
dla_kazdej_linii_pliku $plik_csv {
  $nazwa_grupy = pobierz_nazwe_z_wiersza();
  jezeli_nazwa_grupy_zdefiniowana {
    $id_ostatniej_grupy = dodaj_grupe();
  }
  $id_ostatniej_czesci = dodaj_czesc();
  dodaj_powiazanie_czesc_grupa($id_ostatniej_czesci, $id_ostatniej_grupy);
}

jeżeli tego nie łapiesz to naprawdę - długopis i kartka w dłoń i sobie rozrysuj

0

Wielkie dzięki za pomoc, dużo mi pomógł twój pseudokod. W końcu zrozumiałem jak to działa.

Kod dla potomnych szukających tego samego:

if (($uchwyt = fopen ("import/szablon.csv","r")) !== FALSE) {
while (($data = fgetcsv($uchwyt, 1000, ";")) !== FALSE)
    {
        $num = count($data);
                				
		if($data[0]){	
		(string)$nazwa_grupy = $data[0];
		(string)$typ_grupy = $data[1];
		(string)$numer_grupy = $data[2];
		
		$insert_grupa = "insert into grupa (nazwa,typ,numer) values ('$nazwa_grupy','$typ_grupy','$numer_grupy')";
		mysqli_query($db, $insert_grupa) or die($db);
		
		$id_grupy = mysqli_insert_id($db);
		
		}
		if($data[3]){
			(string)$nazwa_czesci = $data[3];
			(string)$nr_handlowy = $data [4];
			
			$insert_czesc = "insert into czesc (nazwa,nr_handlowy,id_grupy) values ('$nazwa_czesci','$nr_handlowy','$id_grupy')";
			mysqli_query($db, $insert_czesc) or die ($db);
			
			$id_czesci = mysqli_insert_id($db);
			
		}
		
		$insert_czesc_grupa = "insert into czesc_grupa (id_czesci,id_grupy) values ('$id_czesci','$id_grupy')";
		mysqli_query($db, $insert_czesc_grupa) or die ($db);
		
    }
fclose ($uchwyt);
} 

Może nie jest to najbardziej optymalne rozwiązanie ale spełnia swoje zadanie.

0

najważniejsze byłoby tu jeszcze poprawić podatność na sql injection, poza tym - jako kod początkującego jest ok, spełnia zadanie

0

jako zabezpieczenie wystarczy zastosowac na zmiennych addslashes ? Czy kombinować coś więcej?

1

addslashes jest do obejścia
użyj tego: http://php.net/manual/en/mysqli.real-escape-string.php

edit: a najlepiej to naucz się korzystać z PDO

0

Dobrą praktyka jest używanie tego zabezpieczenia do wszystkich zmiennych jakie są przesyłane tak?

1

Tak

0

czyli kazda zmienna:

$mail = mysqli_real_escape_string($db, $_POST['email']); 

troche to dodaje kodu,

cieżko się przestawić z mysqli na pdo?

1

raczej nie powinno być ciężko, ale tak czy siak (czy mysqli czy pdo) - będzie trochę kodu więcej, ale niestety - coś za coś ;)

0

pytam bo przegladalem PDO i jest obiektowe a za wiele obiektowosci nie poznalem jeszcze zapytania calkiem inaczej ale podobno bezpieczniej z bindparameters wychodzi i chyba najlepiej bedzie sie zaczac uczyc pdo bo bardziej przyszlosciowe raczej

1 użytkowników online, w tym zalogowanych: 0, gości: 1