Oh, and the expectation may not be clear.
Mikes Code set all records IDs, but it won't affect any new records. You'd need something more fancy to compute the nextid for a record and the campaign ID then is a must have value from each INSERT, eg you wouldn't be able to work with calling a stored procedure from the id field and APPEND BLANK, that would cause the next id to be computed for campaign id 0, always.
Overall it's rather not a good idea to have a two part primary key. You would use a autoinc id and campaign id and would use Mieks initial approach. Then you still have a sequential number incrementing with each new record of the whole table and of each campaign. To no the recno of the campaign from that would not be possible, but you could
SELECT id, Cast(0 as int) As recno from TheTable Where campaignID = 42 Readwrite
REPLACE ALL recno with Recno() and then have an on-the-fly generated translation from the overall id as a counter of all records to the recno of the campaign.
If mm really means million, that on the fly translation cursor will have some tenthousand records for an average campaign, but it should still be good enough. And if you only want to know the count, simply do
SELECT Count(*) From TheTable GROUP BY campaignID
There is no need to create a sub counter field. I avoid such computed fields wherever possible at whatever costs. The numbering of records is a moving target, since records can also be deleted. You won't want to renumber, ou won't want to update foreign keys and anything else involved with such computed fields, if you once have tried to work it out that way. It's only a burden without the benefit it would need to have to pay the cost.
Bye, Olaf.