HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

Why is my SQL Server query behaving differently on UPDATE than on SELECT?

Submitted by: @import:stackexchange-dba··
0
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:

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] = @RunDetailID


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

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:

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] = @RunDetailID

Code 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] = @RunDetailID

Context

StackExchange Database Administrators Q#94820, answer score: 4

Revisions (0)

No revisions yet.