GETDATE() は一意ではありません。その正確さは、複数のほぼ同時のイベントを同時に提供できるほどのものです。
@@IDENTITY に干渉しないように、独自の ID 値を生成する必要がある場合は、次のことができます...
INSERT INTO
myTable (
id,
field1,
field2
)
SELECT
(SELECT ISNULL(MAX(id), 0) FROM myTable WITH(TABLOCKX)) + 1,
@p1,
@p2
これは、それ自体のトランザクション内で暗黙的に行われ、一意の値が保証されます。
編集
私の最初のコメントは、これは複数のレコードを挿入する場合には機能せず、代わりにソース レコードを個別に反復処理して一度に 1 つずつ挿入する必要があるというものでした。
ただし、次の例は、データのセットを処理するのに適している場合があります...
WITH
sorted_data AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY field1) AS set_id, -- DO NOT include a PARTITION here
*
FROM
inserted
)
INSERT INTO
myTable (
id,
field1,
field2
)
SELECT
(SELECT ISNULL(MAX(id), 0) FROM myTable WITH(TABLOCKX)) + set_id,
@p1,
@p2
FROM
sorted_data
これにより、各行に一意の ID が生成され、同じコードを使用する同時プロセスに対して安全になります。
編集
WITH(TABLOCKX)
更新中に他のプロセスがテーブルから読み取らないようにするために追加しました。これにより、並行プロセスが同じ MAX(id) を確立してから、新しいレコードに重複する ID を挿入しようとするのを防ぎます。
(単一のクエリ構造により、レコードが読み取られた後にレコードが変更されることは既に防止されていましたが、MAX(id) が読み取られてからすべての新しいレコードが挿入された「間」で、他のプロセスがテーブルから読み取りを行うことは防止されませんでした。)