In SQL, can you set a column that allows null values to be unique?
What happens if the table contains multiple rows with null value for that column?
What happens in case you specify a foreign key to that column in another table and a tuple in the referencing table contains a null value for the foreign key?
You can have as many rows with null as you want in a column set with a Unique Index in mysql. Check the table below:
CREATE TABLE `test1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`nullable` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `nullable` (`nullable`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INTO `test1` (`id`, `nullable`)
VALUES
(1, NULL),
(2, NULL),
(3, NULL);
You can add as many records as you want to this table with nulls in the nullable field.
I think I invented the name nullable :).
Related
On MySQL 8 I have this table:
CREATE TABLE `float_values` (
`id` bigint UNSIGNED NOT NULL,
`attribute_id` bigint UNSIGNED NOT NULL,
`value` double(8,2) NOT NULL,
`created_at` date NOT NULL,
`updated_at` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `float_values`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `float_values_created_at_unique` (`created_at`);
ALTER TABLE `float_values`
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;
with this schema:
Schema::create('float_values', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('attribute_id');
$table->float('value');
$table->date('created_at');
$table->date('updated_at');
});
after table created I did this for partitioning on created_at column:
ALTER TABLE float_values
PARTITION BY HASH( YEAR(created_at) )
PARTITIONS 4
but I get this error:
Static analysis:
1 errors were found during analysis.
Unrecognized alter operation. (near "" at position 0) SQL query:
ALTER TABLE float_values PARTITION BY HASH( YEAR(created_at) )
PARTITIONS 4
MySQL said: Documentation
1503 - A PRIMARY KEY must include all columns in the table's partitioning function
I know that the question is duplicate but answers didn't help me!
the error says that we have to announce created_at as primary but we cant have two primary keys I changed created_at to unique but the problem still exists
https://dev.mysql.com/doc/refman/8.0/en/partitioning-limitations-partitioning-keys-unique-keys.html says:
All columns used in the partitioning expression for a partitioned table must be part of every unique key that the table may have.
In other words, every unique key on the table must use every column in the table's partitioning expression. This also includes the table's primary key, since it is by definition a unique key.
This is a blocker for many people who want to use table partitioning in MySQL. You can't always partition by the column you want to partition by, because it's either not in a unique key, or there is some other unique (or primary) key in the table.
Remember: the partitioning expression must be part of EVERY unique key of the table.
Even if you were to make created_at a unique key, there is still the fact that the primary key of this table is on the id column.
There is no way to use partitioning on a MySQL table if you have both a PRIMARY KEY and a UNIQUE KEY, and these two keys have no column in common.
I found my answer.
when I was migrating the table it created a primary increment column on id so when I was doing the alter partition query it was telling me that partitioning column have to be a primary key!
What I shall be doing was that create a table without primary keys and increments column in my schema and then after a simple table without any primary keys created I did create a primary key contains id, created_at columns like this:
First this:
CREATE TABLE `float_values` (
`id` bigint UNSIGNED NOT NULL,
`attribute_id` bigint UNSIGNED NOT NULL,
`value` double(8,2) NOT NULL,
`created_at` date NOT NULL,
`updated_at` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
With this schema:
Schema::create('float_values', function (Blueprint $table) {
$table->unsignedBigInteger('id');
$table->unsignedBigInteger('attribute_id');
$table->float('value');
$table->date('created_at');
$table->primary(['id', 'created_at']);
$table->date('updated_at');
});
and then this query:
alter TABLE float_values add primary key (`id`, `created_at`)
PARTITION BY HASH is useless; don't bother figuring out how to make it work.
Furthermore, as a general rule, Partitioning is not useful unless you have at least a million rows. Since you are asking for a DATE to be UNIQUE, I suspect you will have not more than a few thousand rows.
If you would like to explain the purpose of the table, its eventual size, the goal for using Hash, and some SELECTs that you will use, I can probably explain how to achieve your goals without partitioning.
Scenarios:
For these queries:
... WHERE id = 111 AND created_at BETWEEN ... AND ... -- case 1
... WHERE attribute_id = 222 -- case 2
... WHERE attribute_id = 333 AND created_at BETWEEN ... AND ... -- case 3
Then your table might be non-partitioned:
CREATE TABLE `float_values` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, -- debatable
`attribute_id` bigint UNSIGNED NOT NULL,
`value` double(8,2) NOT NULL,
`created_at` date NOT NULL,
`updated_at` date NOT NULL
PRIMARY KEY(id), -- for case 1
INDEX(attribute_id, created_at) -- for cases 2, 3
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
I have a table A which has an Auto incrementing Primary key.
I have a table B with a field as foreign key referencing to those Primary key values.
I want to add a record in Table A and Table B simultaneously,(note I'm not defining these auto incrementing fields.When I execute my codes the records in table A are created but table B fails to do so. I understand that I cannot reference a foreign key as a auto incrementing null value but is there any alternative to what I'm trying to achieve???
My code for creating tables are:
Table A
Create TABLE IF NOT EXISTS Friends(
friend_id Int PRIMARY KEY AUTO_INCREMENT,
friend_email Varchar(50) NOT NULL UNIQUE,
Password Varchar(20) NOT NULL,
Profile_Name Varchar(30) NOT NULL,
Date_Started DATE NOT NULL,
Num_Of_Friends INT UNSIGNED )
Table B
Create TABLE IF NOT EXISTS myFriends(
friend_id1 Int AUTO_INCREMENT ,
friend_id2 Int NOT NULL,
FOREIGN KEY(friend_id1) REFERENCES Friends(friend_id))
The queries for adding into these tables
For adding into Table A
INSERT INTO `Friends` (`friend_id`, `friend_email`, `Password`, `Profile_Name`, `Date_Started`, `Num_Of_Friends`) VALUES (NULL, '$Email', '$password1', '$Profile_Name', CURRENT_DATE(), '0')";
For adding into Table B
INSERT INTO `myFriends` (`friend_id1`,`friend_id2`) VALUES (NULL,0)";
I have a table which looks like following
CREATE TABLE `groups` (
`id_rec` INT(11) NOT NULL DEFAULT '0',
`id_group` INT(11) NOT NULL DEFAULT '0',
UNIQUE INDEX `unikum` (`id_rec`, `id_group`),
INDEX `idxgroup` (`id_group`))
there is no primary key like id of the table on which i can use insert on duplicate key clause. Now i am trying to insert multiple rows with signle MySQL query in groups table, but i don't want insert duplicates. Now, the solution i came up with is creating and inserting in another temporary table and then use join on group table and temporary table in order to find duplicates or non-duplicates(new) records depending on the join that i should use.
The temporary table looks like following
CREATE TEMPORARY TABLE IF NOT EXISTS $tempTable
(id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
group_id INT(11) NOT NULL,
id_rec INT(11) NOT NULL)
Now at this point i am not sure which join should i use. Any help would be grealty appreciated.
You don't need a primary key for ON DUPLICATE KEY UPDATE to work. The unique index you have is perfectly fine.
You can alternatively use INSERT IGNORE:
INSERT IGNORE INTO `groups` VALUES (1, 1);
If the pair (1, 1) already exists in your table then the above statement will be simply ignored.
Demo here
I'm using an a mySQL db on localhosts. Created table with primary key and another table with foreign key pointing to that one, but when I want to see the results all I geted is "alert" that MySQL returned emty result. Here my tables
CREATE TABLE example_1(
ex1_id int NOT NULL AUTO_INCREMENT,
first_name varchar(50) NULL,
last_name varchar(50) NULL,
CONSTRAINT example_1_pk PRIMARY KEY (ex1_id)
);
CREATE TABLE example_2 (
ex2_id int NOT NULL AUTO_INCREMENT,
acces_lvl int NOT NULL,
CONSTRAINT example_2_pk PRIMARY KEY (ex2_id)
);
CREATE TABLE example_3 (
ex3_id int NOT NULL AUTO_INCREMENT,
first int NOT NULL,
second int NOT NULL,
CONSTRAINT example_3_pk PRIMARY KEY (ex3_id),
FOREIGN KEY (first) REFERENCES example_1(ex1_id),
FOREIGN KEY (second) REFERENCES example_2(ex2_id)
);
Then I add something to db, eg.
INSERT INTO `example_1`(`first_name`, `last_name`) VALUES ('foo', 'bar');
and
INSERT INTO `example_2`(`acces_lvl`) VALUES (2)
then when I try
SELECT * FROM `example_3`
I have nothing, empty results. Shouldn't be there id's from other tables? Am I doing something wrong, or I didn't do something? I'm totally noob in database.
Because you did not insert any data into example_3. Foreign key constraints don't propagate data, they just enforce the data relationship, so when you do insert data into example_3, the values you put in the columns with foreign key constraints have corresponding values in other table.
The composite foreign key indexes do not work as I thought it would.
In the following example, I want only the 10 combinations to be allowed in the child table. But the last insert statement is successful even if there is no matching combination in the parent table.
Is there any other way to achieve that kind of constraint?
drop table if exists child;
drop table if exists parent;
CREATE TABLE parent(
`ID` int(11) default NULL,
`name` varchar(100) default NULL,
`city` varchar(100) default NULL,
key (name,city),
key (ID)
) ENGINE=InnoDB;
create table child(
userID int not null,
`name` varchar(100) default NULL,
`city` varchar(100) default NULL,
key (name,city),
FOREIGN KEY (name,city) REFERENCES parent(name,city),
primary key (userID)
) ENGINE=InnoDB;
insert into parent values (1, 'Amar', 'mumbai');
insert into parent values (2, 'Amar', 'Delhi');
insert into parent values (3, 'Amar', NULL);
insert into parent values (4, 'Akbar', 'mumbai');
insert into parent values (5, 'Akbar', 'Delhi');
insert into parent values (6, 'Akbar', NULL);
insert into parent values (7, 'Anthony', 'mumbai');
insert into parent values (8, 'Anthony', 'Delhi');
insert into parent values (9, 'Anthony', NULL);
insert into parent values (10, NULL, NULL);
insert into child values (2, NULL, 'mumbai');
Don't use nulls in foreign key columns; that way leads to the dark side. You should declare such columns NOT NULL.
According to the documentation
The MATCH clause in the SQL standard controls how NULL values in a
composite (multiple- column) foreign key are handled when comparing to
a primary key. InnoDB essentially implements the semantics defined by
MATCH SIMPLE, which permit a foreign key to be all or partially NULL.
In that case, the (child table) row containing such a foreign key is
permitted to be inserted, and does not match any row in the referenced
(parent) table. It is possible to implement other semantics using
triggers.
since child.name field declared nullable it can contain null values. it does not violate foreign key concept.
the solution is to decalre fk fields as NOT NULL