One of my tables is losing the primary key every time I make an update on that particular table.
Describe zizi_card_household
gives me this result after the update.
+-------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | | NULL | auto_increment |
| householdnumber | varchar(45) | NO | | | |
| cardnumber | varchar(45) | YES | MUL | NULL | |
| startdate | datetime | YES | | NULL | |
| enddate | datetime | YES | | NULL | |
| assignedby | int(11) | YES | | NULL | |
| assigneddate | datetime | YES | | NULL | |
Where it should normally be
+-------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| householdnumber | varchar(45) | NO | MUL | | |
| cardnumber | varchar(45) | YES | MUL | NULL | |
| startdate | datetime | YES | | NULL | |
| enddate | datetime | YES | | NULL | |
| assignedby | int(11) | YES | | NULL | |
SHOW CREATE TABLE
will give this statement which shows a primary key was defined. It's possible that entry is updated whenever the table is altered so it shows the table as it was last altered or created.
CREATE TABLE `zizi_card_household` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`householdnumber` varchar(45) NOT NULL DEFAULT '',
`cardnumber` varchar(45) DEFAULT NULL,
`startdate` datetime DEFAULT NULL,
`enddate` datetime DEFAULT NULL,
`assignedby` int(11) DEFAULT NULL,
`assigneddate` datetime DEFAULT NULL,
`deassignedby` int(11) DEFAULT NULL,
.
.
.
.
`modifiedby` int(11) DEFAULT NULL,
`reprintstatus` tinyint(4) DEFAULT NULL,
`printeddate` datetime DEFAULT NULL,
`printedby` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_householdnumber` (`householdnumber`),
KEY `idx_cardnumber` (`cardnumber`),
KEY `idx_deassignedby` (`deassignedby`),
.
.
.
.
KEY `idx_reprintstatus` (`reprintstatus`)
) ENGINE=InnoDB AUTO_INCREMENT=860137 DEFAULT CHARSET=latin1
Attempting to add a primary key
ALTER TABLE `labour`.`zizi_card_household`
CHANGE COLUMN `id` `id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
at this point gives me
ERROR 1068 (42000): Multiple primary key defined
Repair table
repair table zizi_card_household;
Gives me this but it does solve the problem. The primary key returns but will get ruined the next time the table is updated.
+----------------------------+--------+----------+---------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+----------------------------+--------+----------+---------------------------------------------------------+
| labour.zizi_card_household | repair | note | The storage engine for the table doesn't support repair |
+----------------------------+--------+----------+---------------------------------------------------------+
The table and other tables have a trigger that updates a summary table. It deletes related rows and reconstructs them. It does something like
FOR EACH ROW
begin
delete from zizi_card_summary where householdnumber=new.householdnumber;
insert into zizi_card_summary(
cardnumber,cardhouseholdid,householdnumber,startdate,enddate,assignedby
.
.
.
)
select ch.cardnumber,ch.id,b.householdnumber,
ch.startdate,ch.enddate,ch.assignedby,
.
.
.
.
where b.householdnumber=new.householdnumber and b.beneficiary_type=0;
end
All other tables work just fine. Thanks. Been playing around with this for a week. The application is a Zend framework 1.12.
The db version is 10.1.11-MariaDB-log. The operating system is Linux 2.6.32-573.8.1.el6.x86_64 x86_64.
I can confirm the bug and the workaround as described by Timothy : removing the trigger keeps the Primary key after a record update.
Bug resolution progress is on https://jira.mariadb.org/browse/MDEV-9558
Related
I crawed lots of data, and saved it into mysql table, but there're some data duplicated, and I want to delete them in a effective way.
table (ads_info)
+------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ad_id | varchar(64) | YES | MUL | NULL | |
| adset_id | varchar(64) | YES | MUL | NULL | |
| campaign_id | varchar(64) | YES | | NULL | |
| account_id | varchar(64) | YES | MUL | NULL | |
| conversion_specs | text | YES | | NULL | |
| creative | text | YES | | NULL | |
| effective_status | varchar(32) | YES | | NULL | |
| status | varchar(32) | YES | | NULL | |
| name | varchar(255) | YES | | NULL | |
| tracking_specs | text | YES | | NULL | |
| object_store_url | varchar(255) | YES | | NULL | |
| link | varchar(255) | YES | | NULL | |
| object_type | varchar(32) | YES | | NULL | |
| updated_time | timestamp | YES | | NULL | |
| created_time | timestamp | YES | | NULL | |
+------------------+--------------+------+-----+---------+----------------+
show create table ads_info
CREATE TABLE `ads_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ad_id` varchar(64) DEFAULT NULL,
`adset_id` varchar(64) DEFAULT NULL,
`campaign_id` varchar(64) DEFAULT NULL,
`account_id` varchar(64) DEFAULT NULL,
`conversion_specs` text,
`creative` text,
`effective_status` varchar(32) DEFAULT NULL,
`status` varchar(32) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`tracking_specs` text,
`object_store_url` varchar(255) DEFAULT NULL,
`link` varchar(255) DEFAULT NULL,
`object_type` varchar(32) DEFAULT NULL,
`updated_time` timestamp NULL DEFAULT NULL,
`created_time` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ad_id` (`ad_id`),
KEY `adset_id` (`adset_id`),
KEY `account_id` (`account_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18827534 DEFAULT CHARSET=utf8mb4
There're over ten million ad info in the table, and about 40 thusand repeated. And I want delete all those repeated data.
Here's my poor trial
1)select all repeated ad_id
select ad_id from ads_info group by ad_id having count(id) > 1;
#42387 rows in set (12.42 sec)
The query cost 12s, but I don't know how to do an optimization.
2) use subquery to delete all these repeated data.
delete from ads_info where ad_id in ( select ad_id from (select ad_id from ads_info group by ad_id having count(id) > 1) t);
But I failed to get response from mysql with this trial, it seemed to be hanged with the query.
How can I delete these repeated data?
You needed a UNIQUE key in the first place. This will add it and dedup:
ALTER IGNORE TABLE ads_info
ADD UNIQUE KEY(ad_id);
If you want delete all the occurence then
Instead of IN clause you could try using a join
delete ads_info
from ads_info
INNER JOIN (
select ad_id
from ads_info
group by ad_id
having count(*) > 1
) T ON T.ad_id = ads_info.ad_id
be sure you have and index on ads_info.ad_id
if you have index .. but the query optimizer don't use and you are sure is a valid index you could try using USE or FORCE
delete ads_info
from ads_info
INNER JOIN (
select ad_id
from ads_info
group by ad_id
having count(*) > 1
) T FORCE INDEX FOR JOIN (`ad_id`) ON T.ad_id = ads_info.ad_id
I dont have other ideas on how to optimize this query, runs about 2,5 sec with goodsXML table over 2 million rows. It looks like order by is slowing a lot, but i cant remove it. Also, it depends a lot on how many items selected here gx.categoryID IN(892), because later another tables joins this items set. I cant make joins after this option, because joined tables perform in where clauses.
SELECT MD5(CONCAT(gx.id,598)) citySort,gx.dateCreated lastModifiedSince,IF(DATE(gx.dateModified)>=(IF((EXTRACT(HOUR FROM NOW()) BETWEEN 0 AND 6),DATE(NOW() -INTERVAL 6 HOUR),DATE(NOW()))) OR DATE(gx.dateModified)>=DATE(NOW()),1,0) isActual,
gx.id,p.producerName,gx.categoryID,gx.name,CONCAT('::',gxi.imageName) images,IF(CONCAT('::',gxi.imageName)!='',1,0) imExist,gx.price,gx.oldPrice,gx.oldPricePt,gx.sourceUrl,IF(s.offerPostingType='XML',IF(s.alternateName!='',s.alternateName,s.name),CONCAT(u.lastName,' ',u.name)) shopName,s.logoName,
s.id shopID,s.active shopActive,s.offerPostingType,c.titleAdd,'Москва' cityName,
IF((s.cityID='598' AND s.deliveryByCity=1) OR (sa.cityID='598' AND sa.deliveryByCity=1) OR (s.deliveryByMRCities LIKE '%^598^%' AND s.deliveryByMR=1),1,0) deliveryInYourCity,
IF(s.deliveryByCityAll=1 OR (s.cityID='598' AND s.deliveryByCity=1) OR (sa.cityID='598' AND sa.deliveryByCity=1) OR (s.deliveryByMRCities LIKE '%^598^%' AND s.deliveryByMR=1),1,0) deliveryByCity,
IF(s.deliveryByMail=1,1,0) deliveryByMail,
IF(s.deliveryBySelfAll=1 OR (s.cityID='598' AND s.deliveryBySelf=1) OR (sa.cityID='598' AND sa.deliveryBySelf=1),1,0) deliveryBySelf
FROM goodsXML gx
JOIN category c ON c.id=gx.categoryID
LEFT JOIN producer p ON p.id=gx.producerID
JOIN shop s ON s.id=gx.shopID
LEFT JOIN shopAddress sa ON sa.shopID=s.id
LEFT JOIN users u ON u.id=s.userID
LEFT JOIN goodsXMLImages gxi ON gxi.goodsXMLID=gx.id AND gxi.isMain = 1
WHERE 1=1 AND (s.cityID='598' OR s.deliveryByCityAll=1 OR s.deliveryBySelfAll=1 OR s.deliveryByMail=1 OR sa.cityID='598' OR (s.deliveryByMR=1 AND s.deliveryByMRCities LIKE '%^598^%')) AND (s.isPaying=0 OR u.balance>0) AND gx.categoryID IN(892)
GROUP BY gx.id
ORDER BY isActual DESC,imExist DESC,gx.PPC DESC,gx.payPrior ASC,citySort DESC
LIMIT 0,40
Explain is following:
+----+-------------+-------+--------+--------------------------------+-----------------+----------------+------------------------+--------------------+--------------------------------+
| ID | SELECT_TYPE | TABLE | TYPE | POSSIBLE_KEYS | KEY | KEY_LEN | REF | ROWS | EXTRA |
+----+-------------+-------+--------+--------------------------------+-----------------+----------------+------------------------+--------------------+--------------------------------+
| | | | | | | | | | |
| 1 | SIMPLE | c | const | PRIMARY | PRIMARY | 4 | const | 1 | Using temporary; Using filesor |
| | | | | | | | | | |
| 1 | SIMPLE | gx | ref | ixGroupNameCategoryIDShopIDPro | ixCategoryID... | ixCategoryIDid | 4 | const | 82005 |
| | | | | ducerID | | | | | |
| | | | | | | | | | |
| 1 | SIMPLE | s | eq_ref | PRIMARY | deliveryByMR | PRIMARY | 4 | vsesrazu.gx.shopID | 1 |
| | | | | | | | | | |
| 1 | SIMPLE | sa | ref | shopKey | shopKey | 5 | vsesrazu.s.id | 2 | Using where |
| | | | | | | | | | |
| 1 | SIMPLE | u | eq_ref | PRIMARY | PRIMARY | 4 | vsesrazu.s.userID | 1 | Using where |
| | | | | | | | | | |
| 1 | SIMPLE | p | eq_ref | PRIMARY | PRIMARY | 4 | vsesrazu.gx.producerID | 1 | |
| | | | | | | | | | |
| 1 | SIMPLE | gxi | ref | over | over | 4 | vsesrazu.gx.id | 1 | |
+----+-------------+-------+--------+--------------------------------+-----------------+----------------+------------------------+--------------------+--------------------------------+
Show create table for goodsXML:
CREATE TABLE goodsXML (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
localID char(255) NOT NULL,
groupID char(255) DEFAULT NULL,
dateCreated datetime NOT NULL,
dateModified datetime NOT NULL,
dateModifiedPrice datetime NOT NULL,
name char(255) DEFAULT NULL,
nameHash char(32) NOT NULL,
groupName char(255) DEFAULT NULL,
newGroupName char(255) NOT NULL,
url char(255) NOT NULL,
sourceUrl char(255) NOT NULL,
categoryID int(6) unsigned NOT NULL,
producerID int(6) DEFAULT NULL,
authorID int(6) DEFAULT NULL,
shopID int(6) NOT NULL,
XMLUrlOrder tinyint(2) NOT NULL,
price float(12,2) NOT NULL,
oldPrice float(12,2) NOT NULL,
oldPricePt smallint(3) NOT NULL,
description text,
descriptionHash char(32) NOT NULL,
descriptionForGroup text NOT NULL,
imExist tinyint(1) NOT NULL DEFAULT '0',
imagesForGroup tinyint(1) NOT NULL DEFAULT '0',
videoHighlight text NOT NULL,
videoSiteUrl char(255) NOT NULL,
videoChannelUrl char(255) NOT NULL,
plusesMinuses text NOT NULL,
toIndex tinyint(1) NOT NULL DEFAULT '0',
isRST tinyint(1) NOT NULL DEFAULT '0',
isReplica tinyint(1) NOT NULL DEFAULT '0',
status tinyint(1) NOT NULL DEFAULT '0',
comment char(255) NOT NULL,
daysLeft tinyint(2) NOT NULL,
PPC float(5,2) DEFAULT '0.00',
payPrior tinyint(1) NOT NULL DEFAULT '4',
PRIMARY KEY (id),
UNIQUE KEY ixGroupNameCategoryIDShopIDProducerID (shopID,localID),
KEY ixGroupNameCategoryID (groupName,categoryID),
KEY ixStatusShopID (status,shopID),
KEY ixCategoryID (categoryID),
KEY authorID (authorID),
KEY ixDateModified (dateModified,imExist),
KEY daysLeft (daysLeft),
KEY sourceUrl (sourceUrl),
KEY ixCategoryIDid (categoryID,id)
) ENGINE=MyISAM AUTO_INCREMENT=4218880 DEFAULT CHARSET=utf8
The EXPLAIN shows that it needs to scan about 82K rows of gx. There are apparently about that many rows with categoryID = 892, correct? Most of the rest is straightforward JOINs.
Don't use MyISAM, use InnoDB.
INT(6) -- the (6) means nothing. Perhaps you meant MEDIUMINT UNSIGNED? INT is 4 bytes; MEDIUMINT is 3.
Are you 'always' searching by category? If so, make use of InnoDB's "clustered" PK by switching to PRIMARY KEY (categoryID, id), INDEX(id) and chuck the two existing indexes starting with categoryID.
Don't use CHAR unless the column is truly fixed length; use VARCHAR.
Don't use FLOAT(m,n), it can lead to subtle rounding errors. For Money, use DECIMAL(m,n); for Scientific values, use FLOAT.
ORs defeat optimizations. See if you can redesign the schema to avoid some of them.
What is LIKE '%^598^%'? Do you have a list of numbers in that column?
After switching to InnoDB, decrease key_buffer_size to only 30M and increase innodb_buffer_pool_size to 70% of available RAM`.
I've got a problem which drives me crazy. I searched on the internet but all i could find was: The data on which the foreign key references, is not inserted. Well, I checked it like 100 times, they are inserted.
My tables are:
Stundenanfrage:
CREATE TABLE IF NOT EXISTS Stundenanfrage(
LehrerKuerzel CHAR(10),
Anfangszeit TIMESTAMP,
Endzeit TIMESTAMP,
StundeGehalten TINYINT,
Akzeptiert TINYINT,
Lernprozess TEXT,
Sterne INT, -- 1-5 1 schlecht; 5 gut
BetrauNr INT REFERENCES ILB_Betrauung(BetrauNr),
PRIMARY KEY(LehrerKuerzel, Anfangszeit, Endzeit, BetrauNr),
FOREIGN KEY(LehrerKuerzel, Anfangszeit, Endzeit) REFERENCES Lehrerzeiten(LehrerKuerzel, Anfangszeit, Endzeit)
);
Lehrerzeiten:
CREATE TABLE IF NOT EXISTS Lehrerzeiten(
LehrerKuerzel CHAR(10) REFERENCES ILB_Lehrer,
Anfangszeit TIMESTAMP ,
Endzeit TIMESTAMP ,
Einzelunterricht TINYINT(1) DEFAULT 0,
Thema VARCHAR(100),
PRIMARY KEY(LehrerKuerzel, Anfangszeit, Endzeit)
);
And ilb_betrauung:
CREATE TABLE IF NOT EXISTS ILB_Betrauung(
BetrauNr INT PRIMARY KEY AUTO_INCREMENT,
LehrerKuerzel CHAR(10) REFERENCES ilb_lehrer,
MatNr CHAR(20) REFERENCES fw_schueler,
zweckmaeßig_erachtet_Lehrer TINYINT,
zweckmaeßig_erachtet_Schueler TINYINT,
Betrauung_AV TINYINT,
Eltern_informiert TINYINT
);
The inserted data:
My update query looks like this:
UPDATE stundenanfrage SET Akzeptiert = 1
WHERE LehrerKuerzel = "bb" AND Anfangszeit = "2017-02-20 12:20:00" AND
Endzeit = "2017-02-20 13:00:00";
and threw an error:
Error Code: 1452. Cannot add or update a child row: a foreign key constraint fails (`db_ilb`.`stundenanfrage`, CONSTRAINT `stundenanfrage_ibfk_1` FOREIGN KEY (`LehrerKuerzel`, `Anfangszeit`, `Endzeit`) REFERENCES `lehrerzeiten` (`LehrerKuerzel`, `Anfangszeit`, `Endzeit`)
I also joined all tables and selected that particular record I wanted to update:
SELECT * FROM stundenanfrage s
JOIN lehrerzeiten l ON s.Lehrerkuerzel = l.Lehrerkuerzel AND s.Anfangszeit =
l.Anfangszeit AND s.Endzeit = l.Endzeit
WHERE l.LehrerKuerzel = "bb" AND l.Anfangszeit = "2017-02-20 12:20:00" AND
l.Endzeit = "2017-02-20 13:00:00" AND s.BetrauNr = 1;
The output was that one record I wanted to update. I also asked my teacher about this error and she had no clue either.
Check Extra:
mysql> DESC `Stundenanfrage`;
+----------------+------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------+------+-----+-------------------+-----------------------------+
| LehrerKuerzel | char(10) | NO | PRI | NULL | |
| Anfangszeit | timestamp | NO | PRI | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| Endzeit | timestamp | NO | PRI | NULL | |
| StundeGehalten | tinyint(4) | YES | | NULL | |
| Akzeptiert | tinyint(4) | YES | | NULL | |
| Lernprozess | text | YES | | NULL | |
| Sterne | int(11) | YES | | NULL | |
| BetrauNr | int(11) | NO | PRI | NULL | |
+----------------+------------+------+-----+-------------------+-----------------------------+
8 rows in set (0.00 sec)
See: 12.3.5 Automatic Initialization and Updating for TIMESTAMP and DATETIME.
Try:
CREATE TABLE IF NOT EXISTS Stundenanfrage (
LehrerKuerzel CHAR(10),
Anfangszeit TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
Endzeit TIMESTAMP,
StundeGehalten TINYINT,
Akzeptiert TINYINT,
Lernprozess TEXT,
Sterne INT, -- 1-5 1 schlecht; 5 gut
BetrauNr INT REFERENCES ILB_Betrauung(BetrauNr),
PRIMARY KEY(LehrerKuerzel, Anfangszeit, Endzeit, BetrauNr),
FOREIGN KEY(LehrerKuerzel, Anfangszeit, Endzeit)
REFERENCES Lehrerzeiten(LehrerKuerzel, Anfangszeit, Endzeit)
);
mysql> DESC `Stundenanfrage`;
+----------------+------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------+------+-----+-------------------+-------+
| LehrerKuerzel | char(10) | NO | PRI | NULL | |
| Anfangszeit | timestamp | NO | PRI | CURRENT_TIMESTAMP | |
| Endzeit | timestamp | NO | PRI | NULL | |
| StundeGehalten | tinyint(4) | YES | | NULL | |
| Akzeptiert | tinyint(4) | YES | | NULL | |
| Lernprozess | text | YES | | NULL | |
| Sterne | int(11) | YES | | NULL | |
| BetrauNr | int(11) | NO | PRI | NULL | |
+----------------+------------+------+-----+-------------------+-------+
8 rows in set (0.00 sec)
okay, so im having a weird issue with this foreign key constraint.
The data type is Int(11) and all tables and databases are using utf8_general_ci but I'm still getting an issue! the only table that inherited the Medicine_ID is the First Aid table.
Here's my schema:
tbl_Medicine
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| Medicine_ID | int(11) | NO | PRI | NULL | |
| Brand_Name | varchar(45) | YES | | NULL | |
| Generic_Name | varchar(45) | YES | | NULL | |
| Countable | int(11) | YES | | NULL | |
+--------------+-------------+------+-----+---------+-------+
tbl_batch
+---------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+---------+------+-----+---------+-------+
| Batch_ID | int(11) | NO | PRI | NULL | |
| Purchase_Date | date | YES | | NULL | |
+---------------+---------+------+-----+---------+-------+
tbl_Stock
+-----------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------+------+-----+---------+-------+
| Stock_ID | int(11) | NO | PRI | NULL | |
| Medicine_ID | int(11) | NO | PRI | NULL | |
| Batch_ID | int(11) | NO | PRI | NULL | |
| Expiration_Date | date | YES | | NULL | |
| Quantity | int(45) | YES | | NULL | |
| Unit_Price | int(11) | YES | | NULL | |
+-----------------+---------+------+-----+---------+-------+
tbl_inventory
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| Inventory_ID | int(11) | NO | PRI | NULL | |
| Building | varchar(45) | NO | PRI | NULL | |
| Stock_ID | int(11) | NO | PRI | NULL | |
| Medicine_ID | int(11) | NO | PRI | NULL | |
| Quantity | varchar(45) | YES | | NULL | |
+--------------+-------------+------+-----+---------+-------+
tbl_Activity
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| Activity_ID | varchar(10) | NO | PRI | NULL | |
| Purpose | varchar(50) | YES | | NULL | |
| Organization | varchar(50) | YES | | NULL | |
| Reciever | varchar(50) | YES | | NULL | |
| Recieve_Date | date | YES | | NULL | |
| Act_Date | date | YES | | NULL | |
| Validator | varchar(10) | YES | | NULL | |
+--------------+-------------+------+-----+---------+-------+
Heres the creation query:
CREATE TABLE IF NOT EXISTS `csb_inventory`.`tbl_batch` (
`Batch_ID` INT(11) NOT NULL COMMENT '',
`Purchase_Date` DATE NULL DEFAULT NULL COMMENT '',
PRIMARY KEY (`Batch_ID`) COMMENT '')
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS `csb_inventory`.`tbl_medicine` (
`Medicine_ID` INT(11) NOT NULL COMMENT '',
`Brand_Name` VARCHAR(45) NULL DEFAULT NULL COMMENT '',
`Generic_Name` VARCHAR(45) NULL DEFAULT NULL COMMENT '',
`Countable` INT(11) NULL DEFAULT NULL COMMENT '',
PRIMARY KEY (`Medicine_ID`) COMMENT '')
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS `csb_inventory`.`tbl_stock` (
`Stock_ID` INT(11) NOT NULL COMMENT '',
`Medicine_ID` INT(11) NOT NULL COMMENT '',
`Batch_ID` INT(11) NOT NULL COMMENT '',
`Expiration_Date` DATE NULL DEFAULT NULL COMMENT '',
`Quantity` INT(45) NULL DEFAULT NULL COMMENT '',
`Unit_Price` INT(11) NULL DEFAULT NULL COMMENT '',
PRIMARY KEY (`Stock_ID`, `Medicine_ID`, `Batch_ID`) COMMENT '',
INDEX `fk_tbl_Stock_tbl_Medicine_idx` (`Medicine_ID` ASC) COMMENT '',
INDEX `fk_tbl_Stock_tbl_Batch1_idx` (`Batch_ID` ASC) COMMENT '',
CONSTRAINT `batch`
FOREIGN KEY (`Batch_ID`)
REFERENCES `csb_inventory`.`tbl_batch` (`Batch_ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `medicine`
FOREIGN KEY (`Medicine_ID`)
REFERENCES `csb_inventory`.`tbl_medicine` (`Medicine_ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS `csb_inventory`.`tbl_inventory` (
`Inventory_ID` INT(11) NOT NULL COMMENT '',
`Building` VARCHAR(45) NOT NULL COMMENT '',
`Stock_ID` INT(11) NOT NULL COMMENT '',
`Medicine_ID` INT(11) NOT NULL COMMENT '',
`Quantity` VARCHAR(45) NULL DEFAULT NULL COMMENT '',
PRIMARY KEY (`Inventory_ID`, `Building`, `Stock_ID`, `Medicine_ID`) COMMENT '',
INDEX `fk_tbl_Inventory_tbl_Building1_idx` (`Building` ASC) COMMENT '',
INDEX `fk_tbl_Inventory_tbl_Stock1_idx` (`Stock_ID` ASC, `Medicine_ID` ASC) COMMENT '',
CONSTRAINT `building`
FOREIGN KEY (`Building`)
REFERENCES `csb_patient`.`tbl_building` (`Building`),
CONSTRAINT `stockitem`
FOREIGN KEY (`Stock_ID` , `Medicine_ID`)
REFERENCES `csb_inventory`.`tbl_stock` (`Stock_ID` , `Medicine_ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS `csb_inventory`.`tbl_firstaid` (
`FirstAid_ID` VARCHAR(10) NOT NULL COMMENT '',
`Activity_ID` VARCHAR(10) NOT NULL COMMENT '',
`Quantity` SMALLINT(6) NOT NULL COMMENT '',
`Inventory_ID` INT(11) NOT NULL COMMENT '',
`Medicine_ID` INT(11) NOT NULL COMMENT '',
PRIMARY KEY (`FirstAid_ID`, `Activity_ID`, `Inventory_ID`, `Medicine_ID`) COMMENT '',
INDEX `activity_id` (`Activity_ID` ASC) COMMENT '',
INDEX `fk_tbl_firstaid_tbl_inventory1_idx` (`Inventory_ID` ASC, `Medicine_ID` ASC) COMMENT '',
CONSTRAINT `activity_id`
FOREIGN KEY (`Activity_ID`)
REFERENCES `csb_inventory`.`tbl_activity` (`Activity_ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tbl_firstaid_tbl_inventory1`
FOREIGN KEY (`Inventory_ID` , `Medicine_ID`)
REFERENCES `csb_inventory`.`tbl_inventory` (`Inventory_ID` , `Medicine_ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
I have read alot of threads regarding the same issue and tested them out.
I made sure that im using the same table_type, collation, and data_type. I even checked all other tables that are related that might have been causing the issue but no good. I was able to successfully add foreign keys to firstAid but only the Medicine_ID is the one failing.
help? xD
Make sure that you have tbl_building on before create tbl_inventory.
I have the tables Players and PlayerMeta
mysql> DESCRIBE Players;
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| ID | int(5) | NO | PRI | NULL | auto_increment |
| PlayerName | varchar(20) | NO | PRI | NULL | |
| Birthdate | date | YES | | NULL | |
| Location | varchar(20) | YES | | NULL | |
| FirstName | varchar(15) | YES | | NULL | |
| Whitelisted | tinyint(1) | NO | | 1 | |
+-------------+-------------+------+-----+---------+----------------+
mysql> DESCRIBE PlayerMeta;
+----------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------+------+-----+---------+-------+
| ID | int(5) | NO | PRI | NULL | |
| JoinDate | date | YES | | NULL | |
| BuildQuota | int(2) | NO | | 2 | |
| RegisteredDate | date | YES | | NULL | |
| HideBirthdate | tinyint(1) | NO | | 0 | |
+----------------+------------+------+-----+---------+-------+
I am trying to execute this command, and it returns Query OK:
ALTER TABLE PlayerMeta
ADD CONSTRAINT fk_PlayerID
FOREIGN KEY (ID)
REFERENCES Players(ID)
ON UPDATE CASCADE
ON DELETE CASCADE;
Yet, when I run SHOW CREATE TABLE PlayerMeta, it does not show the constraint, nor is it in INFORMATION_SCHEMA
Any thoughts? Thanks.
EDIT: Here is SHOW CREATE TABLE PlayerMeta:
mysql> SHOW CREATE TABLE PlayerMeta;
... a bunch of lines ...
| PlayerMeta | CREATE TABLE `PlayerMeta` (
`ID` int(5) NOT NULL,
`JoinDate` date DEFAULT NULL,
`BuildQuota` int(2) NOT NULL DEFAULT '2',
`RegisteredDate` date DEFAULT NULL,
`HideBirthdate` tinyint(1) NOT NULL DEFAULT '0',
UNIQUE KEY `ID` (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
EDIT(2): The problem was ID in PlayerMeta was already a primary key and a foreign key would not apply in conjunction with it.
You cannot create foreign keys for MyISAM.
Only InnoDB supports them.
So the solution for you is to change the storage engine for both tables.
ALTER TABLE Players ENGINE=InnoDB;
ALTER TABLE PlayerMeta ENGINE=InnoDB;
Then re-apply your ALTER with adding a FK constraint.
MySQL will not permit you to create a FOREIGN KEY constraint on a column which is itself a PRIMARY KEY. If your design is such that the two tables share a one-to-one relationship and both hold information about a Player, it may not make sense to separate them and instead combine both tables into one.
In any case, if you wish to keep them separate and enforce a FOREIGN KEY relationship on them, you need to remove the PRIMARY KEY on PlayerMeta.ID. You may still have a UNIQUE, non primary key index on it.