Thread View: pl.comp.lang.perl
14 messages
14 total messages
Started by MaRc
Thu, 10 Mar 2011 20:35
perl - wyciąganie danych z bazy
Author: MaRc
Date: Thu, 10 Mar 2011 20:35
Date: Thu, 10 Mar 2011 20:35
101 lines
3440 bytes
3440 bytes
witam
męczę się nad wyciągnięciem danych z bazy danych.
mylą mi się fetchall_array, fetchall_arrayhref, fetchrow_array itd. które
jest do czego i jak się do tego dobrać. Wybaczcie, ale po lekturze perldoc
(nie jestem biegły w angielskim) za chorobe nie mogę tego zakumać. Jakby
były tam przykłady użycia ze zwracanymi danymi było by łatwiej, a tak to
się męczę.
mam taki krótki testowy skrypt:
----------
#!/usr/bin/perl
use DBI;
use Data::Dumper;
$dbase = DBI->connect("DBI:mysql:database=test;host=localhost","root","",
{ RaiseError => 1 });
$dbase->do("SET NAMES utf8");
$sth = $dbase->prepare("SELECT id FROM users");
$sth->execute;
$ile_wierszy = $sth->rows();
print "Pobrałem $ile_wierszy \n";
@users = $sth->fetchall_arrayref();
print "@users\n";
print Dumper(\@users);
$dbase->disconnect();
@tab = qw/a b c d e f g h/;
print Dumper(\@tab);
------------
uruchomienie tego skutkuje wyświetleniem:
/skrypty$ ./dane.pl
Pobrałem 11
ARRAY(0x9e30f48)
$VAR1 = [
[
[
'1'
],
[
'2'
],
[
'4'
],
[
'5'
],
[
'6'
],
[
'7'
],
[
'8'
],
[
'9'
],
[
'10'
],
[
'11'
],
[
'12'
]
]
];
$VAR1 = [
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h'
];
---------
jak widać utworzona ręcznie tabela jest ok.
generalnie moje zapytanie zwraca same id, jedna kolumne w wierszu- zwraca
liste. chcę te dane wepchnąć do tablicy @users.
jak użyłem fetchrow_array to perl krzyczy, że ma jeszcze nie pobrane dane
z uchwytu. więc użyłem fetchall zeby pobrać wszystko i jak widać z dumpa
po części działa bo jako tako dane są jakieś pobrane, ale nie w sposób w
jaki ja bym chciał.
wiem, można to zrobić w while i pushem wpychać kolejne wyniki do tabeli,
ale nie o to chodzi. chcę to zrobić w jednym zapytaniu i co najważniejsze
w końcu opanować te wszystkie fetch'e.
będzie ktoś tak dobry i po krótce opisze mi te fetche, kiedy ich używać i
jak się dostać do tych pobranych danych. z góry wielkie dzięki.
pomoże ktoś?
Re: perl - wyciąganie danych z bazy
Author: Adam Osuchowski
Date: Thu, 10 Mar 2011 22:26
Date: Thu, 10 Mar 2011 22:26
41 lines
2642 bytes
2642 bytes
MaRc wrote:
> @users = $sth->fetchall_arrayref();
fetchall_arrayref zwraca referencję czyli skalar, więc w zasadzie powinno
być $users, a nie @users, ale patrz równiez na uwagę niżej.
> wiem, można to zrobić w while i pushem wpychać kolejne wyniki do tabeli,
> ale nie o to chodzi. chcę to zrobić w jednym zapytaniu i co najważniejsze w
> końcu opanować te wszystkie fetch'e.
Można i przez while, ale map będzie bardziej zwięzły:
@users = map { $_->[0] } @{$sth->fetchall_arrayref()};
W tej postaci już musi być @users bo zwracamy tablicę, a nie referencję
do niej.
> będzie ktoś tak dobry i po krótce opisze mi te fetche, kiedy ich używać i
> jak się dostać do tych pobranych danych. z góry wielkie dzięki.
Nazewnictwo jest dość logiczne:
fetchall_* -- zwracją wszystkie wiersze.
fetchrow_* -- zwracają jeden (kolejny) wiersz.
*_arrayref -- zwracają referencję do tablicy
*_hashref -- zwracają referencję do hasza
fetchall_arrayref dodatkowo posiada drugi parametr określający czy każdy
z wierszy ma być zapisany jako hash (wraz z polami, które należy
wyciągnąć) czy jako tablica (wraz z kolejnością pól). fetchall_hashref
ma parametr określający które pole ma być kluczem w zwracanym haszu.
Najlepiej będzie jak sobie uruchomisz po kolei każdą z metod i zobaczysz
Dumperem co dokładnie zwraca, bo szybki rzut oka na taki wynik da Ci
więcej informacji niż suchy opis z dokumentacji.
Zainteresuj się też metodami selectall_*, selectrow_* i selectcol_*.
Dla statycznych zapytań (tzn. takich, gdzie nie ma bindowania parametrów,
czyli jest stała treść zapytania) te metody w zasadzie sprowadzają się do
prepare() + execute() w jednym wywołaniu. Nazewnictwo jest podobne, choć
są różnice w szczegółach działania względem metod fetch*().
Re: perl - wyciąganie danych z bazy
Author: MaRc
Date: Fri, 11 Mar 2011 08:29
Date: Fri, 11 Mar 2011 08:29
43 lines
2476 bytes
2476 bytes
W dniu 10.03.2011 23:26, Adam Osuchowski pisze: > MaRc wrote: >> @users = $sth->fetchall_arrayref(); > > fetchall_arrayref zwraca referencję czyli skalar, więc w zasadzie powinno > być $users, a nie @users, ale patrz równiez na uwagę niżej. to wziąłem z dokumentacji, z przykładu, ale jak zmieniałem na skalar to dump nie pokazywał żadnej różnicy. w sumie prawidłowo > fetchall_* -- zwracją wszystkie wiersze. > fetchrow_* -- zwracają jeden (kolejny) wiersz. > *_arrayref -- zwracają referencję do tablicy > *_hashref -- zwracają referencję do hasza fetchall_arrayref zwraca referencje do tablicy zawierającej wszystkie wiersze z zapytania. skoro moje zapytanie zwraca jedynie jeden wiersz, jeśli dobrze to zrozumiałem to wynik powinien być chyba taki: $users = [1,2,3,4,5] a dump pokazuje ze jest taki: @users = ([['1']],[['2']].[['3']],[['4']],[['5']]) lub co jest jednoznaczne $users = [ [['1']],[['2']].[['3']],[['4']],[['5']] ] W dokumentacji pisze: "It returns a reference to an array that contains one reference per row." Czyli z tego co rozumiem zwraca referencje która zawiera kolena referencje po jednej na wiersz. w moim rozumowaniu powinna być "podwójna" referencja, czyli w moim przypadku powinno chyba być: $users = [ ['1'],['2'],['3'],['4'],['5'] ] i dostep do tego np $users[0]->[0] a praktycznie wygląda to tak, że jest jedna referencja więcej :( To jak to jest z tym zwracaniem referencji? Sorki, za marudzenie ale próbuje to jakoś zrozumieć.
Re: perl - wyciąganie danych z bazy
Author: Stachu 'Dozzie' K.
Date: Fri, 11 Mar 2011 08:43
Date: Fri, 11 Mar 2011 08:43
36 lines
2325 bytes
2325 bytes
On 2011-03-11, MaRc <marc@gmails.com> wrote:
> fetchall_arrayref zwraca referencje do tablicy zawierającej wszystkie
> wiersze z zapytania. skoro moje zapytanie zwraca jedynie jeden wiersz,
Mówisz o tym zapytaniu?
#v+
$sth = $dbase->prepare("SELECT id FROM users");
#v-
Jeśli tak, to kto ci nakłamał że to tylko jeden wiersz?
> jeśli dobrze to zrozumiałem to wynik powinien być chyba taki:
>
> $users = [1,2,3,4,5]
>
> a dump pokazuje ze jest taki:
>
> @users = ([['1']],[['2']].[['3']],[['4']],[['5']])
>
> lub co jest jednoznaczne
>
> $users = [ [['1']],[['2']].[['3']],[['4']],[['5']] ]
Jakoś ciężko mi w to uwierzyć. Wklej jeszcze raz stosowny fragment kodu,
odbierz dane do $users i wklej wynik działania Data::Dumper na $users.
Poza tym nie zgadza ci się głębokość zwróconej struktury. Jeśli $users
zawiera [ [[]] ], to @users powinno zawierać ( [ [[]] ] ), a według
ciebie zawiera jeden poziom mniej.
Oducz się przepisywania z podmienianiem danych. Do tego trzeba naprawdę
dobrze umieć Perla.
--
Secunia non olet.
Stanislaw Klekot
Re: perl - wyciąganie danych z bazy
Author: MaRc
Date: Fri, 11 Mar 2011 09:19
Date: Fri, 11 Mar 2011 09:19
94 lines
3282 bytes
3282 bytes
W dniu 11.03.2011 09:43, Stachu 'Dozzie' K. pisze:
> Jeśli tak, to kto ci nakłamał że to tylko jeden wiersz?
przepraszam, mój błąd. przeklikałem się. miałem na myśli, że zwraca jedną
kolumnę na wiersz.
> Jakoś ciężko mi w to uwierzyć.
$users = [1,2,3,4,5] - to jest coś co chciałem osiągnąć i myślałem, że tak
powinno być, ale się jednak myliłem i stąd moje posty :)
> Wklej jeszcze raz stosowny fragment kodu,
> odbierz dane do $users i wklej wynik działania Data::Dumper na $users.
#v+
$sth = $dbase->prepare("SELECT id FROM users LIMIT 5");
$sth->execute;
$ile_wierszy = $sth->rows();
print "Pobrałem $ile_wierszy \n";
$users = $sth->fetchall_arrayref();
print "Print Dumperem skalara \$users\n";
print Dumper($users);
$sth->execute;
@users = $sth->fetchall_arrayref();
print "Print Dumperem tablicy \@users\n";
print Dumper(\@users)
#v-
a to wynik:
#v+
Pobrałem 5
Print Dumperem skalara $users
$VAR1 = [
[
'1'
],
[
'2'
],
[
'4'
],
[
'5'
],
[
'6'
]
];
Print Dumperem tablicy @users
$VAR1 = [
[
[
'1'
],
[
'2'
],
[
'4'
],
[
'5'
],
[
'6'
]
]
];
#v-
biorąc pod uwagę, że "$users = $sth->fetchall_arrayref();" to jak
powinienem prawidłowo dostać sie do danych?
print "$users[0]->[0]"; nic mi nie drukuje
print "${$users[0]}->[0]"; nic mi nie drukuje
print "${$users[0]}[0]"; nic mi nie drukuje
print "$users->[0]->[0]"; drukuje pierwsza wartość
print "$$users[0]->[0]"; drukuje pierwsza wartość
> Poza tym nie zgadza ci się głębokość zwróconej struktury. Jeśli $users
> zawiera [ [[]] ], to @users powinno zawierać ( [ [[]] ] ), a według
> ciebie zawiera jeden poziom mniej.
no może coś przeklikałem :/
> Oducz się przepisywania z podmienianiem danych. Do tego trzeba naprawdę
> dobrze umieć Perla.
no racja.
Re: perl - wyciąganie danych z bazy
Author: Stachu 'Dozzie' K.
Date: Fri, 11 Mar 2011 10:47
Date: Fri, 11 Mar 2011 10:47
58 lines
3244 bytes
3244 bytes
On 2011-03-11, MaRc <marc@gmails.com> wrote:
> W dniu 11.03.2011 09:43, Stachu 'Dozzie' K. pisze:
>> Jeśli tak, to kto ci nakłamał że to tylko jeden wiersz?
> przepraszam, mój błąd. przeklikałem się. miałem na myśli, że zwraca jedną
> kolumnę na wiersz.
>> Jakoś ciężko mi w to uwierzyć.
> $users = [1,2,3,4,5] - to jest coś co chciałem osiągnąć i myślałem, że tak
> powinno być, ale się jednak myliłem i stąd moje posty :)
To ty chcesz najpierw pobrać dane do $users jako tablica wierszy,
z których każdy jest tablicą (jednoelementową) pól, a potem chcesz
spłaszczyć tę tablicę.
perldoc perllol.
Alternatywnie (i raczej tak bym podchodził) powinieneś użyć metody
selectcol_arrayref().
> biorąc pod uwagę, że "$users = $sth->fetchall_arrayref();" to jak
> powinienem prawidłowo dostać sie do danych?
> print "$users[0]->[0]"; nic mi nie drukuje
> print "${$users[0]}->[0]"; nic mi nie drukuje
> print "${$users[0]}[0]"; nic mi nie drukuje
> print "$users->[0]->[0]"; drukuje pierwsza wartość
> print "$$users[0]->[0]"; drukuje pierwsza wartość
perldoc perllol. Tam jest to wszystko opisane.
[...]
> print Dumper(\@users)
> #v-
[...]
> Print Dumperem tablicy @users
> $VAR1 = [
> [
> [
> '1'
> ],
[...]
>> Poza tym nie zgadza ci się głębokość zwróconej struktury. Jeśli $users
>> zawiera [ [[]] ], to @users powinno zawierać ( [ [[]] ] ), a według
>> ciebie zawiera jeden poziom mniej.
>
> no może coś przeklikałem :/
No pewnie, teraz już jasne. Nieprawidłowo uznałeś to co zwraca
Data::Dumper za właściwą zawartość tablicy, a przecież podałeś mu
referencję do tej tablicy, więc oczywistym jest że głębokość referencji
będzie jeden większa.
Powyższe stwierdzenie czytać aż do zrozumienia, bo jest zawiłe.
--
Secunia non olet.
Stanislaw Klekot
Re: perl - wyciąganie danych z bazy
Author: MaRc
Date: Fri, 11 Mar 2011 11:30
Date: Fri, 11 Mar 2011 11:30
20 lines
1753 bytes
1753 bytes
W dniu 11.03.2011 11:47, Stachu 'Dozzie' K. pisze: > To ty chcesz najpierw pobrać dane do $users jako tablica wierszy, > z których każdy jest tablicą (jednoelementową) pól, a potem chcesz > spłaszczyć tę tablicę. no w sumie krótko mówiąc tak to wygląda. > perldoc perllol. dzięki, biorę się za lekturę > No pewnie, teraz już jasne. Nieprawidłowo uznałeś to co zwraca > Data::Dumper za właściwą zawartość tablicy, a przecież podałeś mu > referencję do tej tablicy, więc oczywistym jest że głębokość referencji > będzie jeden większa. > > Powyższe stwierdzenie czytać aż do zrozumienia, bo jest zawiłe. No nie przesadzaj, aż tak zawiłe nie jest. Jest zrozumiałe.
Re: perl - wyciąganie danych z bazy
Author: MaRc
Date: Sat, 12 Mar 2011 10:10
Date: Sat, 12 Mar 2011 10:10
72 lines
2515 bytes
2515 bytes
W dniu 11.03.2011 11:47, Stachu 'Dozzie' K. pisze:
> perldoc perllol.
qrde, jakoś w tym perldocu nie mogę wszystkiego znaleźć. Oczywiście już
wiem jak dobrać się do poszczególnych wartości w referencjach ale za
chorobę nie widzę przykładu jak użyć foreach na referencji.
Pomijając przykład z bazą, do testu zrobiłem takie dane:
#v+
@tab = ('ala','ma','kota','krzys','lubi','puchatka');
print "tablica \@tab ma wartosc\n", Dumper(@tab),"\n";
print "="x20,"\n";
$ref_tab = \@tab;
print "referencja do tablicy \@tab ma wartosci:\n",Dumper($ref_tab);
print "="x20,"\n";
print "Druga wartość w referncji to: $$ref_tab[2]\n";
print "="x20,"\n";
#v-
to mi printuje:
#v+
./tablice.pl
tablica @tab ma wartosc
$VAR1 = 'ala';
$VAR2 = 'ma';
$VAR3 = 'kota';
$VAR4 = 'krzys';
$VAR5 = 'lubi';
$VAR6 = 'puchatka';
====================
referencja do tablicy @tab ma wartosci:
$VAR1 = [
'ala',
'ma',
'kota',
'krzys',
'lubi',
'puchatka'
];
====================
Druga wartość w referncji to: kota
#v-
znaczy się, że ok. ale jak mogę wylistować wszystkie wartości z referencji?
z tablicy to łatwo
#v+
foreach (@tab) {
print;
}
#v+
ale jak zamiast @tab uzyje $ref_tab to foreach zwraca mi tablice.
#v+
foreach ($ref_tab)
{
print;
};
#v-
printuje mi:
#v+
ARRAY(0x8b27c10)
#v-
jak dostać się do danych z referencji w pętlach?
Re: perl - wyciąganie danych z bazy
Author: MaRc
Date: Sat, 12 Mar 2011 10:15
Date: Sat, 12 Mar 2011 10:15
17 lines
1252 bytes
1252 bytes
W dniu 12.03.2011 11:10, MaRc pisze:
> #v+
> foreach ($ref_tab)
> {
> print;
> };
> #v-
qrde, pośpieszyłem się z tamtym postem.
#v+
foreach (@{$reftab})
{
print;
};
#v-
Re: perl - wyciąganie danych z bazy
Author: MaRc
Date: Mon, 14 Mar 2011 12:17
Date: Mon, 14 Mar 2011 12:17
118 lines
3090 bytes
3090 bytes
no to lecimy dalej z wyciąganiem danych z bazy.
fetchall zwraca mi referencje do tablicy i na tym chce zrobic foreach ale
nie wiem jak dobrać się po kolei do poszczególnych elementów w pętli.
#v+
my $allhost = $dbase->prepare("SELECT id FROM nodes WHERE ownerid = ?");
my $hid;
my @hid;
foreach $id ((2))
{
$allhost->execute($id);
$hid = $allhost->fetchall_arrayref();
#print "${@hid[0]} \n";
#print "$$hid[0]->[0]\n";
};
print Dumper($hid);
#v-
dumper zwraca mi referencje tablicy gdzie każdy wiersz to kolejna referencja.
#v+
$VAR1 = [
[
'2'
],
[
'950'
],
[
'1197'
],
[
'1780'
],
[
'1781'
],
[
'1782'
],
[
'1783'
],
[
'1784'
],
[
'1785'
],
[
'1786'
],
[
'1787'
],
[
'2413'
],
[
'2414'
],
[
'3178'
],
[
'3179'
],
[
'3180'
],
[
'3181'
],
[
'3182'
],
[
'3183'
],
[
'3184'
],
[
'3185'
],
[
'3186'
],
[
'3187'
],
[
'3188'
],
[
'3189'
],
[
'3190'
],
[
'3191'
],
[
'3192'
],
[
'3193'
],
[
'3234'
]
];
#v-
jak mogę dobrać się do tych wartości w pętli foreach?
Re: perl - wyciąganie danych z bazy
Author: MaRc
Date: Mon, 14 Mar 2011 12:28
Date: Mon, 14 Mar 2011 12:28
13 lines
1133 bytes
1133 bytes
W dniu 14.03.2011 13:17, MaRc pisze:
> $hid = $allhost->fetchall_arrayref();
juz mam
#v+
foreach $row (@$hid)
{
print "@$row\n"
}
#v-
qrde, z tymi @,$ troche pogibane, ciężko zajarzyć którego kiedy użyć :(
Re: perl - wyciąganie danych z bazy
Author: Antiloop
Date: Thu, 14 Apr 2011 06:47
Date: Thu, 14 Apr 2011 06:47
37 lines
2341 bytes
2341 bytes
On 14 Mar, 14:28, MaRc <m...@gmails.com> wrote:
> W dniu 14.03.2011 13:17, MaRc pisze:
>
> > $hid = $allhost->fetchall_arrayref();
>
> juz mam
> #v+
> foreach $row (@$hid)
> {
> print "@$row\n"}
>
> #v-
>
> qrde, z tymi @,$ troche pogibane, ciężko zajarzyć którego kiedy użyć :(
Hmm...
Mje doświdczenie (niewielkie) podpowiada mi że ja bym jednak zrobił to
tak :
Najpierw zrobił bym porzadek z pobieraniem danych do tablicy.
Metoda której używasz tworzy tablice dereferencji wiec dobrze było
zwracać dane do wyrażenia tablicowego, czyli :
#v+
@hid = $allhost->fetchall_arrayref();
#v-
ale jeśli zamierzasz tylko te dane wyświetlić to :
#v+
foreach$row(${$allhost->fetchall_arrayref()}[0])
{
print $row;
}
#v-
Zastanawiający jest fakt iż nie korzystasz z metody fetchrow_array(),
gdyż ja zawsze korzystałem własnie z niej.
Jakie są plusy z korzystania z fetchall_arrayref()?
Sam miałem i mam problemy z wielowymiarowymi tablicami, hashami i
referencjami -ale polecam treningi z xml :) - potrafią sporo
rozjaśnić.
Re: perl - wyciąganie danych z bazy
Author: Maciej Misiak
Date: Thu, 14 Apr 2011 20:24
Date: Thu, 14 Apr 2011 20:24
12 lines
1615 bytes
1615 bytes
W dniu 2011-04-14 08:47, Antiloop pisze: > Zastanawiający jest fakt iż nie korzystasz z metody fetchrow_array(), > gdyż ja zawsze korzystałem własnie z niej. > Jakie są plusy z korzystania z fetchall_arrayref()? Z reguły w przypadkach małych ilości danych żadne, dopiero jak się robią duże ilości rekordów albo dowolne ilości, ale w wielu wątkach to referencje potrafią zaoszczędzić wiele pamięci. -- grizzley
Re: perl - wyciąganie danych z bazy
Author: Szymon Sokół
Date: Fri, 15 Apr 2011 21:18
Date: Fri, 15 Apr 2011 21:18
63 lines
3812 bytes
3812 bytes
On Thu, 14 Apr 2011 22:24:08 +0200, Maciej Misiak wrote:
> W dniu 2011-04-14 08:47, Antiloop pisze:
>
>> Zastanawiający jest fakt iż nie korzystasz z metody fetchrow_array(),
>> gdyż ja zawsze korzystałem własnie z niej.
>> Jakie są plusy z korzystania z fetchall_arrayref()?
>
> Z reguły w przypadkach małych ilości danych żadne, dopiero jak się robią
> duże ilości rekordów albo dowolne ilości, ale w wielu wątkach to
> referencje potrafią zaoszczędzić wiele pamięci.
Podstawową zaletą grupy funkcji fetchall_hashref, fetchall_arrayref,
selectall_hashref, selectall_arrayref jest to, że zwracają jednym
wywołaniem komplet danych generowanych przez dane zapytanie SQL. Jest to
zarazem podstawowa wada. Wada, bo zjada sporo pamięci, zaleta, bo można
hurtem na całości danych operować, zamiast rekord po rekordzie.
Przykładowo, w celu wypisania imion wszystkich Nowaków i Kowalskich (osobno
jednych, osobno drugich) z tabeli 'obywatele' można zrobić:
my $sth = $dbh->prepare("SELECT imie, nazwisko FROM obywatele WHERE nazwisko=?");
for my $nazwisko ('Nowak', 'Kowalski') {
$sth->execute( $nazwisko );
while ( my @row = $sth->fetchrow_array ) {
print "@row\n";
}
}
albo:
my $sth = $dbh->prepare("SELECT imie, nazwisko FROM obywatele WHERE nazwisko=?");
for my $nazwisko ('Nowak', 'Kowalski') {
$sth->execute( $nazwisko );
while ( my $row = $sth->fetchrow_arrayref ) {
print "@$row\n";
}
}
ale można też:
my $sth = $dbh->prepare("SELECT imie, nazwisko FROM obywatele WHERE nazwisko=?");
for my $nazwisko ('Nowak', 'Kowalski') {
$sth->execute( $nazwisko );
my $all_rows = $sth->fetchall_arrayref;
for my $row ( @$all_rows ) {
print "@$row\n";
}
}
albo wręcz:
for my $nazwisko ('Nowak', 'Kowalski') {
my $all_rows = $dbh->selectall_arrayref("SELECT imie, nazwisko FROM obywatele WHERE nazwisko=?", {}, $nazwisko);
for my $row ( @$all_rows ) {
print "@$row\n";
}
}
--
Szymon Sokół (SS316-RIPE) -- Network Manager B
Computer Center, AGH - University of Science and Technology, Cracow, Poland O
http://home.agh.edu.pl/szymon/ PGP key id: RSA: 0x2ABE016B, DSS: 0xF9289982 F
Free speech includes the right not to listen, if not interested -- Heinlein H
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads