Set a foreign key to nullable in laravel - mysql

Assume I have a the tables users and persons. An entry in persons can have a user id or not. So a person can have a user, but this is optional.
This means that the foreign key in persons needs to be nullable.
This is my database migration:
$table->bigInteger('user_id')->nulleable()->unsigned();
$table->foreign('user_id')->nulleable()->references('id')->on('users');
Sadly, when I check the database columns it says, that the field is not nullable
+------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------------+------+-----+---------+----------------+
| user_id | bigint unsigned | NO | MUL | NULL | |
+------------+-----------------+------+-----+---------+----------------+
How can I set the foreign key to nullable? I have tried various combinations I found online, but nothing works.
Thank you very much in advance.

You don't have to repeat nullable (not nulleable) to the second ligne,
try this :
$table->unsignedBigInteger('user_id')->nullable();
$table->foreign('user_id')->references('id')->on('users');

Related

MySQL Adding Foreign Key Error 1215

I know such a question is asked before. I made sure that they have the same data type and also checked my syntax, but I am still getting the error:
ALTER TABLE meetings ADD FOREIGN KEY (ownerName) REFERENCES employees(name);
ERROR 1215 (HY000): Cannot add foreign key constraint
mysql> desc `meetings`;
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| room | int(6) | NO | | NULL | |
| ownerName | varchar(30) | NO | | NULL | |
| ownerID | varchar(30) | NO | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> desc `employees`;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| username | varchar(30) | NO | PRI | NULL | |
| pswd | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
What am I doing wrong?
name is not primary key in employees table so .. try using username
ALTER TABLE meetings ADD FOREIGN KEY (ownerName) REFERENCES employees(username);
or as suggested by DanielE or you can use the column name but need an UNIQUE index for this column
Change the primary key of 'employees' from user name to name. Then you can use
ALTER TABLE meetings ADD FOREIGN KEY (ownerName) REFERENCES employees(name);
What am I doing wrong? Error 1215 is probably the least of the problems here.
Some of the answers given for this question suggest making username the referenced column in employees rather than name, which is fine as far as it goes, but ignores some really fundamental issues in the schema and quite possibly wasn't the poster's intention for these columns. The rest of this answer is based on my own set of assumptions.
meetings table
Looking at the meetings table, I'm left wondering about the purpose of the ownerID column. Since the intention is to have ownerName as a foreign key to employees, what exactly is ownerID? The name suggests it also somehow references employees, but there is no id or ownerID in employees. Also, if any column starting owner... refers to an employee then why would you need both in the meetings table? One of them is surely redundant. Why is ownerID a VARCHAR(30)? ID columns tend to be INT. Of course, I may be reading to much into this and ownerID may have some other purpose that has nothing to do with an employee, but if that's the case the name is likely going to cause confusion in the future.
The meetings table also has an INT surrogate key in id. There's another INT for room. Since room isn't a foreign key, it suggests that rooms are either consistently identified only by number (which would be strange in my experience) and that there is nothing more to a 'room' that's worth capturing (e.g. location, capacity, equipment etc.) to bother with modelling data about the room in a separate table (again unlikely). Alternatively, room might itself be a foreign key referencing an INT id column in an, as yet undefined, rooms table.
employees table
If we accept ownerID as a more appropriate foreign key to the employee that owns the meeting (it uses less memory to index than either name or username) then consistency would suggest another surrogate key id as the primary key in the employees table. It's not necessary to do this, username would be unique and is fine on it's own, but it's simpler and more efficient. The other suggestion made that name should be the PK in employees is wrong - it presupposes that names are always unique.
A single column to cover an employee name would also be unusual.
The point made about referencing a PK or a unique index is well made (even if it's not strictly necessary in Innodb), I'd just say that ownerName is the wrong foreign key and username and name are the wrong references because there is a better alternative.
And, finally, is a NULL password (pswd) a good idea?

mySQL: What is preventing my foreign key constraint?

I have tried everything I can think of but I am still having problems creating a table.
I have a user table with a primary key username
+---------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-------------+------+-----+---------+-------+
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
| username | varchar(50) | NO | PRI | NULL | |
| administrator | tinyint(1) | YES | | NULL | |
| fullname | text | YES | | NULL | |
| description | text | YES | | NULL | |
| password | varchar(60) | NO | | NULL | |
+---------------+-------------+------+-----+---------+-------+
and I want to create a new table like this:
CREATE TABLE sessions (
created_at DATETIME,
updated_at DATETIME,
token VARCHAR(50) NOT NULL,
username VARCHAR(50),
PRIMARY KEY (token),
FOREIGN KEY(username) REFERENCES users (username)
);
but I get a nasty error:
ERROR 1215 (HY000): Cannot add foreign key constraint
I usually find this error is caused by a mismatch in the data type of the pk/fk pair but this time both are clearly varchar(50) so it looks like the problem is elsewhere.
I have also tried this just in case:
CREATE TABLE sessions (
created_at DATETIME,
updated_at DATETIME,
token VARCHAR(50) NOT NULL,
username varchar(50) NOT NULL, #<- ***added not null***
PRIMARY KEY (token),
FOREIGN KEY(username) REFERENCES users (username)
);
mysql>SHOW ENGINE INNODB STATUS
LATEST FOREIGN KEY ERROR
2016-08-03 15:13:23 a46fcb70 Error in foreign key constraint of table savesdev/sessions:
FOREIGN KEY(username) REFERENCES users (username)):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
It seems the error is raised under two circumstances:
1) When there is a mismatch (which I have ruled out)
column types in the table and the referenced table do not match for constraint.
2) When there is no suitable index on the referenced column
Cannot find an index in the referenced table where the referenced columns appear as the first columns
I think both of these are covered so what's the deal?
Can anyone spot my error?
Maybe your columns username have different charset can you try this :
ALTER TABLE sessions MODIFY username VARCHAR(50) CHARACTER SET utf8;
ALTER TABLE users MODIFY username VARCHAR(50) CHARACTER SET utf8;
As suggested by #Graeme Stuart here is a link to see how we can check the charterer set of a database / table or a column : How do I see what character set a MySQL database / table / column is?

Get the auto increment-primary key column programatically

witch is the auto increment field in a mysql table?
I have a table structure, for example:
table name is my_table and the fields are my_id, my_name, my_blah.. The one of fields is an auto incremented primary key. Witch is it?
How can I get the name of auto increment field on this table with a php code and/or a mysql query?
You can use the MySQL SHOW COLUMNS query to retrieve information about the columns in a table:
mysql> SHOW COLUMNS FROM `test`;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| col1 | varchar(100) | YES | | NULL | |
| col2 | int(11) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
The extra column will contain auto_increment for the primary key field.
You could try with a
SHOW COLUMNS FROM TableName
See here: http://dev.mysql.com/doc/refman/5.0/en/show-columns.html
Use a MySQL client and issue the query SHOW CREATE TABLE my_table.
It shows you the code one needs to run to create that table. You can see the column names, types (and lengths), other attributes each column may have (they depend on the type). AUTO_INCREMENT is such an attribute.
It also shows you the PK and the indexes of the table.

Should the auto increment column be the primary key?

I'm confused as to how to assign primary keys.
For example, let's say I have these two tables:
users table where the user_id is unique:
+---------+----------+--------------+
| user_id | username | password |
+---------+----------+--------------+
| 1 | hello | somepassword |
| 2 | world | another |
| 3 | stack | overflow |
+---------+----------+--------------+
posts table where the post_id is unique:
+---------+---------+--------------+
| post_id | user_id | content |
+---------+---------+--------------+
| 1 | 1 | Hello World! |
| 2 | 1 | Another. |
| 3 | 3 | Number 3. |
| 4 | 2 | Stack. |
| 5 | 1 | Overflow. |
+---------+---------+--------------+
Obviously for the users table the primary key should be user_id, but what should the primary key be in the posts table? post_id or user_id? Please explain.
The primary key for the Posts table should also be the auto increment value, post_id, because it's the only thing that uniquely identifies each post, because each post has an id unlike any other. The user_id won't always be unique because the same user could have multiple posts (as far as I know) so it can't uniquely identify the posts. If you need to relate information between the tables you can always do a join on the user_id from both tables, however to identify things with a primary key, the post_id would be your best bet.
Surely, you have this sceneraio:
A user can post several posts.
A post can be posted, logically, by one user only.
Thus, you are dealing with a One-To-Many model.
Once these things are clear to you, you can guess that the primary key of users must appear as a foreign key in posts. This is what you obviously have done already.
Now, wether post_id is enough as the primary key of posts depends on the whole entity relationship model you have (how many other entities do you have and what are their relationship to each others).
However, you will not need, for this specific scenario to combine the foreign key user_id as a part of the primary key of posts.
Note: when you implement your tables, please add the constraints of auto_increment and not null to user_id and post_id.
Let's summerize all this mess in SQL:
Table users:
mysql> create table users (user_id int(2) unique auto_increment not null, username varchar(15) not null, password varchar(20) not null, primary key(user_id));Query OK, 0 rows affected (0.33 sec)
Table posts:
mysql> create table posts(post_id int(2) unique auto_increment not null, user_id int(2) not null, content varchar(50) not null, foreign key(user_id) references users(user_id), primary key(post_id));
Query OK, 0 rows affected (0.26 sec)
Of course it should be user_id because when you use ORM then it will map tables automatically from proper naming of keys
You may refer ORM here : Good PHP ORM Library?

query a table in mysql which does not have primary key

I am new to database, and run into a time issue when querying a table where no field is indicated as primary key.
for example
+-----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+-------+
| a_id | char(10) | NO | | | |
| media | char(3) | YES | | NULL | |
| label | char(37) | YES | | NULL | |
As you can see, no of the field have any key specification. When I do a query like
"select label from table where a_id=?", the query is extremely slow. Is this caused by the lack of primary key?
thanks,
No, it is caused by lack of indexes. A primary key must contain a unique and non-null value. If you add an index on the column, it may contain duplicates, but your query will still be faster.
If you want the field to be unique, but you don't want it to be a primary key (although you should wonder why), you can even add a unique index. It will force the value to be unique, but it's no primary key.
That can be convenient when you want the table to have an id and a description that should both be unique. Usually you'll make the id the primary key, and the description just unique.