Katarzyna Kajzar

Katarzyna Kajzar PHP developer

Temat: Import danych do tabeli mysql z pliku

Witajcie!

Usiłuję zimportować dane z pliku txt do tabeli w bazie, a następnie updatować regularnie tabelę. Dane są z gry, więc dość dynamiczne. Część rekordów będzie znikać, część się pojawiać, pozostałe będą wymagać aktualizacji.

Wymodzić udało mi się tylko coś takiego:


CREATE TEMPORARY TABLE temptable (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`tag` varchar(200) NOT NULL,
`members` int(11) NOT NULL,
`villages` int(11) NOT NULL,
`points` int(11) NOT NULL,
`all_points` int(11) NOT NULL,
`rank` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE = MEMORY;

LOAD DATA LOCAL INFILE 'D:/yt/ally.txt' INTO TABLE temptable
FIELDS TERMINATED BY ',';

UPDATE ally JOIN temptable USING (id) SET ally.id = temptable.id;

DROP TEMPORARY TABLE temptable;


Oczywiście nie działa. Tabela ally jest pusta, podejrzewam, że UPDATE na pustej nie zadziała, jak jednak poradzić sobie z tym, żeby update działał zawsze, też kasując lub dodają rekordy? I co jest źle w tym zapytaniu?

Szukałam w sieci, nie znalazłam, dlatego pytam.

Wojciech Gardziński

Wypowiedzi autora zostały ukryte. Pokaż autora
Katarzyna Kajzar

Katarzyna Kajzar PHP developer

Temat: Import danych do tabeli mysql z pliku

Obeszłam problem w taki sposób, zapewne nieelegancko..


CREATE TABLE temptable (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`tag` varchar(200) NOT NULL,
`members` int(11) NOT NULL,
`villages` int(11) NOT NULL,
`points` int(11) NOT NULL,
`all_points` int(11) NOT NULL,
`rank` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE = MEMORY;

LOAD DATA LOCAL INFILE 'D:/yt/ally.txt' INTO TABLE temptable
FIELDS TERMINATED BY ',';

DROP TABLE ally;

RENAME TABLE temptable TO ally;

Temat: Import danych do tabeli mysql z pliku

Katarzyna K.:
Witajcie!

Usiłuję zimportować dane z pliku txt do tabeli w bazie, a następnie updatować regularnie tabelę.

Jeżeli nie działa to znaczy, że nie wiesz co robisz.

Poczytaj to:
http://stackoverflow.com/questions/4205181/insert-to-t...Ten post został edytowany przez Autora dnia 13.09.13 o godzinie 13:09
Marcin Mackiewicz

Marcin Mackiewicz Programista JAVA, RS
Adware Polska

Temat: Import danych do tabeli mysql z pliku

Faktycznie koleżanka nie wie co robi...

Na samym początku zastanowiłbym się co chcę osiągnąć. Piszesz o usuwaniu, dodawaniu i aktualizacji poszczególnych rekordów w tabeli którą założyłaś. Na końcu jednak zawsze kasujesz całą tabelę (DROP TABLE) i zakładasz nową o tej samej nazwie. Czy to jest twoim celem? Bo jeżeli tak to może po prostu nie baw się we wrzucanie danych do bazy tylko analizuj dane bezpośrednio z pliku.

W sumie to zastanowiłbym się czy mogę dane przetwarzać w inny sposób niż plik. Samo rozwiązanie z plikiem jest już mało eleganckim rozwiązaniem...

Proponuję:
1. Stworzyć tabelę
CREATE TABLE temptable (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`tag` varchar(200) NOT NULL,
`members` int(11) NOT NULL,
`villages` int(11) NOT NULL,
`points` int(11) NOT NULL,
`all_points` int(11) NOT NULL,
`rank` int(11) NOT NULL,
`active` boolean,
PRIMARY KEY (`id`)
);


2. Wykonać program w języku który znasz (PHP) który wrzuci dane w odpowiedni sposób

Program do wrzucania danych:
1. Weź plik o uporządkowanej strukturze tekstowej w którym jeden wiersz odpowiada jednemu wierszowi tabeli SQL a kolejne kolumny są rozdzielone jakimś znakiem przestankowym
2. Przeczytaj plik linia po linii i utwórz z niego tablicę
$array[iterator] = array( id, name, ..., rank)
Przydatna funkcja
/**
* Funkcja pobiera dane z zadanego pliku i przetwarza go do tablicy
* @param string $plik Sciezka do pliku
* @param string $separatorKolumny Znak podzialu na kolumny
* @param string $znakCytownia Znak cytowania danych w kolumnie. Jezeli nie zostanie podany to funkcja dziala bez naku cytowania
* @return array Tablica zawierajaca dane z pliku
*/
public function getFileCSV($plik, $separatorKolumny, $znakCytownia = NULL) {
$rows = array();
if (is_readable($plik) ) {
$handler = fopen($plik, 'r');
$iter = 0;
if ( isset( $znakCytownia ) ) {
while ( $stdrow = fgetcsv( $handler, NULL, $separatorKolumny, $znakCytownia) ) {
$rows[$iter] = $stdrow;
$iter += 1;
}
} else {
while ( $stdrow = fgetcsv( $handler, NULL, $separatorKolumny) ) {
$rows[$iter] = $stdrow;
$iter += 1;
}
}
}
return $rows;
}

3. Ustawiam wartość kolumny template.active na false
UPDATE template set active = false;
4. Przeglądam każdy wiersz z tablicy i sprawdzam czy wiersz o danym id istnieje w bazie danych w tabeli template
SELECT id FROM template WHERE id = {zmienna}
Jezeli nie znalazłem wiersza o podanym id to dodaję do tabeli nowy wiersz
INSERT INTO template(id, name, .., active) VALUES(1, 'test', .., TRUE);
UWAGA! Ważne aby kolumna active była ustawiona na TRUE.
Jeżeli znalazłem wiersz o podanym id to aktualizuje dane w nim zawarte danymi z pliku
UPDATE template SET kolumna = wartosc, active = TRUE WHERE id = {zmienna};
UWAGA! Ważne aby kolumna active była ustawiona na TRUE.

Na początku ustawiłem kolumnę active na false po to aby wiedzieć które rekordy zostały dodane lub zaktualizowane. template.active = false w tym momencie oznacza, że dany rekord nie znajdował się w pliku. Takie rekordy można posprzątać jeżeli jest taka potrzeba
DELETE FROM template WHERE active IS FALSE;
Ten post został edytowany przez Autora dnia 14.09.13 o godzinie 00:21

konto usunięte

Temat: Import danych do tabeli mysql z pliku

przeczytałem i aż usiadłem z wrażenie jak można pokaleczyć ten temat
Marcin M.:
Faktycznie koleżanka nie wie co robi...

Na samym początku zastanowiłbym się co chcę osiągnąć. Piszesz o usuwaniu, dodawaniu i aktualizacji poszczególnych rekordów w tabeli którą założyłaś. Na końcu jednak zawsze kasujesz całą tabelę (DROP TABLE) i zakładasz nową o tej samej nazwie. Czy to jest twoim celem? Bo jeżeli tak to może po prostu nie baw się we wrzucanie danych do bazy tylko analizuj dane bezpośrednio z pliku.

TEMPORARY TABLE to nie to samo co TABLE bardzo duża różnica
w przypadku MySQL-a jest to bardzo wydajny sposób na pracę ze zbiorem danych który sobie tworzymy w dowolny sposób np. za pomocą CREATE a później LOAD DATA

Taka konstrukcja jaką zastosowała koleżanka jest prawie ok, ja zamiast UPDATE dał bym INSERT INTO ON DUPLICATE KEY UPDATE

http://dev.mysql.com/doc/refman/5.0/en/insert-on-dupli...

W sumie to zastanowiłbym się czy mogę dane przetwarzać w inny sposób niż plik. Samo rozwiązanie z plikiem jest już mało eleganckim rozwiązaniem...

Proponuję:
1. Stworzyć tabelę
CREATE TABLE temptable (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`tag` varchar(200) NOT NULL,
`members` int(11) NOT NULL,
`villages` int(11) NOT NULL,
`points` int(11) NOT NULL,
`all_points` int(11) NOT NULL,
`rank` int(11) NOT NULL,
`active` boolean,
PRIMARY KEY (`id`)
);


po co tworzysz obiekt globalny?

2. Wykonać program w języku który znasz (PHP) który wrzuci dane w odpowiedni sposób


aaaaaaa, a jak ma 10000 rekordów..... matrix
Program do wrzucania danych:
1. Weź plik o uporządkowanej strukturze tekstowej w którym jeden wiersz odpowiada jednemu wierszowi tabeli SQL a kolejne kolumny są rozdzielone jakimś znakiem przestankowym
2. Przeczytaj plik linia po linii i utwórz z niego tablicę
$array[iterator] = array( id, name, ..., rank)
Przydatna funkcja
/**
* Funkcja pobiera dane z zadanego pliku i przetwarza go do tablicy
* @param string $plik Sciezka do pliku
* @param string $separatorKolumny Znak podzialu na kolumny
* @param string $znakCytownia Znak cytowania danych w kolumnie. Jezeli nie zostanie podany to funkcja dziala bez naku cytowania
* @return array Tablica zawierajaca dane z pliku
*/
public function getFileCSV($plik, $separatorKolumny, $znakCytownia = NULL) {
$rows = array();
if (is_readable($plik) ) {
$handler = fopen($plik, 'r');
$iter = 0;
if ( isset( $znakCytownia ) ) {
while ( $stdrow = fgetcsv( $handler, NULL, $separatorKolumny, $znakCytownia) ) {
$rows[$iter] = $stdrow;
$iter += 1;
}
} else {
while ( $stdrow = fgetcsv( $handler, NULL, $separatorKolumny) ) {
$rows[$iter] = $stdrow;
$iter += 1;
}
}
}
return $rows;
}


przetwarzanie w ten deseń to jakiś potworek

3. Ustawiam wartość kolumny template.active na false
UPDATE template set active = false;
4. Przeglądam każdy wiersz z tablicy i sprawdzam czy wiersz o danym id istnieje w bazie danych w tabeli template
SELECT id FROM template WHERE id = {zmienna}
Jezeli nie znalazłem wiersza o podanym id to dodaję do tabeli nowy wiersz
INSERT INTO template(id, name, .., active) VALUES(1, 'test', .., TRUE);
UWAGA! Ważne aby kolumna active była ustawiona na TRUE.
Jeżeli znalazłem wiersz o podanym id to aktualizuje dane w nim zawarte danymi z pliku
UPDATE template SET kolumna = wartosc, active = TRUE WHERE id = {zmienna};
UWAGA! Ważne aby kolumna active była ustawiona na TRUE.

wtf, skoro masz już dane w dwu tabvelkach to po co pętla w PHP, ajjj aż mnie oczy zaszczypały
Na początku ustawiłem kolumnę active na false po to aby wiedzieć które rekordy zostały dodane lub zaktualizowane. template.active = false w tym momencie oznacza, że dany rekord nie znajdował się w pliku. Takie rekordy można posprzątać jeżeli jest taka potrzeba
DELETE FROM template WHERE active IS FALSE;

a teraz pomyśl masz kilkaset tysięcy rekordów .... ja już zapłakałem

spoko można mówić że jak jest kilka rekordów to cacy - nie jest cacy - pokazywanie ludziom kompletnego antywzorca postępowania jest złe i powinno być piętnowane niezależnie od ilości danyhch

konto usunięte

Temat: Import danych do tabeli mysql z pliku

Katarzyna K.:
Witajcie!

Usiłuję zimportować dane z pliku txt do tabeli w bazie, a następnie updatować regularnie tabelę. Dane są z gry, więc dość dynamiczne. Część rekordów będzie znikać, część się pojawiać, pozostałe będą wymagać aktualizacji.

Wymodzić udało mi się tylko coś takiego:


CREATE TEMPORARY TABLE temptable (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`tag` varchar(200) NOT NULL,
`members` int(11) NOT NULL,
`villages` int(11) NOT NULL,
`points` int(11) NOT NULL,
`all_points` int(11) NOT NULL,
`rank` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE = MEMORY;

LOAD DATA LOCAL INFILE 'D:/yt/ally.txt' INTO TABLE temptable
FIELDS TERMINATED BY ',';

UPDATE ally JOIN temptable USING (id) SET ally.id = temptable.id;

DROP TEMPORARY TABLE temptable;


Oczywiście nie działa. Tabela ally jest pusta, podejrzewam, że UPDATE na pustej nie zadziała, jak jednak poradzić sobie z tym, żeby update działał zawsze, też kasując lub dodają rekordy? I co jest źle w tym zapytaniu?

Szukałam w sieci, nie znalazłam, dlatego pytam.

zastosuj konstrukcję on duplicate key update wraz z insertem - dodasz lub aktualizujesz dane które występują w załadowywanym pliku txt

http://dev.mysql.com/doc/refman/5.0/en/insert-on-dupli...

jak chcesz skasować nadmiarowe dane to zrób to za pomocą DELETE

DELETE t1 from temptable as t2 RIGHT JOIN ally as t1 on t1.id = t2.id WHERE t2.id is nullTen post został edytowany przez Autora dnia 15.09.13 o godzinie 18:19
Marcin Mackiewicz

Marcin Mackiewicz Programista JAVA, RS
Adware Polska

Temat: Import danych do tabeli mysql z pliku

Ale mi kolega pojechał... i ma racje. Iteracyjne rozwiązania nie są dobre i tu nie ma żadnego ale. Już Ci kiedyś mówiłem, że z MySQL nie wymiatam bo na nim nie pracuje. Zaproponowałem rozwiązanie które zadziała z każdą bazą danych uznając, że przy X niewiadomych przy pytaniu (chociażby engine bazy) może zaistnieć jeszcze Y problemów.
Mogłem też rzucić linkiem jak co niektórzy robią i stwierdzić... radź se sama.

Mając do przetrawienia dużą ilość danych na pewno szukałbym dobrego rozwiązania i nie wątpię, że w pierwszej kolejności przy MySQL uderzył bym do ciebie :)

konto usunięte

Temat: Import danych do tabeli mysql z pliku

Marcin M.:
Ale mi kolega pojechał... i ma racje. Iteracyjne rozwiązania nie są dobre i tu nie ma żadnego ale. Już Ci kiedyś mówiłem, że z MySQL nie wymiatam bo na nim nie pracuje. Zaproponowałem rozwiązanie które zadziała z każdą bazą danych uznając, że przy X niewiadomych przy pytaniu (chociażby engine bazy) może zaistnieć jeszcze Y problemów.
Mogłem też rzucić linkiem jak co niektórzy robią i stwierdzić... radź se sama.

Mając do przetrawienia dużą ilość danych na pewno szukałbym dobrego rozwiązania i nie wątpię, że w pierwszej kolejności przy MySQL uderzył bym do ciebie :)

Spoko, spoko ;)
Katarzyna Kajzar

Katarzyna Kajzar PHP developer

Temat: Import danych do tabeli mysql z pliku

Panowie, wielkie dzięki Wam obu!

Rozwiązanie iteracyjne testowałam sobie jakiś czas temu w php. Napisałam i.. nie działało, chociaż napisane poprawnie było. Rekordów tam jest koło miliona, więc puściłam sobie pętelkę na lokalnej maszynie, szła 8h, "trochę" za długo.

SQLa znam tylko podstawy i bardzo brakuje mi "insert into on key duplicate" i podobnych konstrukcji. Jeśli jesteście w stanie polecić mi jakiś zwarty kurs zaawansowanego sqla, to bradzo proszę.

Co do różnicy między insert i update to ogarniam, naprawdę. ;)Ten post został edytowany przez Autora dnia 16.09.13 o godzinie 00:13
Marcin Mackiewicz

Marcin Mackiewicz Programista JAVA, RS
Adware Polska

Temat: Import danych do tabeli mysql z pliku

Hehehe...
Przy takiej ilości danych rozwiązanie iteracyjne jest do piachu. Nawet bym się nie odezwał :)
Katarzyna Kajzar

Katarzyna Kajzar PHP developer

Temat: Import danych do tabeli mysql z pliku

Ja chciałam sprawdzić jak to jest z tą optymalizacją w praktyce, a sam kod iteracyjny skomplikowany nie jest, więc nie było to problemem. :-)

Pozdrawiam i dobrego dnia :)

konto usunięte

Temat: Import danych do tabeli mysql z pliku

Rozwiązania iteracyjne są też ok, a 1 mln. rekordów na taką zabawę to nie jest dużo.

Sam mam rozwiązanie poarte na XMLReader i robię INSERT/UPDATE ok 700k rekordów codziennie. Takie przelecenie zajmuje ok 35 min.

Zamiast INSERT można pokusić się o REPLACE INTO które spowoduje nadpisanie rekordu jeżeli istnieje.
Wcześniej ustawić jakąś flagę na wszystkie rekordy w bazie żeby wyczyścić śmieci po wszystkim.
Katarzyna Kajzar

Katarzyna Kajzar PHP developer

Temat: Import danych do tabeli mysql z pliku

35 minut odpada na hostingu, bo kilkują po kilku

Wojciech Gardziński

Wypowiedzi autora zostały ukryte. Pokaż autora

Następna dyskusja:

Import tabeli excel ze stru...




Wyślij zaproszenie do