Bigquery Error: UPDATE/MERGE must match at most one source row for each target row - google-bigquery

Just wondering if someone could help with the following error:
UPDATE/MERGE must match at most one source row for each target row
My query is as below:
UPDATE `sandbox.sellout` s
SET s.SKU_Label = TRIM(SKU_TEMP.SKU)
FROM (SELECT SKU, Old_SKU FROM `sandbox.ref_sku_temp`) SKU_TEMP
WHERE TRIM(SKU_TEMP.Old_SKU) = TRIM(s.SKU)

If a row in the table to be updated joins with more than one row from the FROM clause, then the query generates the following runtime error: UPDATE/MERGE must match at most one source row for each target row.
Data Manipulation Language Syntax.

It occurs because the target table of the BigQuery contains duplicated row(w.r.t you are joining). If a row in the table to be updated joins with more than one row from the FROM clause, then BigQuery returns this error:
Solution
Remove the duplicated rows from the target table and perform the UPDATE/MERGE operation
Define Primary key in BigQuery target table to avoid data redundancy

Issue is with the duplicate rows in the source table. Please consider removing the the dups and run the query. Or post the sample data here.

Add DISTINCT to your select statement like this:
UPDATE `sandbox.sellout` s
SET s.SKU_Label = TRIM(SKU_TEMP.SKU)
FROM (SELECT DISTINCT SKU, Old_SKU FROM `sandbox.ref_sku_temp`) SKU_TEMP
WHERE TRIM(SKU_TEMP.Old_SKU) = TRIM(s.SKU)

Related

Update multiple rows in the target table from one row in the source table using a natural key

I need to update two columns in a FACT table using data from a dimension table. the challenge is that I don't have a primary key that match both tables, so I have to use a natural key, two columns to create a unique value. besides the source have a single record and the target has multiples records. if I do a merge I get
ora-30926 unable to get a stable set of rows
and if I do an update I get another error. please I need help.
I try this update statement:
UPDATE dw.target_table obc
SET
( obc.sail_key,
obc.durations ) = (
SELECT
sd.sail_key,
sd.durations
FROM
dw.source_table sd
WHERE
obc.code_1 = sd.code_2
AND obc.date_1 = sd.date_2
)
WHERE
obc.item NOT IN (
30,
40
)
AND obc.sail_key = 0
and OBC.load_date between to_date('01-12-2018','DD-MM-YYYY')
AND to_date ('31-12-2018','DD-MM-YYYY');
and I try this merge statement:
MERGE INTO dw.target_table obc
USING ( SELECT distinct
code_2,date_2,durations,sail_key
FROM dw.source_table
) tb_dim
ON ( obc.code_1 = tb_dim.code_2
AND obc.date_1 = tb_dim.date_2 )
WHEN MATCHED THEN UPDATE SET obc.durations = tb_dim.durations,
obc.sail_key = tb_dim.sail_key
WHERE
obc.sail_key = 0
AND obc. NOT IN (
30,
40
)
AND obc.loaddate BETWEEN TO_DATE('01-01-2012','DD-MM-YYYY')
AND TO_DATE ('31-01-2012','DD-MM-YYYY');
ora-30926 unable to get a stable set of rows
This means (code_2,date_2) is not a unique key of tb_dim. Consequently your USING subquery does not produce a set which matches just one row to any row in obc. Consequently the MERGE fails, because Oracle cannot determine which row from the USING subquery should be applied to the target. The DISTINCT does not help because it is applied to the whole projection and it seems you have multiple different values of durations,sail_key for each permutation of code_2,date_2.
You don't say which error you get when you run your UPDATE but presumably it's ORA-01779 or ORA-01427. Something indicating the subquery isn't returning a set of joining keys.
So how do you fix the situation? We cannot give you the correct solution because this is a failure of your data model or your specification. Solving requires an understanding of your business that we do not have. But generally you need to find an extra rule which reduces the USING subquery to a set. That is:
add a third key column which allows the ON clause to map one row in tb_dim to one row in obc; or
use row_number() analytic function in the subquery to fake such a column, preferably ordering by a meaningful column such as date; or
add a criterion WHERE clause of the subquery to remove duplicate values of code_2,date_2.
Alternatively, if you don't care which particular values of durations,sail_key get applied you can use an aggregate:
USING (SELECT code_2
,date_2
,max(durations) as durations
,max(sail_key) as sail_key
FROM dw.source_table
group by code_2,date_2 ) tb_dim
Use whatever function makes sense to you.

Is Oracle MERGE NOT MATCHED THEN UPDATE possible?

We'd like to set the IS_DEL bit = 1 when a record exists in a Target table that doesn't exist in the Source table.
Is it possible to use a MERGE statement using the WHEN NOT MATCHED clause, but make it perform an UPDATE?
When attempting to do so, I'm getting a "ORA-00905: missing keyword" message.
MERGE
INTO AMEPSA.ENTERPRISE_LOCATION trg
USING (
SELECT C.LOCATION_KEY as LOCATION_KEY
FROM AMEPSA.ENTERPRISE_LOCATION C
INNER JOIN AMESTAGE.VW_LOCATION L ON C.REC_SRC_KEY_CD = L.LOCATION_ID
WHERE C.CURR_REC_IND = 'Y'
) src
ON (trg.LOCATION_KEY = src.LOCATION_KEY)
WHEN NOT MATCHED THEN UPDATE
SET trg.IS_DEL = 1
Does the "WHEN NOT MATCH" clause only support "THEN INSERT"?
From the documentation:
Use the MERGE statement to select rows from one or more sources for update or insertion into a table or view. You can specify conditions to determine whether to update or insert into the target table or view.
The syntax looks for rows in the source table (src) which do or do not have matching rows in the target table (trg). If there is a matching target row then it updates that; if there is not a matching row then it inserts a new row in the target table.
It does not, and cannot, look for rows in the target table that are not matched in the source table - which is what you are trying to identify and update.
The syntax diagrams for WHEN MATCHED and WHEN NOT MATCHED also make it clear that you cannot do WHEN NOT MATCHED THEN UPDATE.
Yes you can only insert when not match. See exact options in oracle merge.
The condition can refer to either the data source or the target table. If the condition is not true, then the database skips the update operation when merging the row into the table.

Creation of a temporary table in postgres

I'm trying to create a temporary table in Postgres (to speed up joining, as there will be a lot of similar queries throughout a session). The SQL that will be called at the beginning of a session is the following:
CREATE TEMPORARY TABLE extended_point AS
SELECT (
point.id,
local_location,
relative_location,
long_lat,
region,
dataset,
region.name,
region.sub_name,
color,
type)
FROM point, region, dataset
WHERE point.region = region.id AND region.dataset = dataset.id;
The tables point has the columns id::int, region::int, local_location::point, relative_location::point, long_lat:point (longitude, latitude).
Region has the columns id::int, color::int, dataset::int, name::varchar, sub_name::varchar.
Dataset has the columns id::int, name::varchar, type:varchar.
When this is run, I get the error message: [25P02] ERROR: current transaction is aborted, commands ignored until end of transaction block.
As a side, the commands are executed in PyCharm, and is part of a Python project.
Any suggestions?
Thanks in advance :)
There is an important difference between these two queries:
select 1, 'abc';
select (1, 'abc');
The first query returns one row with two columns with values 1 and 'abc'. The second one returns a row with one column of pseudo-type record with value (1, 'abc').
Your query tries to create a table with one column of pseudo-type record. This is impossible and should end with
ERROR: column "row" has pseudo-type record
SQL state: 42P16
Just remove brackets from your query.
As a_horse stated, [25P02] ERROR does not apply to the query in question.
Btw, my advice: never use keywords as table/column names.

Oracle 10g update table i from table 2 column join error

I have the following Oracle 10g sql which to me looks about right:
update ( select OLD1.TC_CUSTOMER_NUMBER,NEW1.PRD_CUST_NUMBER
FROM TBYC84_PROFILE_ACCOUNT OLD1,
TMP_PRD_KEP NEW1
WHERE
OLD1.TC_CUSTOMER_NUMBER = NEW1.KEP_CUST_NUMBER )
SET
TC_CUSTOMER_NUMBER = PRD_CUST_NUMBER
But i am getting this error when i run the script:
SQL Error: ORA-01779: cannot modify a column which maps to a non key-preserved table
01779. 00000 - "cannot modify a column which maps to a non key-preserved table"
*Cause: An attempt was made to insert or update columns of a join view which
map to a non-key-preserved table.
*Action: Modify the underlying base tables directly.
I have done done some research on this error but not quite sure how to remedy.
So my question is, how can i fix this or is there a better way to write the update sql?
Any help would be appreciated.
many thanks
UPDATE
I have changed the update sql to this:
update
TBYC84_PROFILE_ACCOUNT PA
set
(
PA.TC_CUSTOMER_NUMBER
) = (
select
TPK.PRD_CUST_NUMBER
from
TMP_PRD_KEP TPK
where
TPK.KEP_CUST_NUMBER = PA.TC_CUSTOMER_NUMBER
)
Now this has updated the TBYC84_PROFILE_ACCOUNT table AND nulled out the TC_CUSTOMER_NUMBER
column.
Why did it do this?
There may be more than one row in the TBYC84_PROFILE_ACCOUNT.TC_CUSTOMER_NUMBER
that has the same account number but for different user_id's.
Please can anyone assist in helping me resolve this.
All I need to to is update the TBYC84_PROFILE_ACCOUNT.TC_CUSTOMER_NUMBER to the one that is xrefed in the TMP_PRD_KEP, surely this is not impossible.
many thanks
For an UPDATE statement, all the columns that are updated must be extracted from a key-preserved table.
Also:
A key-preserved table is one for which every primary key or unique key value in the base table is also unique in the join view.
Here.
In this case, TBYC84_PROFILE_ACCOUNT is being updated. So, it must be key-preserved in the view's subquery. Currently it is not. It must be changed in a way that it becomes key-preserved by involving primary or unique columns in the where clause. If not possible, you should try to update the base table instead.
UPDATE
In case of the table update problem, assuming the subquery returns at most one distinct value for the TC_CUSTOMER_NUMBER column, the reason you get NULLs is that all records are being updated even if they do not have any matching records in the TMP_PRD_KEP table. So, the parent update statement needs to be fitted with a where clause:
update
TBYC84_PROFILE_ACCOUNT PA
set
(
PA.TC_CUSTOMER_NUMBER
) = (
select
TPK.PRD_CUST_NUMBER
from
TMP_PRD_KEP TPK
where
TPK.KEP_CUST_NUMBER = PA.TC_CUSTOMER_NUMBER
)
where exists(select *
from TMP_PRD_KEP TPK
where TPK.KEP_CUST_NUMBER = PA.TC_CUSTOMER_NUMBER)
;
Create a index on the columns used in your where clause predicates. That should solve your problem.

SQL Server: copy data from one column to another column?

I have two tables with the same column anomaly_id. I want to copy the row of anomaly_id from the first table to the second table using this code
UPDATE amb.anamoly_log_update
SET anamoly_id = t2.anomaly_id
FROM amb.anamoly_log_update t1
INNER JOIN amb.anomaly_fee t2 ON t1.anamoly_id=t2.anomaly_id
Even after I did that it shows 0 rows affected, when there is data in amb.anomaly.fee (source table)
Please help
Edit: Comment from post: I just want to copy all the anamoly_id from amb.anamoly_fee to amb.anamoly_log_update. My code might be nonsensical. Please do review it.
To copy the id from anomaly_fee to anamoly_log_update use :
INSERT INTO anamoly_log_update (anamoly_id)
SELECT anamoly_id FROM anomaly_fee
with both columns it looks like that:
INSERT INTO anamoly_log_update (anamoly_id,PID)
SELECT anamoly_id,PID FROM anomaly_fee
You only would copy the data if they where in both tables .. and then there is nothing update because you do not change the data => 0 rows affected
ON t1.anamoly_id=t2.anomaly_id
please think about what you really want to do and change your description ..
Does amb.anamoly_log_update contain at least one row corresponding to the anamoly_id that's present in amb.anamoly_fee? You are trying to join on two tables on anamoly_id.
You need to provide other linkage between tables than t1.anamoly_id=t2.anomaly_id or the query will do nothing
merge into amb.anamoly_log_update as t1
using amb.anomaly_fee as t2
on t1.anamoly_id=t2.anomaly_id
when matched then
update set t1.anamoly_id = t2.anomaly_id