MySQL/POSTGRES how to force foreign key to be NULL - mysql

I have the following SQLite3 database
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
email VARCHAR(75) NOT NULL,
password VARCHAR(128) NOT NULL
);
CREATE TABLE IF NOT EXISTS pads (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name VARCHAR(100) NOT NULL,
user_id INTEGER NOT NULL REFERENCES users(id)
);
CREATE TABLE notes (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
pad_id INTEGER REFERENCES pads(id),
user_id INTEGER NOT NULL REFERENCES users(id),
name VARCHAR(100) NOT NULL,
text text NOT NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL
);
~
I have tried to migrate this sql schema to mysql and postgres, everything seems to be working fine except for one detail.
The table notes should accept pad_id as NULL, if there is no pad a note should be saved but when I try to save a note without a pad I get an error
sqlalchemy.exc.IntegrityError
IntegrityError: (psycopg2.errors.ForeignKeyViolation) insert or update
on table "note" violates foreign key constraint "note_pad_id_fkey"
DETAIL: Key (pad_id)=(0) is not present in table "pad".
But I should be able to save it as NULL, it works fine on SQLite3.
What should I change to be able to accomplish this?
Thank you.

Neither MySQL nor Postgres has a problem, with NULL as padod see examples
Therefore the error messahe comes from postgres, but it is because of the migration
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
email VARCHAR(75) NOT NULL,
password VARCHAR(128) NOT NULL
);
CREATE TABLE IF NOT EXISTS pads (
id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
name VARCHAR(100) NOT NULL,
user_id INTEGER NOT NULL REFERENCES users(id)
);
CREATE TABLE notes (
id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
pad_id INTEGER REFERENCES pads(id),
user_id INTEGER NOT NULL REFERENCES users(id),
name VARCHAR(100) NOT NULL,
`text` text NOT NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL
);
INSERT INTO users VALUES(NULL,'test','pass')
✓
INSERT INTO notes VALUES (NULL,NULL,1,'test','text',NOW(),NOW())
✓
db<>fiddle here
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY NOT NULL,
email VARCHAR(75) NOT NULL,
password VARCHAR(128) NOT NULL
);
CREATE TABLE IF NOT EXISTS pads (
id SERIAL PRIMARY KEY NOT NULL,
name VARCHAR(100) NOT NULL,
user_id INTEGER NOT NULL REFERENCES users(id)
);
CREATE TABLE notes (
id SERIAL PRIMARY KEY NOT NULL,
pad_id INTEGER REFERENCES pads(id),
user_id INTEGER NOT NULL REFERENCES users(id),
name VARCHAR(100) NOT NULL,
"text" text NOT NULL,
created_at timestamp NOT NULL,
updated_at timestamp NOT NULL
);
INSERT INTO users VALUES(DEFAULT,'test','pass')
1 rows affected
INSERT INTO notes VALUES (DEFAULT,NULL,1,'test','text',NOW(),NOW())
1 rows affected
db<>fiddle here

Related

Why am I getting #1264 - Out of range value for column 'Identity_no' at row 1?

I create a table and Identity_no is unique in that but I am getting error when I try to add a integer value with 8 number.Probably I am getting this error because I identified unique to Identity_no.How can I fix that
Here is the code for creating table:
CREATE TABLE Members(
Member_id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
Identity_no INTEGER NOT NULL UNIQUE,
Member_Name varchar(80) NOT NULL,
Member_Surname varchar(80) NOT NULL,
Member_Phone CHAR(11),
MemberCityID INTEGER NOT NULL,
FOREIGN KEY(MemberCityID) REFERENCES Cities(City_id));
Here is the code for adding data:
INSERT INTO Members
(Member_id,Identity_no,Member_Name,Member_Surname,Member_Phone,MemberCityID)
VALUES
(1,89768434566,"John","W","05379621522",78);
The INTEGER type is a 32 bit signed int, which means numbers bigger than 2^31 cannot be stored in a column with this type.
Use BIGINT instead:
CREATE TABLE Members(
Member_id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
Identity_no BIGINT NOT NULL UNIQUE,
Member_Name varchar(80) NOT NULL,
Member_Surname varchar(80) NOT NULL,
Member_Phone CHAR(11),
MemberCityID INTEGER NOT NULL,
FOREIGN KEY(MemberCityID) REFERENCES Cities(City_id));

mysql unable to add foreign key: error 1215 (hy000)

I am getting error 1215 (hy000): cannot add foreign key constraint then I run the following .sql file. The code below is also not creating the documents table, probably because it fails to create its foreign keys. Can anyone show me how to fix the code below so it will create the documents table including its foreign keys without throwing errors:
CREATE DATABASE IF NOT EXISTS petclinic;
GRANT ALL PRIVILEGES ON petclinic.* TO pc#localhost IDENTIFIED BY 'pc';
USE petclinic;
CREATE TABLE IF NOT EXISTS types (
id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(80),
INDEX(name)
) engine=InnoDB;
CREATE TABLE IF NOT EXISTS documenttypes (
id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(80),
INDEX(name)
) engine=InnoDB;
CREATE TABLE IF NOT EXISTS owners (
id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(30),
last_name VARCHAR(30),
address VARCHAR(255),
city VARCHAR(80),
telephone VARCHAR(20),
INDEX(last_name)
) engine=InnoDB;
CREATE TABLE IF NOT EXISTS pets (
id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(30),
birth_date DATE,
type_id INT(4) UNSIGNED NOT NULL,
owner_id INT(4) UNSIGNED NOT NULL,
INDEX(name),
FOREIGN KEY (owner_id) REFERENCES owners(id),
FOREIGN KEY (type_id) REFERENCES types(id)
) engine=InnoDB;
CREATE TABLE IF NOT EXISTS documents (
id int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
client_id int(4) NOT NULL,
type_id INT(4),
name varchar(200) NOT NULL,
description text NOT NULL,
filename varchar(200) NOT NULL,
content mediumblob NOT NULL,
content_type varchar(255) NOT NULL,
created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (client_id) REFERENCES owners(id),
FOREIGN KEY (type_id) REFERENCES documenttypes(id)
) engine=InnoDB;
I tried the advice at this link, but none of those suggestions work with this code. Can someone show me something that does work with this code?
The foreign key columns have to be the exact same data type as the original columns.
Try this:
CREATE TABLE IF NOT EXISTS documents (
id int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
client_id int(4) UNSIGNED NOT NULL,
type_id INT(4) UNSIGNED NOT NULL,
name varchar(200) NOT NULL,
description text NOT NULL,
filename varchar(200) NOT NULL,
content mediumblob NOT NULL,
content_type varchar(255) NOT NULL,
created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (client_id) REFERENCES owners(id),
FOREIGN KEY (type_id) REFERENCES documenttypes(id)
) engine=InnoDB;
Added UNSIGNED to client_id and UNSIGNED NOT NULL to type_id (the NOT NULL part in is not mandatory though)
sqlfiddle demo

MySQL-error 150 solution

I have the following MySQL scripts:
CREATE TABLE user_roles (
id INT AUTO_INCREMENT,
PRIMARY KEY(id),
name TEXT NOT NULL,
access INT NOT NULL DEFAULT '0'
)
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
name TEXT NOT NULL,
email TEXT NOT NULL,
password TEXT NOT NULL,
date_created DATETIME,
roles VARCHAR(50) NOT NULL,
active INT DEFAULT '1',
FOREIGN KEY(roles) REFERENCES user_roles(id)
)
It keeps giving me error 150. Maybe the database isn't well planned? Any help will be greatly appreciated.
The data types of your users.roles and user_roles.id columns must be the same for the FOREIGN KEY constraint to work correctly. Instead try making users.roles an INT:
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
name TEXT NOT NULL,
email TEXT NOT NULL,
password TEXT NOT NULL,
date_created DATETIME,
-- Change this...
roles INT NOT NULL,
active INT DEFAULT '1',
FOREIGN KEY(roles) REFERENCES user_roles(id)
)
UPDATE According to comments, users.roles should be text like "admin, moderator, etc." For correct data normalization, user_roles.id should be keyed against and to get the text name of the role, JOIN them in queries.
You need to separate your statements with a semicolon and use INTS instead of strings:
CREATE TABLE user_roles (
id INT AUTO_INCREMENT,
PRIMARY KEY(id),
name TEXT NOT NULL,
access INT NOT NULL DEFAULT 0
);
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
name TEXT NOT NULL,
email TEXT NOT NULL,
password TEXT NOT NULL,
date_created DATETIME,
roles VARCHAR(50) NOT NULL,
active INT DEFAULT 1,
FOREIGN KEY(roles) REFERENCES user_roles(id)
);

MYSQL, When defining a table does the UNIQUE constraint have to be used in conjunction with an INTEGER or can it be any datatype?

I am wanting to have a label column (VARCHAR) and I want it to be unique, but when I try to create the table it seems to be throwing an error. Can a unique constraint only be used in conjunction with an INTEGER or will it work with other datatypes as well. The error I am getting is (ERRNO 150)
CREATE TABLE IF NOT EXISTS `user`(
user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
`password` VARCHAR(255) NOT NULL
);
CREATE TABLE IF NOT EXISTS `element`(
element_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
label VARCHAR(5) NOT NULL DEFAULT '',
parent_id INT NULL,
user_id INT NOT NULL,
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
edited_on TIMESTAMP NOT NULL,
UNIQUE(label),
KEY element_1 (label),
CONSTRAINT FK_element_1 FOREIGN KEY (user_id) REFERENCES `user` (user_id),
CONSTRAINT FK_element_2 FOREIGN KEY (parent_id) REFERENCES `element` (element_id)
);
The only way I can have this error, if the first table is created with MyISAM engine and the second (tried to be created) with InnoDB.
Check the definition of the created table user, using:
SHOW CREATE TABLE user ;
If that's the case, drop it and recreate it with:
CREATE TABLE IF NOT EXISTS `user`(
user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
`password` VARCHAR(255) NOT NULL
)
ENGINE = InnoDB ;

How do I create this relational table?

Below is a portion of relational data base. I know how to create table Film and assign primary key to it.. but don't understate creating other tables and assigning primary key to it.
Any help?
table Film
CREATE TABLE Film (
Id INTEGER PRIMARY KEY,
Title VARCHAR(35) NOT NULL,
Description VARCHAR(256) NOT NULL,
Year INTEGER NOT NULL CHECK (Year > 1900),
Rating INTEGER NOT NULL DEFAULT 3 CHECK (Rating BETWEEN 1 AND 5)
);
how do I create table FilmFormat and OrderItem ?
CREATE TABLE `jy` (
`PKfield` INTEGER UNSIGNED NOT NULL DEFAULT NULL AUTO_INCREMENT,
`field2` VARCHAR(45) NOT NULL,
PRIMARY KEY (`PKfield`),
CONSTRAINT `FK` FOREIGN KEY `FK` (`PKfield`)
REFERENCES `Film` (`Id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT
)
ENGINE = InnoDB;
This is enough to show you how to create a foreign key constraint between the two tables. As commented, the CHECK constraint will be parsed but ignored.
CREATE TABLE Film (
Id INTEGER PRIMARY KEY,
Title VARCHAR(35) NOT NULL,
Description VARCHAR(256) NOT NULL,
Year INTEGER NOT NULL CHECK (Year > 1900),
Rating INTEGER NOT NULL DEFAULT 3 CHECK (Rating BETWEEN 1 AND 5)
);
CREATE TABLE FilmFormat (
FilmId INTEGER not null,
FormatId INTEGER not null,
Price decimal(16,4) null,
Primary Key(FilmId, FormatId),
Constraint FK_FilmFormat_FilmId FOREIGN KEY (FilmId) REFERENCES Film(Id)
);
Doing the last table will just be doing your work for you.