Как решить проблему дублирования кода в следующем запросе PostgreSQL? - PullRequest
0 голосов
/ 06 августа 2010

У меня есть таблица Inputs и производная таблица Параметры

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 )
);

Следующий запрос проверяет, был ли параметр изменен или еще не присутствует, и вставляет параметр с новым значением.

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 );
}

Как мне лучше всего решить дублирование 2 подзапросов MyParameter?

Любые другие советы по очистке запроса, подобного этому

1 Ответ

3 голосов
/ 06 августа 2010

Вам следует избегать ненормализованных таблиц. Вы должны использовать представление для удобного просмотра таблицы параметров. Это было бы намного, намного проще.

Вы должны использовать ненормализованную сводную таблицу, только если ваше представление недостаточно быстрое. Но любые ненормализованные таблицы должны поддерживаться с помощью триггеров, так как в противном случае вы рискуете, что эти таблицы выйдут из синхронизации.

Для этого вы можете создать триггер на Parameters, который вставит в Inputs при вставке. Если вы когда-либо удаляете или обновляете эти столбцы в Parameters, тогда поддержка Inputs будет затруднена. Вы должны были бы удалить строки, когда в Parameters нет соответствующей строки - вам нужно сохранить счет в Inputs, чтобы знать, когда в Parameters нет соответствующей строки. Производительность одновременного вставки / обновления / удаления будет плохой, так как любое изменение в Parameters должно блокировать строку в Inputs. Это все безобразно и плохо - вид - намного лучшее решение.

...