U kunt het specificeren van een expliciete volgorde als volgt vermijden:
INSERT dbo.TargetTable (ID, FIELD)
SELECT
Row_Number() OVER (ORDER BY (SELECT 1))
+ Coalesce(
(SELECT Max(ID) FROM dbo.TargetTable WITH (TABLOCKX, HOLDLOCK)),
0
),
FieldValue
FROM dbo.SourceTable
WHERE {somecondition};
Houd er echter rekening mee dat dit slechts een manier is om te voorkomen dat u een bestelling opgeeft en niet garandeert dat elke originele bestelling van gegevens behouden blijft. Er zijn andere factoren die ervoor kunnen zorgen dat het resultaat wordt geordend, zoals een ORDER BY
in de buitenste vraag. Om dit volledig te begrijpen, moet men zich realiseren dat het concept "niet besteld (op een bepaalde manier)" niet hetzelfde is als "de oorspronkelijke volgorde behouden" (wat op een bepaalde manier IS besteld!). Ik geloof dat vanuit een puur relationeel databaseperspectief het laatste concept niet bestaat , per definitie (hoewel er database-implementaties kunnen zijn die dit schenden, is SQL Server daar niet een van).
De reden voor de vergrendelingshints is om te voorkomen dat een ander proces de waarde die u van plan bent te gebruiken tussen de delen van de uitgevoerde query invoegt.
Opmerking:veel mensen gebruiken (SELECT NULL)
om de beperking "geen constanten toegestaan in de ORDER BY-clausule van een vensterfunctie" te omzeilen. Om de een of andere reden geef ik de voorkeur aan 1
meer dan NULL
.
Ook:ik denk dat een identiteitskolom veel beter is en in plaats daarvan moet worden gebruikt. Het is niet goed voor gelijktijdigheid om uitsluitend hele tabellen te vergrendelen. Understatement.