我有一组跟踪访问日志的表。日志包含有关用户访问的数据,包括用户代理字符串。由于我们知道用户代理字符串,无论出于所有意图和目的,practically unlimited,这些都需要存储为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。
答案 0 :(得分:0)
我不确定是否有跨平台的方式来做到这一点。对于每个受支持的后端,您可能必须拥有许多特殊情况。例如,对于SQL Server,您将使用merge语句作为解决方案的基础。其他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
答案 1 :(得分:0)
您需要对每个表执行单独的插入操作。你不能同时插入两者。
如果在插入后使用MS SQL Server,则可以通过SCOPE_IDENTITY()获取插入的id,然后在另一个表插入中使用它。