MYSQL allowing me to insert nulls in PK and FK - mysql

I have been testing a database i am doing right now and i am noticing that it is letting me insert null values into fields that are part of a primary key, despite stating in the script that the value of the field should be NOT NULL. I am using MAC's MySQL Workbench, and I have been googling around and can't figure out why this is happening. (Maybe I am too brain-fried right now... I am even starting to doubt myself)
Part of the script of the database creation (these are the tables I have tested..):
DROP DATABASE IF EXISTS solytierra ;
CREATE DATABASE IF NOT EXISTS solytierra DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
USE solytierra ;
DROP TABLE IF EXISTS solytierra.Cliente ;
CREATE TABLE IF NOT EXISTS solytierra.Cliente (
CIF VARCHAR(25) NOT NULL,
Nombre VARCHAR(100) NULL,
EmailGeneral VARCHAR(45) NULL,
Web VARCHAR(45) NULL,
Notas VARCHAR(150) NULL,
insertado Timestamp,
CONSTRAINT pk_Cliente PRIMARY KEY (CIF)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS solytierra.PersonaContacto ;
CREATE TABLE IF NOT EXISTS solytierra.PersonaContacto (
Cliente_CIF VARCHAR(25) NOT NULL,
Nombre VARCHAR(50) NOT NULL,
Apellidos VARCHAR(100) NOT NULL,
Notas VARCHAR(150) NULL,
CONSTRAINT pk_PersonaContacto PRIMARY KEY (Cliente_CIF , Nombre , Apellidos),
CONSTRAINT fk_PersonaContacto_Cliente FOREIGN KEY (Cliente_CIF)
REFERENCES solytierra.Cliente (CIF)
ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB;
...
It will let me create Clients without CIF, "PersonaContacto" without Cliente_CIF or without "Nombre"....
I have also tested other databases that i already had that used to work and it is happening the same in an all them.

Got it!!
I don't know what sql mode i was running on by default, but with this:
SET sql_mode = TRADITIONAL;
It is now running perfectly! I didn't know that there were different sql modes! Thanks a lot to everyone for your time and efforts! It really helped me to see that the problem was in my workbench, not the code and look for the answer accordingly! I hope this thread will be useful for future beginners like me!

If the value being stored in the column CIF is actually a NULL, then the expression LENGTH(CIF) should also return NULL. (If it's a zero length string, then LENGTH(CIF) will return 0.
To verify:
SELECT c.CIF, LENGTH(c.CIF) FROM solytierra.Cliente c ;
SELECT c.CIF FROM solytierra.Cliente c WHERE c.CIF IS NULL;
If you are running an INSERT statement, I can't explain the behavior you are observing, either MySQL allowing a NULL value to be stored or MySQL providing an implicit default value.)
If it's a zero length string being stored, that's the behavior we would expect if the columns were not explicitly declared to be NOT NULL but were later declared to part of the primary key. It's also the behavior we'd expect if the column were defined NOT NULL DEFAULT ''.
When the NOT NULL is omitted from the column declaration and the column is later declared to be part of the PRIMARY KEY, MySQL will use an an implicit default value based on the datatype of the column (zero length string for VARCHAR, zero for an integer, etc.)
But I'm not able to reproduce the problem you report, with the table definitions you've posted.
I recommend you check the table definition by getting the output from:
SHOW CREATE TABLE solytierra.Cliente;

Related

MSSql GUID to MySQL Migration [duplicate]

Im revisiting my database and noticed I had some primary keys that were of type INT.
This wasn't unique enough so I thought I would have a guid.
I come from a microsoft sql background and in the ssms you can
choose type to "uniqeidentifier" and auto increment it.
In mysql however Ive found that you have to make triggers that execute on insert for the tables you want
to generate a guide id for. Example:
Table:
CREATE TABLE `tbl_test` (
`GUID` char(40) NOT NULL,
`Name` varchar(50) NOT NULL,
PRIMARY KEY (`GUID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Trigger:
CREATE TRIGGER `t_GUID` BEFORE INSERT ON `tbl_test`
FOR EACH ROW begin
SET new.GUID = uuid();
Alternatively you have to insert the guid yourself in the backend.
Im no DB expert but still remember that triggers cause performance problems.
The above is something I found here and is 9 years old so I was hoping something has changed?
As far as stated in the documentation, you can use uid() as a column default starting version 8.0.13, so something like this should work:
create table tbl_test (
guid binary(16) default (uuid_to_bin(uuid())) not null primary key,
name varchar(50) not null
);
This is pretty much copied from the documentation. I don't have a recent enough version of MySQL at hand to test this.
You can make a
INSERT INTO `tbl_test` VALUES (uuid(),'testname');
This would generate a new uuid, when you call it.
Or you can also use the modern uuid v4 by using one of these functions instead of the standard uuid(), which is more random than the uuid in mysql
How to generate a UUIDv4 in MySQL?
You can use since 8.0.13
CREATE TABLE t1 (
uuid_field VARCHAR(40) DEFAULT (uuid())
);
But you wanted more than unique, but here are only allowed internal functions and not user defined as for uuid v4, for that uyou need the trogger
As per the documentation, BINARY(x) adds some hidden padding bytes to the end of each entry, & VARCHAR(40) also wastes space by not being encoded directly in binary. Using VARBINARY(16) would be more efficient.
Also, more entropy (unguessability / security) per byte is available from RANDOM_BYTES(16) than standardized UUIDs, because they use some sections to encode constant metadata.
Perhaps the below will work for your needs.
-- example
CREATE TABLE `tbl_test` (
`GUID` VARBINARY(16) DEFAULT (RANDOM_BYTES(16)) NOT NULL PRIMARY KEY,
`Name` VARCHAR(50) NOT NULL
);

MySQL: Expression of generated column contains disallowed function? CONCAT?

I have a table with a virtual generated column that concatenates five other columns (int and char) using CONCAT_WS(). This table contains 200-odd records and is never updated - it's just used as a lookup table. Recently, after months of untroubled processing, when I update records in a child table during which a SELECT is performed on this table, I sometimes see this error (ignore the "ITEM UPDATE FAILED" - that's me):
I am in development with a many changes every day, so it is impossible for me to determine if there is a correlating change. I have recently added "created" and "lastmodified" datetime fields to several tables with CURRENT_TIMESTAMP for DEFAULT or ON UPDATE, but not to this table.
Here's the table:
{EDIT} --- adding table definition:
CREATE TABLE `cpct_fixedfield` (
`id` int(11) UNSIGNED NOT NULL,
`name` varchar(256) NOT NULL,
`label` varchar(50) NOT NULL,
`field` int(11) NOT NULL,
`start` int(11) NOT NULL,
`rectype` int(11) NOT NULL ,
`mediatype` char(1) NOT NULL DEFAULT '' ,
`length` int(11) NOT NULL,
`userdefined` tinyint(1) NOT NULL,
`defaultval` varchar(5) NOT NULL,
`helpcode` varchar(10) NOT NULL,
`mandatory` varchar(2) NOT NULL ,
`idx` varchar(20) GENERATED ALWAYS AS (concat_ws('.',`field`,`rectype`,`mediatype`,`start`,`length`)) VIRTUAL NOT NULL)
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
The length of the data in field never exceeds 11chars. I can view the entire table in pma or Mysql Workbench and the virtual field materialises in all records without complaint, which suggests to me that there is nothing wrong with either the expression for the virtual column or the data in the columns that expression draws on.
The error occurs in several contexts when I am updating a child table. All the updates occur in Stored Procedures/Functions. One section of code that seems to trigger the error is this:
SET idxvar = CONCAT_WS(".", SUBSTRING(tmpfldkey,3,1), rectype, ptype, position, "%") COLLATE utf8mb4_general_ci;
SELECT id INTO ffid FROM cpct_fixedfield WHERE idx LIKE idxvar AND idx != "0.0..6.2";
All the variables involved are varchars or ints. utf8mb4_general_ci is used throughout the database.
I cannot find any reference in MYSQL documentation to CONCAT or CONCAT_WS being unsafe, and none of the columns referenced has a default using a non-deterministic function. All the other questions I can find in this forum and elsewhere about this error have arisen because of the use of non-deterministic functions like CURRENT_TIMESTAMP() in the virtual field, or a component of the field.
I replaced the SELECT on the table with a (large) CASE statement and all was well, and in fact, after I did this then reverted to the SELECT I had no errors for many hours. But it just happened again (so I'm back to the case statement).
I have run out of ideas - I'm hoping someone has some knowledge/experience that can help.
Thanks

Using MySQL to Generate SHA-256 Hashes?

Here's what I'm trying to do:
CREATE TABLE IF NOT EXISTS hashes (
id int NOT NULL AUTO_INCREMENT,
text varchar(50) NOT NULL,
hash varchar(64) NOT NULL AS (SHA2(CONCAT(text), 256) STORED,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
And then I want to run an insert like this:
INSERT INTO `hashes` (`text`) VALUES ('testing');
From the research I've done, the id should be automatically generated since auto_increment is enabled, so I don't need to define it in the insert query.
From my CREATE TABLE query, the hash should be automatically generated based upon the data entered into the text field. However, when I run the CREATE TABLE command I get an error with this line:
hash varchar(64) NOT NULL AS (SHA2(CONCAT(text), 256) STORED
I'm just wanting the hash to be automatically generated similar to how CURRENT_TIMESTAMP will automatically generate the current time by default.
What am I doing wrong?
It seems you have syntax error. You should write NOT NULL after SHA2 hash function. Please try:
CREATE TABLE IF NOT EXISTS hashes (
id int NOT NULL AUTO_INCREMENT,
text varchar(50) NOT NULL,
hash varchar(64) AS (SHA2(CONCAT(text), 256)) STORED NOT NULL ,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
INSERT INTO `hashes` (`text`) VALUES ('testing');
You don't need to declare your hash column as NOT NULL. It's based on another NOT NULL column, text, so the hash will naturally be NOT NULL as well.
You also have forgotten a closing parenthesis.
hash varchar(64) AS (SHA2(CONCAT(text), 256) STORED,
1 2 3 3 2 ^
You need another closing paren where I indicated ^.
If you already have the table filled by some content, you can Alter it with :
ALTER TABLE `page` ADD COLUMN `hash` char(64) AS (SHA2(`content`, 256)) AFTER `content`
This solution will add hash column right after the content one, make hash for existing and new records too. Unique index can be added to prevent insertion of large content duplicates.

phpMyAdmin - "Please enter a valid length"

I'm trying to create a table in phpMyAdmin, and I keep getting the same error no matter how I manipulate the SQL code. This is the preview SQL that phpMyAdmin generates
CREATE TABLE `puppies`.`animals` (
`id` INT(11) NOT NULL AUTO_INCREMENT ,
`puppy_name` VARCHAR(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`breed_id` INT(11) NOT NULL ,
`description` VARCHAR(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`price` DECIMAL(10,2) NOT NULL ,
`picture_url` VARCHAR(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`sold` TINYINT(1) NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE = InnoDB;
I've tried it with multiple variations of brackets and commas.
I have also faced the same issue and what I did was clicked on Preview SQL and copy the sql query and paste it in the SQL Run
To those still experiencing this, and don't want to wait for it to randomly work again:
I just encountered this, and cannot find any explanation other than some bug.
I tried:
CREATE TABLE `database`.`measurement_types` (
`TypeID` INT(2) NOT NULL AUTO_INCREMENT ,
`Name` VARCHAR(32) NOT NULL ,
`Description` VARCHAR(256) NOT NULL ,
PRIMARY KEY (`TypeID`)) ENGINE = InnoDB;
Which produced the same "Please enter valid length" error
Tried a few times with different length values, but kept getting the same error.
--SOLUTION--
So I just created the table with a single column first, then altered it with the two other columns like so:
CREATE TABLE `database`.`measurement_types` (
`TypeID` INT(2) NOT NULL AUTO_INCREMENT ,
PRIMARY KEY (`TypeID`)) ENGINE = InnoDB;
And then:
ALTER TABLE `measurement_types`
ADD `Name` VARCHAR(32) NOT NULL AFTER `TypeID`,
ADD `Description` VARCHAR(256) NOT NULL AFTER `Name`;
And that worked.
I also tried to delete the table and create it with the first SQL again, and this time it worked. Seems pretty random
I've had the same issue, seems to be a bug with VARCHAR fields. My solution was to make those fields INT, create the table, and then change them back to VARCHAR
You can also solve it by restarting your mysql... It worked for me.
It is a bug with varchar. If you change collation to utf8mb4_general_ci it should fix the problem
There seems to be some issue with PhpMyAdmin.
It needs 'Collation' value if column type is of varchar. You will encounter the error “Please enter a valid length” if the Collation field is empty for varchar. So basically both fields 'Size' and 'Collation' are mandatory and cannot be empty.
Please set Collation field with some value like 'utf8mb4_general_ci' to resolve the issue.
I solved the issue of "Please enter a valid length" by adding one by one column separately and by giving length to all the columns as the database needs to know how much memory it will consume.
It is definitely a problem with varchar fields but does not always happen.
You can still create your table by copying out the SQL query and executing the raw query.
As stated in the official docs, I think it is mandatory to give a specific length in later versions of phpMyAdmin.
I solved my “Please enter a valid length” by typing the length values for the data types that weren't of a dynamic memory allocation type. So therefore they obviously needed to know how much memory they could use for storage. Or by all means a valid length
If you use Varchar you have to give a length. Otherwise, it will not save.
My solution was to set a value for every varchar type.

Issue Converting varchar to nvarchar mysql

Sorry if this is an easy question, I am coming to MySQL from SQL Server.
When I execute my create statement it contains nvarchar but commits to the database as varchar. Even in my alter statement afterwards the column does not change at all. Does the collation or DB engine make a difference?
During execution I am not encountering any issues in results, other than the fact the column changes datatype. I attached a screencast of my activity http://screencast.com/t/wc94oei2
I have not been able to find anyone with similar issues through my Google searches
Did you mean, this..
CREATE TABLE stars (
idstars int(11) NOT NULL AUTO_INCREMENT,
Name nvarchar(200) DEFAULT NULL,
PRIMARY KEY (idstars),
UNIQUE KEY Name_UNIQUE (Name)
)
----turns to---
CREATE TABLE stars (
idstars int(11) NOT NULL AUTO_INCREMENT,
Name varchar(200) DEFAULT NULL,
PRIMARY KEY (idstars),
UNIQUE KEY Name_UNIQUE (Name)
)