Foro de elhacker.net

Programación => Bases de Datos => Mensaje iniciado por: bettu en 18 Noviembre 2017, 13:47 pm



Título: Implementar un disparador en Postgresql
Publicado por: bettu en 18 Noviembre 2017, 13:47 pm
Buenas!

Estoy intentando implementar un disparador (o disparadores) en Postgresql. Me piden que se mantenga correctamente actualizada la columna number_toys de la tabla LETTER. Se quiere mantener el cálculo de nombre de juguetes frente a posibles cambios que se puedan producir a los juguetes pedidos en las cartas. Se puede suponer que los usuarios o programas no actualizarán nunca directamente la columna number_toys de la tabla LETTER, y que en el momento de insertar una nueva carta, el valor de la columna number_toy serà 0.

El schema que tengo es el siguiente:

Código
  1. BEGIN WORK;
  2. SET TRANSACTION READ WRITE;
  3.  
  4.  
  5. SET datestyle = DMY;
  6.  
  7. CREATE TABLE CHILD(
  8. child_id SMALLINT,
  9. child_name VARCHAR(255) NOT NULL,
  10. birth_date DATE NOT NULL,
  11. gender VARCHAR(255) NOT NULL,
  12. address VARCHAR(255),
  13. city VARCHAR(255),
  14. CONSTRAINT PK_CHILD PRIMARY KEY(child_id),
  15. CONSTRAINT VALID_GENDER CHECK (gender IN ('m', 'f')),
  16. CONSTRAINT VALID_DATE CHECK (birth_date <= now())
  17. );
  18.  
  19. CREATE TABLE SIBLING(
  20. child_id1 SMALLINT,
  21. child_id2 SMALLINT,
  22. CONSTRAINT PK_SIBLING PRIMARY KEY(child_id1, child_id2),
  23. CONSTRAINT CHILD1_FK FOREIGN KEY (child_id1) REFERENCES CHILD(child_id),
  24. CONSTRAINT CHILD2_FK FOREIGN KEY (child_id2) REFERENCES CHILD(child_id)
  25. );
  26.  
  27.  
  28. CREATE TABLE LETTER(
  29. letter_id SMALLINT,
  30. arrival_date DATE NOT NULL DEFAULT NOW(),
  31. number_toys INTEGER NOT NULL DEFAULT 0,
  32. child_id SMALLINT,
  33. CONSTRAINT PK_LETTER PRIMARY KEY(letter_id),
  34. CONSTRAINT CHILD_FK FOREIGN KEY (child_id) REFERENCES CHILD(child_id),
  35. CONSTRAINT VALID_CHILD_ID CHECK (child_id IS NOT NULL)
  36. );
  37.  
  38. CREATE TABLE TOY(
  39. toy_id SMALLINT,
  40. toy_name VARCHAR(255) NOT NULL,
  41. price REAL NOT NULL,
  42. toy_type VARCHAR(255) NOT NULL,
  43. manufacturer VARCHAR(255),
  44. CONSTRAINT PK_TOY PRIMARY KEY(toy_id),
  45. CONSTRAINT POSITIVE_PRICE CHECK (price > 0),
  46. CONSTRAINT VALID_TYPE CHECK(toy_type IN ('symbolic', 'rule', 'educational', 'cooperative', 'other'))
  47. );
  48.  
  49. CREATE TABLE WISHED_TOY(
  50. letter_id SMALLINT,
  51. toy_id SMALLINT,
  52. CONSTRAINT PK_WISHED_TOY PRIMARY KEY(letter_id, toy_id),
  53. CONSTRAINT LETTER_FK FOREIGN KEY (letter_id) REFERENCES LETTER(letter_id),
  54. CONSTRAINT TOY_FK FOREIGN KEY (toy_id) REFERENCES TOY(toy_id)
  55. );
  56.  
  57.  
  58. CREATE TABLE FAMILY_TOYS(
  59. child_id SMALLINT,
  60. sibling_id SMALLINT,
  61. letter_id SMALLINT,
  62. toy_id SMALLINT,
  63.  
  64. CONSTRAINT PK_FAMILY_TOYS PRIMARY KEY(child_id, sibling_id, letter_id, toy_id),
  65. CONSTRAINT FAMILY_FK_SIBLING FOREIGN KEY (child_id,sibling_id) REFERENCES SIBLING(child_id1, child_id2),
  66. CONSTRAINT FAMILY_FK_LETTER FOREIGN KEY (letter_id) REFERENCES LETTER(letter_id),
  67. CONSTRAINT FAMILY_FK_TOY FOREIGN KEY (toy_id) REFERENCES TOY(toy_id)
  68. );
  69.  
  70. COMMIT;
  71.  

Por ahora lo que tengo es esto, pero no es correcto y no sé que es lo que me falta/falla. ¿Alguna alma caritativa por favor?  :-* :-* :-*

Código
  1. BEGIN
  2.  
  3. RAISE INFO ''update_numbertoys_letter execution'';
  4.  
  5.  
  6. IF (TG_OP = ''UPDATE'') THEN
  7.  
  8.    PERFORM update_numbertoys_by_letter(NEW.child_id);
  9.    IF(NEW.child_id <> OLD.child_id) THEN
  10.        PERFORM update_numbertoys_by_letter(OLD.child_id);
  11.    END IF;
  12.    RETURN NULL;
  13. ELSIF (TG_OP = ''INSERT'') THEN
  14.    PERFORM update_numbertoys_by_letter(NEW.child_id);
  15. ELSIF (TG_OP = ''DELETE'') THEN
  16.    PERFORM update_numbertoys_by_letter(OLD.child_id);
  17. END IF;
  18.  
  19. RETURN NULL;
  20.  
  21. END;
  22. ' LANGUAGE plpgsql;
  23.  
  24. CREATE TRIGGER trigger_update_numbertoys_letter AFTER INSERT OR DELETE OR UPDATE OF child_id ON child FOR EACH ROW  
  25. EXECUTE PROCEDURE update_numbertoys_letter();
  26.  
  27. COMMIT;


Gracias,