If I have a mysql table with the 2 columns:
ID Date
1 2012-03-05
2 2012-02-21
3 2013-06-12
4 2011-01-15
5 2013-02-23
and I have an array of random updates such as
$arr = array('2'=>'2013-03-23','4'=>'2013-03-19','5'=>'2011-08-09');
(where the index is the ID and the value is the date)
is there a way to update the table with one statement?
the reason I am doing this, is because I need to make hundreds+ of changes and single updates would be alot of statements.
If ID is unique or a primary key, you can do
INSERT INTO `Table` (ID, `Date`)
VALUES ('2', '2013-03-23'), ('4', '2013-03-19'), ('5', '2011-08-09')
ON DUPLICATE KEY UPDATE `Date` = VALUES(`Date`)
Note that this might affect the auto increment value and it might insert new records into the table.
Related
I have a table having id set to auto increment.
I have records 1 to 10 and I have deleted records 3 and 7.
So is their any way I can add records 3 and 7 again?
Yes, you have to "force" the id.
INSERT INTO table (id, field1) VALUES (3, "value"); // id = 3
But if you let the id "null" or not set, it will be incremented :
INSERT INTO table (field1) VALUES ("value"); // id = 8
In Mysql You can override the auto-increment id simply assingning the value you need .. this is perfectly legal ..
so you can insert your row with id 3 and 7 using
insert into your_table (id, col1, col2 ..) values (3, 'value_for_col1', 'value_for_col2'...)
the autoincrement only works if no value is specified for the field, in other words you can insert the specifying the value of the field with autoincrement, example: insert in db.banks (id, description,status, created_at,updated_at) values ('3', 'Central Bank', '1', '2017-04-14 10:30:22', null);
Case 1:
ID Loc In Out
----------------------------------------------------------------
null null null null
Working query for this case:
INSERT INTO Inventory VALUES( 'PA', 'Area 1', now(), NULL );
Case 2:
ID Loc In Out
----------------------------------------------------------------
PA Area 1 2017-11-16 11:20:09 null
Working query for this case:
INSERT IGNORE INTO Inventory VALUES( 'PA', 'Area 1', now(), NULL );
Case 3:
ID Loc In Out
----------------------------------------------------------------
PA Area 1 null 2017-11-16 11:20:09
Working query for this case:
INSERT INTO Inventory VALUES( 'PA', 'Area 1', now(), NULL )
ON DUPLICATE KEY UPDATE In = now(), Out = NULL;
How can I combine the above 3 "Working query" into one?
Basically, the goal is to only execute case 3 if PK == Duplicate and In == NULL. Thanks.
INSERT IGNORE and INSERT ... ON DUPLICATE KEY UPDATE are mutually exclusive. They both handle the situation when the row to be inserted conflicts with an already existing row on an UNIQUE INDEX.
IGNORE converts the errors into warnings and this basically lets the query succeed and ignore the new values.
ON DUPLICATE KEY UPDATE updates some of the fields of the existing row with the new values.
Both clauses are used only if an UNIQUE INDEX conflict happens; they are ignored otherwise. This makes both of them work in your case #1
Basically, the goal is to only execute case 3 if PK == Duplicate and In == NULL.
A carefully crafted ON DUPLICATE KEY UPDATE clause can do the job:
INSERT INTO Inventory VALUES('PA', 'Area 1', NOW(), NULL)
ON DUPLICATE KEY UPDATE
`In` = IF(ISNULL(`In`), VALUES(`In`), `In`),
`Out` = NULL
The value of expression IF(ISNULL(`In`), VALUES(`In`), `In`) is VALUES(`In`) (the value of In in the VALUES() list to be inserted) if the current value of column In is NULL or the current value of column In if it is not NULL.
This way, the value of column In is replaced by the value provided by the INSERT query only if its current value is NULL.
Current rows in t1:
id,f1,f2,f3
1,'01','02','03'
2,'11','12','13'
4,'41','42','43'
Wherein f1 is a unique key field.
Now we perform this query:
INSERT INTO `t1` (`f1`, `f2`, `f3`) VALUES
('11', '12', '13'),
('21', '22', '23'),
('31', '32', '33'),
('41', '42', '43'),
('51', '52', '53')
ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)
How do I get the last insert IDs of all the rows inserted/updated?
For the example above, I believe the IDs would be:
2
5
6
4
7
Right?
But how do I get them from MySQL after a batch INSERT query with ON DUPLICATE KEY UPDATE clause like this?
From this answer, LAST_INSERT_ID "gives you the id of the FIRST row inserted in the last batch" and one can simply get all the rest IDs in a sequential manner if the rows are all freshly INSERT-ed.
Apparently, when we have ON DUPLICATE KEY UPDATE, it's a totally different story. So is there any way to get all the last insert IDs of a batch INSERT with ON DUPLICATE KEY UPDATE? Tried google but found nothing helpful.
Why do I need this
After inserting in t1, I need to associate the rows just inserted with one of the rows in t2. It's a many-to-many relationship so I would need to insert in t1_x_t2 with the ID of the row from t2 and all the IDs just inserted in t1.
Is there any other way to achieve this?
You can use triggers in MySql for this purpose on events AFTER INSERT and AFTER UPDATE. In trigger body you will get the old and new values that you can use to insert, update or delete in another table. MySQL doc link: https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html
This question already has answers here:
Check if a row exists, otherwise insert
(12 answers)
MySQL Conditional Insert
(13 answers)
Closed 9 years ago.
I want to run a set of queries to insert some data into an SQL table but only if the record satisfying certain criteria are met. The table has 4 fields: id (primary), fund_id, date and price
I have 3 fields in the query: fund_id, date and price.
So my query would go something like this:
INSERT INTO funds (fund_id, date, price)
VALUES (23, '2013-02-12', 22.43)
WHERE NOT EXISTS (
SELECT *
FROM funds
WHERE fund_id = 23
AND date = '2013-02-12'
);
So I only want to insert the data if a record matching the fund_id and date does not already exist. If the above is correct it strikes me as quite an inefficient way of achieving this as an additional select statement must be run each time.
Is there a better way of achieving the above?
Edit: For clarification neither fund_id nor date are unique fields; records sharing the same fund_id or date will exist but no record should have both the same fund_id and date as another.
This might be a simple solution to achieve this:
INSERT INTO funds (ID, date, price)
SELECT 23, DATE('2013-02-12'), 22.5
FROM dual
WHERE NOT EXISTS (SELECT 1
FROM funds
WHERE ID = 23
AND date = DATE('2013-02-12'));
p.s. alternatively (if ID a primary key):
INSERT INTO funds (ID, date, price)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE ID = 23; -- or whatever you need
see this Fiddle.
Although the answer I originally marked as chosen is correct and achieves what I asked there is a better way of doing this (which others acknowledged but didn't go into). A composite unique index should be created on the table consisting of fund_id and date.
ALTER TABLE funds ADD UNIQUE KEY `fund_date` (`fund_id`, `date`);
Then when inserting a record add the condition when a conflict is encountered:
INSERT INTO funds (`fund_id`, `date`, `price`)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE `price` = `price`; --this keeps the price what it was (no change to the table) or:
INSERT INTO funds (`fund_id`, `date`, `price`)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE `price` = 22.5; --this updates the price to the new value
This will provide much better performance to a sub-query and the structure of the table is superior. It comes with the caveat that you can't have NULL values in your unique key columns as they are still treated as values by MySQL.
Assuming you cannot modify DDL (to create a unique constraint) or are limited to only being able to write DML then check for a null on filtered result of your values against the whole table
FIDDLE
insert into funds (ID, date, price)
select
T.*
from
(select 23 ID, '2013-02-12' date, 22.43 price) T
left join
funds on funds.ID = T.ID and funds.date = T.date
where
funds.ID is null
Is it possible to set constraints for VARCHAR columns in MySQL?
I would like to not permit more than one row of a specific value.
______________
| MyTable |
--------------
| pk id INT |
| name VARCHAR |
If I now inserted two rows with the same name, "peter", I would like to throw an error. So, the constraint should only check if there is already a "peter" stored. But multiple rows of other values have to work.
INSERT INTO MyTable VALUES (1, "peter");
INSERT INTO MyTable VALUES (2, "peter"); // This should fail
INSERT INTO MyTable VALUES (3, "steven");
INSERT INTO MyTable VALUES (4, "steven"); // Shall succeed
Is it possible in some way in MySQL to check for specified values?
no, thats not possible using constraints. you could add an unique constraint on name, but that would prevend all duplicate entrys, not just "peter". with that said, you'll have to do this additional check on your own.
Set the column to be UNIQUE. MySQL querys trying to insert a duplicate value will fail.
INSERT:
insert into <table> (<columns>,unique(<unique column>));
UPDATE:
alter table <table> add unique(<unique column>));