รับตารางนี้:
CREATE TABLE dbo.Target (
TargetId int identity(1, 1) NOT NULL,
Color varchar(20) NOT NULL,
Action varchar(10) NOT NULL, -- of course this should be normalized
Code int NOT NULL,
CONSTRAINT PK_Target PRIMARY KEY CLUSTERED (TargetId)
);
ในสองสถานการณ์ที่แตกต่างกันเล็กน้อยฉันต้องการแทรกแถวและคืนค่าจากคอลัมน์ข้อมูลประจำตัว
สถานการณ์ 1
INSERT dbo.Target (Color, Action, Code)
OUTPUT inserted.TargetId
SELECT t.Color, t.Action, t.Code
FROM
(VALUES
('Blue', 'New', 1234),
('Blue', 'Cancel', 4567),
('Red', 'New', 5678)
) t (Color, Action, Code)
;
สถานการณ์ที่ 2
CREATE TABLE #Target (
Color varchar(20) NOT NULL,
Action varchar(10) NOT NULL,
Code int NOT NULL,
PRIMARY KEY CLUSTERED (Color, Action)
);
-- Bulk insert to the table the same three rows as above by any means
INSERT dbo.Target (Color, Action, Code)
OUTPUT inserted.TargetId
SELECT t.Color, t.Action, t.Code
FROM #Target
;
คำถาม
ฉันสามารถพึ่งพาค่าเอกลักษณ์ที่ส่งคืนจากการdbo.Target
แทรกตารางเพื่อส่งคืนตามลำดับที่มีอยู่ใน 1) VALUES
ส่วนคำสั่งและ 2) #Target
ตารางเพื่อให้ฉันสามารถเชื่อมโยงพวกเขาตามตำแหน่งของพวกเขาในชุดแถวเอาท์พุท
สำหรับการอ้างอิง
นี่คือโค้ด C # ที่ถูกลดขนาดบางส่วนที่แสดงให้เห็นถึงสิ่งที่เกิดขึ้นในแอปพลิเคชัน (สถานการณ์ที่ 1 ซึ่งเร็ว ๆ นี้จะถูกแปลงเป็นใช้SqlBulkCopy
):
public IReadOnlyCollection<Target> InsertTargets(IEnumerable<Target> targets) {
var targetList = targets.ToList();
const string insertSql = @"
INSERT dbo.Target (
CoreItemId,
TargetDateTimeUtc,
TargetTypeId,
)
OUTPUT
Inserted.TargetId
SELECT
input.CoreItemId,
input.TargetDateTimeUtc,
input.TargetTypeId,
FROM
(VALUES
{0}
) input (
CoreItemId,
TargetDateTimeUtc,
TargetTypeId
);";
var results = Connection.Query<DbTargetInsertResult>(
string.Format(
insertSql,
string.Join(
", ",
targetList
.Select(target => $@"({target.CoreItemId
}, '{target.TargetDateTimeUtc:yyyy-MM-ddTHH:mm:ss.fff
}', {(byte) target.TargetType
})";
)
)
)
.ToList();
return targetList
.Zip( // The correlation that relies on the order of the two inputs being the same
results,
(inputTarget, insertResult) => new Target(
insertResult.TargetId, // with the new TargetId to replace null.
inputTarget.TargetDateTimeUtc,
inputTarget.CoreItemId,
inputTarget.TargetType
)
)
.ToList()
.AsReadOnly();
}
MERGE
แต่ดูเหมือนว่าปลอดภัยและชัดเจนเพียงแค่ใช้