【问题标题】:Is it possible to have one MySQL query and depending if a row exists choose INSERT or UPDATE?是否可以有一个 MySQL 查询并根据行是否存在选择 INSERT 或 UPDATE?
【发布时间】:2021-02-07 14:21:32
【问题描述】:

我正在处理一个项目,但目前遇到了一个问题。我有一个记录玩家访问数据的表。每个玩家都有自己唯一的 id 和他们访问过的地方的名称,包括访问日期和次数。

示例行: TestUser Server12 2020-10-25 12:00:00 25

现在速度是这个问题的一部分,因为我需要它相对快速,因为我正在对多达 70 名玩家进行比较。我认为批量查询会更可取,因为它会显着减少执行时间,但是,问题是如何检查特定对(user and server) 的表中是否存在该行,如果不插入新行,如果是,则使用访问计数增量后的当前日期值更新当前现有行(+1)

我知道INSERT ON DUPLICATE KEY,但这不起作用,因为它使用主键来查找行,并且我使用带有服务器名称的玩家唯一 ID。

所以我的问题是,是否有任何方法可以执行一个查询,如果该行不存在,它会执行插入操作,或者使用这两个指定的列更新现有行。

我之前的解决方案:

选择语句检查是否存在:

$"SELECT Count(*) FROM `visited` WHERE playerid='{playerID}' AND server_name='{serverName}'"

然后根据选择结果执行以下操作之一: 插入:

INSERT INTO visited (playerid, server_name, visit_count, last_visit_date) " +
                    $"VALUES ('{playerID}', '{v}', IFNULL(visit_count,0)+1, '{DateTime.Now:MM/dd/yyyy hh:mm:ss tt}')

更新:

UPDATE visited SET visit_count=IFNULL(visit_count,0)+1, last_visit_date='{DateTime.Now:MM/dd/yyyy hh:mm:ss}' WHERE playerid='{playerID}' AND server_name='{v}'

旧的解决方案真的很慢,特别是如果我按玩家要求做的话。

【问题讨论】:

  • 查看UPSERT。本质上是INSERTUPDATE 的组合。
  • 我会再次尝试替换,但是,INSERT ON DUPLICATE KEY 和 INSERT IGNORE 并不能解决问题。编辑:替换将无法正常工作,因为它需要一个主键。正如帖子中提到的,我的目标是使用一对唯一的 PlayerId 结合 ServerName。
  • “我知道 INSERT ON DUPLICATE KEY,但这不起作用,因为它使用主键来查找行,并且我使用带有服务器名称的玩家唯一 ID。” i> 您是否真的尝试过,或者您只是假设它只适用于主键?因为它适用于每个唯一键。所以试试看吧。
  • 嗯,我试过了,它使用了自增主键。据我所知,ON DUPLICATE KEY 没有 WHERE 子句,我可以在其中提供两对列作为比较

标签: c# mysql sql sql-update sql-insert


【解决方案1】:

在 MySQL 中,您可以使用 on duplicate key 语法。首先,您需要对列(playerid, server_name) 具有唯一(或主键)约束。如果它不存在,请创建它:

 alter table visited 
     add constraint ck_visited_uniq 
     unique (playerid, server_name)

那么,你可以这样做:

insert into visited (playerid, server_name, visit_count, last_visit_date)
values (?, ?, 1, now())
on duplicate key update 
    visit_count = coalesce(visit_count, 0) + 1, 
    last_visit_date = now()

注意事项:

  • 这使用绑定参数(由?s 表示)而不是连接查询字符串中的值

  • 您似乎想要last_visit_date 的当前日期/时间:如果是这样,则无需从您的应用程序中传递 if,您可以使用内置函数 now()

  • 我知道您想要一个初始的 visit_count1,然后每次提示都会递增

【讨论】:

    【解决方案2】:

    我使用这种方式,所以我不必总是在 Primary ID (key) 上中继

    if exists(select 1 from [{tablename}] where {Where_cmd} )
    BEGIN
     update {tablename} set {...} where {Where_cmd};
    END  
    ELSE 
     INSERT INTO {tablename} (...) Values(...);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-24
      • 2019-12-01
      • 2015-02-05
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多