Search code examples
phpmysqlvalidationdata-integrity

Data integrity and restrictions


Using the following table layout:

TABLE Something
(
    SomethingId             
    Name      
    DateCreated
    IsObsolete ('Y','N')       
    PRIMARY KEY (SomethingId)
    Foreign Key (SomethingTypeCode)
;


TABLE SomethingType
(
    SomethingTypeCode ('1','2','3')             
    Description             
    PRIMARY KEY (SomethingTypeCode)
);

With a PHP/MySQL setup is there some way that I can restrict through a constraint or index that for each SomethingTypeCode (1, 2, 3) identified in the Something table, there can only be one IsObsolete = N associated with it?

I hope that explains what I am trying to accomplish. I just don't know what to look into to resolve this. I want data integrity to be maintained as much as possible in the db itself and then extend that to the PHP.


EDIT:

In response to the confusion I am getting with VoteyDisciple answer.

EmailTypeCode: P = Personal, B = Business, S = School

Here is my design:

enter image description here

This will allow a Person to have more then one type of email in a given typecode (i.e. 2 business emails) and avoid duplication in the db and not require any nulls. Since i am only concerned with having one active email in each category (the one that will be used by the system) that is where the IsObsolete comes into play. I can keep the history, avoid duplication, avoid nulls, and ensure unique email addresses entered into the system here.

Of course this also brings about my problem as stated in original question.

VoteyDisciple's approach

VoteyDisciple please let me know if I depicted it wrong (or correct).

enter image description here

"If there can be only one for a given type" - Only one active not a time, not only one in the system.
"Now ActiveId can be NULL" - I have emphasized I do not want NULLs
"or it can point to a specific Something record." The type defines the record.

On top of my responses above this seems to add undo complexity into any queries. My responses are based on my understanding of what you have presented. We are either not understanding each other or it is only on my end. I appreciate your input, but as presented I don't see it as a viable solution.


Solution

  • You should be able to deal with this in a MySQL trigger:

    DELIMITER $$
    CREATE TRIGGER before_something_update 
    BEFORE UPDATE ON Something
    FOR EACH ROW BEGIN
       IF NEW.IsObsolete = 'N' THEN
          UPDATE Something SET IsObsolete = 'Y' WHERE SomethingId != NEW.SomethingId AND SomethingTypeID = NEW.SomethingTypeId;
       END IF; 
    DELIMITER ;
    

    And something similar on insert. The trigger will check to see if you're trying to set IsObselete to N and if you are then update all the rows that have the same type that are not the current row and set them to Y.

    You may get into issues with deadlocks if you're using InnoDB but I don't think you'll have an issue with MyISAM.