2008-12-08 74 views
1

在我的數據庫模式中,我有一個標識的實體。該標識符可以重新使用,因此與實體存在一對多關係。例如:一個人可以有一個暱稱。暱稱不是唯一的,可以在很多人中共享。因此,該模式可能類似於:在與另一個表有關係的表中插入行

PERSON 
id 
name 
nickname_id 

NICKNAME 
id 
name 

的問題是,插入一個新的人的時候,我得先查詢NICKNAME,看是否存在綽號。如果沒有,那麼我必須在NICKNAME中創建一行。插入許多人時,這可能會很慢,因爲每個人插入都會導致對NICKNAME的查詢。

我可以通過首先查詢所有暱稱的暱稱來優化大插入。 JPA查詢語言:

SELECT n FROM NICKNAME n WHERE name in ('Krusty', 'Doppy', 'Flash', etc) 

然後根據需要創建新的暱稱,然後在人員上設置nickname_id。

這使軟件變得複雜一點,因爲它必須臨時將暱稱存儲在內存中。此外,有些數據庫對IN子句的參數有限制(SQL Server是2100左右),因此我執行了多個查詢。

我很好奇這個問題是如何處理的。更具體地說,當一個數據庫被標準化並且一個實體與另一個實體有關係時,插入一個新的實體基本上導致必須檢查另一個實體。對於大型插入,除非將操作提升到代碼域,否則這可能會很慢。有沒有辦法自動插入相關的表格行?

僅供參考我使用Hibernate的JPA實現的

+0

SELECT n FROM中的'n'不正確;你可能是指身份證。 – 2008-12-08 20:29:04

回答

1

我不知道如果一個ORM可以處理這個問題,但在直接的SQL你可以:

  1. 創建名稱/暱稱對的表,
  2. INSERT INTO暱稱表選擇暱稱FROM temp WHERE暱稱NOT IN(選擇暱稱FROM暱稱表)
  3. 插入主表知道暱稱存在。

在你的例子中,除非一個人可以有多個暱稱,否則你可以擁有一個可用的暱稱列。

+0

這當然是我如何處理這個,除了我會使用左連接而不是在聲明中,因爲他們傾向於更好地執行(至少在SQL Server中)。 – HLGEM 2008-12-08 20:42:12

0

確實?我會在Person表中使暱稱成爲varchar列,並忘記暱稱表。暱稱是一個人的屬性,而不是一個單獨的實體。

這是一個簡單的例子,你的'標識符'真的受益於實體關係嗎?

編輯:好吧,明白這只是一個人爲的例子。這個問題很好,因爲它經常出現。

標準SQL支持一種帶有可選「...ON DUPLICATE KEY UPDATE...」子句的INSERT語句形式。對這種語法的支持因數據庫品牌而異。如果您將一個UNIQUE約束添加到暱稱表中的標識名稱中,則重複條目將調用子句的UPDATE部分(您可以執行虛擬更新,而不是更改任何內容)。

CREATE TABLE Nickname (
    id SERIAL PRIMARY KEY, 
    name VARCHAR(20) UNIQUE 
); 

INSERT INTO Nickname (name) VALUES ("Bill") 
    ON DUPLICATE KEY UPDATE name = name; 
+0

我的人稱暱稱架構只是一個例子。我的問題是如何插入大量與另一個實體(表)有關係的數據。 – 2008-12-08 20:09:11

0
INSERT INTO Person(Name, NicknameID) 
    VALUES(:name, (SELECT id FROM Nickname WHERE Name = :nickname)) 

如果INSERT失敗,因爲該暱稱不存在,然後將暱稱,然後那個人紀錄。

我假設:name和:nickname標識包含用戶名和暱稱的主機變量 - 並且該person.id列將從SQL中省略時自動分配一個值。適應你的情況。

如果您認爲大多數暱稱實際上都是唯一的,您可以簡單地嘗試無條件地插入暱稱,但忽略如果暱稱已存在則發生的錯誤。

0

另外,也許'MERGE'的聲明可以幫助?它提供了插入新值或更新existng值的選項。語法和suport因DB而異,但可能比'ON DUPLICATE'選項更常見。

相關問題