[Leaplist] coding - rdbms, revisions, and fks

John Simpson jms1 at jms1.net
Thu Dec 3 04:42:40 EST 2009


On 2009-11-30, at 1258, Jason Boxman wrote:
> 
> An excellent approach that naturally lends itself to managing invoices.  I suppose the solution naturally follows the described problem.
> 
> A better example of the issue is, let's say I have four tables:
> 
> people, addresses, campaigns, mailings.
> 
> A person can belong to a campaign via a mailing many times.  Each time, a mailing would be sent to an address, of which a person can have many addresses.
> 
> If a person or address is ever removed that is a part of a mailing, the integrity of the whole thing blows up.  Historically, at least, 2 years after a mailing, if a person is removed, the accurate count of recipients is wrong.  That might effect the calculated response rate, return rate, and so forth in some report of historical data.
> 
> So some mechanism must exist to handle such a situation.

as you do the mailings, add a record to a history table which contains snapshots of whatever data you might need in the future.

what you're really after is a permanent record: something electronic which serves the same purpose as a file cabinet full of paper, but without the file cabinets or paper. and you need to be able to submit custom queries against it, because you don't know what kinds of questions you're going to need to answer in the future.

to me that sounds like a job for a new SQL table. for the sake of this discussion, let's call the new table "history".

since "people" and "addresses" are the things which might be changed or removed over time, keep a record of what their values were at the time you used them by copying the full contents of every field in those records into your "history" table, as you actually process the lists.

i'm assuming this is a normal direct-mail system, where a single campaign might consist of multiple mailings, each person might have multiple addresses, and each piece mailed is sent to one specific address. your existing schema will look something like this:

people:
	pid	int4		not null primary key
	name	varchar(40)	not null

addresses:
	aid	int4		not null primary key
	pid	int4		not null references people ( pid )
	addr1	varchar(40)	not null
	addr2	varchar(40)
	city	varchar(30)	not null
	state	char(2)		not null
	zip	char(9)		not null

campaigns:
	cid	int4		not null primary key
	descr	varchar(40)	not null

mailings:
	mid	int4		not null primary key
	cid	int4		not null references campaigns ( cid )
	cseq	int4		not null
	started	timestamp
	ended	timestamp
	count	int4		not null default 0

the "history" table would look something like this...

history:
	hid	sequence	not null primary key
	sent	timestamp	not null default now

	mid	int4		not null references mailings ( mid )
	mseq	int4		not null

	pid	int4		not null
	name	varchar(40)	not null

	aid	int4		not null
	pid	int4		not null
	addr1	varchar(40)	not null
	addr2	varchar(40)
	city	varchar(30)	not null
	state	char(2)		not null
	zip	char(9)		not null

as you process the mail pieces, you execute "INSERT INTO history" queries which contain the mid (mailing id you're processing) and mseq (sequence of this piece within the processing of that mailing, which your program will calculate in memory as you go along) as well as the full contents of the "people" and "messages" records you're using to get the data for the label.


> And yet old information needs to be hidden from view, for example.  It's kind of like reference counting garbage collection.  A person can't go away via DELETE if there's any existing reference, or bad stuff happens.

if the historical data is in a separate "history" table, then it cannot and will not show up in your existing queries which don't use that table. this makes it about as "hidden from view" as you can get.

you can (and probably should) make the history table table "write only" by using GRANT and REVOKE to ensure that the SQL user which the app uses, does not have UPDATE or DELETE permission on the table.

REVOKE ALL ON history FROM xyz
GRANT SELECT,INSERT ON history TO xyz

you may need to adjust the syntax for whatever SQL server you're using, but i'm sure you see the idea.


> The more complicated case is, if an address is changed, maybe the street is changed, because a mailing came back, and there's a report that tracks returned mails.  The output of the report is now incorrect.  So then can an address never be changed if it is assigned to a mailing?

the address in the "history" record cannot be changed. after all, you can't change the fact that you did actually send a mail piece to that address.

however, you can change the address in the "live" tables any time you like. the historical record won't be changed at all.

the upshot is this: your reporting programs are going to have to be changed to use the history table. however, that can be a good thing. not only can your report show what the address was that you actually sent it to, but you can compare that to the "live" records and tell whether or not the record has been changed since.


> Or in that case, do you have a mailings_addresses table and simply copy it at that time, so the original address can be changed or deleted as necessary in the future as clerical needs demand.

which is basically the same thing i described above.


> In my case, I am implementing an is_deleted column for managing deleted records, perhaps disallowing DELETE unless there's some big fat warning and a specific level of granted access.

that's also a good idea, for a few reasons:

- it allows you to remove records from processing

- it allows you to "un-delete" records if needed

you could also only GRANT SELECT,INSERT,UPDATE on the tables for the app's SQL user, and if you ever need to DELETE anything you would either have to do it manually, or go into a special administration area (or a different app) which logs into the SQL server using a different userid, and is therefore allowed to execute DELETE queries in those tables.


----------------------------------------------------------------
| John M. Simpson    ---   KG4ZOW   ---    Programmer At Large |
| http://www.jms1.net/                         <jms1 at jms1.net> |
----------------------------------------------------------------
| http://video.google.com/videoplay?docid=-1656880303867390173 |
----------------------------------------------------------------





-------------- next part --------------
A non-text attachment was scrubbed...
Name: PGP.sig
Type: application/pgp-signature
Size: 194 bytes
Desc: This is a digitally signed message part
Url : http://lists.leap-cf.org/pipermail/leaplist/attachments/20091203/87ec09de/PGP.bin


More information about the Leaplist mailing list