[PostgreSQL/PHP] Probleem met sql-query in script

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • bokkiewok
  • Registratie: Juni 2001
  • Laatst online: 07-11-2024
Hoi,

Ik zit met een probleem waar ik zelf niet uitkom.
De situatie:

Een tabel met gegevens over projecten. Projecten worden voorzien van een id, dit is een integer.
Ik wil vanuit een form de tabel kunnen uitbreiden met nieuwe projecten.
Dat is op zich geen probleem, ware het niet dat een query in het script een andere output geeft dan in de database zelf. Het betreft een query om de hoogste integer van de id-kolom te vinden.
Op de psql command line gaat dit commando goed. Zoda ik het in php in een script giet, dan krijg ik compleet andere output. En die output kan ik niet verklaren.
De query in psql:

SQL:
1
2
3
4
5
select max(p_id) from projects;
 max
-----
  18
(1 row)


Deze geeft dus de juiste waarde terug, 18.

Nu in het script:

PHP:
1
2
3
$q_id = "select max(p_id) from projects";
$qr_id = pg_query($q_id);
$p_id = $qr_id + 1;


Ik verwacht dus in $qr_id het getal 18, en deze wil ik met 1 ophogen voor het volgende ID van een nieuw project, wat ik met een insert in wil geven. Als ik $qr_id echo krijg ik echter "Resource id #3" terug. Dat is niet wat ik verwacht.
Zie ik iets over het hoofd ? Zo ja, wat ?

Acties:
  • 0 Henk 'm!

  • Tjolk
  • Registratie: Juni 2007
  • Laatst online: 04-07 18:32
De output van pg_query() is een resource. Je zult $qr_id dus nog moeten fetchen met bijvoorbeeld pg_fetch_result() om er een string van te maken.

[ Voor 5% gewijzigd door Tjolk op 23-10-2009 11:34 ]

Tjolk is lekker. overal en altijd.


Acties:
  • 0 Henk 'm!

  • dev10
  • Registratie: April 2005
  • Laatst online: 30-06 22:19
Je krijgt nu een resultset terug, die je even moet omzetten door middel van pg_fetch_result().

edit:
Met ^^

[ Voor 14% gewijzigd door dev10 op 23-10-2009 11:34 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Je snapt ook dat het uidelen van ID's op deze manier niet echt handig is. Het is wachten op problemen.

Stel er worden 2 requests tegelijk gedaan, request 1 vraag het hoogste ID op, tegelijkertijd vraag request 2 het ID op. Dan verhogen ze beide het ID met 1, en proberen dus met hetzelfde ID te inserten.

Je kunt beter kijken naar de faciliteiten die de database zelf bied. Ik ken PostgreSQL niet, maar vaak is er iets als een Auto Increment kolom of iets van Sequences die je hiervoor kunt gebruiken.
Ger schreef op vrijdag 23 oktober 2009 @ 11:34:
Je zult $qr_id dus nog moeten fetchen met bijvoorbeeld pg_fetch_result() om er een string van te maken.
Echter wil je er helemaal geen string van maken, want het is een numerieke waarde die je selecteert ;)

[ Voor 23% gewijzigd door Woy op 23-10-2009 11:39 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • user109731
  • Registratie: Maart 2004
  • Niet online
bokkiewok schreef op vrijdag 23 oktober 2009 @ 11:30:
Ik verwacht dus in $qr_id het getal 18, en deze wil ik met 1 ophogen voor het volgende ID van een nieuw project, wat ik met een insert in wil geven.
Wat als twee gebruikers tegelijk een project toevoegen? Dan heb je kans dat ze hetzelfde id terugkrijgen en allebei proberen een insert met $id+1 te doen.

Niet doen dus. PostgreSQL kan automatisch het id-veld invullen. Dat is veiliger en minder werk :)

edit: wat ^^ zegt dus.

[ Voor 10% gewijzigd door user109731 op 23-10-2009 11:42 ]


Acties:
  • 0 Henk 'm!

  • bokkiewok
  • Registratie: Juni 2001
  • Laatst online: 07-11-2024
Woy schreef op vrijdag 23 oktober 2009 @ 11:37:
Je snapt ook dat het uidelen van ID's op deze manier niet echt handig is. Het is wachten op problemen.

Stel er worden 2 requests tegelijk gedaan, request 1 vraag het hoogste ID op, tegelijkertijd vraag request 2 het ID op. Dan verhogen ze beide het ID met 1, en proberen dus met hetzelfde ID te inserten.

Je kunt beter kijken naar de faciliteiten die de database zelf bied. Ik ken PostgreSQL niet, maar vaak is er iets als een Auto Increment kolom of iets van Sequences die je hiervoor kunt gebruiken.

[...]

Echter wil je er helemaal geen string van maken, want het is een numerieke waarde die je selecteert ;)
Klopt. Echter, deze database beheer ik zelf, hij word door anderen gebruikt om wat data aan de hand van wat views te bekijken. De mutaties op de tabel zijn klein, en worden door mij uitgevoerd. Ik ben er dus niet bang voor dat er 2 requests tegelijk worden gedaan.

Maar je hebt wel gelijk dat het een numerieke waarde moet zijn. Eens gaan uitzoeken hoe dat in zijn werk gaat.

[ Voor 5% gewijzigd door bokkiewok op 23-10-2009 11:44 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
bokkiewok schreef op vrijdag 23 oktober 2009 @ 11:43:
[...]
Klopt. Echter, deze database beheer ik zelf, hij word door anderen gebruikt om wat data aan de hand van wat views te bekijken. De mutaties op de tabel zijn klein, en worden door mij uitgevoerd. Ik ben er dus niet bang voor dat er 2 requests tegelijk worden gedaan.
Dat is natuurlijk geen reden om het dan maar op een slechte manier aan te pakken. Er kunnen best redenen zijn waarom je je ID generatie in je applicatie wilt doen, maar als je geen goede reden hebt, moet je het gewoon aan je database overlaten. Je voorkomt dan gewoon problemen.

En het feit dat je er geen problemen mee verwacht is geen goede reden ;)

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • UltimateB
  • Registratie: April 2003
  • Niet online

UltimateB

Pomdiedom

Een tip bokkiework, als je niet zeker bent van de return van een functie gebruik dan var_dump($mVar); om te kijken wat erin zit. Scheelt een hoop tijd ;)

"True skill is when luck becomes a habit"
SWIS


Acties:
  • 0 Henk 'm!

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
Ga nooit met MAX() het hoogste id ophalen om daarmee een nieuw id aan te "kunnen" maken, dat gaat grote problemen opleveren. PostgreSQL (en bv. ook Oracle) gebruikt sequences, ga die dan ook gebruiken, ze zijn er niet voor niets.

SQL:
1
2
3
4
5
6
CREATE TABLE foo(
id SERIAL PRIMARY KEY,
content TEXT
);

INSERT INTO foo(content) VALUES('bar') RETURNING id;

Met deze opzet zal PostgreSQL zelf een sequence aanmaken en deze als default waarde aanroepen wanneer er een nieuw record in de tabel wordt gezet. Wanneer je dan een insert doet, krijg je het aangemaakte id als antwoord retour. De insert moet je dus net zoals een select keurig gaan fetchen en dan krijg je keurig antwoord op de vraag welk id is aangemaakt.

Uiteraard kun je ook vooraf al met NEXTVAL() de volgende waarde voor het id opvragen en deze in de insert zetten, net wat je handiger vindt.

Ps. RETURNING bestaat sinds versie 8.2, mocht je dus met een nog oudere versie aan de slag gaan, zal het niet werken en moet je wel met NEXTVAL() aan de slag wanneer je vooraf het id wilt weten. Achteraf kun je het id opvragen met LASTVAL(), zie ook de handleiding hoofdstuk 9.
Pagina: 1