Hi Sam,

On Wed, 20 Jun 2007 15:33:23 -0400, you wrote:

>Not specific to SQLite, but we're working on an app that needs to keep
>versioned data (i.e., the current values plus all previous values).  The
>versioning is integral to the app so it's more than just an audit trail or
>history.
>
>Can anyone share experiences with the database structure for this type of
>requirement or point me to helpful resources?

Joe Celko has a good chapter on temporal data
in his book "SQL for smarties" [1].

Some time ago I found a bash script from Mike Chirico
which maintains a notes database:
http://souptonuts.sourceforge.net/code/n.html
and changed it to my liking as a 
demonstration of temporal data [2].

Editing it for publication here may have introduced some
mistakes, testing is left to you ;)

References and quotes:
[1]
Google for ISDN-13: 978-0-12-369379-2

[2]
-- init database
PRAGMA page_size=4096;
PRAGMA cache_size=100;
PRAGMA default_cache_size=100;

-- define schema
BEGIN TRANSACTION;

 DROP TABLE IF EXISTS notes;
 CREATE TABLE notes (
        nkey      INTEGER PRIMARY KEY, -- names ROWID
        -- category left out in this demo
        msg       TEXT
 );

-- '9999-12-31 23:59:59' means 'end-of-times'
 DROP TABLE IF EXISTS audit;
 CREATE TABLE audit (
        nkey      INTEGER,
        -- category left out in this demo
        msg       TEXT,
        timeFr    DATETEXT,
        timeTo    DATETEXT DEFAULT '9999-12-31 23:59:59',
        PRIMARY KEY (nkey,timeFr)
 );

 CREATE TRIGGER audit_insert_notes 
 AFTER INSERT ON notes FOR EACH ROW 
  BEGIN
        INSERT INTO audit (nkey, msg, timeFr)
         VALUES (new.nkey, new.msg, CURRENT_TIMESTAMP);
  END;

 CREATE TRIGGER audit_update_notes 
 AFTER UPDATE ON notes FOR EACH ROW
 BEGIN 
  UPDATE audit SET timeTo = CURRENT_TIMESTAMP
   WHERE nkey == new.nkey
     AND timeTo == '9999-12-31 23:59:59';
  INSERT INTO audit (nkey, msg, timeFr)
   VALUES (new.nkey, new.msg, CURRENT_TIMESTAMP);
 END;

 CREATE TRIGGER audit_delete_notes
 AFTER DELETE ON notes FOR EACH ROW
 BEGIN
  UPDATE audit SET timeTo = CURRENT_TIMESTAMP
        WHERE nkey == old.nkey
     AND timeTo == '9999-12-31 23:59:59';
  END;

 DROP VIEW IF EXISTS sh_audit;
 CREATE VIEW sh_audit AS
  SELECT *,
        strftime('%H:%M:%S',
        (strftime('%s',CASE timeTo 
                WHEN '9999-12-31 23:59:59' THEN CURRENT_TIMESTAMP
                ELSE timeTo 
        END) - strftime('%s',timeFr)),'unixepoch') AS lifespan
  FROM audit
  ORDER BY nkey,timeFr;

 DROP VIEW IF EXISTS sh_status;
 CREATE VIEW sh_status AS
  SELECT
        COUNT(CASE 
                WHEN timeTo == '9999-12-31 23:59:59' THEN 1 
                ELSE NULL 
        END) AS active,
        COUNT(CASE 
                WHEN timeTo <   CURRENT_TIMESTAMP    THEN 1
                ELSE NULL
        END) AS deleted
   FROM audit
  GROUP BY nkey;

COMMIT;  -- done definitions

-- test data
 INSERT INTO notes (msg) VALUES ('note 1 version 1');
 INSERT INTO notes (msg) VALUES ('note 2 version 1');
 UPDATE notes SET msg = 'note 1 version 2' WHERE nkey == 1;
 UPDATE notes SET msg = 'note 2 version 2' WHERE nkey == 2;
 UPDATE notes SET msg = 'note 1 version 3' WHERE nkey == 1;

-- queries
SELECT * FROM sh_audit;
SELECT * FROM sh_status;

SELECT 'notes';
SELECT * FROM notes;

SELECT 'audit';
SELECT * FROM audit;

SELECT 'audit with timediff';
SELECT * FROM sh_audit;


>Thanks,
>
>Sam
>

I hope this helps.
-- 
  (  Kees Nuyt
  )
c[_]

-----------------------------------------------------------------------------
To unsubscribe, send email to [EMAIL PROTECTED]
-----------------------------------------------------------------------------

Reply via email to