Updating a table by referencing another table - sql

I have a table CustPurchase (name, purchase) and another table CustID (id, name).
I altered the CustPurchase table to have an id field. Now, I want to populate this newly created field by referencing the customer ids from the CustID table, using:
UPDATE CustPurchase
SET CustPurchase.id = CustID.id
WHERE CustPurchase.name = CustID.name;
I keep getting syntax errors!

I believe you are after the useful UPDATE FROM syntax.
UPDATE CustPurchase SET id = CI.id
FROM
CustPurchase CP
inner join CustID CI on (CI.name = CP.name)
This might have to be the following:
UPDATE CustPurchase SET id = CI.id
FROM
CustID CI
WHERE
CI.name = CustPurchase.name
Sorry, I'm away from my Postgres machine; however, based upon the reference, it looks like this is allowable. The trouble is whether or not to include the source table in the from_list.

Joining by name is not an ideal choice, but this should work:
UPDATE custpurchase
SET id = (SELECT c.id
FROM CUSTID c
WHERE c.name = custpurchase.name)
The caveat is that if there's no match, the value attempting to be inserted would be NULL. Assuming the id column won't allow NULL but will allow duplicate values:
UPDATE custpurchase
SET id = (SELECT COALESCE(c.id, -99)
FROM CUSTID c
WHERE c.name = custpurchase.name)
COALESCE will return the first non-NULL value. Making this a value outside of what you'd normally expect will make it easier to isolate such records & deal with appropriately.
Otherwise, you'll have to do the updating "by hand", on a name by name basis, to correct instances that SQL could not.

Related

Many-to-one row updates in SQL?

So I'm trying to update data from a temporary table into a main table.
Let's call these tables temp, and services.
The pseudocode would be something like this...
Sort temp by inserted_on
When service_id and location match in both tables:
If temp.column1 is not null, replace services.column1
If temp.column2 is not null, replace services.column2
etc...
I've got this bit working, although when I have multiple source rows in the temp table that match the condition, not all fields are being updated.
For example, I might have two rows with identical service_id and location, in one row column1 is null and column2 has a value, and in the next row the opposite is true. I need to update these one by one in the order they came in, and overwrite old data if necessary.
I also need to join the temp table inside the UPDATE to retrieve the keys I'm matching on.
I've tried the below code, but it only seems to be updating certain rows, and I can't quite figure out what the logic is behind it.
I'm not worried about the order, I'm just trying to figure out why it's leaving some blanks when there is data ready to fill the gaps.
UPDATE sloc
SET
sloc.ata = COALESCE(tmp.ata, sloc.ata),
sloc.atd = COALESCE(tmp.atd, sloc.atd),
sloc.atp = COALESCE(tmp.atp, sloc.atp),
sloc.eta = COALESCE(tmp.eta, sloc.eta),
sloc.etd = COALESCE(tmp.etd, sloc.etd),
sloc.etp = COALESCE(tmp.etp, sloc.etp),
sloc.plat = COALESCE(tmp.plat, sloc.plat),
sloc.plats_up = COALESCE(tmp.plats_up, sloc.plats_up),
sloc.cis_plats_up = COALESCE(tmp.cis_plats_up, sloc.cis_plats_up)
FROM
services_locations sloc
INNER JOIN services svc ON svc.id = sloc.sid
INNER JOIN ref_tiploc tloc ON tloc.id = sloc.tpl_id
INNER JOIN trainstatus_tmp tmp ON svc.rid = tmp.rid AND tloc.tpl = tmp.tpl

Update value if columns in different tables match

I have the following two tables:
CREATE TABLE CustomProperties (
ID INTEGER PRIMARY KEY
, programID INTEGER
, Key VARCHAR
)
CREATE TABLE XXXCustom (
licID INTEGER
, propID INTEGER -- points to CustomProperties.ID
, Value VARCHAR
)
CustomProperties serves as a register of different types of custom properties which my programs can contain. XXXCustom stores the custom properties actually used by program XXX (another table stores properties shared by all programs).
Now, if I want to modify an object's custom property, I know both the Key and the Value I want to modify it to. However, I first need to "convert" the Key into the relevant ID, which I then use to locate the desired row in XXXCustom.
I tried
UPDATE XXXCustom
SET pp.Value = 'TEST'
FROM CustomProperties cp INNER JOIN XXXCustom pp
ON pp.propID = cp.ID AND pp.Key = 'test'
But this throws a syntax error, probably because UPDATE doesn't have a FROM clause, nor can you use JOIN directly in an UPDATE. Fair enough.
So I tried
UPDATE (SELECT cp.Key, pp.Value
FROM CustomProperties cp INNER JOIN FtoolCustom pp
WHERE cp.ID = pp.propID)
SET pp.Value = 'TEST'
ON pp.Key = 'test'
But this also throws a syntax error, I believe because UPDATE doesn't work on subqueries, but requires a qualified table name.
So now I'm out of ideas. Do I have to do this manually in steps: first "convert" the Key to its ID and then use that ID to update XXXCustom?
How about:
UPDATE XXXCustom
SET value='myval'
WHERE licID=(SELECT id FROM CustomProperties WHERE key='mykey');

How to update table field value in one table from field value in another table

I am trying to update field value from one table to another.
Item with bomRev='A' in Destination table look like show below
Same Item bomRev='A' in source table looks like
I want to update partid field in destination table for bomRev=A by the value in Source filed i want to destination looks exactly like the source.
I tried this but no luck
UPDATE [MIBOMD]
SET [MIBOMD].[partId] = [assy].[partId]
FROM [MIBOMD] INNER JOIN [assy] ON [MIBOMD].[partId] = [assy].[partId]
WHERE bomRev='A' and [bomItem]='600797' AND [MIBOMD].[partId]!=[assy].[partId];
UPDATE m
SET [partId] = a.[partId]
FROM
[MIBOMD] m
INNER JOIN
[assy] a
ON m.[bomItem] = a.[ItemId]
AND m.bomEntry = a.bomEntry
WHERE
m.bomRev='A'
AND m.[bomItem]='600797'
AND m.[partId]!=a.[partId];
You actually were pretty close! Just a couple of key differences. Before I explain I have used Table Aliases in the code I provided it is a shorthand way of referring to the table throughout the query that will make it a little easier to follow and read. To Alias a table after the table name in the from statement simply add a space and an alias or a space " AS " alias.
Now your Join as on partid in your version and that was your main issue. Because you want the records where partid are not the same so you can change the partid of the assy table. Looking at your dataset I was able to determine that the shared key was mibomd.bomItem and assy.ItemId. After clearing that up everything should be good.
Per your comment the only other thing that needed to be added was a second condition on the join to make it unique. [MIBOMD].bomEntry = assy.bomEntry
A little about join conditions. Typically you always want to figure out what the unique relationship between the 2 tables are (bomItem = ItemId and bomEntry = bomEntry) and that is what will go in the ON area of the join. Rarely that will be different and will be for very specific purposes.
Per your comment on how to insert the missing records
INSERT INTO MIBOMD (bomItem, bomRev, bomEntry, lineNbr, dType, partId)
SELECT
bomItem = a.ItemId
,bomRev = 'A' --or change the value to what you want
,a.bomEntry
,lineNbr = ???? --not sure how you are figure this out do if you wan it to be the next line number you can figure that out automatically if you need
,a.partId
FROM
assy a
LEFT JOIN MIBOMD m
ON a.ItemId = m.bomItem
AND a.bomEntry = m.bomEntry
WHERE
m.bomItem IS NULL
This time you would use a left join from assy to mibomd and figure out when they don't match mibomd.bomItem IS NULL

updating values of a table from another table through a join changes all values to 1 single value

I have 3 tables: raw_sales, sales and details. raw_sales is being populated using COPY from a txt file. All the fields in raw_sales are either string or text. After importing, we run an sql to populate sales and details. There is a foreign key (sale_id) in details. Here's a sample INSERT command that we use to populate sales and details.
INSERT INTO sales (source, source_identifier)
(SELECT DISTINCT
'FOO' AS source,
"identifier" AS source_identifier
FROM raw_sales
LEFT JOIN sales
ON sales.source_identifier = raw_sales.identifier
AND sales.source = 'FOO'
WHERE sales.id IS NULL
AND identifier IS NOT NULL);
INSERT INTO details (sale_id, description)
(SELECT DISTINCT
sales.id AS sale_id,
"improvements" as description
FROM raw_sales
JOIN sales
ON sales.source_identifier = raw_sales.identifier
AND sales.source = 'FOO'
LEFT JOIN details AS existing
ON existing.sale_id = sales.id
WHERE existing.id IS NULL
AND "improvements" != '');
This seems to work fine. After this, there's another sql that's being ran to update existing tables. The query is as follows
UPDATE details SET
description = "improvements"
FROM raw_sales
JOIN sales
ON sales.source_identifier = raw_sales.identifier
AND sales.source = 'FOO'
JOIN details AS existing
ON existing.sale_id = sales.id
WHERE existing.id IS NOT NULL;
This query updates all rows in the details table to a single value, the first non-empty value from raw_sales table. How can I change the above sql so that it updates the existing records in the details table?
There are several problems with your query:
if details.id is a primary key (field id typically is), then what is the point in comparing it to NOT NULL? You're not using any left joins, there is no way it could possibly be NULL if it truly is an identifier.
UPDATE table t SET ... FROM ... requires linking the table t with something on the FROM section, but you're not, therefore each row of table will be updated to any single random row from the FROM results.
Perhaps you want to do this:
UPDATE details SET
description = "improvements"
FROM raw_sales
JOIN sales ON (sales.source_identifier = raw_sales.identifier AND sales.source = 'FOO')
JOIN details AS existing ON (existing.sale_id = sales.id)
WHERE existing.id = details.id;

SQL-Oracle: Updating table multiple row based on values contained in the same table

I have one table named: ORDERS
this table contains OrderNumber's which belong to the same person and same address lines for that person.
However sometimes the data is inconsistent;
as example looking at the table screenshot: Orders table with bad data to fix -
you all can noticed that orderNumber 1 has a name associated to and addresses line1-2-3-4. sometimes those are all different by some character or even null.
my goal is to update all those 3 lines with one set of data that is already there and set equally all the 3 rows.
to make more clear the result expected should be like this:
enter image description here
i am currently using a MERGE statement to avoid a CURSOR (for loop )
but i am having problems to make it work
here the SQL
MERGE INTO ORDERS O USING
(SELECT
INNER.ORDERNUMBER,
INNER.NAME,
INNER.LINE1,
INNER.LINE2,
INNER.LINE3,
INNER.LINE4
FROM ORDERS INNER
) TEMP
ON( O.ORDERNUMBER = TEMP.ORDERNUMBER )
WHEN MATCHED THEN
UPDATE
SET
O.NAME = TEMP.NAME,
O.LINE1 = TEMP.LINE1,
O.LINE2 = TEMP.LINE2,
O.LINE3 = TEMP.LINE3,
O.LINE4 = TEMP.LINE4;
the biggest issues i am facing is to pick a single row out of the 3 randomly - it does not matter whihc of the data - row i pick to update the line/s
as long i make the records exaclty the same for an order number.
i also used ROWNUM =1 but it in multip[le updates will only output one row and update maybe thousand of lines with the same address and name whihch belong to an order number.
order number is the join column to use ...
kind regards
A simple correlated subquery in an update statement should work:
update orders t1
set (t1.name, t1.line1, t1.line2, t1.line3, t1.line4) =
(select t2.name, t2.line1, t2.line2, t2.line3, t2.line4
from orders t2
where t2.OrderNumber = t1.OrderNumber
and rownum < 2)