Why Django CheckConstraint doesn't works on MySQL - mysql

When I create one class with constraint like below:
constraints = [
models.CheckConstraint(
check=models.Q('plan' == 1),
name="custom_constraint"
)
]
I receive the message:
(models.W027) MySQL does not support check constraints.
HINT: A constraint won't be created. Silence this warning if you don't care about it.
Why Django CheckConstraints works with PostgreSQL and not with MySQL?

As per MySQL documentation, the CHECK constraints are ignored by the MySQL database prior to 8.0.16:
Prior to MySQL 8.0.16, CREATE TABLE permits only the following limited version of table CHECK constraint syntax, which is parsed
and ignored**:
CHECK (expr)
As of MySQL 8.0.16, CREATE TABLE permits the core features of table and column CHECK constraints, for all storage engines.
CREATE TABLE permits the following CHECK constraint syntax, for
both table constraints and column constraints:
[CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
So before 8.0.16, the CHECK constraint was indeed parsed, but the database engine ignored it, and thus data could violate the constraints.
Some specific constraints like NOT NULL, UNIQUE, and FOREIGN KEY are however enforced, but not generic constraints (like a column that should have a specific value).

Related

Creating foreign key requires ENGINE keyword to be included in MySQL statement

My server data .. Ubuntu - NGINX - MySQL
I need to create a table in wordpress database with a foreign key with wp_posts table .. but I noticed that to create a foreign key in the new table I must include ENGINE keyword into create table statement, I don't know why but creating foreign key failed when ENGINE keyword not included.
Of course I need this statement to be programmatically for my clients so I cannot include ENGINE='USER DB ENGINE' .. So Is there anyway to use the default database engine?
P.S. I should include ENGINE keyword.
MySQL supports foreign keys only for specific database engines. The two most commonly used and present in an installation are:
MyISAM
InnoDB
InnoDB supports foreign key constraints, MyISAM does not. It is somewhere on the to do list to implement foreign key constraints in MyISAM, however nobody got to that in the last 15 years (plus/minus a few).

mysql error 150 with INNODB [duplicate]

I am trying to import a .sql file and its failing on creating tables.
Here's the query that fails:
CREATE TABLE `data` (
`id` int(10) unsigned NOT NULL,
`name` varchar(100) NOT NULL,
`value` varchar(15) NOT NULL,
UNIQUE KEY `id` (`id`,`name`),
CONSTRAINT `data_ibfk_1` FOREIGN KEY (`id`) REFERENCES `keywords` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I exported the .sql from the same database, I dropped all the tables and now im trying to import it, why is it failing?
MySQL: Can't create table './dbname/data.frm' (errno: 150)
From the MySQL - FOREIGN KEY Constraints Documentation:
If you re-create a table that was dropped, it must have a definition that conforms to the foreign key constraints referencing it. It must have the correct column names and types, and it must have indexes on the referenced keys, as stated earlier. If these are not satisfied, MySQL returns Error 1005 and refers to Error 150 in the error message, which means that a foreign key constraint was not correctly formed. Similarly, if an ALTER TABLE fails due to Error 150, this means that a foreign key definition would be incorrectly formed for the altered table.
Error 150 means you have a problem with your foreign key. Possibly the key on the foreign table isn't the exact same type?
You can get the actual error message by running SHOW ENGINE INNODB STATUS; and then looking for LATEST FOREIGN KEY ERROR in the output.
Source: answer from another user in a similar question
Data types must match exactly. If you are dealing with varchar types, the tables must use the same collation.
I think all these answers while correct are misleading to the question.
The actual answer is this before you start a restore, if you're restoring a dump file with foreign keys:
SET FOREIGN_KEY_CHECKS=0;
because naturally the restore will be creating some constraints before the foreign table even exists.
In some cases, you may encounter this error message if there are different engines between the relating tables. For example, a table may be using InnoDB while the other uses MyISAM. Both need to be same
Error no. 150 means a foreign key constraint failure. You are probably creating this table before the table the foreign key depends on (table keywords). Create that table first and it should work fine.
If it doesn't, remove the foreign key statement and add it after the table is created - you will get a more meaningful error message about the specific constraint failure.
There are quite a few things that can cause errno 150, so for people searching this topic, here is what I think is a close to exhaustive list (source Causes of Errno 150):
For errno 150 or errno 121, simply typing in SHOW ENGINE INNODB STATUS, there is a section called "LATEST FOREIGN KEY ERROR". Under that it will give you a very helpful error message, which typically will tell you right away what is the matter. You need SUPER privileges to run it, so if you don't have that, you'll just have to test out the following scenarios.
1) Data Types Don't Match: The types of the columns have to be the same
2) Parent Columns Not Indexed (Or Indexed in Wrong Order)
3) Column Collations Don't Match
4) Using SET NULL on a NOT NULL Column
5) Table Collations Don't Match: even if the column collations match, on some MySQL versions this can be a problem.
6) Parent Column Doesn't Actually Exist In Parent Table. Check spelling (and perhaps a space at the beginning or end of column)
7) One of the indexes on one of the columns is incomplete, or the column is too long for a complete index. Note that MySQL (unless you tweak it) has a maximum single column key length of 767 bytes (this corresponds to a varchar(255) UTF column)
In case you get an errno 121, here are a couple of causes:
1) The constraint name you chose is already taken
2) On some systems if there is a case difference in your statement and table names. This can bite you if you go from one server to another that have different case handling rules.
Sometimes MySQL is just super stupid - i can understand the reason cause of foreign-keys.. but in my case, i have just dropped the whole database, and i still get the error... why? i mean, there is no database anymore... and the sql-user i'm using has no access to any other db's on the server... i mean, the server is "empty" for the current user and i still get this error? Sorry but i guess MySQL is lying to me... but i can deal with it :) Just add these two lines of SQL around your fucky statement:
SET FOREIGN_KEY_CHECKS = 0;
# some code that gives you errno: 150
SET FOREIGN_KEY_CHECKS = 1;
Now the sql should be executed... If you really have a foreign-key problem, it would show up to you by the line where you will enable the checks again - this will fail then.. but my server is just quiet :)
usually, the mismatch between foreign key & primary key causes the
error:150.
The foreign key must have the same datatype as the primary key. Also, if the primary key is unsigned then the foreign key must also be unsigned.
I had same issue. It was related to table's column Collation and Character Set.
Make sure Character Set and Collation must be same for both columns on two tables. If you want to set a foreign key on that.
Example- If you put foreign key on userID column of userImage table referencing userID column of users table.Then Collation must be same that is utf8_general_ci and Character set utf8 for both columns of tables. Generally when you create a table mysql takes these two configuration from server settings.
After cruising through the answers above, and experimenting a bit, this is an effective way to solve Foreign Key errors in MySQL (1005 - error 150).
For the foreign key to be properly created, all MySQL asks for is:
All referenced keys MUST have either PRIMARY or UNIQUE index.
Referencing Column again MUST have identical data type to the Referenced column.
Satisfy these requirements and all will be well.
I experienced this error when have ported Windows application to Linux. In Windows, database table names are case-insensitive, and in Linux they are case-sensitive, probably because of file system difference. So, on Windows table Table1 is the same as table1, and in REFERENCES both table1 and Table1 works. On Linux, when application used table1 instead of Table1 when it created database structure I saw error #150; when I made correct character case in Table1 references, it started to work on Linux too. So, if nothing else helps, make you sure that in REFERENCES you use correct character case in table name when you on Linux.
Change the engines of your tables, only innoDB supports foreign keys
If the PK table is created in one CHARSET and then you create FK table in another CHARSET..then also you might get this error...I too got this error but after changing the charset to PK charset then it got executed without errors
create table users
(
------------
-------------
)DEFAULT CHARSET=latin1;
create table Emp
(
---------
---------
---------
FOREIGN KEY (userid) REFERENCES users(id) on update cascade on delete cascade)ENGINE=InnoDB, DEFAULT CHARSET=latin1;
This error can occur if two tables have a reference, for example, one table is Student and another table is Education, and we want the Education table to have a foreign key reference of Student table. In this instance the column data type for both tables should be same, otherwise it will generate an error.
In most of the cases the problem is because of the ENGINE dIfference .If the parent is created by InnoDB then the referenced tables supposed to be created by MyISAM & vice versa
In my case. I had problems with engine and charset because my Hosting server change settings and my new tables was MyISAM but my old tables are InnoDB. Just i changed.
Please make sure both your primary key column and referenced column have the same data types and attributes (unsigned, binary, unsigned zerofill etc).
A real edge case is where you have used an MySQL tool, (Sequel Pro in my case) to rename a database. Then created a database with the same name.
This kept foreign key constraints to the same database name, so the renamed database (e.g. my_db_renamed) had foreign key constraints in the newly created database (my_db)
Not sure if this is a bug in Sequel Pro, or if some use case requires this behaviour, but it cost me best part of a morning :/
The column of PARENT table to which you are referring to from child table has to be unique. If it is not, cause an error no 150.
I had the same error. In my case the reason for the error was that I had a ON DELETE SET NULL statement in the constraint while the field on which I put the constraint in its definition had a NOT NULL statement. Allowing NULL in the field solved the problem.
I faced this kind of issue while creating DB from the textfile.
mysql -uroot -padmin < E:\important\sampdb\createdb.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\create_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\create_absence.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\insert_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\insert_absence.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\load_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\load_absence.sql
I just wrote the above lines in Create.batand run the bat file.
My mistake is in the sequence order of execution in my sql files. I tried to create table with primary key and also foreign key. While its running it will search for the reference table but tables are not there.
So it will return those kind of error.
If you creating tables with foreign key then check the reference
tables were present or not. And also check the name of the reference
tables and fields.
I had a similar problem but mine was because i was adding a new field to an existing table that had data , and the new field was referencing another field from the parent table and also had the Defination of NOT NULL and without any DEFAULT VALUES. - I found out the reason things were not working was because
My new field needed to autofill the blank fields with a value from the parent table on each record, before the constraint could be applied. Every time the constraint is applied it needs to leave the Integrity of the table data intact. Implementing the Constraint (Foreign Key) yet there were some database records that did not have the values from the parent table would mean the data is corrupt so MySQL would NEVER ENFORCE YOUR CONSTRAINT
It is important to remember that under normal circumstances if you planned your database well ahead of time, and implemented constraints before data insertion this particular scenario would be avoided
The easier Approach to avoid this gotcha is to
Save your database tables data
Truncate the table data (and table artifacts i.e indexes etc)
Apply the Constraints
Import Your Data
I Hope this helps someone
Create the table without foreign key, then set the foreign key separately.
Perhaps this will help? The definition of the primary key column should be exactly the same as the foreign key column.
Make sure that the all tables can support foreign key - InnoDB engine
I had a similar problem when dumping a Django mysql database with a single table. I was able to fix the problem by dumping the database to a text file, moving the table in question to the end of the file using emacs and importing the modified sql dump file into the new instance.
HTH Uwe
I've corrected the problem by making the variable accept null
ALTER TABLE `ajout_norme`
CHANGE `type_norme_code` `type_norme_code` VARCHAR( 2 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL
I got the same problem when executing a series of MySQL commands. Mine occurs during creating a table when referencing a foreign key to other table which was not created yet. It's the sequence of table existence before referencing.
The solution: Create the parent tables first before creating a child table which has a foreign key.

Error 1059: Identifier Name Too Long on Foreign Key Constraints from Existing Table

I have some pre-existing tables in a production database. When I run show create table existing_table it shows the SQL required to create the table, which involves several CONSTRAINT FOREIGN KEY REFERENCES involving constraints with names like:
_xxxxxxxxxxx_xxxxxxxxxxx_xx_f87560e38ebd0f6_fk_customer_customer_id
This seems normal, but when I try to create a tmp table like new_existing_table that runs the same SQL as shown in the create table query, I get the following error:
ERROR 1059 (42000): Identifier name '_xxxxxxxxxxxx_xxxxxxx_xxxxxx_xx_7435260ed6a242b0_fk_customer_customer_id' is too long
If this was the SQL that generated the original table, how is it failing when I create the new table? Even if I make the table name really short, like tmp, I get the same error.
I'm using MySQL, InnoDB on Amazon RDS.
This looks like a problem related to MySQL Bug #44541, which was fixed in MySQL Server versions 5.1.69, 5.5.31, 5.6.11, and 5.7.1.
The length of internally generated foreign key names was not checked. If internally generated foreign key names were over the 64 character limit, this resulted in invalid DDL from SHOW CREATE TABLE. This fix checks the length of internally generated foreign key names and reports an error message if the limit is exceeded.
The problem is, the bug allowed tables with invalid definitions to be created, so the server version that's important here isn't the server version you're trying to load onto -- it's the server version that was running when and where the table was created. The fix doesn't do anything other than prevent newly created tables from having invalid auto-generated identifiers.
The identifier is the constraint identifier, and its value isn't particularly important -- it's only used to tell you, in an error message, the foreign key constraint that was about to be violated... so you can just remove it. The only time you need to explicitly declare it is when the auto-generated one would be too large.
From http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html, you'll notice that the keyword CONSTRAINT is optional, and even if supplied, the symbol following it is still optional. The symbol is the element that's giving you a problem. It's limited to 64 characters. It always has been, but due to a bug, the limit wasn't properly imposed.
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]

Is mysql compatible with sql-92?

The other day I was trying to create a table in mysql usign a standard syntax:
create table client(
rc character varying(11)
constraint client_pk primary key
);
However, mysql doesn't support setting a primary key this way. (I'm 99% sure it's compliant with the sql-92 norm)
So my question: Does MySQL fail to support at even these basic things from a 20 year old standard, or am I missing something?
EDIT: my goal is NOT to create this table using using some mysql dialect, but to create this table using a standardized syntax. And the question is whether it is possible.
To answer your question, no, MySQL is not fully compliant with the SQL-92 specification, in that MySQL supports only a subset of the specification, and MySQL has some significant(ly useful) extensions which are not part of the SQL-92 specification.
This is not just about the SQL syntax that MySQL accepts and recognizes, but (the probably bigger issue) is about what MySQL actually does with the syntax, the actual operations that MySQL performs with the syntax that it does accept. That's really a more important issue than the more superficial issue of what syntax MySQL recognizes.
It's not that MySQL is lazy. And it's not that MySQL just doesn't care.
There is an entire section of the MySQL documentation devoted to MySQL differences from the SQL standard. And the most important differences aren't really about syntax, but rather about that fact that "MySQL performs operations differently in some cases."
For example, MySQL accepts syntax for CHECK constraints, but MySQL does not actually do any checking or make any attempt to enforce CHECK constraints. MySQL accepts syntax that meets the SQL-92 specification, but the behavior of MySQL is much different from other databases that accept that same syntax.
As another example, the behavior of MySQL with respect to FOREIGN KEY constraints differs significantly, depending on whether the storage engine for the table is MyISAM or InnoDB.
To get your CREATE TABLE statement to execute in MySQL, you would need to change it.
It looks like the easiest option for you would be to remove constraint client_pk from the sql text. You can either specify the table constraint in the column definition:
create table client(
rc character varying(11) primary key
);
or declare the table constraint separately"
create table client(
rc character varying(11),
primary key (rc)
);
Both of those forms are entirely compatible with the SQL-92 specification.
Note that MySQL does accept the syntax for constraint name definition, when the declaration of the constraint is not on the column, e.g.
create table client(
rc character varying(11),
constraint client_pk primary key (rc)
);
And that syntax is also entirely compatible with SQL-92 specifiction.
But note that MySQL ignores the supplied constraint name, and assigns the name PRIMARY to the primary key constraint. And this is true even if the constraint is declared in a separate ALTER TABLE statement.
Note that the syntax that MySQL accepts, and in some cases the operations it performs, is dependent on the settings of specific MySQL variables, in particular, sql_mode, and of particular concern, in the case of your statement, the setting of the default-storage-engine variable, and whether this table will be created using the MyISAM engine or the InnoDB engine, or even the corner case that default-storage-engine has been set to BLACKHOLE.
I understand that your goal is to "create this table with standardized syntax".
But I think you really DO need to be concerned with at least some minimum subset of MySQL specific syntax, in as far as the variety of possible behaviors that MySQL can exhibit when presented with "standardized syntax". Consider:
SET default-storage-engine = 'MyISAM' ;
SET default-storage-engine = 'InnoDB' ;
SET sql_mode = '' ;
SET sql_mode = 'ANSI' ;
This works for me in MySQL 5.5.29:
create table client(
rc character varying(11),
constraint client_pk primary key(rc)
);
However, as a_horse_with_no_name has pointed out, MySQL ignores the client_pk name and calls it PRIMARY.
References:
http://savage.net.au/SQL/sql-92.bnf.html
http://owen.sj.ca.us/~rk/howto/sql92.html
create table tablename
(
column_Name varchar(20) not null,
column_Name varchar(20),
primary key(column_name)
);
In this way you can create table and set primary key.

MYSQL Contraints - Multiple Checks

Well i am here writing some constraints for a db I am working on and i was wondering if I could do the following:
ALTER TABLE Course
ADD CONSTRAINT cs_level
CHECK (clevel in ('P','I','II','III'))
...instead of this:
ALTER TABLE Course
ADD CONSTRAINT cs_level
CHECK (clevel = 'P' OR clevel = 'I' OR clevel = 'II' OR clevel = 'III')
Even if MySQL enforced CHECK constraints, I'd still be creating a COURSE_LEVEL table:
COURSE_LEVEL_CODE, VARCHAR(3), primary key
COURSE_LEVEL_DESCRIPTION, VARCHAR(120)
...and create a FOREIGN KEY constraint on the COURSE table, clevel column:
ALTER TABLE COURSE
ADD FOREIGN KEY (clevel) REFERENCES COURSE_LEVEL(COURSE_LEVEL_CODE)
Unfortunately, MySQL does not support the CHECK-constraints. They are parsed but ignored.
From the reference manual:
The CHECK clause is parsed but ignored by all storage engines.
You can try to put this check constraint in your business logic before inserting the row.
As Joe Celko says in his book Joe Celko's SQL for Smarties:
Small "pseudo-SQL" products have appeared in the open source arena. Languages such as MySQL are very different in syntax and semantics from Standard SQL, often being little more than a file system interface with borrowed reserved words
A little harsh indeed, but in a way he's correct, since MySQL doesn't support a bunch of Standard SQL features.
MySQL only supports foreign key constraints, not check constraints. Wherever you got that syntax from, it wasn't the MySQL manual.