2010-08-06 3 views
0

J'ai un entrées de table et une table dérivée ParamètresComment résoudre la duplication de code dans la requête PostgreSQL suivante?

CREATE TABLE Configurables 
(
    id SERIAL PRIMARY KEY 
); 

CREATE TABLE Inputs 
(
    configurable integer REFERENCES Configurables(id), 
    name text, 
    time timestamp, 
    PRIMARY KEY(configurable, name, time) 
); 

CREATE TABLE Parameters 
(
    configurable integer, 
    name text, 
    time timestamp, 
    value text, 
    FOREIGN KEY(configurable, name, time) REFERENCES Inputs(configurable, name, time) 
); 

Les contrôles de requête suivants si un paramètre a été modifié, ou est présent pas encore, et insère le paramètre avec une nouvelle valeur.

QString PostgreSQLQueryEngine::saveParameter(int configurable, const QString& name, const QString& value) 
{ 
    return QString("\ 
    INSERT INTO Inputs(configurable, name, time) \ 
     WITH MyParameter AS \ 
     (\ 
     SELECT configurable, name, time, value \ 
     FROM \ 
     (\ 
      SELECT configurable, name, time, value \ 
      FROM Parameters \ 
      WHERE (configurable = %1) AND (name = '%2') AND time = \ 
      (\ 
      SELECT max(time) \ 
      FROM Parameters \ 
      WHERE (configurable = %1) AND (name = '%2') \ 
     ) \ 
      UNION \ 
      SELECT %1 AS configurable, '%2' AS name, '-infinity' AS time, NULL AS value \ 
     )AS foo \ 
    ) \ 
     SELECT %1 AS configurable, '%2' AS name, 'now' AS time FROM MyParameter \ 
     WHERE time = (SELECT max(time) FROM MyParameter) AND (value <> '%3' OR value IS NULL); \ 
     \ 
    INSERT INTO Parameters(configurable, name, time, value) \ 
     WITH MyParameter AS \ 
     (\ 
     SELECT configurable, name, time, value \ 
     FROM \ 
     (\ 
      SELECT configurable, name, time, value \ 
      FROM Parameters \ 
      WHERE (configurable = %1) AND (name = '%2') AND time = \ 
      (\ 
      SELECT max(time) \ 
      FROM Parameters \ 
      WHERE (configurable = %1) AND (name = '%2') \ 
     ) \ 
      UNION \ 
      SELECT %1 AS configurable, '%2' AS name, '-infinity' AS time, NULL AS value \ 
     )AS foo \ 
    ) \ 
     SELECT %1 AS configurable, '%2' AS name, 'now' AS time, '%3' AS value FROM MyParameter \ 
     WHERE time = (SELECT max(time) FROM MyParameter) AND (value <> '%3' OR value IS NULL); \ 
    ").arg(configurable).arg(name).arg(value); 
} 

Comment dois-je mieux résoudre la duplication 2 les sous-requêtes myParameter?

d'autres conseils sur le nettoyage d'une requête comme ceci

+0

Est-ce que vous insérez la même configuration, nom et heure dans les deux tables. Vous avez déjà une clé étrangère dans les paramètres qui fait référence aux entrées. Avez-vous vraiment besoin de dé-normalisation? –

+0

Ajouté Définition configurable. Un configurable a une liste d'entrées, une entrée peut être un paramètre. J'ai choisi de le normaliser pour que je puisse facilement obtenir une vue d'ensemble à partir de la table des entrées. (il y a plus de tables dérivant des entrées puis des paramètres) – Pieter

Répondre

3

Vous devez éviter les tables de-normalisées. Vous devriez utiliser une vue pour une vue d'ensemble facile du tableau des paramètres. Ce serait beaucoup, beaucoup plus facile.

Vous ne devez utiliser la table récapitulative normalisée que si votre vue n'est pas assez rapide. Mais toutes les tables dénormalisées doivent être gérées à l'aide de déclencheurs, sinon vous risquez de désynchroniser ces tables.

Pour cela, vous pouvez créer un déclencheur sur Parameters qui sera upsert en Inputs lors de l'insertion. Si jamais vous supprimez ou mettez à jour ces colonnes sur Parameters alors le maintien Inputs serait compliqué. Vous devez supprimer des lignes lorsqu'il n'y a pas de ligne correspondante dans Parameters - vous devez maintenir les comptes dans Inputs, pour savoir s'il n'y a pas de ligne correspondante dans Parameters. Les performances d'insertion/mise à jour/suppression simultanées seront nulles, car tout changement dans Parameters devra bloquer une ligne dans Inputs. Tout cela est laid et mauvais - une vue est une meilleure solution.

Questions connexes