/ Forside / Teknologi / Udvikling / PHP / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
PHP
#NavnPoint
rfh 3959
natmaden 3372
poul_from 3310
funbreak 2700
stone47 2230
Jin2k 1960
Angband 1743
Bjerner 1249
refi 1185
10  Interkril.. 1146
Undgå klippe-klistre SQ
Fra : Tom


Dato : 11-03-07 16:27

Hej

Jeg ender ofte med en funktion, der klippe-klistrer SQL sammen.
Dette synes jeg selvsagt ikke er ret kønt og vil høre om det er en
betragtning I er enige i og hvad man kan gøre for at undgå den?

Se koden nedenfor, som enten henter en specifik række eller alle rækker [1]

Jeg har fravalgt metoden med at den altid henter alle rækker men kun
returnerer den ønskede række pga. performance.

Andre betragtninger omkring koden i sig selv er også velkomne.

[1]


function Fetch_Media_Data ($ID)
{
if (preg_match ("/^(\d+)?$/", $ID) == False) exit ("Fetch_Media_Data: ID
not numeric or empty -->". $ID ."<--.");

$SQL = "
SELECT *
FROM files
WHERE 1

if ($ID) $SQL .= " AND SNO = '". $ID ."' ";

$SQL .= "ORDER BY Category ASC, Filename_Original ASC ";


$data = mysql_query ($SQL, $this->Link) or die(mysql_error
($this->Link));
while ($hr = mysql_fetch_array ($data, MYSQL_ASSOC))
{
$arr_media [] = $hr;
}
mysql_free_result ($data);

return $arr_media;
}



 
 
N/A (11-03-2007)
Kommentar
Fra : N/A


Dato : 11-03-07 18:00



Konrad (11-03-2007)
Kommentar
Fra : Konrad


Dato : 11-03-07 18:00

Michael Zedeler wrote:

>...(nårh nej, det kan man ikke i php), et
> resultatsæt (nårh nej, det kan man heller ikke)

Ah hva' kan man ikke????

function getSQLDataSet($SQL) {
db_connect();
$result=mysql_query($SQL);
db_disconnect();
return $result;
}

virker fint.




Michael Zedeler (11-03-2007)
Kommentar
Fra : Michael Zedeler


Dato : 11-03-07 18:16

Konrad skrev:
> Michael Zedeler wrote:
>
>> ...(nårh nej, det kan man ikke i php), et
>> resultatsæt (nårh nej, det kan man heller ikke)
>
> Ah hva' kan man ikke????
>
> function getSQLDataSet($SQL) {
> db_connect();
> $result=mysql_query($SQL);
> db_disconnect();
> return $result;
> }
>
> virker fint.

Ja. Men så er det ikke databaseuafhængigt. Det var det, der var min
temmelig svært forståelige pointe. Af samme grund har jeg sendt et nyt
indlæg hvor det er klippet væk.

Mvh. Michael.
--
Which is more dangerous? TV guided missiles or TV guided families?
I am less likely to answer usenet postings by anonymous authors.
Visit my home page at http://michael.zedeler.dk/

Konrad (11-03-2007)
Kommentar
Fra : Konrad


Dato : 11-03-07 18:36

Michael Zedeler wrote:
> Konrad skrev:
>> Michael Zedeler wrote:
>>
>>> ...(nårh nej, det kan man ikke i php), et
>>> resultatsæt (nårh nej, det kan man heller ikke)
>>
>> Ah hva' kan man ikke????
>>
>> function getSQLDataSet($SQL) {
>> db_connect();
>> $result=mysql_query($SQL);
>> db_disconnect();
>> return $result;
>> }
>>
>> virker fint.
>
> Ja. Men så er det ikke databaseuafhængigt. Det var det, der var min
> temmelig svært forståelige pointe. Af samme grund har jeg sendt et nyt
> indlæg hvor det er klippet væk.

Nå!!! Forstod ikke helt - så den først bagefter. Ja, det er da rigtigt.





Michael Zedeler (11-03-2007)
Kommentar
Fra : Michael Zedeler


Dato : 11-03-07 18:14

Dette er 2. version af denne posting. Jeg er igang med at sende en
cancel-besked på den første.

Tom skrev:
> Jeg ender ofte med en funktion, der klippe-klistrer SQL sammen.
> Dette synes jeg selvsagt ikke er ret kønt og vil høre om det er en
> betragtning I er enige i og hvad man kan gøre for at undgå den?

Det kan ikke helt undgåes med mindre du vil bruge et bibliotek til at
skrue forespørgsler sammen. Til gengæld bør man bruge prepared
statements hvor det er muligt.

> Se koden nedenfor, som enten henter en specifik række eller alle rækker [1]
>
> Jeg har fravalgt metoden med at den altid henter alle rækker men kun
> returnerer den ønskede række pga. performance.
>
> Andre betragtninger omkring koden i sig selv er også velkomne.
>
> function Fetch_Media_Data ($ID)
> {
> if (preg_match ("/^(\d+)?$/", $ID) == False) exit ("Fetch_Media_Data: ID
> not numeric or empty -->". $ID ."<--.");

Det regulære udtryk kan lige så godt reduceres til /^\d*$/.

> $SQL = "
> SELECT *
> FROM files
> WHERE 1
>
> if ($ID) $SQL .= " AND SNO = '". $ID ."' ";
>
> $SQL .= "ORDER BY Category ASC, Filename_Original ASC ";

Sortering af resultatet kan blive en meget dyr affære på større tabeller
og bør derfor være valgfrit.

> $data = mysql_query ($SQL, $this->Link) or die(mysql_error
> ($this->Link));
> while ($hr = mysql_fetch_array ($data, MYSQL_ASSOC))
> {
> $arr_media [] = $hr;
> }
> mysql_free_result ($data);

Hm. Tjaeh. Det er så en ubeskriveligt dyr operation, du har gang i der.
Du kopierer jo hele resultatet til et array, som man efterfølgende kun
kan lave lineær søgning i. Jeg ville nøjes med at returnere en closure,
som kan bruges til at hente fra resultatsættet en række ad gangen.

Jeg ved godt at du har det svært med at tale om hvad opgaven går ud på,
men i denne situation er designet altså temmelig afhængigt af hvordan
din funktion skal bruges.

Mvh. Michael.
--
Which is more dangerous? TV guided missiles or TV guided families?
I am less likely to answer usenet postings by anonymous authors.
Visit my home page at http://michael.zedeler.dk/

Konrad (11-03-2007)
Kommentar
Fra : Konrad


Dato : 11-03-07 18:50

Michael Zedeler wrote:

(...)
> Hm. Tjaeh. Det er så en ubeskriveligt dyr operation, du har gang i
> der. Du kopierer jo hele resultatet til et array, som man
> efterfølgende kun kan lave lineær søgning i.

Jeg er helt og aldeles enig. PHP egner sig i mine øjne ikke til den slags
abstraktioner i databasesammenhæng. Her er optimerede ultrakorte SQL-kald og
håndkodede små scripts/rutiner at foretrække, da databasen er akilleshælen
performancemæssigt.

Der vil altid komme gentagelser eller beslægtede kald man så kan lave
generel kode over - og det BØR man gøre - men ét kald der skal kunne
håndtere det hele holder imho slet ikke.





Tom (11-03-2007)
Kommentar
Fra : Tom


Dato : 11-03-07 23:12

> Det kan ikke helt undgåes med mindre du vil bruge et bibliotek til at
> skrue forespørgsler sammen.

OK, det var også min egen konklusion.

> Til gengæld bør man bruge prepared
> statements hvor det er muligt.

Ja, jeg burde sætte mig ind i PEAR snarest. Koden bliver altså noget
smukkere af det.


> Det regulære udtryk kan lige så godt reduceres til /^\d*$/.

Jep, levn fra et andet udtryk jeg kopierede fra.
Tak.


> Sortering af resultatet kan blive en meget dyr affære på større tabeller
> og bør derfor være valgfrit.

Enig.


>> {
>> $arr_media [] = $hr;
>> }
>
> Hm. Tjaeh. Det er så en ubeskriveligt dyr operation, du har gang i der.
> Du kopierer jo hele resultatet til et array, som man efterfølgende kun
> kan lave lineær søgning i. Jeg ville nøjes med at returnere en closure,
> som kan bruges til at hente fra resultatsættet en række ad gangen.

Jeg aner ikke hvad en closure er, men mon det er det samme som Perls
references?
Hvordan gør man det i php?


> Jeg ved godt at du har det svært med at tale om hvad opgaven går ud på,
> men i denne situation er designet altså temmelig afhængigt af hvordan
> din funktion skal bruges.

Hehe, ved nu ikke om jeg har svært ved det.
I dette konkrete tilfælde er det jo fint, for der spørger jeg helt generelt
om 1) betragtninger 2) løsning på et problem jeg kun kan se en grim løsning


I det tilfælde du refererer til spurgte jeg meget specifikt til hvordan man
får kædet en $hr på et eksisterende array, og der blev jeg bare irriteret
over at en som Bertel ikke kan overskue opgaven (da han ikke havde læst
indlægget andet end overfladisk) og så vælger at angribe min forklaring som
jeg så måtte henvise til faktisk stod der to gange med forskellige
formuleringer.


Men, i dette tilfælde har jeg en DB klasse som abstraktion.
Den returnerer et array som de forskellige funktioner så kan hygge sig med
uden at kende det mindste til DB strukturen.
Det ville være fint at returnere en reference for at optimere mod
performance.
Eksempel eller link ville være helt perfekt!

Tak for svaret.



Michael Zedeler (11-03-2007)
Kommentar
Fra : Michael Zedeler


Dato : 11-03-07 23:38

Tom skrev:
>> Det kan ikke helt undgåes med mindre du vil bruge et bibliotek til at
>> skrue forespørgsler sammen.
>
> OK, det var også min egen konklusion.
>
>> Til gengæld bør man bruge prepared
>> statements hvor det er muligt.
>
> Ja, jeg burde sætte mig ind i PEAR snarest. Koden bliver altså noget
> smukkere af det.

Det har intet med pear at gøre.

>> Hm. Tjaeh. Det er så en ubeskriveligt dyr operation, du har gang i der.
>> Du kopierer jo hele resultatet til et array, som man efterfølgende kun
>> kan lave lineær søgning i. Jeg ville nøjes med at returnere en closure,
>> som kan bruges til at hente fra resultatsættet en række ad gangen.
>
> Jeg aner ikke hvad en closure er, men mon det er det samme som Perls
> references?
> Hvordan gør man det i php?

Prøv at google efter "php closure" der var en pænt god forklaring som
nummer 1, 2 eller 3 i resultatet.

>> Jeg ved godt at du har det svært med at tale om hvad opgaven går ud på,
>> men i denne situation er designet altså temmelig afhængigt af hvordan
>> din funktion skal bruges.
>
> Hehe, ved nu ikke om jeg har svært ved det.
> I dette konkrete tilfælde er det jo fint, for der spørger jeg helt generelt
> om 1) betragtninger 2) løsning på et problem jeg kun kan se en grim løsning
> på
>
> I det tilfælde du refererer til spurgte jeg meget specifikt til hvordan man
> får kædet en $hr på et eksisterende array, og der blev jeg bare irriteret
> over at en som Bertel ikke kan overskue opgaven (da han ikke havde læst
> indlægget andet end overfladisk) og så vælger at angribe min forklaring som
> jeg så måtte henvise til faktisk stod der to gange med forskellige
> formuleringer.

Ja. Til gengæld er der også god grund til at blive forvirret, da du har
byttet ordet "plads" ud med "dimension". Bare fordi man stopper et
ekstra element i et array, får det ikke en ekstra dimension. Hvis der
var tale om en vektor, kunne man sige at den hører til i et rum af
dimensionen n + 1, men det er matematiksnak. Når man snakker om f. eks.
todimensionelle arrays, betyder det at der er n*m uafhængige pladser,
hvor n er længden på den ene led og m er længden på den anden led. I dit
oprindelige indlæg har du altså at gøre med et todimensionelt array
(tilnærmelsesvis).

> Men, i dette tilfælde har jeg en DB klasse som abstraktion.
> Den returnerer et array som de forskellige funktioner så kan hygge sig med
> uden at kende det mindste til DB strukturen.

Den løsning virker kun i nogle bestemte situationer. Det er i hvert fald
sikkert at hvis du også har det med som "best practise" at man hiver
hele tabeller ind i hukommelsen, så får du et skaleringsproblem.

> Det ville være fint at returnere en reference for at optimere mod
> performance.
> Eksempel eller link ville være helt perfekt!

Det med at lave databaseabstraktionslag er prøvet hundredevis af gange
og kun ganske få af forsøgene ser ud til at have ført til noget
fornuftigt. Du er indledningsvis nødt til at gøre dig nogle tanker om
hvad det skal bruges til, hvilket du jo igen har undladt at skrive noget om.

For at hjælpe lidt på vej, kan jeg starte med at spørge om det skal være
et objekt-persistenslag eller ej? Objektpersistenslag er der nemlig en
masse af, så der er masser af inspiration derude. Det mest oplagte
eksempel er Hibernate (det er godt nok skrevet i Java, men hvis du
bliver indenfor PHP-verdenen tror jeg ikke der er meget inspiration at
hente).

Hvis det ikke er til objekt-persistens, er der også mere simple lag, der
blot søger at give udvikleren et konsistent api, hvor
databaseuafhængighed er et væsentligt kriterie. PEAR::DB er et meget
kluntet eksempel på sådan et lag. Hvis du gerne vil se hvordan det
skulle være gjort, så tag et kig på perls DBI.

Jeg arbejder selv på et lag som giver mulighed for at behandle meget,
meget store datamængder ekstremt hurtigt (den database jeg arbejder på
lige nu er over 4 TB - vel at mærke uden store BLOBs eller andet fyld),
hvor man dog stadigvæk får lov til at holde operationerne på et relativt
højt abstraktionsniveau. Til det formål er det fuldstændig omsonst at
prøve at behandle hver række fra databasen som et objekt. Buffering er
også noget skidt - selv det at hive værdierne ud af den struktur der
holder dem, er noget jeg prøver at undgå. OTL er nok det tætteste, man
kan komme på det bibliotek, men der er nogle væsentlige forskelle (en af
dem er at OTL er i C++ hvor mit lag er i perl og er mindre afhængigt af
at have en database i nærheden).

Så der er mange beslutninger at træffe og hvis man vil lave et lag der
virkelig kan bruges til noget, er man nødt til at tage tænkehatten på og
beholde den på i meget lang tid.

Mvh. Michael.
--
Which is more dangerous? TV guided missiles or TV guided families?
I am less likely to answer usenet postings by anonymous authors.
Visit my home page at http://michael.zedeler.dk/

Søg
Reklame
Statistik
Spørgsmål : 177559
Tips : 31968
Nyheder : 719565
Indlæg : 6408937
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste