Update value if columns in different tables match - sql

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');

Related

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

Recommended way to deal with updating m2m table postgres

I have the below tables
A project table
project_id,project_name
A skill table
skill_id,skill_name
A project_skill table (many to many relationship)
project_skill_id,project_id,skill_id
The browser will have a form which asks the user to enter a project name and and SO style autocomplete for tags. I'm sending the below json format back to sql for insertion
{"project_name":"foo","skills":["bar","baz"]}
My question relates to a situation where the user gets to edit an existing project.Assuming the user removes "baz" from skills and includes "zed". How do i properly deal with updating the many to many table
{"project_name":"foo","skills":["bar","zed","biz"]}
Do i remove all records from the m2m table and do a fresh insert with the new skills?
remove all records based on project_id
insert new records of bar,zed,biz
Do i check in the server what was removed/added and remove only what was actually removed
remove baz from table
add biz
This also pertains to modifying project_name etc. Do i check what was modified and update the necessary or perform a complete delete and insert
I'd use a CTE with a MERGE (note this is SQL Server but Postgres should be similar):
;WITH src AS
(
SELECT p.project_id, s.skill_id
FROM
dbo.project AS p
INNER JOIN #input AS i ON p.project_name = i.project_name
INNER JOIN dbo.skill AS s ON i.skill_name = s.skill_name
)
MERGE INTO dbo.project_skill AS tgt
USING src
ON tgt.project_id = src.project_id AND tgt.skill_id = src.skill_id
WHEN NOT MATCHED BY TARGET THEN
INSERT (project_id, skill_id) VALUES (src.project_id, src.skill_id)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
where #input contains the new values:
DECLARE #input TABLE
(
project_name VARCHAR(100),
skill_name VARCHAR(100)
);

How to import values into a column from another table in Access

I created an Access Database and I wish to import a subset of data from a master table into a smaller table using SQL Queries. Basically, I want the smaller (Customer) table to reflect any changes made in the bigger (Total) table.
I tried the following code:
UPDATE Customer SET Brand =
(SELECT Brand FROM Total WHERE Chance = -1) ; Chance is a binary column
WHERE EXIST (SELECT Brand FROM Total WHERE Chance = -1);
, but I get an error: "operation must use an updateable query" and my file is not a read-only file.
Is there another Query that I can use to perform the same task?
Update statement in MS Access database should looks like:
UPDATE Customer AS C
INNER JOIN Total AS T ON T.PK = C.FK
SET C.Brand = T.Brand
WHERE T.Chance=-1;
Where:
PK = Primary Key
FK = Foreign Key

In SQL How do I copy values from one table to another based on another field's value?

Okay I have two tables
VOUCHERT with the following fields
ACTIVATIONCODE
SERIALNUMBER
VOUCHERDATADBID
UNAVAILABLEAT
UNAVAILABLEOPERATORDBID
AVAILABLEAT
AVAILABLEOPERATORDBID
ACTIVATIONCODENEW
EXT1
EXT2
EXT3
DENOMINATION -- I added this column into the table.
and the second table is VOUCHERDATAT with the following fields
VOUCHERDATADBID
BATCHID
VALUE
CURRENCY
VOUCHERGROUP
EXPIRYDATE
AGENT
EXT1
EXT2
EXT3
What I want to do is copy the corresponding VALUE from VOUCHERDATAT and put it into DENOMINATION of VOUCHERT. The linking between the two is VOUCHERDATADBID. How do I go about it?
It is not a 1:1 mapping. What I mean is there may be 1000 SERIALNUMBERS with a same VOUCHERDATADBID. And that VOUCHERDATADBID has only entry in VOUCHERDATAT, hence one value. Therefore, all serial numbers belonging to a certain VOUCHERDATADBID will have the same value.
Will JOINS work? What type of JOIN should I use? Or is UPDATE table the way to go?
Thanks for the help !!
Your problem is one of design. None of your tables are in any of the normal forms, not even in the first normal form (1NF). You should not add a column to the VOUCHERT table, but create a new table (pick the name) with the following columns: SERIALNUMBER, VALUE, VOUCHERDATADBID (maybe ACTIVATIONCODE too - need to know the primary key on VOUCHERT to be sure if ACTIVATIONCODE should be included in the new table). Normalization is the database design process that aims to resolve any possible INSERT/UPDATE/DELETE anomalies. This should solve your INSERT issue.
Hope this helps.
You can do a join between these two tables and you will get a 'view'. You can update this view like:
UPDATE (SELECT *
FROM VOUCHERT A JOIN VOUCHERDATAT B
ON A.VOUCHERDATADBID = B.VOUCHERDATADBID)
SET DENOMINATION = VALUE;
You may put outer join if you need.
VOUCHERDATADBID MUST BE PRIMARY KEY in VOUCHERDATAT and FOREIGN KEY in VOUCHERT, otherwise you will get an error:
ORA-01779: cannot modify a column which maps to a non key-preserved table
update (
select v.DENOMINATION
, vd.VALUE
from VOUCHERT v
join VOUCHERDATAT vd
on vd.VOUCHERDATADBID = v.VOUCHERDATADBID
) t
set t.DENOMINATION = t.Value
If the voucherdatadbid is not a primary key, this should work:
UPDATE vouchert
SET denomination =
(SELECT MAX(value)
FROM voucherdatat
WHERE voucherdatadbid = vouchert.voucherdatadbid);

Updating a table by referencing another table

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.