Adding a primary key for 2 columns has given me another issue, when INSERTing, that the second part of the key doesn’t automatically get given a value.
On an INSERT, if the ROWID or INTEGER PRIMARY KEY column is not explicitly given a value, then it will be filled automatically with an unused integer, usually one more than the largest ROWID currently in use.
I was thinking of using AUTOINCREMENT but that seems to be advised against, so I’m wondering where I can get a value for the 2nd part of a 2 part key.
So I guess each job is unique, but a client may have several jobs and be repeated in the table and you don’t want the same clien/job pairing twice.
I’m thinking either job should be an AI PK and client ID just a foreign key and index, or this should be more than one table.
Normally I would use a composite key in a 2 col look-up table for many-to-many, but this looks like one-to-many.
I’m no database guru, hopfully one who is can clarify. But I’m thinking the point of a composite key is to ensure a unique pairing. If one column in the key is AI they will be unique anyway making the composite redundant.
I think I understand the issue, unfortunately I’m having trouble thinking of a solution.
There will be an unknown number of clients, each having an unknown number of jobs. What you are looking for is a way to have something like “nested auto increments” or a “multidimensional array”. When a new client is added they would get the next client id value. And when an existing client has a new job added, that would get the next job id value.
I’m thinking the job table should have a field that keys to the client table but I can’t think of an easy way to have the client table have a field that keys to the job table.
In other words (because both are unknown) client.id = job.client_id
could be doable, but not client.job_id = job.id
This would be the domain of a join table, usually.
What gandalf is roughly describing would be INSERT…SELECT. Something to the tune of
INSERT into `matters` (`mid`,`cid`,`other`,`columns`) SELECT MAX(`mid`)+1, cidvaluehere, "othervalue", "columnsvalue" FROM `matters` WHERE `cid` = cidvaluehere;
Thanks guys. It’s never a good idea to start something like this shortly before bedtime :yawn: and it doesn’t help that I thought I had an answer and went about it half-cock. Thanks for digging deep within my head to realise what I was actually trying to do.
I will make sure I’ve had plenty of coffee before trying your solution Marc.
So the key to solving that mental issue is to understand that you can issue the following command to your SQL server:
SELECT 1,2,3 FROM `matters`
and it will work - it will simply return rows containing the values 1, 2, and 3.
If you specify a literal (read: anything other than a field name), then it returns that literal.
So what we’re telling the system to do is to find the MAX value of the MID, and then the literal values for the rest of the fields. So the INSERT query sees a result that reads as a tuple that matches the number of columns specified, and simply uses those values.
This code will generate a need for a composite PK, which is what your question was trying to do I make no judgements on whether that’s the correct method (partially it depends on your other tables’ structure…) but this will generate a table that looks like
So… it doesn’t want you to autoincrement, but does it automatically for you even if you DONT autoincrement. Because…logic. #4 is the real difference, i suppose…
I don’t… really know that there would be a significant difference if you’re only updating rows on a non-regular and non-intensive basis.
It also sounds like SQLite is running its own overhead by having a hidden automatic not-quite-autoincrementing field in every table. So… shrug
Interesting documentation, I’m not quite sure what to make of this:
the purpose of AUTOINCREMENT is to prevent the reuse of ROWIDs from previously deleted rows.
…
AUTOINCREMENT guarantees that automatically chosen ROWIDs will be increasing but not that they will be sequential.
My take is it’s not recommended because of resource use, though how much of an impact it might be is unclear (I imagine it’s insignificant until it isn’t)
AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and disk I/O overhead and should be avoided if not strictly needed.
The recommended is to have the key be a “rowid” that is pretty much an autoincrement except that ids of deleted rows can be reused.