I'm trying to add a foreign key constraint to the table ag by using:
alter table ag
add foreign key fk_ag_protein1 (protein_PID) references protein (PID);
But I get the following error message:
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
(`mux_new`.`#sql-884_3`, CONSTRAINT `#sql-884_3_ibfk_1` FOREIGN KEY (`protein_PID`)
REFERENCES `protein` (`PID`))"
To get more details I checked output from:
SHOW ENGINE INNODB STATUS\G
Which was:
LATEST FOREIGN KEY ERROR
------------------------
TRANSACTION 193923, ACTIVE 0 sec inserting, thread declared inside InnoDB 4999
mysql tables in use 2, locked 2
5 lock struct(s), heap size 1248, 2 row lock(s), undo log entries 1
MySQL thread id 3, OS thread handle 0x1714, query id 143 localhost ::1 root copy
to tmp table
alter table ag
add foreign key fk_ag_protein1 (protein_PID) references protein (PID)
Foreign key constraint fails for table `mux_new`.`#sql-884_3`:
,
CONSTRAINT `#sql-884_3_ibfk_1` FOREIGN KEY (`protein_PID`) REFERENCES `protein
` (`PID`)
Trying to add in child table, in index `fk_ag_protein1` tuple:
DATA TUPLE: 2 fields;
0: len 4; hex 80000000; asc ;;
1: len 3; hex 002711; asc ' ;;
But in parent table `mux_new`.`protein`, in index `PRIMARY`,
the closest match we can find is record:
PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 696e66696d756d00; asc infimum ;;
But I do not understand this at all. The table ag currently contains some data but protein does not.
Any ideas of what my problem could be or things I could check?
Protein table:
describe protein output:
+---------------------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------+---------+------+-----+---------+-------+
| PID | int(11) | NO | PRI | NULL | |
| uniprot_UniprotAC | char(6) | YES | MUL | NULL | |
| pubmedhits_id | int(11) | YES | MUL | NULL | |
| internallyDefinedNames_id | int(11) | YES | MUL | NULL | |
| comment | int(11) | YES | MUL | NULL | |
+---------------------------+---------+------+-----+---------+-------+
show create table protein output:
CREATE TABLE `protein` (
`PID` int(11) NOT NULL,
`uniprot_UniprotAC` char(6) COLLATE utf8_unicode_ci DEFAULT NULL,
`pubmedhits_id` int(11) DEFAULT NULL,
`internallyDefinedNames_id` int(11) DEFAULT NULL,
`comment` int(11) DEFAULT NULL,
PRIMARY KEY (`PID`),
KEY `fk_protein_uniprot1_idx` (`uniprot_UniprotAC`),
KEY `fk_protein_pubmedhits1_idx` (`pubmedhits_id`),
KEY `fk_protein_internallyDefinedNames1_idx` (`internallyDefinedNames_id`),
KEY `fk_protein_comments1_idx` (`comment`),
CONSTRAINT `protein_ibfk_4` FOREIGN KEY (`uniprot_UniprotAC`) REFERENCES `uniprot` (`UniprotAC`),
CONSTRAINT `protein_ibfk_1` FOREIGN KEY (`comment`) REFERENCES `comments` (`idcomments`),
CONSTRAINT `protein_ibfk_2` FOREIGN KEY (`internallyDefinedNames_id`) REFERENCES `internallydefinednames` (`id`),
CONSTRAINT `protein_ibfk_3` FOREIGN KEY (`pubmedhits_id`) REFERENCES `pubmedhits` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
ag table:
describe ag:
+-------------+--------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------------------------+------+-----+---------+-------+
| Article_AID | mediumint(5) unsigned zerofill | NO | PRI | NULL | |
| Name | varchar(200) | YES | | NULL | |
| Form | varchar(150) | YES | | NULL | |
| Mw | varchar(40) | YES | | NULL | |
| Source | varchar(260) | YES | | NULL | |
| protein_PID | int(11) | YES | | NULL | |
+-------------+--------------------------------+------+-----+---------+-------+
show create table ag:
`ag` (
`Article_AID` mediumint(5) unsigned zerofill NOT NULL,
`Name` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL,
`Form` varchar(150) COLLATE utf8_unicode_ci DEFAULT NULL,
`Mw` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL,
`Source` varchar(260) COLLATE utf8_unicode_ci DEFAULT NULL,
`protein_PID` int(11) DEFAULT NULL,
PRIMARY KEY (`Article_AID`),
KEY `fk_ag_Article1_idx` (`Article_AID`),
CONSTRAINT `fk_ag_Article1` FOREIGN KEY (`Article_AID`) REFERENCES `article` (`AID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
I figured out what the problem was. In the ag table the protein_PID column was added when there was already data in the table and when it was first created it was set to be not null. Then the rows where all set to 0 for protein_PID as default and since there was no data in protein I could not add the foreign key.
Make PID and protein_PID both to not NULL
May this will solve your issue
Related
I have two huge tables from which i have select huge amount of data.
Tables store Purchase Order Details and product information.
PURCHASE_ORDER_DETAILS.
CREATE TABLE `PURCHASE_ORDER_DETAILS` (
`PURCHASE_ORDER_NUMBER_PF` INT(20) NOT NULL,
`PRODUCT_CODE_PF` VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`ORDER_QUANTITY` INT(8) DEFAULT NULL,
`UNIT_PRICE` DECIMAL(12,2) DEFAULT NULL,
`ORDER_FULLFILLMENT_DUE_DATE` DATETIME DEFAULT NULL,
`DELIVERY_ADDRESS` VARCHAR(64) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`DELIVERY_CITY` VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`DELIVERY_ZIP` BIGINT(10) DEFAULT NULL,
`other columns`
PRIMARY KEY (`PURCHASE_ORDER_NUMBER_PF`,`PRODUCT_CODE_PF`),
KEY `RMAPWBTX_PUCH_ORDE_DLST_INDX` (`DELIVERY_STATE_ID_FK`),
KEY `RMAPWBTX_PUCH_ORDE_DLTY_INDX` (`DELIVERY_TYPE_FK`),
KEY `RMAPWBTX_PUCH_ORDE_TACO_INDX` (`TAX_CODE_FK`),
KEY `RMAPWBMS_PUOR_DETL_PDCO_FK` (`PRODUCT_CODE_PF`),
KEY `RMAPWBTX_PUOR_DETL_TACO_FK` (`TAX_CODE_FK`),
KEY `CREATED_DATE_INDX` (`CREATED_DATE`),
KEY `MODIFIED_DATE_INDX` (`MODIFIED_DATE`),
CONSTRAINT `RMAPWBMS_PUOR_DETL_PDCO_FK` FOREIGN KEY (`PRODUCT_CODE_PF`)
REFERENCES `PRODUCT` (`PRODUCT_CODE_PK`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `RMAPWBMS_PUOR_DETL_PONU_FK` FOREIGN KEY
(`PURCHASE_ORDER_NUMBER_PF`) REFERENCES `PURCHASE_ORDER`
(`PURCHASE_ORDER_NUMBER_PK`),
CONSTRAINT `RMAPWBTX_PO_DETL_DSID_FK` FOREIGN KEY
(`DELIVERY_STATE_ID_FK`) REFERENCES `STATE` (`STATE_ID_PK`),
CONSTRAINT `RMAPWBTX_PUOR_DETL_TACO_FK` FOREIGN KEY (`TAX_CODE_FK`)
REFERENCES `TAX` (`TAX_CODE_PK`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=INNODB DEFAULT CHARSET=latin1;
PRODUCT
CREATE TABLE `PRODUCT` (
`PRODUCT_CODE_PK` VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`PRODUCT_DESC` VARCHAR(256) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`FEE_BILL_CODE` VARCHAR(32) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`other columns`
PRIMARY KEY (`PRODUCT_CODE_PK`),
KEY `CREATED_DATE_INDX` (`CREATED_DATE`),
KEY `MODIFIED_DATE_INDX` (`MODIFIED_DATE`),
KEY `PRODUCT_EXCO_FK` (`EXPENSE_CODE_ID_FK`),
KEY `FK_PRODUCT_ENTITY_TYPE` (`ENTITY_TYPE_CODE_FK`),
CONSTRAINT `FK_PRODUCT_ENTITY_TYPE` FOREIGN KEY (`ENTITY_TYPE_CODE_FK`) REFERENCES `ENTITY_TYPE` (`ENTITY_TYPE_CODE_PK`)
) ENGINE=INNODB DEFAULT CHARSET=latin1
Below query is taking ~10min to get ~1M records.
EXPLAIN SELECT * FROM
PURCHASE_ORDER_DETAILS POD
JOIN PRODUCT PRD ON POD.PRODUCT_CODE_PF=PRD.PRODUCT_CODE_PK;
+----+-------------+-------+------+----------------------------+-----------------
-----------+---------+-----------------------------------------------+-------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+----------------------------+----------------------------+---------+-----------------------------------------------+-------+-------+
| 1 | SIMPLE | PRD | ALL | PRIMARY | NULL | NULL | NULL | 14283 | NULL |
| 1 | SIMPLE | POD | ref | RMAPWBMS_PUOR_DETL_PDCO_FK | RMAPWBMS_PUOR_DETL_PDCO_FK | 34 | REALREMIT_PROD_ALTISOURCE.PRD.PRODUCT_CODE_PK | 40 | NULL |
+----+-------------+-------+------+----------------------------+----------------------------+---------+-----------------------------------------------+-------+---
Edit1:
Above query was an example, below is the actual query where i am trying to fetch 1M records (main table POD has 22M records).
SELECT `some columns`
FROM `REALREMIT_PPIPFC_MIG`.MIGR_ORDER_DENORM MPO
INNER JOIN PURCHASE_ORDER_DETAILS POD
ON MPO.PURCHASE_ORDER_NUMBER_PK=POD.PURCHASE_ORDER_NUMBER_PF
INNER JOIN PRODUCT PRD
ON POD.PRODUCT_CODE_PF=PRD.PRODUCT_CODE_PK
INNER JOIN EXPENSE_CODE EXP
ON PRD.EXPENSE_CODE_ID_FK=EXP.EXPENSE_CODE_ID_PK
WHERE MPO.BATCH_ID=1;
Explain Output for the above query
+----+-------------+-------+--------+-------------------------------------+----------------------------+---------+--------------------------------------------------------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------------------------+----------------------------+---------+--------------------------------------------------------+-------+-------------+
| 1 | SIMPLE | PRD | ALL | PRIMARY,PRODUCT_EXCO_FK | NULL | NULL | NULL | 14283 | NULL |
| 1 | SIMPLE | EXP | eq_ref | PRIMARY | PRIMARY | 4 | REALREMIT_PROD_ALTISOURCE.PRD.EXPENSE_CODE_ID_FK | 1 | NULL |
| 1 | SIMPLE | POD | ref | PRIMARY,RMAPWBMS_PUOR_DETL_PDCO_FK | RMAPWBMS_PUOR_DETL_PDCO_FK | 34 | REALREMIT_PROD_ALTISOURCE.PRD.PRODUCT_CODE_PK | 40 | NULL |
| 1 | SIMPLE | MPO | ref | MIGR_PO_NBR_INDX,MIGR_BATCH_ID_INDX | MIGR_PO_NBR_INDX | 4 | REALREMIT_PROD_ALTISOURCE.POD.PURCHASE_ORDER_NUMBER_PF | 1 | Using where |
+----+-------------+-------+--------+-------------------------------------+----------------------------+---------+--------------------------------------------------------+-------+-------------+
4 rows in set (0.20 sec)
Both database have same charset
Columns used in join have the same collate
Both tables have same charset
I have created new table in which primary key is concatenated column - PURHCASE_ORDER_NUMBER_PF and PRODUCT_CODE_PF and then i have added a new index on PRODUCT_CODE_PF
Will index be used in this case and/or is this the best way to make use of index in join.
Thanks
These may help:
MPO: INDEX(BATCH_ID, PURCHASE_ORDER_NUMBER_PK) -- in this order
EXP: INDEX(EXPENSE_CODE_ID_PK) -- unless it is the PRIMARY KEY
But, without knowing what is in "some columns", I can't predict how much they will help. And it would help to have SHOW CREATE TABLE for MPO and EXP.
How much RAM do you have? What is the value of innodb_buffer_pool_size? I ask because you may be thrashing.
I have 2 main tables (professional_account & professional_profile) and 3 sub tables (prof_knows_about, prof_keywords & prof_recent_jobs) which are 1:many off professional_profile.
A FT search should match the search term in professional_profile.professional_statement, OR any row (for that professional_id) of prof_knows_about.knowledge_desc, OR any row of prof_keywords.keyword OR any row of prof_recent_jobs.job_title
In a 5.6.35 server it works as expected, but in 5.7.10 I only get results if the search term is in professional_profile.professional_statement or prof_knows_about.knowledge_desc - the search term is not found in the other two tables. Both servers run on freeBSD UNIX.
I tried both servers with the query pasted into the shell. Both also give same EXPLAIN output. Used a dump from the 5.7 on the 5.6 to ensure same data and table creates.
I did a show variables on both servers, but hard to compare as there are many extra values in the 5.7. Set both to same sql_mode.
Tables, query and explain listed below.
Is this an issue with my query, or my 5.7 server?
select email, PROFILE.*
FROM professional_account as ACC
join professional_profile as PROFILE on ACC.professional_id=PROFILE.professional_id
join prof_knows_about as KNOWS on PROFILE.professional_id=KNOWS.professional_id
join prof_keywords as KEYW on PROFILE.professional_id = KEYW.professional_id
join prof_recent_jobs as ROLES on PROFILE.professional_id=ROLES.professional_id
where status in ('LIVE','EDITS')
and (
match (knowledge_desc) against ('ramble')
or match (job_title) against ('ramble')
or match (keyword) against ('ramble')
or match (professional_statement) against ('ramble')
)
group by PROFILE.professional_profile_id
+----+-------------+---------+------------+--------+--------------------------------+-----------------+---------+---------------------------+------+----------+---------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+--------+--------------------------------+-----------------+---------+---------------------------+------+----------+---------------------------------+
| 1 | SIMPLE | KNOWS | NULL | ALL | professional_id | NULL | NULL | NULL | 43 | 100.00 | Using temporary; Using filesort |
| 1 | SIMPLE | PROFILE | NULL | ref | PRIMARY,professional_statement | professional_id | 4 | xxx.KNOWS.professional_id | 1 | 28.57 | Using where |
| 1 | SIMPLE | ACC | NULL | eq_ref | PRIMARY | PRIMARY | 4 | xxx.KNOWS.professional_id | 1 | 100.00 | NULL |
| 1 | SIMPLE | ROLES | NULL | ref | professional_id | professional_id | 4 | xxx.KNOWS.professional_id | 1 | 100.00 | NULL |
| 1 | SIMPLE | KEYW | NULL | ref | professional_id | professional_id | 4 | xxx.KNOWS.professional_id | 2 | 100.00 | Using where |
+----+-------------+---------+------------+--------+--------------------------------+-----------------+---------+---------------------------+------+----------+---------------------------------+
CREATE TABLE professional_account (
professional_id int(11) NOT NULL AUTO_INCREMENT,
email varchar(60) NOT NULL,
PRIMARY KEY (professional_id),
KEY email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE professional_profile (
professional_profile_id int(11) NOT NULL AUTO_INCREMENT,
professional_id int(11) NOT NULL,
status enum('BLANK','PART_WAIT','PART_APP','COMP_WAIT','COMP_APP','LIVE','EDITS') DEFAULT NULL,
professional_statement text,
PRIMARY KEY (professional_profile_id),
KEY professional_id (professional_id),
FULLTEXT KEY professional_statement (professional_statement),
CONSTRAINT fk_professional_profile_professional_account FOREIGN KEY (professional_id) REFERENCES professional_account (professional_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE prof_knows_about (
prof_knows_about_id int(11) NOT NULL AUTO_INCREMENT,
professional_id int(11) NOT NULL,
knowledge_desc varchar(100) DEFAULT NULL,
PRIMARY KEY (prof_knows_about_id),
KEY professional_id (professional_id),
FULLTEXT KEY knowledge_desc (knowledge_desc),
CONSTRAINT fk_prof_knows_about_professional_profile1 FOREIGN KEY (professional_id) REFERENCES professional_profile (professional_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE prof_keywords (
prof_keywords_id int(11) NOT NULL AUTO_INCREMENT,
professional_id int(11) NOT NULL,
keyword varchar(20) DEFAULT NULL,
PRIMARY KEY (prof_keywords_id),
KEY professional_id (professional_id),
FULLTEXT KEY keyword (keyword),
CONSTRAINT fk_prof_keywords_professional_profile1 FOREIGN KEY (professional_id) REFERENCES professional_profile (professional_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE prof_recent_jobs (
prof_recent_jobs_id int(11) NOT NULL AUTO_INCREMENT,
professional_id int(11) NOT NULL,
job_title varchar(100) DEFAULT NULL,
experience tinyint(2) DEFAULT NULL,
PRIMARY KEY (prof_recent_jobs_id),
KEY professional_id (professional_id),
FULLTEXT KEY job_title (job_title),
CONSTRAINT fk_prof_recent_jobs_professional_profile1 FOREIGN KEY (professional_id) REFERENCES professional_profile (professional_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE prof_keywords (
prof_keywords_id int(11) NOT NULL AUTO_INCREMENT,
professional_id int(11) NOT NULL,
keyword varchar(20) DEFAULT NULL,
PRIMARY KEY (prof_keywords_id),
KEY professional_id (professional_id),
FULLTEXT KEY keyword (keyword),
CONSTRAINT fk_prof_keywords_professional_profile1 FOREIGN KEY (professional_id) REFERENCES professional_profile (professional_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
So i'm trying to create a library database and was wondering if something i'm trying to achieve is possible through the use of triggers or similar.
I have this table called "category" which contains the different categories that you can borrow, like books or dvds.
And depending on what product category you lend from, you have different times allowed, like books you can borrow for 3 weeks but dvds are only allowed 3 days.
+--------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(100) | NO | | NULL | |
| time_allowed | time | NO | | NULL | |
| days_allowed | varchar(400) | NO | | NULL | |
+--------------+---------------+------+-----+---------+----------------+
And then i have the table "Borrowed" which looks like this
+---------------+-------------------+-------+-----+----------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-------------------+-------+-----+----------------------+-----------------------------+
| id | int(11) | NO | PRI | None | auto_increment |
| item_id | int(11) | NO | | NULL | |
| date_borrowed | timestamp | NO | | CURRENT_TIMESTAMP | |
| return_by | datetime | NO | | None | |
| returned | enum('No','Yes') | NO | | No | |
| borrower_id | int(11) | NO | | None | |
| time_returned | timestamp | Yes | | CURRENT_TIMESTAMP | ON UPDATE CURRENT_TIMESTAMP |
+---------------+-------------------+-------+-----+----------------------+-----------------------------+
Now what i want to do is take the "date_borrowed" from "Borrowed" + "time_allowed" + "days_allowed" from the "Category" table to create the datetime value for "return_by" in the "Borrowed" table.
So if the "date_borrowed" is "2016-01-01 12:00:00" and a dvd is borrowed then the "return_by" should be "2016-01-04 12:00:00".
Is this possible to do through Triggers ?
Any and all feedback is much appreciated.
UPDATE:
CREATE TABLE `borrowed` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`item_id` int(11) DEFAULT NULL,
`date_borrowed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`return_by` datetime NOT NULL,
`returned` enum('No','Yes') CHARACTER SET utf8 NOT NULL DEFAULT 'No',
`borrower_id` int(11) NOT NULL,
`time_returned` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `borrower_id_idx` (`borrower_id`),
KEY `item_id_idx` (`item_id`),
CONSTRAINT `borrowed_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `items` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT `borrower_id` FOREIGN KEY (`borrower_id`) REFERENCES `borrower` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
CREATE TABLE `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) CHARACTER SET utf8 NOT NULL,
`time_allowed` time NOT NULL,
`days_allowed` varchar(400) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
CREATE TABLE `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`item_name` varchar(150) CHARACTER SET utf8 NOT NULL,
`item_uniqueid` varchar(100) CHARACTER SET utf8 NOT NULL COMMENT 'This can be a Serial Number or a ISBN number. But has to be unique for that item',
`item_status` enum('Ok','Damaged','Broken') CHARACTER SET utf8 NOT NULL,
`item_comment` longtext CHARACTER SET utf8,
`item_retired` enum('No','Yes') CHARACTER SET utf8 NOT NULL DEFAULT 'No',
`item_dop` date NOT NULL COMMENT 'item_dop = Item Date Of Purchaes',
`item_category` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `id_category_idx` (`item_category`),
CONSTRAINT `id_category` FOREIGN KEY (`item_category`) REFERENCES `category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
First you need to allow NULLs for the return_by column:
ALTER TABLE `borrowed`
ALTER `return_by` DROP DEFAULT;
ALTER TABLE `borrowed`
CHANGE COLUMN `return_by` `return_by` DATETIME NULL AFTER `date_borrowed`;
Then create a BEFORE INSERT trigger for the borrowed table:
DELIMITER //
CREATE TRIGGER `borrowed_before_insert` BEFORE INSERT ON `borrowed` FOR EACH ROW BEGIN
set new.return_by = (
select new.date_borrowed
+ interval c.days_allowed day
+ interval time_to_sec(c.time_allowed) second
from items i
join category c on c.id = i.item_category
where i.id = new.item_id
);
END//
DELIMITER ;
SQLFiddle-Demo
If you ever update the date_borrowed column, you will also need an UPDATE trigger to ajust the return_by value.
Assuming that you time_allowed is in HOUR, your days_allowed is in number of days (an not a varchar for string) and the two tables are related by a column relation_key and key you could suing a select llike this
select TIMESTAMPADD(HOUR, c.time_allowed,
TIMESTAMPADD( DAY ,c.days_allowed,b.date_borrowed) )
from Borrowed as b
inner join catogory on b.relation_key = c.key
The following query is using the join buffer and I was wondering if someone could explain to me why this is so. Just trying to gain more understanding about mysql and indexing.
mysql> EXPLAIN SELECT events.event_topic_id, event_topic_name, event_topic_image, event_type_name,city_name FROM events
-> JOIN event_topic ON event_topic.event_topic_id=events.event_topic_id
-> JOIN event_type ON event_type.event_type_id = event_topic.event_type_id
-> JOIN locations ON locations.location_id=events.location_id
-> JOIN city ON city.city_id=locations.city_id
-> WHERE event_date > NOW()
-> GROUP BY events.event_topic_id, city.city_id;
+----+-------------+-------------+--------+---------------------------------------+-----------------+---------+--------------------------------------+------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------+--------+---------------------------------------+-----------------+---------+--------------------------------------+------+----------+----------------------------------------------+
| 1 | SIMPLE | city | index | PRIMARY | city_name | 52 | NULL | 6 | 100.00 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | locations | ref | PRIMARY,city_id | city_id | 1 | PremiumCONNECT.city.city_id | 1 | 100.00 | Using index |
| 1 | SIMPLE | events | ref | location_id,event_topic_id,event_date | location_id | 2 | PremiumCONNECT.locations.location_id | 3 | 100.00 | Using where |
| 1 | SIMPLE | event_type | index | PRIMARY | event_type_name | 52 | NULL | 2 | 100.00 | Using index; Using join buffer |
| 1 | SIMPLE | event_topic | eq_ref | PRIMARY,event_type_id | PRIMARY | 1 | PremiumCONNECT.events.event_topic_id | 1 | 100.00 | Using where |
+----+-------------+-------------+--------+---------------------------------------+-----------------+---------+--------------------------------------+------+----------+----------------------------------------------+
Events table:
CREATE TABLE `events` (
`event_id` smallint(8) unsigned NOT NULL AUTO_INCREMENT,
`location_id` smallint(3) unsigned NOT NULL,
`event_date` datetime NOT NULL,
`event_topic_id` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`event_id`),
KEY `location_id` (`location_id`),
KEY `event_topic_id` (`event_topic_id`),
KEY `event_date` (`event_date`),
CONSTRAINT `events_ibfk_2` FOREIGN KEY (`event_topic_id`) REFERENCES `event_topic` (`event_topic_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `events_ibfk_3` FOREIGN KEY (`location_id`) REFERENCES `locations` (`location_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=91 DEFAULT CHARSET=latin1
Event topic table:
CREATE TABLE `event_topic` (
`event_topic_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`event_topic_name` varchar(100) DEFAULT NULL,
`event_topic_description` text NOT NULL,
`event_topic_cost` decimal(7,2) DEFAULT NULL,
`event_type_id` tinyint(3) unsigned NOT NULL,
`event_topic_clickthrough` tinytext,
`event_topic_length` varchar(6) NOT NULL,
`event_topic_image` varchar(41) DEFAULT NULL,
`event_topic_image_md5` char(32) NOT NULL,
PRIMARY KEY (`event_topic_id`),
KEY `event_type_id` (`event_type_id`),
KEY `topic_image_sha1` (`event_topic_image_md5`),
CONSTRAINT `event_topic_ibfk_1` FOREIGN KEY (`event_type_id`) REFERENCES `event_type` (`event_type_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=latin1
Event type table:
CREATE TABLE `event_type` (
`event_type_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`event_type_name` varchar(50) NOT NULL,
`conf_email` text,
PRIMARY KEY (`event_type_id`),
KEY `event_type_name` (`event_type_name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
Locations table:
CREATE TABLE `locations` (
`location_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`location_name` varchar(50) NOT NULL,
`location_address` tinytext NOT NULL,
`location_capacity` smallint(6) NOT NULL,
`city_id` tinyint(3) unsigned NOT NULL,
`gps_coords` varchar(30) DEFAULT NULL,
PRIMARY KEY (`location_id`),
KEY `city_id` (`city_id`),
CONSTRAINT `locations_ibfk_1` FOREIGN KEY (`city_id`) REFERENCES `city` (`city_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1
Cities table:
CREATE TABLE `city` (
`city_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`city_name` varchar(50) NOT NULL,
PRIMARY KEY (`city_id`),
UNIQUE KEY `city_name` (`city_name`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
As it says in 'http://dev.mysql.com/doc/refman/5.1/en/explain-output.html': "Tables from earlier joins are read in portions into the join buffer, and then their rows are used from the buffer to perform the join with the current table."
So in your case, you had already joined event_topic, so the optimizer was able to use event_topic content from the join buffer.
Using a buffer is a good thing; you probably noticed the undesirable "Using temporary; Using filesort" on the first line of EXPLAIN output, which is probably from the GROUP BY and is probably unavoidable in this case.
By the way, will you run into problems with the "UNIQUE" constraint on city_name? I'm thinking of Springfield (two in New Jersey), Washington, Greenville, etc.
Try using:
"STRAIGHT_JOIN" and "FORCE INDEX":
EXPLAIN SELECT events.event_topic_id, event_topic_name, event_topic_image, event_type_name,city_name FROM events
-> straight_join event_topic force index(primary) ON event_topic.event_topic_id=events.event_topic_id
-> straight_join event_type force index(primary) ON event_type.event_type_id = event_topic.event_type_id
-> straight_join locations force index(primary) ON locations.location_id=events.location_id
-> straight_join city force index(primary) ON city.city_id=locations.city_id
-> WHERE event_date > NOW()
-> GROUP BY events.event_topic_id, city.city_id;
BTW, using a join buffer is not good. It means that you need to improve or reference to correct index.
I've tried to look another person's questions but they all seem different from mine.
My problem is I keep getting ERROR 1452 problem "ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails" even though I think the foreign key is under the constraint.
My tables are
CREATE TABLE `Users` (
`id` int(11) unsigned NOT NULL,
`username` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`joinTime` datetime DEFAULT NULL,
`isRemoved` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
UNIQUE KEY `username` (`username`),
KEY `isRemoved` (`isRemoved`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `RoleGroups` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` text NOT NULL,
`description` text NOT NULL,
`createdTime` datetime NOT NULL,
`lastUpdate` datetime DEFAULT NULL,
`isRemoved` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `isRemoved` (`isRemoved`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `RoleGroupsUsers` (
`groupId` int(11) unsigned NOT NULL,
`userId` int(11) unsigned NOT NULL,
`addedTime` datetime NOT NULL,
KEY `fkGroup_groupId` (`groupId`),
KEY `fkGroup_userId` (`userId`),
CONSTRAINT `fkGroup_groupId` FOREIGN KEY (`groupId`) REFERENCES `RoleGroups` (`id`),
CONSTRAINT `fkGroup_userId` FOREIGN KEY (`userId`) REFERENCES `Users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
I hide few attributes from the Users table to simplify the question.
My current data are
mysql> SELECT id, username, joinTime FROM Users ORDER BY joinTime ASC;
+----------+-----------+---------------------+
| id | username | joinTime |
+----------+-----------+---------------------+
| 1 | admin | 2011-07-22 01:20:29 |
| 2 | johndoe | 2011-07-22 01:26:07 |
| 3 | janedoe | 2011-07-22 01:26:07 |
| 31201958 | yonas1 | 2011-07-22 01:32:38 |
| 49494052 | bvnarayan | 2011-07-22 11:51:05 |
+----------+-----------+---------------------+
5 rows in set (0.00 sec)
mysql> SELECT * FROM RoleGroups;
+----+---------------+---------------+---------------------+------------+-----------+
| id | name | description | createdTime | lastUpdate | isRemoved |
+----+---------------+---------------+---------------------+------------+-----------+
| 1 | member | Member | 2011-07-22 01:20:29 | NULL | 0 |
| 2 | administrator | Administrator | 2011-07-22 01:20:29 | NULL | 0 |
+----+---------------+---------------+---------------------+------------+-----------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM RoleGroupsUsers;
+---------+----------+---------------------+
| groupId | userId | addedTime |
+---------+----------+---------------------+
| 2 | 1 | 2011-07-22 01:20:29 |
| 1 | 1 | 2011-07-22 01:20:29 |
| 1 | 2 | 2011-07-22 01:26:07 |
| 1 | 3 | 2011-07-22 01:26:07 |
| 1 | 31201958 | 2011-07-22 01:32:38 |
+---------+----------+---------------------+
5 rows in set (0.00 sec)
And when the error popped out when i tried
mysql> INSERT INTO RoleGroupsUsers (groupId, userId, addedTime) VALUES (1, 49494052, '2011-07-22 14:51:05');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`roswell`.`rolegroupsusers`, CONSTRAINT `fkGroup_groupId` FOREIGN KEY (`groupId`) REFERENCES `RoleGroups` (`id`))
It is really strange since there is already a row in RoleGroups table with id 1. And what makes it more strange is this error keeps occurring in one of my workstation while the other running well. My development workstation uses Windows 7 and XAMPP server. And my other workstation uses OS X and MAMP.
UPDATE
It was working few hours ago in the second workstation but I don't know why now it doesn't work. (It might be because I do some configurations in the second workstation that I'm not aware of)
UPDATE AGAIN
The MySQL version
#/Applications/MAMP/Library/bin/mysql --version
/Applications/MAMP/Library/bin/mysql Ver 14.14 Distrib 5.5.9, for osx10.4 (i386) using EditLine wrapper
You need to upgrade MySQL on the OSX machine. This is a bug in MySQL versions 5.5.9 through 5.5.12 on OSX.
See: MySQL bug report, MySQL 5.5.13 patch notes (ref 2nd item)