2016-03-29 29 views
4

我有一個數據庫中存儲項目的表。每個項目都有一個唯一的ID,DB在插入時自動生成(自動遞增)。
用戶可能執行將X項添加到數據庫的特定任務,但是我的程序(使用MySQL連接器的C++服務器應用程序)應該立即返回數據庫生成的ID。例如,如果我添加6個項目,則服務器必須向客戶端返回6個新的唯一ID。
什麼是做這種事最快/最乾淨的方式?到目前爲止,我一直在做INSERT,其次是SELECT,對於每個新項目或INSERT,然後是last_insert_id,但是如果有50個項目要添加,則至少需要幾秒鐘,這對用戶體驗來說是不好的。最快的方法來選擇幾個插入的行

sql_task.query("INSERT INTO `ItemDB` (`ItemName`, `Type`, `Time`) VALUES ('%s', '%d', '%d')", strName.c_str(), uiType, uiTime); 

獲取ID:

uint64_t item_id { sql_task.last_id() }; //This calls mysql_insert_id 
+0

請加一些代碼請 –

+0

好吧,我加了一些代碼。這一切都很好,但一點都不快。 – Spook

回答

-1

正如你ID是自動增加的,你可以做只有兩個SELECT查詢 - 前後INSERT查詢:

SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name = 'dbTable' AND table_schema = DATABASE(); 
-- 
-- INSERT INTO dbTable... (one or many, does not matter); 
-- 
SELECT LAST_INSERT_ID() AS lastID; 

這會給你的在第一個和最後一個插入的ID之間插入序列。然後你可以很容易地計算出它們的數量。

+0

這並不容易。併發會話也可以增加插入ID。當然,MySQL的多主集羣不會增加1. – rkosegi

+0

我同意rkosegi,因爲我也擔心這一點。如果我有一個外部工具可以將項目添加到同一個表中,並且我碰巧在同一時間添加項目,則客戶端可能會獲得一些不同的ID。 – Spook

+0

@rkosegi一般是的,你是對的,但它取決於。由於InnoDB在插入過程中執行鎖定,所以其他插入必須等待插入才能完成事務(如果存在這種情況)。一切都取決於實施。 – mitkosoft

1

我相信你需要稍微反思一下你的設計。讓我們用一個銷售訂單的類比。通過銷售訂單(或發票#),用戶可以獲得發票編號(auto_incr)以及多個行項目編號(也包括auto_inc)。

選擇銷售訂單和所有行項目(從GUI)插入並執行插入。首先,插入銷售訂單行並將其ID保存在變量中,以便後續調用插入行項目。但是訂單項只是插入而不立即返回其auto_inc標識值。應用程序最終只返回銷售訂單號。您的應用如何在隨後的通話中使用該銷售訂單號碼取決於您。但它不需要馬上立即檢索所有X或50行,因爲它具有銷售訂單號碼並保存在某個地方。我們稱之爲銷售訂單號XYZ。

當你真正需要的信息,一個例子通話可能看起來像

select lineItemId 
from lineItems 
where salesOrderNumber=XYZ 
order by lineItemId 

你需要記住的是,在一個多用戶系統中沒有接收號碼的連續塊的保證。這對您也不重要,因爲它們都附有正確的銷售訂單編號。

同樣,以上只是一個類比,用於說明目的。

+0

這個比喻很棒,謝謝!其實,這甚至不是我的設計,因爲我試圖重現服務器的行爲,但這部分是令人困惑的。用戶可以一次購買幾件商品,服務器將它們添加到數據庫中,然後爲每件商品返回一個唯一的ID給客戶。他們做得非常快,所以我想知道是否有我錯過的東西。 – Spook

0

這是一個常見但難以解決的問題。不確定的MySQL,但PostreSQL使用序列生成自動ID。插入框架(對象關係映射器)在他們期望插入許多值時使用它們:他們直接查詢一系列ID的序列,然後使用那些已知的ID插入新行。這樣,每次插入後都不需要額外的查詢來獲取ID。

不利的一面是,當不同的編寫者混合插入時,關係ID插入時間可能不是單調的。這對數據庫來說不是問題,但有些(寫得不好的)程序可以預期它是。

相關問題