patternsqlMinor
Why is my SQL Server query behaving differently on UPDATE than on SELECT?
Viewed 0 times
differentlywhyupdatesqlquerythanserverselectbehaving
Problem
I've written a SQL Server query that updates records to have a sequential number after partitioning on a field. When I run it as a SELECT statement, everything looks great:
However, when I make the query into an UPDATE command, it begins skipping even numbers:
```
DECLARE @RunDetailID INT = 448
DECLARE @JobDetailID INT
SELECT @JobDetailID = [JobDetailID] FROM [RunDetails] WHERE [RunDetailID] = @RunDetailID
UPDATE
[MRDFStorage]
SET
[Seq9] = [OrderedRecords].[NewSeq9],
[Overlay1] = [OrderedRecords].[NewSeq9],
[Overlay10] = RIGHT([OrderedRecords].[NewSeq9], 4)
FROM
(
SELECT
[Records].*,
[Records].[SortField] + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY [Records].[SortField] ORDER BY [Re
DECLARE @RunDetailID INT = 448
DECLARE @JobDetailID INT
SELECT @JobDetailID = [JobDetailID] FROM [RunDetails] WHERE [RunDetailID] = @RunDetailID
SELECT
[OrderedRecords].[NewSeq9],
RIGHT([OrderedRecords].[NewSeq9], 4)
FROM
(
SELECT
[Records].*,
[Records].[SortField] + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY [Records].[SortField] ORDER BY [Records].[RunDetailID], [Records].[SortField], [Records].[PieceID]) AS VARCHAR), 4) NewSeq9
FROM
(
SELECT
[MRDFStorageID],
[RunDetailID],
[SortField],
[PieceID],
[Seq9],
[BallotType]
FROM
[MRDFStorage]
JOIN [BallotStyles] ON [MRDFStorage].[SortField] = [BallotStyles].[Style] and [BallotStyles].[JobDetailID] = @JobDetailID
WHERE
[RunDetailID] IN (SELECT [RunDetailID] FROM [RunDetails] WHERE [JobDetailID] = @JobDetailID AND [RunStatusID] <> 0)
) Records
) OrderedRecords
JOIN MRDFStorage ON [OrderedRecords].[MRDFStorageID] = [MRDFStorage].[MRDFStorageID]
WHERE
[MRDFStorage].[RunDetailID] = @RunDetailIDHowever, when I make the query into an UPDATE command, it begins skipping even numbers:
```
DECLARE @RunDetailID INT = 448
DECLARE @JobDetailID INT
SELECT @JobDetailID = [JobDetailID] FROM [RunDetails] WHERE [RunDetailID] = @RunDetailID
UPDATE
[MRDFStorage]
SET
[Seq9] = [OrderedRecords].[NewSeq9],
[Overlay1] = [OrderedRecords].[NewSeq9],
[Overlay10] = RIGHT([OrderedRecords].[NewSeq9], 4)
FROM
(
SELECT
[Records].*,
[Records].[SortField] + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY [Records].[SortField] ORDER BY [Re
Solution
Not seeing the data you have makes this a bit harder but I managed to reproduce what you see if you see with this:
The key factor here is the two rows in
You are joining to
insert into RunDetails(RunDetailID, JobDetailID) values(448, 1)
insert into MRDFStorage(RunDetailID, SortField) values(448, 'S1')
insert into MRDFStorage(RunDetailID, SortField) values(448, 'S1')
insert into MRDFStorage(RunDetailID, SortField) values(448, 'S1')
insert into BallotStyles(JobDetailID, Style) values(1, 'S1')
insert into BallotStyles(JobDetailID, Style) values(1, 'S1')The key factor here is the two rows in
BallotStyles. You are joining to
BallotStyles in the inner most query and with data like above you will get duplicate rows for each row in MRDFStorage. Since you are not using any of the columns in BallotStyles you are only checking for existence of rows and that can be done with a exists clause instead and that will of course not create the duplicate rows.UPDATE
[MRDFStorage]
SET
[Seq9] = [OrderedRecords].[NewSeq9]
FROM
(
SELECT
MRDFStorageID,
[Records].[SortField] + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY [Records].[SortField] ORDER BY [Records].[RunDetailID], [Records].[SortField], [Records].[PieceID]) AS VARCHAR), 4) NewSeq9
FROM
(
SELECT
M.[MRDFStorageID],
M.[RunDetailID],
M.[SortField],
M.[PieceID],
M.[BallotType]
FROM
[MRDFStorage] as M
-- Remove this join
-- JOIN [BallotStyles] ON M.[SortField] = [BallotStyles].[Style] and [BallotStyles].[JobDetailID] = @JobDetailID
WHERE
[RunDetailID] IN (SELECT [RunDetailID] FROM [RunDetails] WHERE [JobDetailID] = @JobDetailID) and
-- Add this exists check instead of the join
EXISTS (
SELECT *
FROM BallotStyles AS BS
WHERE M.SortField = BS.Style and
BS.JobDetailID = @JobDetailID
)
) Records
) OrderedRecords
JOIN MRDFStorage ON [OrderedRecords].[MRDFStorageID] = [MRDFStorage].[MRDFStorageID]
WHERE
[MRDFStorage].[RunDetailID] = @RunDetailIDCode Snippets
insert into RunDetails(RunDetailID, JobDetailID) values(448, 1)
insert into MRDFStorage(RunDetailID, SortField) values(448, 'S1')
insert into MRDFStorage(RunDetailID, SortField) values(448, 'S1')
insert into MRDFStorage(RunDetailID, SortField) values(448, 'S1')
insert into BallotStyles(JobDetailID, Style) values(1, 'S1')
insert into BallotStyles(JobDetailID, Style) values(1, 'S1')UPDATE
[MRDFStorage]
SET
[Seq9] = [OrderedRecords].[NewSeq9]
FROM
(
SELECT
MRDFStorageID,
[Records].[SortField] + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY [Records].[SortField] ORDER BY [Records].[RunDetailID], [Records].[SortField], [Records].[PieceID]) AS VARCHAR), 4) NewSeq9
FROM
(
SELECT
M.[MRDFStorageID],
M.[RunDetailID],
M.[SortField],
M.[PieceID],
M.[BallotType]
FROM
[MRDFStorage] as M
-- Remove this join
-- JOIN [BallotStyles] ON M.[SortField] = [BallotStyles].[Style] and [BallotStyles].[JobDetailID] = @JobDetailID
WHERE
[RunDetailID] IN (SELECT [RunDetailID] FROM [RunDetails] WHERE [JobDetailID] = @JobDetailID) and
-- Add this exists check instead of the join
EXISTS (
SELECT *
FROM BallotStyles AS BS
WHERE M.SortField = BS.Style and
BS.JobDetailID = @JobDetailID
)
) Records
) OrderedRecords
JOIN MRDFStorage ON [OrderedRecords].[MRDFStorageID] = [MRDFStorage].[MRDFStorageID]
WHERE
[MRDFStorage].[RunDetailID] = @RunDetailIDContext
StackExchange Database Administrators Q#94820, answer score: 4
Revisions (0)
No revisions yet.