YapfHoofdpagina | Info | Hulp | FAQ (veelgestelde vragen) | Speciale pagina's | Aanmelden


Printervriendelijke versie | Voorbehoud | Privacybeleid

Duplicaten in PostgreSQL

Uit Yapf


Inhoud

Heeft PostgreSQL ook 'ON DUPLICATE'?

Van MySQL gebruikers krijg ik af en toe de vraag of PostgreSQL ook een 'ON DUPLICATE' functie heeft. Met die functie kun je in MySQL aangeven dat er een alternatieve actie gedaan moet worden wanneer een insert query een dubbele waarde voor een key invoert.

Mijn eerste reactie is dan "Waarom zit je een dubbele waarde in te voeren?"

In MySQL schijnt dit veel gebruikt te worden om bijvoorbeeld hits van een webserver te tellen. De tabel bevat dan een kolom voor de URL die geteld moet worden met een unique key er op, en een INT kolom om de telling in bij te houden. Het beleid is dan om altijd te INSERTen en wanneer de waarde voor de URL al bestond via de 'ON DUPLICATE' een UPDATE query op te starten.

PostgreSQL heeft geen 'ON DUPLICATE', maar wel triggers en rules, waarmee je veel flexibelere oplossingen kunt maken.

De test tabel

Deze tabel kun je gebruiken om deze rule en trigger mee te testen:

  1. CREATE TABLE users(
  2.   userid SERIAL,
  3.   username VARCHAR(255),
  4.   spampoints INTEGER
  5. );

Er zit op deze tabel geen unique contraint. Dat is om aan te tonen dat de rules en triggers inderdaad werken. In productie zou je er natuurlijk wel een unique op zetten.

Oplossingen

De Rule oplossing

Met een RULE is de ON DUPLICATE zo gepiept:

  1. CREATE RULE
  2.     users_rule
  3. AS
  4.     ON INSERT TO
  5.         users
  6.     WHERE
  7.         (EXISTS ( SELECT 1 FROM users
  8. WHERE users.username= new.username))
  9.     DO INSTEAD
  10.         (UPDATE users
  11.             SET
  12.     spampoints = users.spampoints + 1
  13. WHERE
  14.     users.username = new.username);

De trigger oplossing

Als het perse nodig moet zijn dat je meerdere dubbelen tegelijk in kunt voeren dan is er altijd nog de goede oude trigger:

  1. CREATE OR REPLACE
  2.     FUNCTION users_update_trigger() RETURNS
  3. TRIGGER
  4. AS
  5.     $body$
  6.     DECLARE
  7.         junk integer;
  8.     BEGIN
  9.          SELECT INTO junk 1 FROM
  10. users WHERE username=NEW.username;
  11.     IF FOUND THEN
  12.         UPDATE users SET spampoints =
  13. spampoints+1 WHERE username=NEW.username ;
  14.         RETURN NULL;
  15.     ELSE
  16.         NEW.spampoints=1;
  17.         RETURN NEW;
  18.     END IF;
  19.  
  20. END;
  21. $body$
  22. LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY
  23. INVOKER;

Let op dat de trigger hier NULL teruggeeft om te voorkomen dat de INSERT alsnog wordt gedaan. Let ook op dat ik de waarde van spampoints hier op 1 forceer. Ik ga er stiekum vanuit dat je niet ook nog eens een waarde voor spampoints mee gaat geven als je een dubbel record in zit te voeren. (oh wat heerlijk tegendraads dit allemaal...)

En de trigger:

  1. CREATE TRIGGER users_tr
  2. BEFORE
  3.     INSERT
  4. ON
  5.     users
  6. FOR EACH
  7.     ROW
  8. EXECUTE PROCEDURE
  9.     users_update_trigger();

Teruggeplaatst van "http://www.yapf.net/index.php/Duplicaten_in_PostgreSQL"

Deze pagina is 278 maal bekeken. Deze pagina is het laatst bewerkt op 21 dec 2008 om 12:30.


Zoeken

Bladeren
Hoofdpagina
Gebruikersportaal
In het nieuws
Recente wijzigingen
Willekeurige pagina
Hulp
Bewerken
Brontekst bekijken
Hulp bij bewerken
Paginaopties
Overlegpagina
Opmerking toevoegen
Printervriendelijke versie
Pagina-informatie
Paginageschiedenis
Verwijzingen naar deze pagina
Verwante wijzigingen
Mijn pagina's
Aanmelden / registreren
Speciale pagina’s
Nieuwe pagina's
Bestandslijst
Statistieken
Foutrapporten
Meer …