PHP SQL Check Referential Integrity for whole DB - mysql

I was wondering if there was an option to check the referntial integrity of my database without checking everything manually. I must mention that I'm completely new to SQL and have the task to check the referential integrity.
With the search I found this question:
how to find records that violate referential integrity
which was already helpful, but I got quite a lot of tables and I was wondering if there was a faster way than writting hundreds of the querys in the format of the question I found.
Thanks for helping,
Yíu
EDIT:
I know that most databases check that automatically, but I'm a student and the task says
"These scripts should illustrate updating and referential integrity of your database.
! Please point explicitly where you check referential integrity (adding rows, modifying rows, deleting rows). "
So I guess I have to check it manually.

The most databases check referencing, like MySQL too. So have a look at FOREIGN KEY and REFERENCES command
http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
Sample from MySQL page
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE
) ENGINE=INNODB;
Child automatically check and need parent row. If you delete parents, all child rows will deleted to (ON DELETE CASCADE).

Related

MySQL "Duplicate Foreign Key", but key doesn't exist

I need to create a foreign key, but executing the following results in the error: "Error Code: 1826. Duplicate foreign key constraint name 'FK_ProjectBase_Program'"
alter table ipos5.ProjectBase
add constraint FK_ProjectBase_Program foreign key (Program) references Program(OID);
If I execute:
select *
from information_schema.TABLE_CONSTRAINTS
where CONSTRAINT_TYPE = 'FOREIGN KEY'
result = def ipos5 FK_ProjectBase_Program ipos5 projectbase FOREIGN KEY
I can see the existing key definition, but if I show the structure for the target TABLE_NAME, it is not there.
This is on an active database with a large amount of data, using InnoDB, so dump/restore is a very last resort.
I am using a 3rd party framework, which does not allow me to manually specify a foreign key name (so I HAVE to use the one specified), but my application errors during startup because it cannot create the key.
Is there a way to rebuild the information_schema database? I am really hoping to avoid doing a dump and rebuild of the application database, as it is quite large.
I ended up duplicating the table structure, copying the data into it, dropping the original table, then re-creating it and copying the data back. Orphaned foreign key reference is now gone.

Cascading delete removes unintended records

I typically develop in MS Access and occasionally connect to a MySQL back end. I have a MySQL back end that isn't cascading deletes as I'd expect when I delete records. I'm wondering if it's because of how I've set up the table relationships (foreign keys). I don't know enough about MySQL to know if I've done this right. In designer view I set up the relationships using the designer view in MySQL. For a composite primary key field (InterviewID, Coder ID) in tblInterviews I created two separate relations to tblSB for each of these two primary key fields (tblSB includes a 3rd field, SBid, as its composite PK). The designer view is a little different from Access in that you can't highlight more than one field at a time to set up relationships. I did find forums that discuss the syntax for setting up the relationship with the foreign key but I don't know if it's equivalent to what I did in designer. I suspect not because currently when I try to delete a specific record (unique InterviewID, CoderID combination) ALL interview records for the CoderID in the InterviewID, CoderID combination get deleted (and this cascades through to other child tables as well). I also am wondering if I need to set up my primary key in a way that I am not currently doing (e.g., setting it up as an index, also). Any help would be appreciated. Thanks in advance.
To see what you've created, look at the DDL. (SHOW CREATE TABLE)
To enforce foreign key constraints--including cascading deletes--you probably want to use the innodb engine. The myisam engine will accept DDL that declares foreign keys, but it won't enforce them.
MySQL will let a foreign key target a non-unique column. The MySQL docs say
Deviation from SQL standards: A FOREIGN KEY constraint that references
a non-UNIQUE key is not standard SQL. It is an InnoDB extension to
standard SQL.
They call it an extension to SQL. I call it a mistake.
It means you can declare tblSB.interviewID as a foreign key referencing tblInterviews.interviewID. A standard SQL dbms wouldn't allow that.
The 5.6 docs say
However, the system does not enforce a requirement that the referenced
columns be UNIQUE or be declared NOT NULL. The handling of foreign key
references to nonunique keys or keys that contain NULL values is not
well defined for operations such as UPDATE or DELETE CASCADE. You are
advised to use foreign keys that reference only UNIQUE and NOT NULL
keys.
To my way of thinking, they're saying, "It was a bad idea, but we don't know how to fix it. So it's up to you to avoid it. We could warn you when you try it, but we're not going to do that, either."
Based on your comments, I'd say this constraint is right . . .
CONSTRAINT tblInterviewRecordtblSB
FOREIGN KEY (InterviewID, CoderID)
REFERENCES tblinterviewrecord (InterviewID, CoderID)
ON DELETE CASCADE ON UPDATE CASCADE
but these two are not, and should be deleted.
CONSTRAINT tblSB_ibfk_1
FOREIGN KEY (InterviewID)
REFERENCES tblinterviewrecord (InterviewID)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT tblSB_ibfk_2
FOREIGN KEY (CoderID)
REFERENCES tblinterviewrecord (CoderID)
ON DELETE CASCADE ON UPDATE CASCADE

Adding constraints in phpMyAdmin

I feel like I'm being stupid, but I can't find anywhere on the phpMyAdmin interface to add constraints to foreign keys e.g. CASCADE ON DELETE
I've looked for similar questions on here and on the phpMyAdmin wiki but I can't find anything about it.
I realise I could do this via the query interface, but I'd like to know how to do it through the graphical interface.
First, you should have your storage engine as InnoDB. Then select a table and go to 'Structure' tab.
Under the table you will see 'Relation view', click it. From there you could add constraints.
CASCADE
Whenever rows in the master (referenced) table are deleted (resp. updated), the respective rows of the child (referencing) table with a matching foreign key column will get deleted (resp. updated) as well. This is called a cascade delete (resp. update[2]).
RESTRICT
A value cannot be updated or deleted when a row exists in a foreign key table that references the value in the referenced table. Similarly, a row cannot be deleted as long as there is a reference to it from a foreign key table.
NO ACTION
NO ACTION and RESTRICT are very much alike. The main difference between NO ACTION and RESTRICT is that with NO ACTION the referential integrity check is done after trying to alter the table. RESTRICT does the check before trying to execute the UPDATE or DELETE statement. Both referential actions act the same if the referential integrity check fails: the UPDATE or DELETE statement will result in an error.
SET NULL
The foreign key values in the referencing row are set to NULL when the referenced row is updated or deleted. This is only possible if the respective columns in the referencing table are nullable. Due to the semantics of NULL, a referencing row with NULLs in the foreign key columns does not require a referenced row.
Firstly, you should choose storage engine as InnoDB.
Follow this way: click database_name -> More -> Designer

mysql drop foreign key without table copy

I have an InnoDB table claims which has about 240 million rows. The table has a foreign key constraint: CONSTRAINT FK78744BD7307102A9 FOREIGN KEY (ID) REFERENCES claim_details (ID). I want to delete the table claim_details as quickly as possible.
Based on some experimentation it seems that if I use SET foreign_key_checks = 0; drop claim_details and then re-enable foreign keys, mysql will continue to enforce the constraint even though the table no longer exists. So, I believe I must drop the constraint from the table.
I have tried to use ALTER TABLE claims DROP FOREIGN KEY FK78744BD7307102A9 to drop the constraint and the query has been in a state of "copy to tmp table" for over 24 hours (on a machine with no other load). I don't understand why dropping a constraint requires making a copy of the table. Is there any way to prevent this?
mysql version 5.1.48.
Starting with MySQL 5.6, MySQL supports dropping of foreign keys in-place/without copying. Oracle calls this Online DDL.
This table lists all Online DDL operations and their runtime behavior.
From my experience, dropping foreign keys and the corresponding constraints on a 600GB table is almost instantaneous. With 5.5 it would probably have taken days.
The only disadvantage that I am aware of is, that 5.6 does not allow you to reclaim table space. I.e. if you are using innodb_file_per_table, that file will not shrink when you drop indices. Only the unused data in the file will grow. You can easily check using SHOW TABLE STATUS, and the Data_free column.
I think there is no a good way to drop that foreign key
http://dev.mysql.com/doc/refman/5.5/en/innodb-create-index-limitations.html
"MySQL 5.5 does not support efficient creation or dropping of FOREIGN KEY constraints. Therefore, if you use ALTER TABLE to add or remove a REFERENCES constraint, the child table is copied, rather than using Fast Index Creation." This probably refers also to older versions of mysql.
I think the best method will be to dump data from claims with mysqldump, recreate table without foreign key referencing to claim_details, disable key check with SET foreign_key_checks = 0; in case you have other foreign keys and import back data for claims. Just remember to make separate dumps for data and structure so you don't need to edit this huge file to remove foreign key from table creation syntax.

delete 1 record from a table and automatically delete all records associated with the user_id in mysql

I have been trying to learn from reading tutorials online and stuff but I just can't put my finger on it.
I have 2 tables at the moment (i'll have a lot more later on as I build my application) so I want to knock out this issue before expanding and coding.
I have my tables set to use InnoDB and I have each table related to each other by using user_id as foreign keys.
If i issue a DELETE query on the main users table, how can i get all records from other tables that are linked to the user_id field get deleted as well?
I know its simple, but I think I just need to ask the question myself so I can understand the answer rather than reading the answer... heh
thank a lot for any help.
Since they are InnoDB tables with proper FK relationships, you can simply use ON DELETE CASCADE in the foreign key definition. For example in one of the related tables:
FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE
However, this requires altering your existing schema to modify the foreign keys.
See the MySQL FOREIGN KEY docs for complete information.
You can cascade the DELETE using a DELETE trigger or using the technique Michael suggested, or you can manually write enough DELETE statements (deleting the entities from the bottom of the hierarchy upwards so you don't violate the foreign key constraints) though the latter is clearly not an ideal solution in terms of maintenance.
You may wish to use the TRIGGER approach if you want to fine tune the delete process (e.g. in case you don't want to destroy certain data related to the foreign key, or if you wanted to move it elsewhere or associate it to a different ID).
this is mysql example
ALTER TABLE table_with_foregin_key ADD FOREIGN KEY ( foreign_key_column )
REFERENCES table_name (
user_id
) ON DELETE CASCADE ON UPDATE CASCADE;