Constant column value in MySQL table - mysql

I have a table in MySQL. I'd like to set a column value for a table to be a constant integer. How can I do this?

Unfortunately MySQL does not support SQL check constraints. You can
define them in your DDL query for compatibility reasons but they are
just ignored. You can create BEFORE INSERT and BEFORE UPDATE triggers
which either cause an error or set the field to its default value when
the requirements of the data are not met.
So here you can find a way around through MYSQL TRIGGER.
Sample Table:
DROP TABLE IF EXISTS `constantvaluetable`;
CREATE TABLE `constantvaluetable` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`constValue` int(11) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB;
Trigger:
DROP TRIGGER IF EXISTS trigger_const_check;
delimiter //
CREATE TRIGGER trigger_const_check BEFORE INSERT ON constantvaluetable
FOR EACH ROW
BEGIN
IF NEW.constValue <> 71 THEN
SIGNAL SQLSTATE '45000' SET message_text ='Only allowed value is 71';
END IF;
END //
delimiter ;
Test:
INSERT INTO constantvaluetable(constValue) VALUES(71);
INSERT INTO constantvaluetable(constValue) VALUES(66);
Result:
The first insert statement will succeed.
The second insert statement will fail. And the following error message will be shown:
[Err] 1644 - Only allowed value is 71
Note: Assuming your CONSTANT value is 71.

Do you really want to do this?
Would the following not suffice
Select Field1, field2, field3 , 5 as `ConstantField` from myTable

Although 71's trigger solution is the general purpose approach, since it can be used for more complicated conditions, in your case where you just want to check for a constant value, you can stay closer to database logic and add a foreign key to a table that just contains that one allowed value in it, e.g.
create table tbl_checkconst (constraintvalue int primary key);
insert into tbl_checkconst values (71);
alter table yourtable
add constraint fk_yourtable_constcheck
foreign key (column1)
references tbl_chechconst (constraintvalue);
It will actually add some overhead (since it will need to add an index), but would express your constraint in database logic, and your constant usually has a meaning that is in this way designed into the database model (although it is just 1 value now), and you (and any user with the correct permissions) can easily add more allowed values by adding it to the tbl_checkconst-table without modifying your trigger code.
And another reason I added it is that I guess you are really actually looking for a foreign key: In one of your comments you said you are trying to create a "double foreign key to a reference table". If I understand that correctly, you might want to use a composite foreign key, since you are able to combine columns for a foreign key:
alter table yourtable
add constraint fk_yourtable_col1col2
foreign key (column1, column2)
references your_reference_table (refcolumn1, refcolumn2);

You would just set up a CHECK constraint in your table when you set it up. Something like this is all you need in most DBMSs
CREATE someTable
(
someValue int(4) CHECK (someValue = 4)
)
However, with MySQL, CHECK constraints don't behave the same as they do in other DBMSs. The situation is a little more tricky. The answer seems to be here: https://stackoverflow.com/a/14248038/5386243

Related

Foreign key created an extra column mySQL

On of my foreign keys in a table within MySQL added an extra not null column labeled Customers_CustomerID, so I am not able to enter or update the table as required for my assignment. How can I fix this?
Several options. We could 1) drop the column 2) change the column to allow NULL values, 3) change the column definition to specify a non-NULL DEFAULT value for the column, 4) add a BEFORE INSERT trigger to set a non-NULL value to the column, 5) supply a valid value on an INSERT. Lot's of possibilities.
We could provide some additional assistance with the syntax for each of those options, but without the column definition, we can't give the exact syntax that would be required for adding DEFAULT value attribute.
It might not be possible to drop the column, if its used in an index or referenced in a foreign key constraint. The syntax to remove the column would be something like this:
ALTER TABLE mytable DROP customers_customerid ;
The syntax to change the column definition, would be something like this, to specify a DEFAULT value:
ALTER TABLE mytable CHANGE
customers_customerid customers_customerid BIGINT NOT NULL DEFAULT '1' COMMENT 'foo' ;
^^^^^^^^^^^
But we need to know the entire column definition, and repeat that, adding/changing just the bits that need to be changed. The statement above includes guesses about the datatype, et al.
We can get the current definition of the column from the definition of the table with a statement like this:
SHOW CREATE TABLE mytable;
Note: the statement to add a foreign key constraint doesn't add a column to the table. the statement(s) that you executed must have included syntax to add a column.
You haven't really defined what you're trying to fix. What do you mean by saying you are "not able to enter or update the table"? What tool are you trying to update it with?
Here's an example from the MySQL documentation on how you should create two tables and link them with a foreign key:
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE
) ENGINE=INNODB;

How to drop auto_increment from a mysql table

this should be a very easy issue but I couldn't find a solution that works.
I migrate the date from Oracle to MYSQL and during the process, all primary keys were set to auto_increment.
However, there are a lot of identified relationships (parent PK is the same of children).
So the correct way to do the transaction is to insert into the parent tables, get result.insertId from this interaction and then insert the same value in the child table. I know that I could simply ignore the auto_increment sending the id in the insert command but I didn't like to just let this go.
As the solutions I read about say that I need to change the column to the exactly the same specification but auto_increment, I run the following SQL:
alter table added_object modify column id_interaction_object int(11) not null;
.. And I get the following message:
ERROR 1833 (HY000): Cannot change column 'id_interaction_object': used
in a foreign key constraint 'FK__METRIC__ADDED_OBJECT' of table
'metric'
Any tips?
Thanks
You need to disable foreign key checks:
SET FOREIGN_KEY_CHECKS=0;
alter table added_object modify column id_interaction_object int(11) not null;
SET FOREIGN_KEY_CHECKS=1;

MySQL UNIQUE CONSTRAINT failing in CREATE TABLE with subsequent INSERT

Using phpMyAdmin and MySQL v5.5.49 consider:
CREATE TABLE op_sys (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
version VARCHAR(255) NOT NULL,
-- UNIQUE KEY name_version (name, version)
-- CONSTRAINT name_version UNIQUE (name, version)
-- UNIQUE(name, version)
-- CONSTRAINT UNIQUE(name, version)
)ENGINE=InnoDB;
I've tried all four of the commented out attempts to simply stop INSERT INTO sys_op duplicate values for "name" and "version". All four are processed without error.
The insert into:
INSERT INTO op_sys(name, version)
VALUES ('ANDROID','ANDROID');
executes "successfully". ANDROID ANDROID is now a row. Where have I gone wrong or what step am I not aware of? I've checked the MySQL manual and several different posts here that seem to say I'm doing it correctly... Thanks.
You seem to misunderstand what UNIQUE KEY means:
A UNIQUE index creates a constraint such that all values in the index
must be distinct. An error occurs if you try to add a new row with a
key value that matches an existing row. For all engines, a UNIQUE
index permits multiple NULL values for columns that can contain NULL.
If your table has UNIQUE(name, version), then you can do:
INSERT INTO op_sys(name, version) VALUES ('ANDROID','ANDROID');
But, the next time you do it, it will fail because the table already holds a record with the same pair(name, version) as in the record you want to insert.
To prevent inserting a record that has the same value for name and version`, you could use a trigger:
CREATE TRIGGER different_values BEFORE INSERT ON op_sys
FOR EACH ROW BEGIN
DECLARE identical_values CONDITION FOR SQLSTATE '45000';
IF NEW.name = NEW.version THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Identical values for name and version';
END IF;
END;
It will run before each INSERT on table sys_op, and if the name and version fields hold identical values, it will generate an error and the insertion will fail.
The error returned looks like this:
ERROR 1644 (45000): Identical values for name and version
Documentation:
- CREATE INDEX
- CREATE TRIGGER
- SIGNAL
A multi-column unique index prevents you to have the same 2 values for these 2 fields between records. This means, you cannot have 2 records, where name and version are 'ANDROID','ANDROID'. However, a unique index does not prevent these fields from having the same value within a single row.
You either have to implement this control in application level, where you check if the 2 field values are the same and if yes, then do not do the insertion.
In the database layer you could ad a before insert trigger and check the 2 fields' value there and raise a custom error message using the signal command.
But I have such a de ja vu feeling. As if you had asked this question before and you could not do an if() in php...

On Duplicate Key Update same as insert

I've searched around but didn't find if it's possible.
I've this MySQL query:
INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8)
Field id has a "unique index", so there can't be two of them. Now if the same id is already present in the database, I'd like to update it. But do I really have to specify all these field again, like:
INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8)
ON DUPLICATE KEY UPDATE a=2,b=3,c=4,d=5,e=6,f=7,g=8
Or:
INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8)
ON DUPLICATE KEY UPDATE a=VALUES(a),b=VALUES(b),c=VALUES(c),d=VALUES(d),e=VALUES(e),f=VALUES(f),g=VALUES(g)
I've specified everything already in the insert...
A extra note, I'd like to use the work around to get the ID to!
id=LAST_INSERT_ID(id)
I hope somebody can tell me what the most efficient way is.
The UPDATE statement is given so that older fields can be updated to new value. If your older values are the same as your new ones, why would you need to update it in any case?
For eg. if your columns a to g are already set as 2 to 8; there would be no need to re-update it.
Alternatively, you can use:
INSERT INTO table (id,a,b,c,d,e,f,g)
VALUES (1,2,3,4,5,6,7,8)
ON DUPLICATE KEY
UPDATE a=a, b=b, c=c, d=d, e=e, f=f, g=g;
To get the id from LAST_INSERT_ID; you need to specify the backend app you're using for the same.
For LuaSQL, a conn:getlastautoid() fetches the value.
There is a MySQL specific extension to SQL that may be what you want - REPLACE INTO
However it does not work quite the same as 'ON DUPLICATE UPDATE'
It deletes the old row that clashes with the new row and then inserts the new row. So long as you don't have a primary key on the table that would be fine, but if you do, then if any other table references that primary key
You can't reference the values in the old rows so you can't do an equivalent of
INSERT INTO mytable (id, a, b, c) values ( 1, 2, 3, 4)
ON DUPLICATE KEY UPDATE
id=1, a=2, b=3, c=c + 1;
I'd like to use the work around to get the ID to!
That should work — last_insert_id() should have the correct value so long as your primary key is auto-incrementing.
However as I said, if you actually use that primary key in other tables, REPLACE INTO probably won't be acceptable to you, as it deletes the old row that clashed via the unique key.
Someone else suggested before you can reduce some typing by doing:
INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);
There is no other way, I have to specify everything twice. First for the insert, second in the update case.
Here is a solution to your problem:
I've tried to solve problem like yours & I want to suggest to test from simple aspect.
Follow these steps: Learn from simple solution.
Step 1: Create a table schema using this SQL Query:
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) NOT NULL,
`password` varchar(32) NOT NULL,
`status` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `no_duplicate` (`username`,`password`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
Step 2: Create an index of two columns to prevent duplicate data using following SQL Query:
ALTER TABLE `user` ADD INDEX no_duplicate (`username`, `password`);
or, Create an index of two column from GUI as follows:
Step 3: Update if exist, insert if not using following queries:
INSERT INTO `user`(`username`, `password`) VALUES ('ersks','Nepal') ON DUPLICATE KEY UPDATE `username`='master',`password`='Nepal';
INSERT INTO `user`(`username`, `password`) VALUES ('master','Nepal') ON DUPLICATE KEY UPDATE `username`='ersks',`password`='Nepal';
Just in case you are able to utilize a scripting language to prepare your SQL queries, you could reuse field=value pairs by using SET instead of (a,b,c) VALUES(a,b,c).
An example with PHP:
$pairs = "a=$a,b=$b,c=$c";
$query = "INSERT INTO $table SET $pairs ON DUPLICATE KEY UPDATE $pairs";
Example table:
CREATE TABLE IF NOT EXISTS `tester` (
`a` int(11) NOT NULL,
`b` varchar(50) NOT NULL,
`c` text NOT NULL,
UNIQUE KEY `a` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
I know it's late, but i hope someone will be helped of this answer
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
You can read the tutorial below here :
https://mariadb.com/kb/en/library/insert-on-duplicate-key-update/
http://www.mysqltutorial.org/mysql-insert-or-update-on-duplicate-key-update/
You may want to consider using REPLACE INTO syntax, but be warned, upon duplicate PRIMARY / UNIQUE key, it DELETES the row and INSERTS a new one.
You won't need to re-specify all the fields. However, you should consider the possible performance reduction (depends on your table design).
Caveats:
If you have AUTO_INCREMENT primary key, it will be given a new one
Indexes will probably need to be updated
With MySQL v8.0.19 and above you can do this:
mysql doc
INSERT INTO mytable(fielda, fieldb, fieldc)
VALUES("2022-01-01", 97, "hello")
AS NEW(newfielda, newfieldb, newfieldc)
ON DUPLICATE KEY UPDATE
fielda=newfielda,
fieldb=newfieldb,
fieldc=newfieldc;
SIDENOTE: Also if you want a conditional in the on duplicate key update part there is a twist in MySQL. If you update fielda as the first argument and include it inside the IF clause for fieldb it will already be updated to the new value! Move it to the end or alike. Let's say fielda is a date like in the example and you want to update only if the date is newer than the previous:
INSERT INTO mytable(fielda, fieldb)
VALUES("2022-01-01", 97)
AS NEW(newfielda, newfieldb, newfieldc)
ON DUPLICATE KEY UPDATE
fielda=IF(fielda<STR_TO_DATE(newfielda,'%Y-%m-%d %H:%i:%s'),newfielda,fielda),
fieldb=IF(fielda<STR_TO_DATE(newfielda,'%Y-%m-%d %H:%i:%s'),newfieldb,fieldb);
in this case fieldb would never be updated because of the <! you need to move the update of fielda below it or check with <= or =...!
INSERT INTO mytable(fielda, fieldb)
VALUES("2022-01-01", 97)
AS NEW(newfielda, newfieldb, newfieldc)
ON DUPLICATE KEY UPDATE
fielda=IF(fielda<STR_TO_DATE(newfielda,'%Y-%m-%d %H:%i:%s'),newfielda,fielda),
fieldb=IF(fielda=STR_TO_DATE(newfielda,'%Y-%m-%d %H:%i:%s'),newfieldb,fieldb);
This works as expected with using = since fielda is already updated to its new value before reaching the if clause of fieldb... Personally i like <= the most in such a case if you ever rearrange the statement...
you can use insert ignore for such case, it will ignore if it gets duplicate records
INSERT IGNORE
... ; -- without ON DUPLICATE KEY

MySQL duplicate entry error even though there is no duplicate entry

I am using MySQL 5.1.56, MyISAM. My table looks like this:
CREATE TABLE IF NOT EXISTS `my_table` (
`number` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`money` int(11) NOT NULL,
PRIMARY KEY (`number`,`name`)
) ENGINE=MyISAM;
It contains these two rows:
INSERT INTO `my_table` (`number`, `name`, `money`) VALUES
(1, 'S. Name', 150), (2, 'Another Name', 284);
Now I am trying to insert another row:
INSERT INTO `my_table` (`number`, `name`, `money`) VALUES
(2, 'S. Name', 240);
And MySQL just won't insert it while telling me this:
#1062 - Duplicate entry '2-S. Name' for key 'PRIMARY'
I really don't understand it. The primary key is on the first two columns (both of them), so the row I am trying to insert HAS a unique primary key, doesn't it?
I tried to repair the table, I tried to optimize the table, all to no avail. Also please note that I cannot change from MyISAM to InnoDB.
Am I missing something or is this a bug of MySQL or MyISAM? Thanks.
To summarize and point out where I think is the problem (even though there shouldn't be):
Table has primary key on two columns. I am trying to insert a row with a new combination of values in these two columns, but value in column one is already in some row and value in column two is already in another row. But they are not anywhere combined, so I believe this is supposed to work and I am very confused to see that it doesn't.
Your code and schema are OK. You probably trying on previous version of table.
http://sqlfiddle.com/#!2/9dc64/1/0
Your table even has no UNIQUE, so that error is impossible on that table.
Backup data from that table, drop it and re-create.
Maybe you tried to run that CREATE TABLE IF NOT EXIST. It was not created, you have old version, but there was no error because of IF NOT EXIST.
You may run SQL like this to see current table structure:
DESCRIBE my_table;
Edit - added later:
Try to run this:
DROP TABLE `my_table`; --make backup - it deletes table
CREATE TABLE `my_table` (
`number` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`money` int(11) NOT NULL,
PRIMARY KEY (`number`,`name`),
UNIQUE (`number`, `name`) --added unique on 2 rows
) ENGINE=MyISAM;
I know this wasn't the problem in this case, but I had a similar issue of "Duplicate Entry" when creating a composite primary key:
ALTER TABLE table ADD PRIMARY KEY(fieldA,fieldB);
The error was something like:
#1062 Duplicate entry 'valueA-valueB' for key 'PRIMARY'
So I searched:
select * from table where fieldA='valueA' and fieldB='valueB'
And the output showed just 1 row, no duplicate!
After some time I found out that if you have NULL values in these field you receive these errors. In the end the error message was kind of misleading me.
I had a similar issue, but in my case it turned out that I used case insensitive collation - utf8_general_ci.
Thus, when I tried to insert two strings which were different in a case-sensitive comparison, but the same in the case-insensitive one, MySQL fired the error and I couldn't understand what a problem, because I used a case-sensitive search.
The solution is to change the collation of a table, e.g. I used utf8_bin which is case-sensitive (or utf8_general_cs should be appropriate one too).
In case this helps anyone besides the OP, I had a similar problem using InnoDB.
For me, what was really going on was a foreign key constraint failure. I was referencing a foreign key that did not exist.
In other words, the error was completely off. The primary key was fine, and inserting the foreign key first fixed the problem. No idea why MySQL got this wrong suddenly.
Less common cases, but keep in mind that according to DOC https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-limitations.html
When running an online ALTER TABLE operation, the thread that runs the ALTER TABLE operation will apply an “online log” of DML operations that were run concurrently on the same table from other connection threads. When the DML operations are applied, it is possible to encounter a duplicate key entry error (ERROR 1062 (23000): Duplicate entry), even if the duplicate entry is only temporary and would be reverted by a later entry in the “online log”. This is similar to the idea of a foreign key constraint check in InnoDB in which constraints must hold during a transaction.
In my case the error was caused by the outdated schema, one column was originally varchar(50) but the dump I was trying to import was created from a modified version of the schema that has varchar(70) for that column (and some of the entries of that field where using more than 50 chars).
During the import some keys were truncated and the truncated version was not unique anymore. Took a while to figure that out, I was like "but this supposedly duplicated key doesn't even exist!".
Try with auto increment:
CREATE TABLE IF NOT EXISTS `my_table` (
`number` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`money` int(11) NOT NULL,
PRIMARY KEY (`number`,`name`)
) ENGINE=MyISAM;
Your code is work well on this demo:
http://sqlfiddle.com/#!8/87e10/1/0
I think you are doing second query (insert...) twice. Try
select * from my_table
before insert new row and you will get that your data already exist or not.
i have just tried, and if you have data and table recreation wouldnt work, just alter table to InnoDB and try again, it would fix the problem
In case anyone else finds this thread with my problem -- I was using an "integer" column type in MySQL. The row I was attempting to insert had a primary key with a value larger than allowed by integer. Switching to "bigint" fixed the problem.
As per your code your "number" and "Name" are primarykey and you are inserting S.NAME in both row so it will make a conflict. we are using primarykey for accessing complete data. here you cant access the data using the primarykey 'name'.
im a beginner and i think it might be the error.
In my case the error was very misleading. The problem was that PHPMyAdmin uses "ALTER TABLE" when you click on the "make unique" button instead of "ALTER IGNORE TABLE", so I had to do it manually, like in:
ALTER TABLE mytbl ADD UNIQUE (columnName);
This problem is often created when adding a column or using an existing column as a primary key. It is not created due to a primary key existing that was never actually created or due to damage to the table.
What the error actually denotes is that a pending key value is blank.
The solution is to populate the column with unique values and then try to create the primary key again. There can be no blank, null or duplicate values, or this misleading error will appear.
For me a noop on table has been enough (was already InnoDB):
ALTER TABLE $tbl ENGINE=InnoDB;
tl;dr: my view showed my table was empty but the view excluded existing rows.
I had the same problem but mine was because I was inserting the same test rows I had used before. When I checked to see if my table was empty, I used a view that excluded different tenants so the search came back empty. When I checked the actual table, the previous records were still there.
Once I had deleted the existing records, the insert worked. Only half a day of frustration lost to this one...
Had this error, when adding a composite primary key that is ADD PRIMARY KEY (column1, column2, ...) The value of all the columns in that row must not be duplicated.
For Example:
You do ADD PRIMARY KEY (name, country, number)
name
country
number
collin
Uk
5
collin
Uk
5
This will throw an error #1062 - Duplicate entry 'collin-UK-5' for key 'PRIMARY' because the columns combined have duplicate
So if you see this format of error just check and ensure that the columns you want to add a composite primary key to combined don't have duplicates.
Another reason you may be getting this error is because the same restriction exists in another related table, and they Keyname on the related table has the exact same name. I've had this happen once and it was quite difficult to identify.
i.e. if you have a trigger that inserts data to a different table (the "related" table) with the same restriction and same Keyname, MySQL will not include the name of the table throwing the error, only the Keyname.
As looking on your error #1062 - Duplicate entry '2-S. Name' for key 'PRIMARY' it is saying that you use primary key in your number field that's why it is showing duplicate Error on Number Field.
So Remove this primary Key then it inset duplicate also.