INNODB Cascade Syntax / Logic Problem - mysql

I have a problem with an SQL database I'm creating. I'm trying to switch it over to use INNODB but I can't seem to get the syntax (or possibly logic) correct for cascading.
Here's a part of the code erroring. It does not like line 40.
Error output in the usual cryptic (to me at least) form:
ERROR 1005 (HY000) at line 36: Can't create table './school/staff.frm' (errno: 150)
Edit:
Here's the whole SQL file I'm trying to pipe in if that helps.

Foreign keys have to be indexes. (role.name)
Try this:
CREATE TABLE IF NOT EXISTS `role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(30) NOT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB;

Did you mean for the "role" column's foreign key constraint to be using the name instead of the ID? It looks like the following line (line 43):
FOREIGN KEY (role) REFERENCES role(name)
should be:
FOREIGN KEY (role) REFERENCES role(id)
This executes without errors.
Alternatively, the "staff.role" column's data type (line 40, role INT NOT NULL) could be changed to CHAR(30) NOT NULL.

Related

Creation of MySQL's generated column utilizing column that is used for foreign key constraint causes error

I try to add a generated stored column to existing table running the following SQL command:
ALTER TABLE routes ADD routes_hash char(32)
AS (MD5(CONCAT(`traveler_id`, `track`))) stored;
MySQL returns the error message:
ERROR 1025 (HY000): Error on rename of './travelers/#sql-558_69' to './travelers/routes'
(errno: 150 - Foreign key constraint is incorrectly formed)
Mysql version is 5.7.20. Here is a database structure:
CREATE TABLE `travelers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `routes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`traveler_id` int(11) NOT NULL,
`track` multilinestring NOT NULL,
PRIMARY KEY (`id`),
KEY `traveler_id` (`traveler_id`),
CONSTRAINT `routes_ibfk_1` FOREIGN KEY (`traveler_id`)
REFERENCES `travelers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I have not found any restrictions in MySQL documentation that forbid usage of the column that participates in foreign key constraint as a part of expression used for build a generated column. However, if I exclude traveler_id from the generated column expression for routes_hash the column is created fine. Is this a bug of MySQL or I am missing something about generated column usage?
Unfortunately, it is a bug of MySQL that affects even current 5.7 and 8.0 versions. I have found description on MySQL's bug tracker https://bugs.mysql.com/bug.php?id=88111 . Please be aware.

Foreign key constraint is incorrectly formed (MariaDB)

I'm just trying to execute a MySQL file within MariaDB, but it gives me the following error: ERROR 1005 (HY000) at line 14: Can't create table roundcube.calendars (errno: 150 "Foreign key constraint is incorrectly formed")
That's the SQL query: https://pastebin.com/4FBA30JM
Unfortunately I can't post it here since it kinda messes up the formatting.
Here's your calendars table definition:
CREATE TABLE IF NOT EXISTS `calendars` (
`calendar_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`color` varchar(8) NOT NULL,
`showalarms` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY(`calendar_id`),
INDEX `user_name_idx` (`user_id`, `name`),
CONSTRAINT `fk_calendars_user_id` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=INNODB CHARACTER SET utf8 COLLATE utf8_general_ci;
I tested this out in a sandbox and the statement is fine. There's nothing wrong with it.
However, I don't see a users table in your linked code sample. Before you can create a table with a foreign key, the following must be true:
The referenced table (users in your case) must exist.
The referenced table must use the InnoDB storage engine.
The referenced column (user_id) must exist in the table.
The referenced column must have exactly the same data type as the foreign key column that references it. In your case, this is INT UNSIGNED (The integer length argument (10) is optional and may be different in the two tables).
The referenced column must be the leftmost column of a KEY. Ideally it should be the entire PRIMARY KEY or UNIQUE KEY, to be compatible with standard SQL. Technically, InnoDB also allows foreign keys to reference non-unique keys, but this is discouraged.
So you must have a table at least like the following already existing in your database:
CREATE TABLE `users` (
`user_id` int(10) UNSIGNED NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=INNODB CHARACTER SET utf8 COLLATE utf8_general_ci;
I had to create this table in my sandbox before your calendars table definition would work.

I don't get whats wrong with the mysql syntax

CREATE TABLE hoofdtoonder
(
id INT NOT NULL,
idondersoorten INT FOREIGN KEY REFERENCES `ondersoort`(`id`) NOT NULL,
)
//making table but the error is with the references its on a mysql database someone please help
It says error at FOREIGN KEY REFERENCES ondersoort(id) NOT NULL. But I don't know what's wrong with the syntax.
There are several things wrong here:
First, for an inline constraint, you don't need to specify foreign key, just references.
The not null clause should come before the references clause.
You have a redundant comma at the end of the last column's specification.
To put it all together:
CREATE TABLE hoofdtoonder (
id INT NOT NULL,
idondersoorten INT NOT NULL REFERENCES `ondersoort`(`id`)
);
MySQL does not support inline foreign key references.
It's true that the SQL language allows for syntax like #Mureinik suggested:
idondersoorten INT NOT NULL REFERENCES `ondersoort`(`id`)
But you will find that MySQL parses this and ignores it. InnoDB does not support inline foreign key syntax. If you now run SHOW CREATE TABLE hoofdtoonder, it'll show this:
CREATE TABLE `hoofdtoonder` (
`id` int(11) NOT NULL,
`idondersoorten` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Where did the REFERENCES go? It was silently discarded. This is actually a beef I have with MySQL, that it recognizes some valid constraint syntax, but ignores it. It doesn't even show you a warning. It just defines the table without the constraint.
In MySQL, you must declare a foreign key as a table-level constraint, like this:
CREATE TABLE hoofdtoonder (
id INT NOT NULL,
idondersoorten INT NOT NULL,
FOREIGN KEY (idondersoorten) REFERENCES `ondersoort`(`id`)
);

ENGINE=InnoDB' at line 10 in SQL

I'm trying to create a table with this sql:
CREATE TABLE angestellte (
PersonalNr int(11) NOT NULL AUTO_INCREMENT,
Vorname varchar(50) NOT NULL,
Nachname varchar(50) NOT NULL,
Beruf varchar(50) NOT NULL,
Gehalt int(11) NOT NULL,
arbeitetInAbteilung int(11) NOT NULL,
PRIMARY KEY (PersonalNr),
FOREIGN KEY abteilung (AbteilungID)
)
ENGINE=InnoDB;
But I get only the message
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')
ENGINE=InnoDB' at line 10
I looked really can't find my mistake but think it's probably something obvious I just don't see.
Supposing you have a table where a field (arbeitetInAbteilung) references a row in another table (say arbeiten), you need to define it like this:
CREATE TABLE `angestellte` (
`PersonalNR` INT(11) NOT NULL AUTO_INCREMENT,
...other fields...
`arbeitetInAbteilung` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`PersonalNR`),
INDEX `FK__arbeiten` (`arbeitetInAbteilung`),
CONSTRAINT `FK__arbeiten` FOREIGN KEY (`arbeitetInAbteilung`)
REFERENCES `arbeiten` (`arbeitID`)
ON UPDATE CASCADE
ON DELETE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
This means that an index will be created to index the field you specify (arbeitetInAbteilung). Then a constraint will be set in place so that this index is linked to the values of another field in a different table, which could be defined like this:
CREATE TABLE `arbeiten` (
`arbeitID` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`arbeitID`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
Note that the two fields must be absolutely identical; if they are text fields, they need to have the same collation; they must be both either NULL or NOT NULL; et cetera. The slightest difference will yield a "Foreign key constraint is incorrectly formed" error, and you'll need to show the engine status for InnoDB and parse its output to understand why.
The ON UPDATE and ON DELETE define what happens when you change a value in the master (arbeiten) table, or you delete it. If the ID 123 becomes 456, CASCADE means that all the rows that referred 123 will now refer 456. Another possibility would be to prevent the operation (RESTRICT), or set the mismatched rows to NULL (SET NULL).
As already commented, your FK syntax is total wrong.
FOREIGN KEY abteilung (AbteilungID)
should be
FOREIGN KEY some_column REFERENCES abteilung (AbteilungID)
Here, some_column should be replaced by the column which you want to designate as the referencing key and the definition of this column should exactly match with column AbteilungID of table abteilung

ERROR 1215 (HY000) at line 13: Cannot add foreign key constraint

I get the following error:
ERROR 1215 (HY000) at line 13: Cannot add foreign key constraint
for the following query:
ALTER TABLE client_generique
ADD CONSTRAINT client_generique_boutique_id_boutique_id
FOREIGN KEY (boutique_id) REFERENCES boutique (id)
ON DELETE SET NULL;
The boutique.id is a primary key unique not null.
The phpmyadmin structure export of the boutique table is this:
--
-- Table structure for table `boutique`
--
CREATE TABLE `boutique` (
`id` bigint(20) NOT NULL,
`nom` varchar(255) NOT NULL,
`identifiant_site` varchar(8) NOT NULL COMMENT 'the eight number identifier from the bank',
`certificate` varchar(255) NOT NULL COMMENT 'changes according to the mode, this will be used as salt in the sha1 that will be sent to the bank as the ''signature''',
`mode` varchar(10) NOT NULL COMMENT 'is the ''vads_ctx_mode'': TEST or PRODUCTION',
`payment_system` varchar(10) NOT NULL COMMENT 'CYBERPLUS OR PAYZEN for the new payment system added in end 2014'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Indexes for table `boutique`
--
ALTER TABLE `boutique`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `unique_mode_per_identifiant_idx` (`identifiant_site`,`mode`);
I do not understand. What is the reason? How to solve this problem?
Could it be that your table client_generique stores values in boutique_id which do not exist in your table boutique?
Since you try to establish a reference to boutique the values must exist in that table.
Thanks for Philipp Dietl for the solution.
It's not possible to add a foreign key constraint with a set null on delete on a not null column.
I've just modified the boutique_id column to a BIGINT (but no BIGINT NOT NULL).