0

我有一组跟踪访问日志的表。日志包含有关用户访问的数据,包括用户代理字符串。由于我们知道用户代理字符串实际上是无限的,因此需要将它们存储为 text/blob 类型。鉴于高度重复,我想将它们存储在一个单独的参考表中,并让我的主访问日志表有一个链接到它的 id。像这样的东西:

accesslogs table:
username|accesstime|ipaddr|useragentid

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

这是一个问题,我正在一个框架内工作,该框架不允许我创建像外键这样的花哨的东西。此外,这必须可跨多个 DBMS 移植。我已经为执行 SELECTS 制定了连接逻辑,但我无法弄清楚如何正确插入。我想做类似的事情

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))
  )
)

有什么方法可以不使用我刚刚编的名字的伪函数吗?我缺少的两部分是如何从上面获取选择以及如何从子查询插入中获取新 id。

4

2 回答 2

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
于 2012-10-25T10:45:32.697 回答
0

您将需要对每个表进行单独的插入。您不能同时插入两者。

如果您在插入后使用 MS SQL Server,您可以通过 SCOPE_IDENTITY() 获取插入的 id,然后在另一个表插入中使用它。

于 2012-10-25T10:59:51.610 回答