MySQL - Copying table data to non-identical table - mysql

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.

Related

Insert Multiple Rows with Where / If statement?

I want to Insert multiple value if <input id="data3" exist. but when there's didn't exist. I want to Insert single row value.
example :
Insert into table (col1,col2,col3)
values ('a','b,'c1'), ('a','b','c2');
Inside database showing
col1 | col2 | col3
a b c1
a b c2
Then if col3 on second row (c2) does not exist. the database still inserting data like this :
col1 | col2 |col3
a b c1
a b
so how to insert only single row value like this :
col1 | col2 |col3
a b c1

Mysql on duplicate key replace all

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;

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'

Return default value for non-existing rows

To the very basic query
SELECT id, column1, column2
FROM table1
WHERE id IN ("id1", "id2", "id3")
in which the the arguments in the where statement are passed as a variable, I need to return values also for rows where the id doesn't exist. In general, this is a very similar problem as outlined here: SQL: How to return an non-existing row? However, multiple parameters are in the WHERE statement
The result right now when id2 doesn't exist:
-------------------------------
| id | column1 | column2 |
-------------------------------
| id1 | some text | some text |
| id3 | some text | some text |
-------------------------------
Desired outcome when id2 doesn't exist
-----------------------------------
| id | column1 | column2 |
-----------------------------------
| id1 | some text | some text |
| id2 | placeholder | placeholder |
| id3 | some text | some text |
-----------------------------------
My first thought was to create a temporary table and join it against the query. Unfortunately, I don't have the rights to create any kind of temporary table so that I am limited to a SELECT statement.
Is there way to do that in with a SQL SELECT query?
Edit:
Indeed, the above mentioned is a hypothetical situation. In the WHERE clause can be hundreds of ids where the amount of missing in unknown.
You can do a derived table to create something like a temp table, but it can only be used for this one query:
SELECT t.id, COALESCE(t.column1, _dflt.column1) AS column1
FROM (
SELECT 'id1' AS id, 'placeholder text 1' as column1
UNION ALL
SELECT 'id2', 'placeholder text 3'
UNION ALL
SELECT 'id3', 'placeholder text 3'
) AS _dflt
LEFT OUTER JOIN table1 t USING (id);
Re comments:
I just tested the method above on MySQL 5.6.15 to see how many distinct SELECTs I can get with a series of UNION ALLs, one row per SELECT.
I got the derived table to return 5332 rows, but I think I could go higher if I had more RAM.
If I try one more UNION ALL, I get: ERROR 1064 (42000): memory exhausted near '' at line 10665. I only have 2.0GB of RAM configured on this VM.
It doesn't matter how many ids are unknown for this solution to work. Just put them all in the derived table. By using LEFT OUTER JOIN, it automatically finds those that exist in your table1, and for the ones that are missing, the entry from the derived table will be matched up with NULLs.
The COALESCE() function returns its first non-null argument, so it'll use columns from the matched rows if those are present. Where none is found, it'll default to the columns in the derived table.
Create a stored procedure that would take as input id1, id2 and so on...
DELIMITER //
CREATE PROCEDURE P1(IN p_in varchar(5))
BEGIN
DECLARE count integer;
SELECT count(id) INTO count FROM TABLE1
WHERE id = p_in;
IF count = 1 THEN
SELECT * from table1 where id = p_in;
ELSE
select p_id, 'some text', 'some text';
END IF;
END//
DELIMITER ;
The call the procedure to get desired output..
CALL P1('id1');
CALL P2('id2');
.. and so on from your program..
Project a derived table containing all the candidate ids you want, then left join to it:
select ids.id, coalesce(table1.column1,'placeholder')
From
(Select 'id1' as id
Union
Select 'id2'
Union
Select 'id3') ids
left join table1
on ids.id1 = table1.id1
and table1.id in (...);
If you are producing the list of candidate ids from an external source (e.g. an application), you could insert the ids into a temporary table and then join to it (MySql doesn't support table variables yet).

MySQL: Insert one column data to another

I'm not soo good at MySQL. But want to improve it a bit, to be able to manipulate tables without serverside languages.
I have one table and two columns. I need to select data from one column and insert in the same table as rows instead.
As I understand I need to select this column data, save it in a temporary table or variable, then loop through results and insert them. But I do not know how to do it.
Could someone help with a simple example.
Thanks ;)
My table:
id | col1 | col2
-----------------
1 | txt | txt4
2 | txt2 | txt5
3 | txt3 | txt6
I need to merge col1 and col2.
Final result:
id | col1
-----------
1 | txt
2 | txt2
3 | txt3
4 | txt4
5 | txt5
6 | txt6
This should work
insert into tablename
(col1_name)
select (col2_name) from tablename;
That will select all of your data from column 2 and insert it into column 1 as new rows. Then, you can drop the second column by doing:
alter table tablename drop col2_name;
Simply replace tablename with the name of your table, and the column names with the name of your column. Also, make sure that both column datatypes are compatible with each other.
Good luck!
If I am reading correct, you want to merge col1 and col2?? then, try this
alter table table1 add column col3 varchar(255);
update table1 set col3 = concat(col1, " ", col2);
alter table table1 drop column col1;
alter table table1 drop column col2;
You could use INSERT ... SELECT from the same table.
I tried this and it worked for me
update table1 set column2=column1;