I'm trying to do a schema update using the app/console doctrine:schema:update --force command, but Doctrine fails on the following part:
An exception occurred while executing 'DROP INDEX IDX_E98F2859A074D5D7 ON contract':
SQLSTATE[HY000]: General error: 1553 Cannot drop index 'IDX_E98F2859A074D5D7': needed in a foreign key constraint
This is trivial to resolve according to another SO question. The table has:
KEY `IDX_E98F2859A074D5D7` (`some_table_id`),
CONSTRAINT `FK_E98F2859A074D5D7` FOREIGN KEY (`some_table_id`) REFERENCES `some_table` (`id`)
So this can be resolved manually by dropping the matching constraint. But is there a way to do it automatically?
If you use the information schema, you can easily construct the necessary ALTER TABLE commands; the relevant tables are here: SCHEMA KEY_COLUMN_USAGE and STATISTICS.
Following is an example for a query which generates the DDL statements:
SELECT CONCAT('ALTER TABLE ',kcu.TABLE_NAME,' DROP FOREIGN KEY ', kcu.CONSTRAINT_NAME,';') AS ddl
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu, INFORMATION_SCHEMA.STATISTICS stat
WHERE stat.table_schema = 'your_schema'
AND kcu.TABLE_NAME = stat.TABLE_NAME
AND kcu.COLUMN_NAME = stat.COLUMN_NAME
AND kcu.REFERENCED_TABLE_NAME IS NOT NULL
INTO OUTFILE '/tmp/ddl.sql';
And you can run it after reviewing it by running this statement:
SOURCE '/tmp/ddl.sql';
Above statement will look up constraint name and corresponding table name for every foreign key constraint, where an index exists on the same foreign key column in the same table. The result is stored in the file given by INTO OUTFILE.
Please review above statement carefully before running the generated ddl.
Related
I have seen several posts on how to get foreign key references but not the actual relationship type like what is shown in MySQL's workbench ER diagram.
Currently I am using below sql to get references
SELECT
`TABLE_SCHEMA`, -- Foreign key schema
`TABLE_NAME`, -- Foreign key table
`COLUMN_NAME`, -- Foreign key column
`REFERENCED_TABLE_SCHEMA`, -- Origin key schema
`REFERENCED_TABLE_NAME`, -- Origin key table
`REFERENCED_COLUMN_NAME` -- Origin key column
FROM
`INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` -- Will fail if user don't have privilege
WHERE
`TABLE_SCHEMA` = SCHEMA() -- Detect current schema in USE
AND `REFERENCED_TABLE_NAME` = 'orders'; -- Only tables with foreign keys
What sql do I need to use to let me know if it is a 1:M, M:1, 1:1,
I have read How to determine cardinality of foreign key using mysql which hints at how to find this info.
Does any have an example sql statment to get the relationship type?
I have a foreign key that was generated with the following command in an old and already deployed migration:
ALTER TABLE `job_template`
ADD COLUMN `parent_id` BIGINT,
ADD FOREIGN KEY fk_job_template_parent_id(parent_id) REFERENCES job_template(id) ON DELETE CASCADE;
Now I am trying to drop this foreign key with following command:
ALTER TABLE job_template DROP FOREIGN KEY fk_job_template_parent_id;
The problem is that this works for mariaDB but not for mySQL and I need a migration that would work in both cases
If I list the SHOW CREATE TABLE command (before the deleting of the foreign key) from both environments I get the following:
mariaDB:
constraint fk_job_template_parent_id foreign key (parent_id) references job_template (id) on delete cascade,
mysql:
constraint job_template_ibfk_5 foreign key (parent_id) references job_template (id) on delete cascade,
The constraint names are different in the 2 environments, and thus I have no way to write a migration that would consistently drop this foreign key.
Is there any way to get around this situation?
Your problem is that you are not explicitly naming your constraints. This leaves each database to pick a name for you. The trick here is to name your foreign key constraints explicitly, when you create the actual tables on both MySQL and MariaDB:
CREATE TABLE job_template (
...,
parent_id int NOT NULL,
CONSTRAINT your_constraint FOREIGN KEY fk_name (parent_id)
REFERENCES job_template(id) ON DELETE CASCADE
);
But fixing your immediate situation would require more work. One option would be to query the information schema table, for the table involved, to find out the actual constraint names:
USE INFORMATION_SCHEMA;
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM KEY_COLUMN_USAGE
WHERE
TABLE_SCHEMA = 'your_db' AND
TABLE_NAME = 'job_template' AND
REFERENCED_COLUMN_NAME IS NOT NULL;
This should return one record for every column and constraint. With this information, you should be able to run your current alter statements.
This is easy enough to do using a tool like Java, or something similar. If you want to do this directly from the database, then you would need dynamic SQL, which probably means writing a stored procedure.
The list of foreign keys is empty for one of my tables in MySql Workbench. When I try to add the missing FK's I get an error of this structure:
Executing:
ALTER TABLE <schema>.<table>
ADD INDEX <index_name> (<column_name> ASC);
ALTER TABLE <schema>.<table_name>
ADD CONSTRAINT <constraint_name>
FOREIGN KEY (<column_name>)
REFERENCES <schema>.<ref_table_name> (<ref_column_name>)
ON DELETE CASCADE
ON UPDATE CASCADE;
Operation failed: There was an error while applying the SQL script to the database.
ERROR 1452: Cannot add or update a child row: a foreign key constraint fails (<schema>.`#sql-49f_6`, CONSTRAINT <constraint_name> FOREIGN KEY (<column_name>) REFERENCES <ref_table_name> (<ref_column_name>) ON DELETE CASCADE ON UPDATE CASCADE)
SQL Statement:
ALTER TABLE <schema>.<table_name>
ADD CONSTRAINT <constraint_name>
FOREIGN KEY (<column_name>)
REFERENCES <schema>.<ref_table_name> (<ref_column_name>)
ON DELETE CASCADE
ON UPDATE CASCADE
Obviously, the foreign key I am trying to create seems to be in the database already. Some research on the web lead me to believe that in some cases MySql Workbench does not list all foreign keys (for various reasons), which might be true for my setup as well. Thus, I tried listing all foreign keys on the table I am trying modify using this query:
SELECT *
FROM
information_schema.KEY_COLUMN_USAGE
WHERE
constraint_schema = <schema> AND table_name = <table_name> AND
referenced_table_name IS NOT NULL;
The result set is as empty as the Workbench foreign key list...
Looking at the error message I seem to have a weird table sitting around my database named #sql-49f_6.
This table was not explicitely created by me.
That said, I am using sqlalchemy to create and manage my database, so all might be due to the sqlalchemy model definition, which looks like this:
TableName = Table(<table_name>,
table_base.metadata,
Column(
<column_name_1>,
Integer(),
ForeignKey('<ref_table_name>.<ref_column_name>', onupdate='CASCADE', ondelete='CASCADE'),
nullable=False
),
Column(
<column_name_2>,
Integer(),
ForeignKey('<ref_table_name_2>.<ref_column_name_2>', onupdate='CASCADE', ondelete='CASCADE'),
nullable=False
)
)
With all of the above, can anyone suggest a solution?
Preferably without having to recreate the database; because, I need to maintain the data contained by the table.
I wasn't able to find the origin of the issue described above.
In need of a solution, I temporarily stored the data contained by the problematic table offline and recreated it from scratch. In this step I also added in the foreign key missing. The issue did not persist. Sorry I cannot shed light on what went wrong initially.
I have had a 1 to many relationship between course and instructor, which I wanted to drop. When I tried to drop the instructorID in course table it told me that. I couldn't drop it as it was a foreign key. Then I decided to drop it like this:
ALTER TABLE course DROP FOREIGN KEY instructorID
But i get this error :
#1091 - Can't DROP 'InstructorID'; check that column/key exists
I don't get what this error means. what am i doing wrong?
Please run an SHOW CREATE TABLE course; to make sure instructorID is the name of foreign key constraint.
Additional:
The error means MySQL searches for a foreign key constraint named "InstructorID" but there is no constraint with such name, maybe this is your column name, but you have to use the constraint name to delete foreign keys.
After you run SHOW CREATE table course;
you should find the fk symbol which is commonly like the one bellow:
(course_ibfk_1)
it may differ according to your mysql version you are using then drop the foreign key using the fk symbol as follow :
alter table course drop foreign key course_ibfk_1;
You need to delete the 'foreign key constraint' and the 'key'.
Alter Table <table name> drop foreign key <constraint_name>
Alter table <table name> drop key <column name>
If any of you still not able to DROP the table. Try this. You can able to see all the details by running this
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'ReferenceTableName'; <-- change only this
If you want to see just the constrains
SELECT
CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'ReferenceTableName';
To drop a FOREIGN KEY constraint:
MySQL:
ALTER TABLE Orders DROP FOREIGN KEY {Constraint/Key_name};
For SQL Server / Oracle / MS Access:
ALTER TABLE Orders DROP CONSTRAINT {Constraint/Key_name};
the reason why you cannot drop InstructorID is because you need to use the name of the constraint of the Foreign key . KevDev specified that you must run 'SHOW CREATE TABLE course' to find the constraint name. after doing so , you can delete the foreign key. BUT wait theres more, the 'key' still stays behind which must get deleted. You can run 'SHOW CREATE TABLE' course to check that the key is still behind. once checking that it is still there then perform what Bobby advised. 'Alter table drop key' in doing so you have fully removed the the foreign key
Can't DROP 'string'; check that column/key exists: ALTER TABLE accreditor_architectures DROP string error show in terminal when remove column from data base in ruby on rails
I am using Mysql Workbench. I have already made the table.
Now I want to add foreign key in a table called Personal_Details that key is primary key in Login table.
But when I am trying to do so, it shows me the following error:
ERROR 1005: Can't create table 'shaadiDB.#sql-404_25' (errno: 121)
SQL Statement:
ALTER TABLE `shaadiDB`.`Personal_Details`
ADD CONSTRAINT `Login_Id`
FOREIGN KEY (`Login_Id` )
REFERENCES `shaadiDB`.`Login` (`Login_Id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION
, ADD INDEX `Login_Id` (`Login_Id` ASC)
It seems that the table Personal_Details is having data from which there might be some rows with Login_Id for which entry is not present in table Login.
If this is the case , then solution would be that you need to move the data to another table, then add constraint. After adding the constraint you need to add all rows back to table 1 by 1.
Error 121: This error explicitly is thrown when there is a duplication in key names.
Immediately after running your Alter ... statement, execute the following and observe the results.
SHOW ENGINE InnoDB STATUS;
Description text from the result will tell you on which key name the duplication is found.
Based on that you modify your ALTER ... statement and execute.
Alternatively you can also find if any such duplicate key name is defined by executing:
select constraint_name, constraint_type, table_name
from information_schema.table_constraints
where table_schema = DATABASE() -- and constraint_type = 'foreign key'
Constraint types can be anything like PRIMARY KEY, FOREIGN KEY, etc.
If you see any key names in the result that you are trying to use in your ALTER .. statement, you should modify them and execute.
before adding any constrain to a table that already have some data might cause this problem,try to add constrain with out data