<p>If I have a table structure that is: </p>

<pre><code>code, description, isdeleted
</code></pre>

<p>where <code>code</code> is the primary key.</p>

<p>The user creates a record, then later on deletes it. Because I am using soft deletes the <code>isdeleted</code> will be set to true. Then in my queries I would be doing a select with the where clause <code>and not isdeleted</code></p>

<p>Now if a user goes to create a new record they may see that code 'ABC' doesn't exist so they tried to recreate it. The select statement won't find it because of the where clause. But there will be a primary key index error.</p>

<p>Should the user be allowed to re-use the record? I would think not since the idea of the soft delete is to keep the record for queries on older data so that joins to the 'deleted' record still work. If the user was allowed to re-use the code then they could change the description which might change the view of the historical data. But is it too harsh to stop them from using that code at all?</p>

<p>Or should I be using a completely hidden primary key and then the 'code' field can be re-used?</p>

[{'answer_id': 70149, 'author': 'Wayne', 'author_id': 8236, 'author_profile': 'https://Stackoverflow.com/users/8236', 'pm_score': 2, 'selected': False, 'text': '<p>I know many people have argued that the data should be natural, but you should be using a primary key that is completely separate from your data if you\'re going to be supporting soft deletes without the intention of always re-using the previous record when this situation arises.</p>\n\n<p>Having a divorced primary key will allow you to have multiple records with the same \'code\' value, and it will allow you to "undelete" (otherwise, why bother with a soft delete?) a value without worrying about overwriting something else.</p>\n\n<p>Personally, I prefer the numeric auto-incremented style of ID, but there are many proponents of GUIDs.</p>\n'}, {'answer_id': 70152, 'author': 'deemer', 'author_id': 11192, 'author_profile': 'https://Stackoverflow.com/users/11192', 'pm_score': 2, 'selected': False, 'text': "<blockquote>\n  <p>Or should I be using a completely\n  hidden primary key and then the 'code'\n  field can be re-used?</p>\n</blockquote>\n\n<p>I think you have answered this pretty well yourself.  If you want the user to be able to re-use the deleted codes, then you should have a separate primary key not visisble to the user.  If it is important that the codes be unique, then the users should generally not be entering them anyway.</p>\n"}, {'answer_id': 70214, 'author': 'Chris Roberts', 'author_id': 475, 'author_profile': 'https://Stackoverflow.com/users/475', 'pm_score': 1, 'selected': False, 'text': "<p>I think it depends on the specific data you're talking about.</p>\n\n<p>If the user is trying to recreate code 'ABC', is it the SAME 'ABC' that was in use last time that has now come out of retirement, or is it a completely different 'ABC'?</p>\n\n<p>If it actually refers to the same real-world 'thing', then there may be no harm in simply 'undeleting' it.  After all - it's the same thing, so logically speaking it should show up as the same thing in historical and new queries.  If your user decides they don't need it any more, then they can delete it and it'll go away.  If at some point in the future they need it again, they can effectively un-delete it by adding it in again.</p>\n\n<p>If, however, the new 'ABC' refers to something (in the real world) which is different to the old 'ABC', then you could argue that the 'code' isn't <em>actually</em> a primary key, in which case, if your data doesn't provide any other natural choice, you may just as well create an arbitrary key.  </p>\n\n<p>A big downside of this is that you'll have to be pretty careful not to let the user create two active records with the same 'code', of course.</p>\n"}, {'answer_id': 70230, 'author': 'micahwittman', 'author_id': 11181, 'author_profile': 'https://Stackoverflow.com/users/11181', 'pm_score': 0, 'selected': False, 'text': '<p>When you select records (excluding soft-deletes) to display them in user interface/ output file, use where not isdeleted.</p>\n\n<p>But when the user requests an insert operation, perform two queries.</p>\n\n<ol>\n<li><p>Lookup all records (ignoring isdeleted value).</p></li>\n<li><p>Based on first query result, perform an UPDATE if it exists (and reverse isdeleted flag) or perform a true INSERT if it does not exist.</p></li>\n</ol>\n\n<p>The nuances of the business logic are up to you.</p>\n'}, {'answer_id': 70243, 'author': 'user10479', 'author_id': 10479, 'author_profile': 'https://Stackoverflow.com/users/10479', 'pm_score': 0, 'selected': False, 'text': '<p>I\'ve done this with user tables, where the email is a unique constraint.  If someone cancels there account, their information is still needed for referential integrity, so what I to is set is_deteled to true, and add \'_deleted\' to the email field.  In this way, if the user decides to sign up again in the future, there is no problem for the user and the unique constraint is not broken.</p>\n\n<p>I think soft delete is good in some situations.  For example, if someone deleted their account from this site and you delete their user then all their posts and answers would be lost.  I think it is much better to soft delete and display their user as "deleted user" or something similar... oh, I also believe in divorced primary keys</p>\n'}]
['https://Stackoverflow.com/questions/70123', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/11355/']