在使用 ADO.NET 操作 SQL Server 時,開發者常透過 SCOPE_IDENTITY() 或 @@IDENTITY 取得剛插入資料的自增主鍵。然而有網友發現:無論新增幾次資料,回傳的 ID 永遠是 1,導致後續刪除、修改功能失效。經排查,問題核心在於資料存取層(DBHelper)的執行方法回傳值設計不當。
使用者在 Windows Forms 專案中,透過 TreeView 顯示商品分類,右鍵選單提供「新增商品」、「刪除商品」、「修改」功能。新增程式碼如下:
private void 添加商品ToolStripMenuItem_Click(object sender, EventArgs e) {
int id = DBHelper.cute("INSERT INTO Cards VALUES ('新商品') SELECT @@IDENTITY AS 'Identity'");
if (id <= 0) { MessageBox.Show("新增失敗。"); return; }
// 後續將 id 存入 TreeNode.Tag 供刪除/修改使用
var node = treeView1.Nodes[0].Nodes.Add("新品牌");
node.Tag = id;
// ...
}
刪除時從 treeView1.SelectedNode.Tag 取得 ID 執行 DELETE,但發現 Tag 值始終為 1,導致找不到對應記錄。
最佳回答一針見血指出:DBHelper.execute 回傳的是「影響行數」,而非 SELECT 的查詢結果。 程式碼中呼叫 DBHelper.cute(推測為 ExecuteScalar 封裝),若內部實際呼叫的是回傳影響行數的方法,則 INSERT 成功永遠回傳 1(影響 1 列),而非新生成的 Identity 值。
ExecuteScalar 才能取得單一值(如 SCOPE_IDENTITY()),ExecuteNonQuery 只回傳影響行數。SCOPE_IDENTITY() 而非 @@IDENTITY,避免觸發器導致取錯值。
string sql = "INSERT INTO Cards (CardsName) VALUES ('新商品'); SELECT CAST(SCOPE_IDENTITY() AS INT);";
int newId = (int)cmd.ExecuteScalar(); // 必須用 ExecuteScalar
使用者提到「再次除錯發現可以刪除了」,原因可能是:第一次執行時資料庫為空,Identity 從 1 開始;但程式邏輯錯誤導致 Tag 存成 1。第二次除錯時,資料庫已有資料,Identity 為 2、3…,但程式碼未改,Tag 仍會被存成 1(影響行數),只是恰好資料庫裡有 ID=1 的舊資料,刪除才「看似」成功。實際上仍是邏輯錯誤。
ExecuteScalar + SCOPE_IDENTITY()。GetScalar、ExecuteNonQuery、Query)。掌握這些細節,即可避免「ID 永遠是 1」這類低級卻隱蔽的 Bug,讓資料操作更穩健可靠。