0

アクセスログを追跡する一連のテーブルがあります。ログには、ユーザーエージェント文字列を含むユーザーのアクセスに関するデータが含まれます。ユーザーエージェントの文字列は、すべての目的と目的で実質的に無制限であることがわかっているため、これらはテキスト/ブロブタイプとして保存する必要があります。重複度が高いため、これらを別の参照テーブルに保存し、メインのアクセスログテーブルに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))
  )
)

名前を作成したばかりの疑似関数を使用しない方法はありますか?私が見逃している2つの部分は、上記からselectを取得する方法と、サブクエリ挿入から新しいIDを取得する方法です。

4

2 に答える 2

0

各テーブルに個別に挿入する必要があります。同時に両方に挿入することはできません。

挿入後に MS SQL Server を使用する場合は、挿入された ID を SCOPE_IDENTITY() で取得し、それを別のテーブル挿入で使用できます。

于 2012-10-25T10:59:51.610 に答える
0

これを行うクロスプラットフォームの方法があるかどうかはわかりません。サポートされているバックエンドごとに、多くの特殊なケースが必要になる場合があります。たとえば、SQL Server の場合、ソリューションの基礎としてマージ ステートメントを使用します。他の DBMS は、サポートしている場合でも別の名前を持っています。「Upsert」を検索すると役立つ場合があります。

Edt - 2 番目のクエリを明示的に追加し、パラメーターを追加しました。

-- 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 に答える