SQL检查记录是否存在

时间:2016-12-11 13:29:31

标签: sql razor exists

所以我花了一些时间来研究检查记录是否存在的最佳方法。结束了这一点。

var checkExistance = "SELECT TOP 1 exerVariName FROM exerciseVariants WHERE exerVariName = '" + exerVariName + "'";

然而,在我的页面上使用它时,我多次失败才能完成这项工作!

var exerVariName = Request.Form["exerVariName"];

var checkExistance = "SELECT TOP 1 exerVariName FROM exerciseVariants WHERE exerVariName = '" + exerVariName + "'";

if (IsPost && Validation.IsValid()) {
    if (ModelState.IsValid) {
        foreach (var c in db.Query(checkExistance)) {                    
            if (c.exerVariName != exerVariName) {
                var insertData = "INSERT INTO exerciseVariants (exerVariName, exerVariNameID) " + 
                "VALUES (@0, @1)";

                db.Execute(insertData, exerVariName, exerciseID); 
                Response.Redirect("~/insertexervariname");
            }
        }
    }
}

所以我放入SQL行的变量是一个请求表单的东西,所以它是一个用户输入,我想检查它是否存在于数据库中,如果它已经存在我不希望它被发布。以上就是我尝试使用foreach中的if ispost

如何实现这一目标? (c#razor / cshtml)

2 个答案:

答案 0 :(得分:0)

您的代码有竞争条件。

执行所需操作的最佳方法是让数据库使用唯一索引/约束来强制执行约束:

create unique index unq_exerciseVariants_exerVariName on exerciseVariants(exerVariName);

如果您想避免更新错误,那么您也可以在更新时进行检查:

INSERT INTO exerciseVariants (exerVariName, exerVariNameID)
      SELECT exerVariName, exerVariNameID
      FROM (SELECT @0 as exerVariName, @1 as exerVariNameID
           ) x
      WHERE NOT EXISTS (SELECT 1
                        FROM exerciseVariants
                        WHERE ev.exerVariName = x.exerVariName
                       );

请注意,如果两个不同的线程尝试同时插入相同的名称,则由于竞争条件,此检查可能不够。这就是为什么最好让数据库强制执行唯一性。

答案 1 :(得分:0)

我绝不是C#的人,但我确实看到了你当前代码的一个逻辑问题。目前,您的EXISTSINSERT查询是分开运行的,由几行.NET代码分隔,可能还有更多实际的机器指令。网络(没有双关语)的结果是,当存在检查显示为真但不再为真时,您最终可能会插入。为避免这种情况,存在检查应出现在WHERE的{​​{1}}子句中。这样的事情应该有效:

INSERT

现在INSERT INTO exerciseVariants (exerVariName, exerVariNameID) VALUES (@0, @1) WHERE EXISTS ( SELECT * exerVariName FROM exerciseVariants WHERE exerVariName = '" + exerVariName + "'"; ) 应该以原子方式发生,这意味着您的检查和实际插入都将同时完成,无论其他线程可能在做什么。