2012-10-25 48 views
0

我有一組跟蹤訪問日誌的表。日誌包含有關用戶訪問的數據,包括用戶代理字符串。由於我們知道用戶代理字符串對於所有意圖和目的都是practically unlimited,因此需要將它們存儲爲文本/ Blob類型。鑑於重複程度高,我想將它們存儲在一個單獨的參考表中,並讓我的主訪問日誌表有一個鏈接到它的ID。事情是這樣的:更大的插入條件插入子查詢

accesslogs table: 
username|accesstime|ipaddr|useragentid 

useragents table: 
id|crc32|md5|useragent 
(the hashes are for indexing and quicker searching) 

這裏的漁獲,我是一個框架,它不給我訪問創建像外鍵花哨的東西里面工作。另外,這必須可以跨多個DBMS移植。我有聯繫邏輯解決選擇,但我很難找出如何正確插入。我想這樣做

INSERT INTO accesslogs (username, accesstime, ipaddr, useragentid) 
VALUES 
(
    :username, 
    :accesstime, 
    :ipaddr, 
    (
    CASE WHEN 
     (
     SELECT id 
     FROM useragents 
     WHERE 
      useragents.crc32 = :useragentcrc32 
      AND 
      useragents.md5 = :useragentmd5 
      AND useragents.useragent LIKE :useragent 
    ) IS NOT NULL 
    THEN 
     THAT_SAME_SELECT_FROM_ABOVE() 
    ELSE 
     GET_INSERT_ID_FROM(INSERT INTO useragents (crc32, md5, useragent) VALUES (:useragentcrc32, :useragentmd5, :useragent)) 
) 
) 

有沒有辦法做到這一點不使用pseudofunctions的名字我只是做了?我缺少的兩個部分是如何從上面獲取選擇以及如何從子查詢插入中獲取新ID。

回答

0

我不確定是否有跨平臺的方式來做到這一點。對於每個受支持的後端,您可能必須有很多特殊情況。例如,對於SQL Server,您將使用合併語句作爲解決方案的基礎。其他DBMS如果完全支持,則會有不同的名稱。搜索「Upsert」可能會有所幫助。

Edt - 將第二個查詢添加爲顯式,並添加參數。

-- SQL Server Example 
--Schema Defs 
Create Table Test (
    id int not null identity primary key, 
    UserAgent nvarchar(50) 
) 

Create Table WebLog (
    UserName nvarchar(50), 
    APAddress nvarchar(50), 
    UserAgentID int 
) 

Create Unique Index UQ_UserAgent On Test(UserAgent) 

-- Values parsed from log 
Declare 
    @UserName nvarchar(50) = N'Loz', 
    @IPAddress nvarchar(50) = N'1.1.1.1', 
    @UserAgent nvarchar(50) = 'Test' 
Declare @id int 

-- Optionally Begin Transaction 
-- Insert if necessary and get id 
Merge 
    Into dbo.Test as t 
Using 
    (Select @UserAgent as UserAgent) as s 
On 
    t.[UserAgent] = s.[UserAgent] 
When Matched Then 
    Update Set @id = t.id 
When Not Matched Then 
    Insert (UserAgent) Values (s.UserAgent); 

If @id Is Null Set @id = scope_identity() 

Insert Into WebLog (UserName, IPAddress, UserAgentID) Values (@UserName, @IPAddress, @id) 

-- Optionally Commit Transaction 
+0

我想你錯過了關於它是如何插入到主表中的部分。沒有合併/插入。如果該值在用戶代理表中,則沒有任何更改,我需要該值。如果它不在那裏,那麼它需要插入,並且我需要新ID的值。 – Dan

+0

你必須爲主表做一個單獨的插入,這只是給你使用的id。如果你需要他們是一個單一的工作單位,使用交易。 – Laurence

+0

「如果該值在用戶代理表中,則沒有任何更改,我需要該值,如果它不在那裏,那麼它需要插入,並且我需要新ID的值。」 - 這正是這樣做的結果在SQL服務器中,它幾乎是upsert的定義。 – Laurence

0

您需要對每個表執行單獨的插入操作。你不能同時插入兩者。

如果您在插入後使用MS SQL Server,則可以通過SCOPE_IDENTITY()獲取插入的ID,然後在另一個表插入中使用它。

+0

如果我不必是便攜式的,並且只寫MS,我會使用INSERT和OUTPUT,它會照顧整個事情。 – Dan