2011-12-16 2 views
2

Я разрабатываю приложение, которое требуется для хранения предыдущих версий строк таблицы базы данных для сохранения истории изменений. Я записываю историю в одну и ту же таблицу, но вам нужны самые последние данные для доступа с помощью уникального идентификатора, который не изменяется с новыми версиями. У меня есть несколько идей о том, как это могло быть сделано, и просто искал какие-нибудь идеи на лучшем способе сделать это, или есть ли какая-либо причина не использовать одну из моих идей:Предлагаемые методы для хранения нескольких версий данных строки SQL

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

  2. Когда данные обновляются, версия старой строки дублируется в новую строку, а новая версия заменяет старую строку. К текущей строке можно получить тот же первичный ключ.

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

+0

Конечно, это будет зависеть от использования всей истории, но вы считали таблицу «backup» - таблицу, в которую вы будете перемещать записи ... и будет иметь вашу основную таблицу только с текущей версией каждой строки. –

+0

Любая конкретная причина для записи истории в одной таблице? – UnhandledExcepSean

+0

Я хочу сохранить историю в той же таблице, в которой история может быть просмотрена в любое время, используя тот же код, который отображает текущие данные, а историю можно редактировать и возвращать в текущий момент в любое время. – johna

ответ

1

# 3 вероятно, лучше, но если вы хотите сохранить данные в одной таблице, я полагаю, вы могли бы добавить столбец datetime, у которого есть значение now(), заполненное для каждой новой строки, и тогда вы могли бы по крайней мере отсортировать по дате по убыванию. 1.

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

R

+0

Я не предоставлял слишком много подробностей относительно моих требований, поскольку мне было интересно, есть ли какие-либо методы, которые я упустил, и просто ищу общие методы, не относящиеся к языку или среде. – johna

+0

В итоге я пошел с вариантом №3. Спасибо. – johna

0

Считаете ли вы использование AutoAudit?

AutoAudit является SQL Server (2005, 2008) утилита Code-Gen, которая создает Audit Trail триггерами с:

  • создания, CreatedBy, Modified, ModifiedBy и RowVersion (увеличивающиеся INT) столбцов в таблица
  • Вставить событие заносится в таблицу аудита
  • Статусы старые и новые значения записываются в таблицу аудита
  • Удалять журналы все конечные значения для аудита tbale
  • вида для восстановления удаленных строк
  • UDF реконструировать Ую Историю
  • Схема аудит Trigger для отслеживания схемы изменения
  • перекодировки-рода триггера, когда Alter Table изменяется на таблице
+0

его зависимый от db .... – Ross

+0

@Ross: это только плакат, не сказал, что RDBMS они использовали, и couse я принял SQL Server! ;) Как правило, вы используете один тип БД, поэтому запрос на агностические решения не особенно полезен. –

+0

Я хотел управлять историей в своем собственном коде, поскольку мне нужно время от времени сравнивать и сообщать об изменениях. DB - SQL Server 2008. – johna

0

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

В таблице есть первичный ключ, который заботится о чем еще.
Столбец имеет следующие столбцы: инкрементный первичный ключ int/bigint, история/дата записи, история записи, тип записи (I, U, D для вставки, обновления, удаления), PK из таблицы в виде FK на TableHist, остальные столбцы всех других столбцов с тем же именем находятся в таблице TableHist.

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

+0

Я согласен, что отдельная таблица предпочтительна во многих ситуациях, но по разным причинам (некоторые из них изложены в моем комментарии к моему вопросу выше). Я предпочитаю одну таблицу для своей ситуации. – johna

+0

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

0
create table table1 (
    Id int identity(1,1) primary key, 
    [Key] varchar(max), 
    Data varchar(max) 
) 
go 

create view view1 as 
with q as (
    select [Key], Data, row_number() over (partition by [Key] order by Id desc) as 'r' 
    from table1 
) 
select [Key], Data from q where r=1 
go 

create trigger trigger1 on view1 instead of update, insert as begin 
    insert into table1 
    select [Key], Data 
    from (select distinct [Key], Data from inserted) a 
end 
go 

insert into view1 values 
    ('key1', 'foo') 
    ,('key1', 'bar') 

select * from view1 

update view1 
set Data='updated' 
where [Key]='key1' 

select * from view1 

select * from table1 

drop trigger trigger1 
drop table table1 
drop view view1 

Результаты:

Key Data 
key1 foo 

Key Data 
key1 updated 

Id Key Data 
1 key1 bar 
2 key1 foo 
3 key1 updated 

Я не уверен, если disctinct требуется.

2

PeopleSoft использует (используется?) «Эффективные датированные записи». Потребовалось немного времени, чтобы повесить его, но это послужило своей цели. Бизнес-ключ всегда расширяется столбцом EFFDT (дата вступления в силу). Поэтому, если у вас есть таблица EMPLOYEE [EMPLOYEE_ID, SALARY], она станет EMPLOYEE [EMPLOYEE_ID, EFFDT, SALARY].

Чтобы получить зарплату работника:

SELECT e.salary 
    FROM employee e 
    WHERE employee_id = :x 
    AND effdt = (SELECT MAX(effdt) 
        FROM employee 
        WHERE employee_id = :x 
        AND effdt <= SYSDATE) 

Интересное приложение было будущие записи знакомства: вы могли бы дать каждому работнику увеличение на 10% эффективной 1 января следующего года, а также предварительно poulate таблицу несколько месяцев заранее , Когда SYSDATE пересечет 1 января, новая зарплата вступит в силу. Кроме того, это было полезно для запуска исторических отчетов. Вместо использования SYSDATE вы подключаете дату из прошлого, чтобы видеть зарплату (или обменные курсы или что-то еще), как они были бы сообщены, если они будут выполняться в то время в прошлом.

В этом случае записи никогда не обновляются и не обновляются, вы просто добавляете записи с новыми эффективными датами. Делает более подробные запросы, но он работает и начинает становиться (смею сказать) нормальным. Есть много страниц на этом, например: http://peoplesoft.wikidot.com/effective-dates-sequence-status

Смежные вопросы