Mysql on duplicate key replace all - mysql

I have a table T1:
Col1 | Col2
-------------
a | 2
b | 3
If Col1 is unique and Col2 is not then I can run the query:
INSERT INTO T1 (Col1, Col2)
VALUES (b,2)
ON DUPLICATE KEY UPDATE
Col2=VALUES(Col2);
and the table now looks like this:
Col1 | Col2
-------------
a | 2
b | 2
If Col1 and Col2 are both unique I would like to run a single query:
INSERT INTO T1 (Col1, Col2)
VALUES (b,2)
ON DUPLICATE KEY -- REPLACE ALL INSTANCES ?
Col1 = VALUES(Col1), Col2=VALUES(Col2);
which results in this:
Col1 | Col2
-------------
b | 2
So the key "b" is now associated with the key "2", replacing both "a"'s association and "b"'s previous association.
Is there a mysql query or extension that can accomplish this? (Clearly this can be done with multiple queries, I'm looking for an analogue of the ON DUPLICATE extension for this use case.)

After looking around for a while, I'm pretty certain that this cannot be done. There is no mention of anything other than UPDATE or IGNORE for ON DUPLICATE KEY in the manual. The requested action is tantamount to doing a DELETE inside an UPDATE statement. (Which you cannot do).
The following code performs the task, I don't like having to wrap it in a transaction but it is the only way to do it at the moment.
START TRANSACTION;
DELETE FROM t1 WHERE Col2 = 2 AND Col1 <> "b"; -- Without checking Col1 the row will be replaced instead of updated if the entry ("b",2) already exists
INSERT INTO t1 (Col1, Col2)
VALUES("b",2)
ON DUPLICATE KEY UPDATE
Col2 = VALUES(Col2);
COMMIT;

Related

MySQL - INSERT without duplicating rows (without informing the PK)

I have to insert a few values into a mysql table, but only if there are no other (almost) equal rows, for example:
TABLE T
KEY | COL1 | COL2
1 | abc | 123
2 | def | 456
The KEY column uses auto increment, and I don't inform it on the statement, like this:
INSERT INTO T (COL1, COL2) VALUES (abc, 123)
The statement above have the same values as the first row. How can I inform mysql that I don't want to insert if the row is a duplicate like that?
I googled for some solutions and found INSERT IGNORE, ..ON DUPLICATE KEY UPDATE and REPLACE in which I would have to inform the PK, but I don't know it (without using a extra query).
you can do like...
> INSERT INTO memos(id,text)
> SELECT 5, 'text to insert'
> WHERE NOT EXISTS(SELECT 1 FROM memos WHERE id = 5 AND text = 'text to insert');
ON DUPLICATE KEY and INSERT IGNORE will work with any unique index, not just the primary key. So you can add a unique index for these columns:
ALTER TABLE T
ADD UNIQUE INDEX (col1, col2);
Making it a multi-column index means that the combination has to be unique, even though each column can be duplicated individually.
if not exists(select * from t where col1 = "abc" and col2 ="123")then
insert into t (col1,col2) values("abc",123 );
end if;

MySQL single row table for configuration settings

I have a table with configuration settings like so:
+-----------------------------+
| Column1 | Column2 | Column3 |
+-----------------------------+
| value1 | value2 | value3 |
+-----------------------------+
As shown, there is one and only one row, so it does not have a primary key. The question is, how do SELECT or UPDATE the row? Particularly the UPDATE since there is no primary key
Simply leave out the WHERE condition:
UPDATE `table` SET `Column1` = 'new value';
or for select:
SELECT * FROM `table`;
-- or
SELECT * FROM `table` LIMIT 1;
To make sure there is always a row, insert an empty row after table creation:
INSERT INTO `table` VALUES ();
Combination of all of three, it is not a good practice though, you must have a primary key to ease up things and keep it auto-incremented.
In your case, if you want to update column 1.
update table1 set column1='newValue'
where column1='value1' and column2='value2' and column3='value3'

Copy content of one table to another, leaving the primary element

I have two tables with same elements, the only differnce is there ids' which are primary key and auto increment.
Table1 | Table2
id1(PK)| id2(PK)
col1 | col1
col2 | col2
col3 | col3
I know some quick ways to do that like,
INSERT INTO table2 SELECT * FROM table1 where id1 = 2
while using such method the content of table2 has id2 = 2 as it copies all the fields directly to table2 from table1, to restric that,
I can also use a method
INSERT INTO table2(col1,col2,col3) SELECT col1,col2,col3 FROM table1 WHERE id1 = 2
such way is good for short tables, but I have lot of columns in my table.
I need a quick way to copy all the columns from table1 to table2 leaving the primary columns which is id2, as it is autoincremented.
Its like I want to copy a specified row from table1 to table2 with different id2(which will be generated as its autoincremented).
Are there any possibilities.
If you do not want to mention column names but want to copy all, then try copy all data into a temp table, then drop pk_id field, and then copy rest of the fields into desired table, lastly drop the temp table.
Refer to one of my answers to a similar queries:
Mysql: Copy row but with new id
We can use temporary table to buffer first from main table and use it to copy to main table again. We can drop the pk field from the temp table and copy all other to the second table.
With reference to the answer by Tim Ruehsen in a referred posting:
CREATE TEMPORARY TABLE tmp_table SELECT * from first_table WHERE ...;
ALTER TABLE tmp_table drop pk_id; # drop autoincrement field
# UPDATE tmp_table SET ...; # just needed to change other unique keys
INSERT INTO second_table SELECT 0, tmp_table.* FROM tmp_table;
DROP TABLE tmp_table;
Copy all rows from table1 except that have same id in table2
INSERT INTO table2(col1, col2, col3)
SELECT t1.col1, t1.col2, t1.col3
FROM table1 t1
WHERE t1.id1 not in (SELECT id2 FROM table2);

MySQL Single Table Scan Update

Is there a way to accomplish a single table scan in MySQL with an UPDATE? The following is a standard example:
IF EXISTS (SELECT * FROM Table1 WHERE Column1='SomeValue')
UPDATE Table1 SET (...) WHERE Column1='SomeValue'
ELSE
INSERT INTO Table1 VALUES (...)
This is the ideal situation I'd like to happen in MySQL (But this is MsSQL):
UPDATE user SET (name = 'jesse') WHERE userid ='10001'
IF ##ROWCOUNT=0
INSERT INTO user (name) VALUES('jeeeeee')
It's sort of reversed in MySQL. You perform the insert, and if the key already exists, then update the row:
INSERT INTO Table1 (col1,col2,col3) VALUES (val1,val2,val3)
ON DUPLICATE KEY UPDATE col1 = val1, col2 = val2, col3 = val3;
This is predicated on you having a unique key for the table (which you do, right?)

MySQL - Copying table data to non-identical table

Let's say I have two tables of similar structure, but one is empty and the other has a few rows of information:
table1
col1 | col2 | col3
red | cow | 1
blue | dog | 2
gray | pig | 3
table2
col1 | col2 | col3 | col4
table3
col1 | col2
Attempting:
insert into `table2` select * from `table1`
will not work because of the unmatched column count, and the same is true substituting table3 for table2.
Altering the * portion of the SELECT statement is not an option for dynamic purposes. So a workaround would have to be a modified SELECT combining the information.
Is there a JOIN statement or something that would merge the structures of the tables and the data so it would look like this:
select * from `table1`,`table2` (JOIN or some other statement)
col1 | col2 | col3 | col4
red | cow | 1 | NULL
blue | dog | 2 | NULL
gray | pig | 3 | NULL
select * from `table1`,`table3` (JOIN or some other statement)
col1 | col2
red | cow
blue | dog
gray | pig
Basically just merging any columns with identical names and nullifying outside matches. Again, it can't refer to specific column names to keep things dynamic. It seems doable, but I'm finding it impossible to find the answer.
Thanks a ton to anybody that can help.
If the target table of the INSERT is a subset of the source table like in your example, then there is a simple solution:
insert into table2(col1, col2, col3)
select *
from table1;
Or, if the first columns of both tables are in the same order like in your example, then you your posted query should actually work:
insert into table2 select * from table1;
I quote the manual for version 5.6 on that:
If you are not running in strict SQL mode, any column not explicitly
given a value is set to its default (explicit or implicit) value. For
example, if you specify a column list that does not name all the
columns in the table, unnamed columns are set to their default values.
Default value assignment is described in Section 10.1.4, “Data Type
Default Values”. See also Section 1.8.6.2, “Constraints on Invalid
Data”.
However, it is almost always a bad idea to depend on "SELECT *" in an INSERT operation. So, in spite of your request, it really should be:
insert into table2(col1, col2, col3)
select col1, col2, col3
from table1;
For anything more you'll have to use DESCRIBE tablex and build your queries dynamically.
You could allow null values for the columns that will end up being excluded.
insert into `table2` (col1, col2, col3) select col1, col2, col3 from `table1`
may also be of use to you.