Upsert on a range - sql-server-2008

I'm aware of this:
IF EXISTS (SELECT * FROM table WHERE pk = #pk)
BEGIN
--Update
END
ELSE
BEGIN
--INSERT
END
But this works for one row. Let's say I have a table min_max M and a temp table __MinMaxImport T. I want to INSERT from T to M, but UPDATE when the pair branch_no/product already exists in M.
INSERT:
INSERT INTO min_max
(user_no, branch_no, product, min_stock, max_stock)
SELECT
#user_no, _branch_no, _product, _min_stock, _max_stock
FROM
traxs_temp..__MinMaxImport
WHERE
session_id = #session_id
UPDATE:
UPDATE min_max SET
date_time = GETDATE(),
user_no = #user_no,
min_stock = _min_stock,
max_stock = _max_stock
FROM
min_max M
INNER JOIN traxs_temp..__MinMaxImport T ON T._product = M.product
AND T._branch_no = M.branch_no
WHERE
session_id = #session_id
What is the best solution to do this? I read about MERGE but I'm not sure how to use it.

MERGE should be able to do it.
MERGE INTO min_max
USING
(
SELECT
#user_no AS _user_no, _branch_no, _product, _min_stock, _max_stock
FROM
traxs_temp..__MinMaxImport
WHERE
session_id = #session_id
) AS Src
ON
(min_max.branch_no = Src._branch_no) AND
(min_max.product = Src._product)
WHEN MATCHED THEN
UPDATE SET
date_time = GETDATE(),
user_no = Src._user_no,
min_stock = Src._min_stock,
max_stock = Src._max_stock
WHEN NOT MATCHED BY TARGET THEN
INSERT
(user_no, branch_no, product, min_stock, max_stock)
VALUES
(Src._user_no,
Src._branch_no,
Src._product,
Src._min_stock,
Src._max_stock)
;

Related

UPDATE FROM WHERE Subquery SQL Server

How can I use a subquery from an UPDATE statement? Here is my query:
UPDATE car_availability
SET availability_status = 'GOOD'
FROM car_trip AS TRIP
WHERE car_availability.car_no = TRIP.car_no
AND NOT EXISTS (SELECT DISTINCT A.car_No
FROM car_maintenance A
WHERE A.car_no = TRIP.vehicle_id
AND start_date = TRIP.workday)
AND EXISTS (SELECT DISTINCT B.car_No
FROM car_maintenance B
WHERE B.car_no = TRIP.vehicle_id
AND end_date IS NOT NULL)
I get an error 'FROM clause in UPDATE and DELETE statements cannot contain subquery sources or joins.'
I want to update availability_status to GOOD in which car exists in car_maintenance with its start_date is equal to workday of car_trip and cars which is in car_maintenance with its end date is not null.
As #McNets said, you need to add the car_availability table to your FROM clause. Try this:
UPDATE CA
SET availability_status = 'GOOD'
FROM car_availability CA
JOIN car_trip AS TRIP ON CA.car_no = TRIP.car_no
WHERE NOT EXISTS (SELECT DISTINCT A.car_No
FROM car_maintenance A
WHERE A.car_no = TRIP.vehicle_id
AND start_date = TRIP.workday)
AND EXISTS (SELECT DISTINCT B.car_No
FROM car_maintenance B
WHERE B.car_no = TRIP.vehicle_id
AND end_date IS NOT NULL)

How to combine while loop in mysql to single update

I have a temporary table named _temp that contains orders that will be sent back to a webpage. When this table is created it populates all the information except the number of photos in each order (currently it will set the number of photos to -1 so that I know it hasn't been updated). I want to update the number of photos in each order to the correct number. I have no idea how to do this without using a while statement and going through each order individually. Here is the code I'm currently using which works fine but is very slow
SET _current_id = (SELECT old_id FROM _temp WHERE photos = -1 LIMIT 1);
WHILE (_current_id IS NOT NULL) DO
UPDATE _temp SET photos = (SELECT COUNT(f.id) FROM files f WHERE f.file_type = "orders" AND f.table_id = _current_id AND deleted = 0) WHERE old_id = _current_id;
SET _current_id = (SELECT old_id FROM _temp WHERE photos = -1 LIMIT 1);
END WHILE;
update _temp t set t.photos = (SELECT COUNT(f.id) FROM files f WHERE f.file_type = "orders" AND f.table_id = t.old_id AND deleted = 0) WHERE old_id = t.old_id;

Update Query With Inline

Is it possible to do an update query like this? It may not be, just a thought I had as to possibly a solution to my predicament of terrible data-structure. What I am trying to accomplish is:
To update the table prodinformation with a count where the entrytype exists in table vet
Set #location varchar(100), #entrydate datetime
Set #location = 'server01.database01.dbo.manhunt
Set #entrydate = GetDate()
Update prodinformation
Set totalenteredtoday = abc.te
FROM prodinformation d
JOIN (SELECT Count(ID)
from #location
WHERE entrytype IN (
Select validentrytype
from vet
where ltrim(rtrim(entrydate)) = #entrydate) As te
Update d
Set totalenteredtoday = te.IdCount
FROM prodinformation As d
JOIN
(
Select [someJoinAttribute]
,Count(ID) As IdCount
From #location
Where entrytype IN ( Select validentrytype
From vet With (Nolock)
Where ltrim(rtrim(entrydate)) = #entrydate
)
Group By [someJoinAttribute]
) As te On d.[someAttribute] = te.[someJoinAttribute]
here [someJoinAttribute] would be the column/attribute to be used to perform join operation

MySQL: Changing trigger definition based on the SET columns within an INSERT

I have two insert statements:
INSERT INTO `users votes` SET `forumtopicid` = '$id'
INSERT INTO `users votes` SET `forumtopicid` = '$forumtopicid', `replyid` = '$id'
Now here is my current trigger definition:
UPDATE `forum topics` ft
SET votes = votes + 1
WHERE NEW.forumtopicid = ft.id
I want to change it so if the INSERT contains replyid, than the UPDATE becomes:
UPDATE `forum replies` fr
SET votes = votes + 1
WHERE NEW.replyid = fr.id
You would use an if statement in the trigger:
if new.replyid is null then
UPDATE `forum topics` ft
SET votes = votes + 1
WHERE NEW.forumtopicid = ft.id;
else
UPDATE `forum replies` fr
SET votes = votes + 1
WHERE NEW.replyid = fr.id;
end if;

Mysql update subquery specify target table

I'm having trouble with updating final_id by selecting the highest final_id already in table and adding +1.
The query below outputs the error: "You can't specify target table 'customer_orders' for update in FROM clause" and I sadly fail to see why..
UPDATE customer_orders
SET final_id = (SELECT final_id FROM customer_orders ORDER BY final_id DESC)+1,
status = 2,
payment_id = '{$transaction_id}',
payment_type = '{$type}',
payment_reserved = '{$amount}',
payment_currency = '{$cur}',
payment_cardnopostfix = '{$postfix}',
payment_fraud_suspicious = '{$fraud}'
WHERE id = '{$order_id}'
I'm trying to set a unique increasing ID for finalized orders in my system.
I hope someone can tell me what I'm doing wrong!
Best regards
You can rewrite your query and use join
UPDATE customer_orders
INNER JOIN (SELECT IFNULL(MAX(final_id),0) as max_id FROM customer_orders)a ON(1=1)
SET final_id = a.max_id+1, status = 2, payment_id = '{$transaction_id}',
payment_type = '{$type}', payment_reserved = '{$amount}',
payment_currency = '{$cur}', payment_cardnopostfix = '{$postfix}',
payment_fraud_suspicious = '{$fraud}'
WHERE id = '{$order_id}'
change the inner query to SELECT max(final_id) FROM customer_orders
Try this:
UPDATE customer_orders
SET final_id = MT.MaxId + 1 -- use the computed max id, and increment
, status = 2
, payment_id = '{$transaction_id}'
, payment_type = '{$type}'
, payment_reserved = '{$amount}'
, payment_currency = '{$cur}'
, payment_cardnopostfix = '{$postfix}'
, payment_fraud_suspicious = '{$fraud}'
FROM customer_orders
-- include a subquery to determine the max id from the customer_orders table
-- and assign 'MT' as the name of the results table
, (SELECT MAX(final_id) as MaxId FROM customer_orders) MT
WHERE id = '{$order_id}'