convert mysql (on duplicate key ) query to oracle merge - mysql

INSERT INTO table1(id,dept_id,name,description,creation_time,modified_time)
VALUES('id','dept_id','name','description','creation_time','modified_time')
ON DUPLICATE KEY UPDATE dept_id=VALUES(dept_id),name=VALUES(name),
description=VALUES(description),creation_time=VALUES(creation_time),
modified_time=VALUES(modified_time)
I used the below oracle to convert the above mysql query. The query fails. Can you please help me figure out what is wrong with the oracle query.
Merge into table1 t1 using
(VALUES ('id','dept_id','name','description','creation_time','modified_time')) as temp
(id,dept_id,name,description,creation_time,modified_time) on t1. id = temp.id
WHEN MATCHED THEN UPDATE SET dept_id=t1.dept_id, description=t1.description, name=t1.name,
creation_time=t1.creation_time, modified_time=t1.modified_time
WHEN NOT MATCHED THEN INSERT (id,dept_id,name,description,creation_time,modified_time)
VALUES ('id','dept_id','name','description','creation_time','modified_time')

To do this, you need to use a table or subquery in the using clause (in your case, you need a subquery).
In Oracle, you can use the dual table if you need to select something without needing to select from an actual table; this is a table that contains only a single row and a single column.
Your merge statement should therefore look something like:
MERGE INTO table1 tgt
USING (SELECT 'id' id,
'dept_id' dept_id,
'name' NAME,
'description' description,
'creation_time' creation_time,
'modified_time' modified_time
FROM dual) src
ON tgt.id = src.id
WHEN MATCHED THEN
UPDATE
SET tgt.dept_id = src.dept_id,
tgt.description = src.description,
tgt.name = src.name,
tgt.creation_time = src.creation_time,
tgt.modified_time = src.modified_time
WHEN NOT MATCHED THEN
INSERT
(tgt.id,
tgt.dept_id,
tgt.name,
tgt.description,
tgt.creation_time,
tgt.modified_time)
VALUES
(src.id,
src.dept_id,
src.name,
src.description,
src.creation_time,
src.modified_time);
Note how the when not matched clause uses the columns from the source subquery, rather than using the literal values you supplied. (I assume that in your actual code, these literal values are actually variables; creation_time is a pretty odd value to store in a column labelled creation_time!).
I've also switched the aliases to make it clearer where you're merging to and from; I find this makes it easier to understand what the merge statement is doing. YMMV.

Related

Select id from input list NOT present in database

With MySql vers 8.0:
CREATE TABLE cnacs(cid VARCHAR(20), PRIMARY KEY(cid));
Then,
INSERT INTO cnacs VALUES('1');
The first two statements execute successfully. The next statement does not, however. My goal is to return a list of unused cid's from the input table [1, 2]:
SELECT * FROM (VALUES ('1'),('2')) as T(cid) EXCEPT SELECT cid FROM cnacs;
In theory, I'd like the output to be '2', since it has not yet been added. The aforementioned query was inspired by Remus's answer on https://dba.stackexchange.com/questions/37627/identifying-which-values-do-not-match-a-table-row
This is at least the correct syntax for what you are trying to do.
If this query is anything more than a learning exercise though I'd rethink the approach, storing these '1' and '2' values (or however many there ends up being) in their own table
SELECT Column_0
FROM (SELECT * FROM (VALUES ROW('1'), ROW('2')) TMP) VALS
LEFT
JOIN cnacs
ON VALS.Column_0 = cnacs.cid
WHERE cnacs.cid IS NULL

Correting wrong insert-from-select SQL statement

here is a mysql statement, can you please tell what is wrong with it
insert into wip_inventory
(wip_inventory.amount)
values (
select
sum(planning.actual_cost) as c
from planning
where planning.progress='no'
)
You would need two sets of parentheses to express this logic using values (one for the values list and one for the subquery). But, that keyword is superfluous anyway:
insert into wip_inventory (wip_inventory.amount)
select sum(planning.actual_cost) as c
from planning
where planning.progress = 'no';
In your query only one record will be added to wip_inventory and will throw error if the subquery returns more than one record.
I think you are trying to insert all records returned from subquery so, use INSERT INTO SELECT:
insert into wip_inventory (wip_inventory.amount)
select sum(planning.actual_cost) as c
from planning
where planning.progress='no'

Select query on update finds no records

I'm missing something here and hope someone can point out my error. The following select statement returns rows as expected.
SELECT sku, releasedate FROM staging_product_dimensions WHERE TO_DAYS(`releasedate`) > TO_DAYS(NOW())-30 ;
Yet when I use the same where condition in an update statement no records are found. Any insight into why?
UPDATE staging_product t1
JOIN staging_product_dimensions t2
ON t1.sku = t2.sku
SET t1.categories = CONCAT(t1.categories,';;','What\'s New')
WHERE TO_DAYS(t2.releasedate) > TO_DAYS(NOW())-30 ;
There are four reasons why you would get no rows from this update:
The syntax is invalid or the code is not running or it is not running on the correct database.
The where clause fails.
The join fails.
The value being set is the same as the original value.
I am discounting (1), because you seem to be able to run a select query with the same columns and tables.
If the next two are not the reason, then the fourth would appear to be. This would only happen if the value were NULL. You might try this set clause instead:
SET t1.categories = CONCAT(COALESCE(t1.categories, ''), ';;', 'What\'s New')

MySQL INSERT INTO single column from a SELECT query pulling data from two other tables - throwing #1062 - Duplicate entry '' for key 2 error

I've got one col (state_not_allowed) in TABLE vendor_product where I'm trying to insert values from product_catalog_varchar.value - but only if there's a sku in vendor_product that matches a sku in product_catalog where product_catalog's id equals product_catalog_varchar's id and product_catalog_varchar's attribute id = 523.
I'm basically trying to do the MySQL equivalent of an Excel VLOOPUP. I need the result of the following query:
SELECT product_catalog_varchar.value
FROM product_catalog_varchar
JOIN product_catalog
ON product_catalog.id = product_catalog_varchar.id
JOIN vendor_product
ON vendor_product.sku = product_catalog.sku
AND product_catalog_varchar.attribute_id = 523
To be inserted in to column state_not_allowed, where the sku in vendor_product = the sku in product_catalog.
I've done some research on INSERT INTO, here and on Google in general. Looks like a lot of the instruction out there is on simplier queries so I haven't been able to find a decent model to figure out what to do. I can tell you that this query doesn't work:
INSERT INTO vendor_product(`state_not_allowed`)
SELECT product_catalog_varchar.value
FROM product_catalog_varchar
JOIN product_catalog
ON product_catalog.id = product_catalog_varchar.id
JOIN vendor_product
ON vendor_product.sku = product_catalog.sku
AND product_catalog_varchar.attribute_id = 523
It throws the following error: #1062 - Duplicate entry '' for key 2
And if I got to vendor_product and look, instead of simply inserting values in to state_not_allowed, it's creating a whole new row (with no data). Clearly, I'm misunderstanding in a fundamental sense here. Help me out? Thanks folks.
This query shows the general idea of what you want to do.
insert into table2
(field1)
select distinct field1
from table1
where field1 in
(select field1
from table1
except
select field1
from table2)
The details vary from RDBMS to RDBMS. For example, Oracle uses the keyword minus instead of except. Your MySql documentation will help you with the details.
Note that while it's tempting to simplify this by using "not in" that construct tends to be slow.

sql query for deleting rows with NOT IN using 2 columns

I have a table with a composite key composed of 2 columns, say Name and ID. I have some service that gets me the keys (name, id combination) of the rows to keep, the rest i need to delete. If it was with only 1 row , I could use
delete from table_name where name not in (list_of_valid_names)
but how do I make the query so that I can say something like
name not in (valid_names) and id not in(valid_ids)
// this wont work since they separately dont identity a unique record or will it?
Use mysql's special "multiple value" in syntax:
delete from table_name
where (name, id) not in (select name, id from some_table where some_condition);
If your list is a literal list, you can still use this approach:
delete from table_name
where (name, id) not in (select 'john', 1 union select 'sally', 2);
Actually, no I retract my comment about needing special juice or being stuck with (AND OR'ing all your options).
Since you have a list of values of what you want to retain, dump that into a temporary table. Then do a delete against the base table for what does not exist in the temporary table (left outer join). I suck at mysql syntax or I'd cobble together your query. Psuedocode is approximate
DELETE
B
FROM
BASE B
LEFT OUTER JOIN
#RETAIN R
ON R.key1 = B.key1
AND R.key2 = B.key
WHERE
R.key1 IS NULL
The NOT EXISTS version:
DELETE
b
FROM
BaseTable b
WHERE
NOT EXISTS
( SELECT
*
FROM
RetainTable r
WHERE
(r.key1, r.key2) = (b.key1, b.key2)
)