Toon posts:

MySQL update

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik heb op mijn mySQL server een database staan voor een login-systeem. Nu heb ik in die database een tabel staan met daarin sessies van de gebruiker:

session_id: session_uid: session_ip:
1166468675796 7 127.0.0.1

enzovoorts.

Wat ik wil dat er gebeurd als een gebruiker inlogd is, dat zijn vorige sessie wordt geupdate met de nieuwe sessie_id. En de andere atrributen ook natuurlijk. Dit kan ik doen met een update query:

update sessions
set session_id X, session_uid Y, session_ip Z
where session_uid = Y;

Dit is natuurlijk leuk, maar wat nou als die user voor het eerst inlogd?? dan is er geen attribuut die Y bevat. Want hij heeft nooit een sessie gehad hiervoor. Dit zou ik kunnen oplossen door tijdens de creatie van een account een lege sessie te initializeren, maar dit vind ik niet zo erg netjes. Ik ben niet zo ver met SQL dus begin niet gelijk te flamen als de oplossing zeer eenvoudig blijkt te zijn. Tuurlijk heb ik een rondje google gedaan en een rondje in mijn SQL boek, maar ik heb niet echt iets kunnen vinden wat mijn probleem tackled. Weten jullie een oplossing?

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Als het record nog niet bestaat zul je het (logischerwijs) moeten maken (en dus een INSERT uitvoeren). Ik zie niet hoe je dat anders op zou willen lossen. Uiteraard maak je zo'n record pas op het moment dat het UID bekend is; voor die tijd zie ik zowieso het nut niet om dat ergens in een sessions tabel bij te houden (je weet immers niet wie het is).

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • MIster X
  • Registratie: November 2001
  • Laatst online: 25-09 21:57
Volgens mij zoek je naar insert ... on duplicate key update ... Daarmee doe je een insert wanneer de key nog niet bestaat, wanneer deze wel bestaat wordt er een update gedaan.

code:
1
2
INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

Verwijderd

Topicstarter
MIster X schreef op maandag 18 december 2006 @ 22:40:
Volgens mij zoek je naar insert ... on duplicate key update ... Daarmee doe je een insert wanneer de key nog niet bestaat, wanneer deze wel bestaat wordt er een update gedaan.

code:
1
2
INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;
_/-\o_ You saved my day, ty

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Persoonlijk vind ik dat een nogal ranzige (want, MySQL-only) oplossing ;)
Je kunt veel beter een exists uitvoeren en aan de hand daarvan een update danwel insert doen, OF gewoon een insert uitvoeren en de exception vangen (if any) en alsnog een insert uitvoeren.

[ Voor 56% gewijzigd door RobIII op 18-12-2006 22:52 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • MIster X
  • Registratie: November 2001
  • Laatst online: 25-09 21:57
RobIII schreef op maandag 18 december 2006 @ 22:50:
Persoonlijk vind ik dat een nogal ranzige (want, MySQL-only) oplossing ;)
Je kunt veel beter een exists uitvoeren en aan de hand daarvan een update danwel insert doen, OF gewoon een insert uitvoeren en de exception vangen (if any) en alsnog een insert uitvoeren.
Wel, dat hangt natuurlijk helemaal van de uiteindelijke toepassing af. Zolang het niet een heel groot project betreft, waarbij de kosten voor een eventuele ombouw naar een andere database minimaal zijn, vind ik het ranzig wanneer je een tabel gaat locken, kijkt of de id al in de tabel staat, uit je neus eet, vervolgens gaat kijken of er een update of een insert uitgevoerd moet worden OF eerst een update/insert uitvoert, een exception afvangt (da's pas ranzig), uit je neus eet en dan alsnog insert/update doet, terwijl er gewoon een functie voor gemaakt is in MySQL (zodat je in alle rust uit je neus kunt eten).

Verwijderd

RobIII schreef op maandag 18 december 2006 @ 22:50:
Persoonlijk vind ik dat een nogal ranzige (want, MySQL-only) oplossing ;)
Je kunt veel beter een exists uitvoeren en aan de hand daarvan een update danwel insert doen, OF gewoon een insert uitvoeren en de exception vangen (if any) en alsnog een insert uitvoeren.
Neem aan dat je bij die laatste 'insert' een 'update' bedoelt?
Doe 't dan andersom: eerst updaten, en wanneer je een rows affected van 0 terug krijgt een insert uitvoeren.
Het gebruik van exceptions voor je normale flow is m.i. net zo ranzig als het gebruiken van MySQL-only oplossingen. Exception handling gebruik je daar waar ze voor bedoeld zijn: het afvangen van uitzonderingen die je niet had kunnen voorzien. Situaties die je van te voren kunt zien aankomen (updaten van een niet bestaand record bv.) kun je in je programma prima opvangen zonder exceptions te gebruiken.

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op dinsdag 19 december 2006 @ 00:38:
Neem aan dat je bij die laatste 'insert' een 'update' bedoelt?
Duh :D Foutje idd ;)
Verwijderd schreef op dinsdag 19 december 2006 @ 00:38:
Doe 't dan andersom: eerst updaten, en wanneer je een rows affected van 0 terug krijgt een insert uitvoeren.
Euh, uiteraard; maar door mijn 'exists' regeltje ben ik vergeten dit (wat jij nu dus zegt) erbij te posten... kortom: een nogal krakkemikkige en gebrekkige post mijnerzijds. Mijn excuses; ik zal voortaan niet meer "vlug posten" voor ik ga toiletteren ;)
Het idee was inderdaad: Doe een 'exists', OF doe een update met daarna een insert als nodig, OF vang desnoods een exception maar blijf uit de buurt van die 'on duplicate key...'-zooi.

[ Voor 11% gewijzigd door RobIII op 19-12-2006 00:43 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • pjonk
  • Registratie: November 2000
  • Laatst online: 22-11 20:39
Ik ben ook geen fan voor het misbruiken van exceptions, maar gebruik in dit geval altijd de Exception variant ander kun je last krijgen van concurency issues.
Als je dit met een Exist doet is er een kans dat een andere gebruiker in de tussentijd net een record invoert en kun je alsnog een Exception om je oren krijgen.

It’s nice to be important but it’s more important to be nice


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
pjonk schreef op dinsdag 19 december 2006 @ 10:22:
Ik ben ook geen fan voor het misbruiken van exceptions, maar gebruik in dit geval altijd de Exception variant ander kun je last krijgen van concurency issues.
Als je dit met een Exist doet is er een kans dat een andere gebruiker in de tussentijd net een record invoert en kun je alsnog een Exception om je oren krijgen.
De exception hoor je zowieso gewoon te vangen, maar als je het in een Exist doet kun je het natuurlijk ook wrappen in een transactie ;)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 14:25

Janoz

Moderator Devschuur®

!litemod

Ikzelf doe altijd eerst de update. Je kunt namelijke makkelijk opvragen hoeveel rijen er al bestaan. Wanneer je '0 rows updated' terug krijgt weet je dat hij niet bestaat en kun je hem toevoegen. Mocht hier eventueel een exceptie optreden (vanwege race problemen) dan kun je in de catch nogmaals een update uitvoeren. Deze werkt gegarandeerd aangezien de exceptie optreed doordat het record bestaat. Op deze manier heb je zonder locken een compleet afgedekt systeem en hoef je geen ranzige mysqlonly meuk te gebruiken.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Verwijderd

Topicstarter
Vinden jullie het erg als ik jullie totaal niet meer volg? :P

  • XWB
  • Registratie: Januari 2002
  • Niet online

XWB

Devver
Verwijderd schreef op dinsdag 19 december 2006 @ 11:37:
Vinden jullie het erg als ik jullie totaal niet meer volg? :P
Het is best eenvoudig hoor :)

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
try
{ 
    mysql_query ( 'UPDATE table' );

    if ( mysql_affected_rows() == 0 )
         mysql_query ( 'INSERT INTO table' );
}
catch ( Exception $e )
{
    mysql_query ( 'INSERT INTO table' );

    // TODO, iets doen met $e
}

March of the Eagles


Verwijderd

Topicstarter
Ah jullie bedoelden het in PHP, ok nu snap ik em ;)

  • jvdmeer
  • Registratie: April 2000
  • Laatst online: 00:19
Ik stuur altijd zoiets naar MS-SQL, dus ik weet niet of MySQL dat ondersteunt:
SQL:
1
2
3
4
IF (SELECT COUNT(*) FROM tabel WHERE key=1)>0
  UPDATE tabel SET veld=3 WHERE key=1
ELSE
  INSERT INTO tabel (key,veld) VALUES (1,3)


Dan laat je het sql in zijn geheel afhandelen. Eventueel zet ik dit ook nog in een SP.

  • sariel
  • Registratie: Mei 2004
  • Laatst online: 22-05-2024
RobIII schreef op maandag 18 december 2006 @ 22:50:
Persoonlijk vind ik dat een nogal ranzige (want, MySQL-only) oplossing ;)
Leg uit aub? Is er uberhaubt SQL code die altijd op elke database werkt? Ik heb onderhand al met een flinke stapel verschillende databases gewerkt (Oracle, MSSQL, MySQL, PgSQL), en iedere keer moest een query net iets anders opgeschreven worden.

Ze zeggen allemaal SQL te ondersteunen, maar doen het allemaal op een net iets andere manier. Dat zijn standaarden voor je.....


edit: SQL code die verder gaat dan "select * from bla" en "insert into bla", hoewel die insert ook nog wel eens rommelt.....

[ Voor 10% gewijzigd door sariel op 19-12-2006 15:10 ]

Copy.com


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
sariel schreef op dinsdag 19 december 2006 @ 15:01:
Leg uit aub? Is er uberhaubt SQL code die altijd op elke database werkt? Ik heb onderhand al met een flinke stapel verschillende databases gewerkt (Oracle, MSSQL, MySQL, PgSQL), en iedere keer moest een query net iets anders opgeschreven worden.
Ik beweer nergens dat het zonder die "On Duplicate key" meteen op een andere database werkt, maar je bent er wel al een stap dichterbij ;)
Ik postte gisteren toevallig iets "soortgelijks" waarbij ik die "disclaimer" wel vermeldde:
RobIII schreef op maandag 18 december 2006 @ 22:57:
Zowieso is GROUP_CONCAT nogal MySQL-only (zoals nog veel meer stuff :X ) en is het dus niet erg makkelijk te porten naar een andere DB zou je dat ooit willen. Ik beweer niet dat het anders veel makkelijker is, maar het is een begin ;)
Helaas heb ik 'm deze keer dus niet vermeld ;)

[ Voor 33% gewijzigd door RobIII op 19-12-2006 16:39 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij

Pagina: 1