How do I convert this PL/SQL update statement so that is works in SQL SERVER?
-
22-07-2019 - |
Question
I've been asked to convert this statement from PL/SQL to SQL Server:
UPDATE pdi_nb_process_complete pdi_end1
SET (pdi_end1.adp_issue_date_time, pdi_end1.adp_print_date_time) =
(SELECT DISTINCT pdi_end1.completion_date + 2
,pdi_end1.completion_date
FROM cl100 cl
WHERE cl.polref = pdi_end1.policy_reference
AND cl.doctyp = 'PSP')
WHERE pdi_end1.adp_print_date_time IS NULL
A straight copy/paste doesn't work - you get a compile error. The closest I have managed is this:
UPDATE pdi_end1
SET pdi_end1.adp_issue_date_time = pdi_end1.completion_date + 2,
pdi_end1.adp_print_date_time = pdi_end1.completion_date
from pdi_nb_process pdi_end1
INNER JOIN cl100 cl ON cl.polref = pdi_end1.policy_reference
AND cl.doctyp = 'PSP'
WHERE pdi_end1.adp_print_date_time IS NULL
But this leaves me short of the DISTINCT. Does anyone have any suggestions?
You can assume the Oracle and SQL Server Databases have the same tables and fields.
Thanks
Solution
I would move the AND cl.doctyp='PSP' condition to the WHERE, because it is not a join condition.
try this:
UPDATE pdi_end1
SET pdi_end1.adp_issue_date_time=pdi_end1.completion_date + 2
,pdi_end1.adp_print_date_time)=pdi_end1.completion_date
FROM pdi_nb_process_complete pdi_endl
INNER JOIN cl100 cl ON cl.polref=pdi_end1.policy_reference
WHERE pdi_end1.adp_print_date_time IS NULL
AND cl.doctyp='PSP'
I would not worry about the DISTINCT, SQL Server will only update the rows one time, see this example:
SET NOCOUNT ON
DECLARE @Test table (RowID int, RowValue int, OtherRowValue int)
INSERT INTO @Test VALUES ( 1, 1, 10)
INSERT INTO @Test VALUES ( 2, 2, 20)
INSERT INTO @Test VALUES ( 3, 3, 30)
INSERT INTO @Test VALUES ( 4, 4, 40)
INSERT INTO @Test VALUES ( 5, 5, 50)
INSERT INTO @Test VALUES ( 6, 6, 60)
INSERT INTO @Test VALUES ( 7, 7, 70)
INSERT INTO @Test VALUES ( 8, 8, 80)
INSERT INTO @Test VALUES ( 9, 9, 90)
INSERT INTO @Test VALUES (10,10,100)
DECLARE @TestJoin table (RowID int, RowValue int)
INSERT INTO @TestJoin VALUES (1,10)
INSERT INTO @TestJoin VALUES (1,10)
INSERT INTO @TestJoin VALUES (1,10)
INSERT INTO @TestJoin VALUES (2,20)
INSERT INTO @TestJoin VALUES (2,20)
INSERT INTO @TestJoin VALUES (2,20)
INSERT INTO @TestJoin VALUES (2,20)
INSERT INTO @TestJoin VALUES (2,20)
INSERT INTO @TestJoin VALUES (3,30)
INSERT INTO @TestJoin VALUES (3,30)
SET NOCOUNT OFF
SELECT ---------------------------returns 5 rows, DISTINCT would only return 1
t.OtherRowValue+2
FROM @Test t
INNER JOIN @TestJoin j ON t.RowID=j.RowID
WHERE t.OtherRowValue=20
AND j.RowValue=20
UPDATE t--------------------------updates only 1 row
SET t.RowValue=t.OtherRowValue+2
FROM @Test t
INNER JOIN @TestJoin j ON t.RowID=j.RowID
WHERE t.OtherRowValue=20
AND j.RowValue=20
OUTPUT:
-----------
22
22
22
22
22
(5 row(s) affected)
(1 row(s) affected)
The SELECT returns 5 rows, however when that same select is put into the UPDATE, only 1 row is affected.
OTHER TIPS
You could change the inner join into a subquery:
inner join (
select distinct policy_reference
from cl100
where doctyp = 'PSP'
) cl on cl.polref = pdi_end1.policy_reference
Or maybe more readable, remove the inner join altogether and replace it with a WHERE statement:
WHERE pdi_end1.adp_print_date_time IS NULL
AND EXISTS (
select *
from cl100 cl
where cl.polref = pdi_end1.policy_reference
and cl.doctyp = 'PSP'
)