Right now, we are trying to migrate a stored procedure from SQL Server to PostgreSQL. In this, We saw a querying method MERGE..USING..WHEN. So I couldn't find the equivalent. So is there any option to replicate this functionality? The actual query is given below.
WITH phase_list AS (
SELECT #id_plant AS id_plant
, id_phase
, date_started
FROM OPENJSON(#phase_list)
WITH (
id_phase INT '$.id_phase',
date_started DATE '$.date_started'
)
WHERE date_started IS NOT NULL
)
MERGE grow.plant_phase AS t
USING phase_list AS s
ON s.id_plant = t.id_plant AND s.id_phase = t.id_phase
WHEN MATCHED AND (t.date_started <> s.date_started) THEN
UPDATE
SET t.date_started=s.date_started,
t.date_updated=getutcdate(),
t.updated_by=#id_user
WHEN NOT MATCHED BY TARGET THEN
INSERT (id_plant, id_phase, date_started, created_by, updated_by)
VALUES (s.id_plant, s.id_phase, s.date_started, #id_user, #id_user)
WHEN NOT MATCHED BY SOURCE AND t.id_plant = #id_plant THEN
DELETE;
Can we replicate the same using any join operation with some if/else conditions? or any other approach?
Related
I'm having trouble on finding what is wrong with this SQL statement. I'm using pyodbc latest and ODBC Driver 17 for SQL Server, here is the statement:
insert_sql = """MERGE VehicleDistanceReport trg
USING (VALUES (?, ?, ?))
src(
Distance,
Ic_Siparis_No,
Vehicle_Hour
)
ON trg.Ic_Siparis_No = src.Ic_Siparis_No
WHEN MATCHED THEN
UPDATE SET
Distance = src.Distance,
Ic_Siparis_No = src.Ic_Siparis_No,
Vehicle_Hour = src.Vehicle_Hour
WHERE trg.NodeGroup LIKE N'%AĞIR%' OR trg.NodeGroup LIKE N'%MAKİNE%'
WHEN NOT MATCHED THEN
INSERT(
id,
Record_No,
Device_No,
License_Plate,
Inı
Distance,
Ic_Siparis_No,
Vehicle_Hour
)
VALUES(
src.Distance,
src.Ic_Siparis_No,
src.Vehicle_Hour
);"""
It says there is a syntax error near WHERE statement but the query seems to work in SQL server.
Your WHEN MATCHED clause is wrong, as the WHERE should be a condition. Also no pooint updating Ic_Siparis_No as it's the joining condition anyway
WHEN MATCHED AND trg.NodeGroup LIKE N'%AĞIR%' OR trg.NodeGroup LIKE N'%MAKİNE%' THEN
UPDATE SET
Distance = src.Distance,
Vehicle_Hour = src.Vehicle_Hour
Don't be tempted to place this condition in the ON clause, it will cause incorrect results.
I have generate many xml with the SQL Server command : FOR XML RAW
In that way i have filled a table with the following schema
ACTION as CHAR(1)
TABLE_NAME as NVARCHAR(25)
PAYLOAD as NVARCHAR(MAX)
I
tbl_1
xmlrow_1
I
tbl_1
xmlrow_2
U
tbl_1
xmlrow_3
D
tbl_1
xmlrow_4
D
tbl_2
xmlrow_5
ACTION is a char ( I = insert, U = update, D = delete)
TABLE_NAME is the table on which i have to act (for insert the data, update it or delete it)
PAYLOAD is a XML serialized by SQL Server using the command FOR XML RAW on original table
PAYLOAD Example :
<row COL1="val_col_1" COL2="val_col_2" .. COLN="val_col_n"/>
I am looking for a way (i am writing a stored procedure so i am looking for TSQL) to deserialize it on the "configured" TABLE_NAME possibly for the UPSERT.
If this is not faseable (as i suspect) i will build the SQL script for insert,update or delete dynamically but i still need to deserialize the XML in the PAYLOAD and don't know how to do
I mean, if there is not a better way, how i can do some like that ?
UPDATE [dbo].[tbl_1]
SET [COL1] = CURRENT_ROW.COL1
,[COL2] = CURRENT_ROW.COL2
,[COL3] = CURRENT_ROW.COL3
FROM ( xmlrow_3 --DESERIALIZE ) AS CURRENT_ROW
--EIDTED : added working example in fiddler
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=ac5925a0a2f93791cc7e7c34179137ae
I have two tables Application and Application_temp . I wrote a merge query to merge data from application_temp to application.
But Update statement is not working. Query is inserting the whole set of records again instead of updating , I doubt it must be because date columns, It would be great if anyone could help me with this.
I tried multiple sources from google, nothing helped. Tried changing various match conditions but din't work.
CREATE PROCEDURE [dbo].[MergeApplication_tempToApplication]
AS
--CREATE UNIQUE INDEX cmdbid ON Application_Temp(cmdb_id) WITH
(IGNORE_DUP_KEY = OFF)
MERGE INTO Application AS Target
USING Application_temp AS Source
ON (
--Target.CMDB_ID=Source.CMDB_ID
--AND Target.Application_Name=Source.Application_Name
Target.maas_application_id = source.maas_application_id
)
WHEN MATCHED
AND (
Target.CMDB_ID <> Source.CMDB_ID
OR Target.Application_Name <> Source.Application_Name
OR Target.Fss_Portfolio <> Source.Fss_Portfolio
OR Target.Managed_By <> Source.Managed_By
--Target.Date_Created <> Source.Date_Created OR
--Target.Date_Updated <> Source.Date_Updated
)
THEN
UPDATE
SET Target.cmdb_id = Source.cmdb_id
,Target.Application_Name = Source.Application_Name
,Target.Fss_Portfolio = Source.Fss_Portfolio
,Target.Managed_By = Source.Managed_By
,Target.Date_Created = Source.Date_Created
,Target.Date_Updated = Source.Date_Updated
WHEN NOT MATCHED
THEN
INSERT (
Application_Name
,cmdb_id
,Fss_Portfolio
,Managed_By
,Date_Created
,Date_Updated
)
VALUES (
source.Application_Name
,source.cmdb_id
,source.Fss_Portfolio
,source.Managed_By
,source.Date_Created
,source.Date_Updated
);
As I said update statement is not working. Can any expert in SQL Server. Help me with this? I have struggling from past month.
I have two tables
Chapters_tbl (chID, name)
Status_tbl (chID, Ch_status)
For every chID in Chapters_tbl, I want to insert that chID into Status_tbl and Ch_status
I can use both a SQL Server stored procedure or Entity Framework in C#.
How can I do this?
Using T-SQL...
INSERT dbo.Status_tbl (chID, Ch_status)
SELECT
c.chID,
Ch_status = 1
FROM
dbo.Chapters c
WHERE
NOT EXISTS (
SELECT 1
FROM dbo.Staus_tbl s
WHERE c.chID = s.chID
);
I have this sql:
UPDATE JOBMAKE SET WIP_STATUS='10sched1'
WHERE JBT_TYPE IN (SELECT JBT_TYPE FROM JOBVISIT WHERE JVST_ID = 21)
AND JOB_NUMBER IN (SELECT JOB_NUMBER FROM JOBVISIT WHERE JVST_ID = 21)
It works until I turn it into a parameterised query:
UPDATE JOBMAKE SET WIP_STATUS='10sched1'
WHERE JBT_TYPE IN (SELECT JBT_TYPE FROM JOBVISIT WHERE JVST_ID = #jvst_id)
AND JOB_NUMBER IN (SELECT JOB_NUMBER FROM JOBVISIT WHERE JVST_ID = #jvst_id)
Duplicated parameter names are not allowed. [ Parameter name = #jvst_id ]
I tried this (which i think would work in SQL SERVER 2005 - although I haven't tried it):
UPDATE JOBMAKE
SET WIP_STATUS='10sched1'
FROM JOBMAKE JM,JOBVISIT JV
WHERE JM.JOB_NUMBER = JV.JOB_NUMBER
AND JM.JBT_TYPE = JV.JBT_TYPE
AND JV.JVST_ID = 21
There was an error parsing the query. [ Token line number = 3,Token line offset = 1,Token in error = FROM ]
So, I can write dynamic sql instead of using parameters, or I can pass in 2 parameters with the same value, but does someone know how to do this a better way?
Colin
Your second attempt doesn't work because, based on the Books On-Line entry for UPDATE, SQL CE does't allow a FROM clause in an update statement.
I don't have SQL Compact Edition to test it on, but this might work:
UPDATE JOBMAKE
SET WIP_STATUS = '10sched1'
WHERE EXISTS (SELECT 1
FROM JOBVISIT AS JV
WHERE JV.JBT_TYPE = JOBMAKE.JBT_TYPE
AND JV.JOB_NUMBER = JOBMAKE.JOB_NUMBER
AND JV.JVST_ID = #jvst_id
)
It may be that you can alias JOBMAKE as JM to make the query slightly shorter.
EDIT
I'm not 100% sure of the limitations of SQL CE as they relate to the question raised in the comments (how to update a value in JOBMAKE using a value from JOBVISIT). Attempting to refer to the contents of the EXISTS clause in the outer query is unsupported in any SQL dialect I've come across, but there is another method you can try. This is untested but may work, since it looks like SQL CE supports correlated subqueries:
UPDATE JOBMAKE
SET WIP_STATUS = (SELECT JV.RES_CODE
FROM JOBVISIT AS JV
WHERE JV.JBT_TYPE = JOBMAKE.JBT_TYPE
AND JV.JOB_NUMBER = JOBMAKE.JOB_NUMBER
AND JV.JVST_ID = 20
)
There is a limitation, however. This query will fail if more than one row in JOBVISIT is retuned for each row in JOBMAKE.
If this doesn't work (or you cannot straightforwardly limit the inner query to a single row per outer row), it would be possible to carry out a row-by-row update using a cursor.