I am trying to Update a column (say c1) from a table (say t1) sitting in database (say d1) with column say (c2) from table (say t2) sitting in database (say d2). The columns used to join two tables are column c3 in table t1 in database d1 and column c4 in table t2 in database d2.
My script for this looks like
UPDATE d1.t1
SET c1 = d2.t2.c2
WHERE d1.t1.c3 = d2.t2.c4;
On executing this, I get an Error 1054 stating that "Unknown column d2.t2.c4 in WHERE clause".
My code is as below:
UPDATE igr_raw_db.`master_database-v3_truncated`
SET `Transaction Type` = igr_keys.`transaction_type`.`Transaction_Type_Final`
WHERE
igr_raw_db.`master_database-v3_truncated`.`document_type` = igr_keys.`transaction_type`.`Reg_Transaction_Type_Raw`;
Here, I have two databases - igr_raw_db and igr_keys.
igr_raw_db has column Transaction Type which I am trying to set to value as per column Transaction_Type_Final in table transaction_type in database igr_keys
and I want to match column document_type with column Reg_Transaction_Type_Raw of the two databases.
I have checked my columns in tables for which I am getting an error and the columns exists with exact same names.
Below is my igr_keys.transaction_type table
Sr No int YES
Reg_Transaction_Type_Raw varchar(255) YES
Transaction_Type_Processed varchar(255) YES
Transaction_Type_Final varchar(255) YES
Below is a snipped of my igr_raw_db.master_database-v3_truncated table
consideration varchar(255) YES
document_type varchar(255) YES
Not able to understand why I am getting Error 1054.
Help will be much appreciated.
Thanks.
You must use multiple-table UPDATE Syntax:
UPDATE d1.t1
JOIN d2.t2 ON d1.t1.c3 = d2.t2.c4
SET d1.t1.c1 = d2.t2.c1;
If more than one row in source table matches a row in destination table then indefinite row from all matched ones will be used for updating. You must avoid this ambiguity (except the case when all these matched rows stores the same value, of course).
Of course you may use correlated query:
UPDATE d1.t1
SET c1 = ( SELECT c1
FROM d2.t2
WHERE d1.t1.c3 = d2.t2.c4 );
but this variant will produce an error if more than one row matches (can be fixed with LIMIT 1) or if correlated query uses another copy of the table to be updated (can be fixed by nested subquery). Also in most cases it should be slower.
Related
I have two tables that have a huge list of columns. They are both the same structure, but different data. However, both tables have an index/auto-increment column that might be similar. Is there an easy way to run a command like this:
insert into table1 (select * from table2);
and have the insert ignore the auto-increment column from table 2? To avoid an error if there's a similar-value in the index column of tables 1 and 2? I want to copy everything over, and have new auto-increments for the table 2 data in table 1.
Alternatively, I don't care what the values are of the auto-increment index. If there was a way to merge the two tables and then re-generate unique AI columns that would also work.
I am aware I could get around this by specifying each field individually in both tables and leaving out the auto-increment column. I'm just wondering if there is an easier way to do this? If there isn't, is there an easy way of generating the field list/statement?
Here is the most efficient way I know of right now. Assuming the A.I. index is called "recno"
ALTER TABLE table1 DROP COLUMN recid;
ALTER TABLE table2 DROP COLUMN recid;
insert into table1 (select * from table2);
ALTER TABLE table1 ADD `recid` INT NOT NULL AUTO_INCREMENT [AFTER `column`], ADD PRIMARY KEY (`recid`);
ALTER TABLE table2 ADD `recid` INT NOT NULL AUTO_INCREMENT [AFTER `column`], ADD PRIMARY KEY (`recid`);
There's not really a way to do that. The * in the SELECT list means "all columns" in ordinal position. There's not exception for columns that meet specified criteria.
The same is true for an omitted list of columns that we're inserting into... it's all of the columns.
The most efficient way (in terms of database resources) to accomplish the specified goal is to list the columns, and omit the auto_increment column from the list.
INSERT INTO t (b,c,d,e) SELECT b,c,d,e FROM s ;
We can get a list of columns names for a table from information_schema.columns...
For example, to get a list of the column names in table2:
SELECT c.column_name
FROM information_schema.columns c
WHERE c.table_schema = 'mydatabase'
AND c.table_name = 'table2'
ORDER
BY c.ordinal_position
To exclude the auto_increment column from the list, we can add a WHERE clause, that excludes that column by it's name
WHERE c.column_name NOT IN ('my_autoincrement_column_name')
or we can check for 'auto_increment' occurring the EXTRA column
WHERE c.extra NOT LIKE '%auto_increment%'
To get a column list for each of the two tables, excluding the auto_increment columns, we could do something like this:
SET group_concat_max_len = 16777216 ;
SELECT GROUP_CONCAT( CONCAT('`',c.column_name,'`')
ORDER BY c.ordinal_position
SEPARATOR ','
) AS `-- column_list`
FROM information_schema.columns c
WHERE c.table_schema = 'mydatabase'
AND c.table_name IN ('table1','table2')
AND c.extra NOT LIKE '%auto_increment%'
GROUP
BY c.table_schema
, c.table_name
ORDER
BY c.table_schema
, c.table_name
EDIT
I'd take the column lists, and build a SQL query.
If we're going to make changes to table2 (dropping the auto_increment column as suggested in another answer to this question), and if we don't need to preserve the values in the column, the easiest change would be to just set all of the values in that column to NULL.
No need to modify table1.
We can remove the auto_increment attribute (and the NOT NULL constraint if that's specified) from the column in table2, and set the column to null. Assuming ai is the name of the auto_increment column, and assuming it's declared to be INT UNSIGNED datatype, we can do:
ALTER TABLE `table2` CHANGE `ai` `ai` INT UNSIGNED COMMENT '' ;
UPDATE `table2` SET `ai` = NULL ;
Then we can do an INSERT INTO table1 SELECT * FROM table2
And then add back the auto_increment attribute to the column in table2.
This approach is more expensive (in terms of the database resources) than a single INSERT ... SELECT.
Generating a column list is an extra step, but the resulting operation would be much more efficient. We could generate a list of columns from just the source table, and then replace the column name with literal NULL value...
INSERT INTO t SELECT NULL,b,c,d FROM s;
I have 2 tables, shows and show_photo
shows structure:
show_photo structure:
What i want to do is update show_photo.modified column with show.year
This is what i tried but nothing gets updated.
UPDATE show_photo t2
JOIN shows t1 ON t1.id = t2.show_id
SET t2.modified = t1.year;
Converting my comment to an answer:
Change the column type from TIMESTAMP to VARCHAR first, run the
UPDATE query; and again change the data type from VARCHAR to INT
Your current table has modified column set to TIMESTAMP. But, you're trying to update its values to integers, which will fail.
I have two tables ,location and locationdata. I want to query data from both the tables using join and to store the result in a new table(locationCreatedNew) which is not already present in the MySQL.Can I do this in MySQL?
SELECT location.id,locationdata.name INTO locationCreatedNew FROM
location RIGHT JOIN locationdata ON
location.id=locationdata.location_location_id;
Your sample code in OP is syntax in SQL Server, the counter part of that in MySQL is something like:
CREATE TABLE locationCreatedNew
SELECT * FROM location RIGHT JOIN locationdata
ON location.id=locationdata.location_location_id;
Referance: CREATE TABLE ... SELECT
For CREATE TABLE ... SELECT, the destination table does not preserve information about whether columns in the selected-from table are generated columns. The SELECT part of the statement cannot assign values to generated columns in the destination table.
Some conversion of data types might occur. For example, the AUTO_INCREMENT attribute is not preserved, and VARCHAR columns can become CHAR columns. Retrained attributes are NULL (or NOT NULL) and, for those columns that have them, CHARACTER SET, COLLATION, COMMENT, and the DEFAULT clause.
When creating a table with CREATE TABLE ... SELECT, make sure to alias any function calls or expressions in the query. If you do not, the CREATE statement might fail or result in undesirable column names.
CREATE TABLE newTbl
SELECT tbl1.clm, COUNT(tbl2.tbl1_id) AS number_of_recs_tbl2
FROM tbl1 LEFT JOIN tbl2 ON tbl1.id = tbl2.tbl1_id
GROUP BY tbl1.id;
NOTE: newTbl is the name of the new table you want to create. You can use SELECT * FROM othertable which is the query that returns the data the table should be created from.
You can also explicitly specify the data type for a column in the created table:
CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;
For CREATE TABLE ... SELECT, if IF NOT EXISTS is given and the target table exists, nothing is inserted into the destination table, and the statement is not logged.
To ensure that the binary log can be used to re-create the original tables, MySQL does not permit concurrent inserts during CREATE TABLE ... SELECT.
You cannot use FOR UPDATE as part of the SELECT in a statement such as CREATE TABLE new_table SELECT ... FROM old_table .... If you attempt to do so, the statement fails.
Please check it for more. Hope this help you.
Use Query like below.
create table new_tbl as
select col1, col2, col3 from old_tbl t1, old_tbl t2
where condition;
Need assistance on the following. How can I copy data from one SQL column table to another sql column table?
I have the following tables
dbo.Thecat62 and dbo.thecase6
inside dbo.Thecat62 , I need to copy the column Work_Order_Job_Start_Date values to dbo.thecase6 column Job_Start_Date. Currently there are null value in the Job_Start_Date column in dbo.thecase6.
I have tried using the following command
INSERT INTO dbo.thecase6 (Job_Start_Date)
SELECT Work_Order_Job_Start_Date
FROM dbo.thecat62
but received the error Cannot insert the value NULL into column 'CaseNo', table 'Therefore.dbo.TheCase6'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Any help will be great!
Thanks!
Because on this table Therefore.dbo.TheCase6 for CaseNo you have specify Not NULL Constraints
something like this
CaseNo int NOT NULL
But you did not select the CaseNo column from the dbo.thecat62 table, so you are explicitly trying to insert nulls into a non-nullable column.
You just need to select the CaseNo column, as well, presuming it does not contain any nulls in teh source table.
INSERT INTO dbo.thecase6 (Job_Start_Date,CaseNo)
SELECT Work_Order_Job_Start_Date,CaseNo FROM dbo.thecat62
The error says it has a column CaseNo which doesn't allow NULL.
Cannot insert the value NULL into column 'CaseNo', table 'Therefore.dbo.TheCase6';
You are inserting rows in the new table which will have just 1 column filled and rest of the columns will be empty
Either
Alter the table in which you are inserting the data and allow the column to allow null values.
Or
if you don't want to allow null values, update the null values to some default values.
I have a SSIS package that copies data from table A to table B and sets a flag in table A so that the same data is not copied subsequently. This works great by using the following as the SQL command text on the ADO Net Source object:
update transfer
set ProcessDateTimeStamp = GetDate(), LastUpdatedBy = 'legacy processed'
output inserted.*
where LastUpdatedBy = 'legacy'
and ProcessDateTimeStamp is not null
The problem I have is that I need to run a similar data copy but from two sources table, joined on a primary / foreign key - select from table A join table B update flag in table A.
I don't think I can use the technique above because I don't know where I'd put the join!
Is there another way around this problem?
Thanks
Rob.
You can use a join in an update statement.
update m
set ProcessDateTimeStamp = GetDate(),
LastUpdatedBy = 'legacy processed',
somefield = t.someotherfield
output inserted.*
from transfer t
join mytable m
on t.id = m.id
where m.LastUpdatedBy = 'legacy'
and m.ProcessDateTimeStamp is null
and t.ProcessDateTimeStamp is not null
The key is to not alias the fields on the left side of the set but to alias everything else. And use the table alias for the table you are updating after the update key word so it knows which table of the join to update.