使用 UPDATE 或 INSERT INTO 时自动递增 Firebird 字段值

问题描述 投票:0回答:2

我已经成为一名 Delphi 程序员 25 年了,但直到现在才设法避免使用 SQL。那时我是 dBase 专家。我在 Windows Server 2012 机器上使用 Firebird 3.0 SuperServer 作为服务。我运行一个用 Delphi 2007 编写的 UDP 侦听器服务,以从我们发布的软件产品接收状态信息。

FB 数据库相当简单。我使用用户的 IP 地址作为主键并记录传入的报告。目前我每天收到大约 150,000 份报告,并且它们记录在文本文件中。

我不想将每个报告插入表中,而是希望使用从每个 IP 地址收到的报告的“运行总计”来增加单个记录中的整数值。它将节省大量数据。

该表包含 IP 地址(主键)、LastSeen(时间戳)和 Hits(整数)字段。还有一些其他字段,但它们并不重要。

收到报告后我使用更新或插入。如果 IP 地址不存在,则插入新行。如果确实存在,则更新记录。

我希望每次收到报告时它都会将“点击数”字段增加 +1。换句话说,如果“Hits”已经 = 1,那么我想将 UPDATE 上的 inc(Hits) 增加到 2。依此类推。基本上,“点击数”字段是 IP 地址发送报告的总次数。

每月添加 300 万行只是为了获得特定 IP 地址的 COUNT 似乎根本没有效率!

有办法做到这一点吗?

sql firebird
2个回答
0
投票

UPDATE OR INSERT
语句不适合这种情况,因为您需要指定要更新或插入的值,因此最终插入和更新都会得到相同的值。您可以通过创建一个
before insert
触发器来解决此问题,该触发器始终将
1
分配给保存计数的字段(忽略插入语句提供的值),但最好使用
MERGE
,因为它可以让您更好地控制结果操作。

例如:

merge into user_stats
  using (
    select '127.0.0.1' as ipaddress, timestamp '2021-05-30 17:38' as lastseen 
    from rdb$database
  ) as src
  on user_stats.ipaddress = src.ipaddress
when matched then 
  update set 
    user_stats.hits = user_stats.hits + 1, 
    user_stats.lastseen = max_value(user_stats.lastseen , src.lastseen)
when not matched then
  insert (ipaddress, hits, lastseen) values (src.ipaddress, 1, src.lastseen)

但是,如果您获得同一 IP 地址的大量更新,并且这些更新是同时处理的,则由于更新冲突,这可能很容易出错。您可以通过插入单个点击来解决此问题,然后使用后台进程将这些记录汇总为单个记录(例如每日)。

另请记住,只有一条记录就无法执行更多分析(例如,点击量的分布、X 天或某个时间 HH:mm 的点击数等)。


0
投票

设置@item := 0;

更新项目集 descricao_item = @item := (@item+1);

更改表项 AUTO_INCRMENT = 1;

© www.soinside.com 2019 - 2024. All rights reserved.