Du kan undvika att ange en explicit ordning enligt följande:
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};
Observera dock att det bara är ett sätt att undvika att specificera en beställning och inte garanterar att eventuell originaldatabeställning kommer att bevaras. Det finns andra faktorer som kan göra att resultatet beställs, till exempel en ORDER BY
i den yttre frågan. För att helt förstå detta måste man inse att begreppet "inte beställt (på ett visst sätt)" inte är detsamma som att "behålla ursprunglig ordning" (som ÄR beställt på ett visst sätt!). Jag tror att ur ett rent relationsdatabasperspektiv finns inte det senare begreppet , per definition (även om det kan finnas databasimplementeringar som bryter mot detta, är SQL Server inte en av dem).
Anledningen till låstipsen är att förhindra fallet där någon annan process infogar med värdet du planerar att använda, mellan de delar av frågan som körs.
Obs:Många använder (SELECT NULL)
för att komma runt begränsningen "inga konstanter tillåtna i ORDER BY-satsen för en fönsterfunktion". Av någon anledning föredrar jag 1
över NULL
.
Dessutom:Jag tycker att en identitetskolumn är vida överlägsen och borde användas istället. Det är inte bra för samtidighet att uteslutande låsa hela bord. Underdrift.