【问题标题】:SQL CE statement to update or insert assets in ASP.Net用于在 ASP.Net 中更新或插入资产的 SQL CE 语句
【发布时间】:2015-01-22 17:43:28
【问题描述】:

我正在创建一个 Web 表单以将信息插入数据库。设置此设置以插入键入的信息没有问题,但是如果数据库中已存在该条目,则尝试将命令重新格式化为 UPDATE 信息时遇到了麻烦。

我在尝试提交更改时收到以下错误:

解析查询时出错。 [Token line number = 1,Token line offset = 7,Token in error = Assets]

说明:在执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详细信息:System.Data.SqlServerCe.SqlCeException:解析查询时出错。 [Token line number = 1,Token line offset = 7,Token in error = Assets]

来源错误:

第 39 行:插入(AssetNumber、SerialNumber、AssetType、Model、Location、DateModified、Comments), 第 40 行:值(@0、@1、@2、@3、@4、@5、@6)“; 第 41 行:db.Execute(insertCommand,assetNumber,serialNumber,assetType,model,toCube,currentTime,cmets); 第 42 行:Response.Redirect("~/AssetLookup"); 第 43 行:}

代码错误出现在第 41 行。我在下面的代码中唯一更改的是 SQL 语句,所以我确信其中有问题。这是我第一次尝试使用 SQL;我做了一些挖掘,试图找出该语句有什么问题,但特别是我在使用 USING ... ON 部分时遇到了问题。我不太确定应该去那里,我觉得这可能是问题所在。

var assetNumber = "";
var serialNumber = "";
var assetType = "";
var model = "";
var toCube = "";
var comments = "";

if(IsPost && Validation.IsValid()){
    assetNumber = Request.Form["assetNumber"];
    serialNumber = Request.Form["serialNumber"];
    assetType = Request.Form["assetType"];
    model = Request.Form["model"];
    toCube = Request.Form["toCube"];
    var currentTime = DateTime.Now;
    comments = Request.Form["comments"];

    var db = Database.Open("Assets");
    var insertCommand = 
    @"MERGE Assets AS Target 
      USING (SELECT assetNumber, serialNumber FROM Assets) AS Source
      ON (Target.assetNumber = Source.assetNumber AND Target.serialNumber = Source.serialNumber)
        WHEN MATCHED THEN 
            UPDATE SET
                AssetNumber=@0,
                SerialNumber=@1,
                AssetType=@2,
                Model=@3,
                Location=@4,
                DateModified=@5,
                Comments=@6                                      
        WHEN NOT MATCHED THEN 
            INSERT (AssetNumber, SerialNumber, AssetType, Model, Location, DateModified, Comments), 
            VALUES (@0, @1, @2, @3, @4, @5, @6)";
    db.Execute(insertCommand, assetNumber, serialNumber, assetType, model, toCube, currentTime, comments);
    Response.Redirect("~/AssetLookup");
}

就像我说的,我确信我的 SQL 语句在某处搞砸了,因为我“有点”理解它,但在 USING...ON 部分特别困惑。根据代码/数据库的其余部分正确设置所有表列和变量名称。有人可以就我应该用于此命令的语法提供一些建议吗?

更新:

根据史蒂夫的评论,我更新了问题以反映这是 SQL CE 而不是标准版本。

【问题讨论】:

  • UPDATEs 通常有一个WHERE 子句-但是我不熟悉MATCHED 语言,但是没有WHERE 的普通UPDATE 会更新每一行。
  • Sql Server 精简版不支持 MERGE stackoverflow.com/questions/14091092/…
  • @Steve 我什至没有想过要检查类似的东西。谢谢你为我省去了很多麻烦!明天我会尝试制定一个重新格式化的版本,省略 MERGE。
  • 很高兴能提供帮助。 Here a full specs comparison
  • 感谢@DourHighArch,重新提交我的更新作为问题的答案。

标签: c# sql asp.net razor


【解决方案1】:

以一种非常基本的方式,我通过将一些 C# if/else 逻辑(因为 SQL CE 也不支持)与基本 SQL 语句混合来实现此功能。

此代码检查表单提交的资产和序列号是否匹配,并在找到匹配项时更新。如果没有返回记录,则将资产添加到数据库中:

var db = Database.Open("Assets");
var query = "SELECT * FROM Assets WHERE AssetNumber = @0 AND SerialNumber = @1";
var record = db.QuerySingle(query, assetNumber, serialNumber);

if (record != null) {
    var updateCommand = 
    @"UPDATE Assets SET
        AssetNumber=@0,
        SerialNumber=@1,
        AssetType=@2,
        Model=@3,
        Location=@4,
        DateModified=@5,
        Comments=@6                                      
    WHERE AssetNumber=@0 AND SerialNumber=@1";
    db.Execute(updateCommand, assetNumber, serialNumber, assetType, model, toCube, currentTime, comments);
} else {
    var insertCommand = 
    @"INSERT INTO Assets (AssetNumber, SerialNumber, AssetType, Model, Location, DateModified, Comments) 
    VALUES (@0, @1, @2, @3, @4, @5, @6)";
    db.Execute(insertCommand, assetNumber, serialNumber, assetType, model, toCube, currentTime, comments);
}

此代码嵌套在前面代码块中列出的if(IsPost...) 方法中,并替换了之前的 SQL 语句。仍然需要做一些工作来进行额外的检查,但基本逻辑完全符合我的要求。

感谢@Steve 为我指明了正确的方向!

【讨论】:

    【解决方案2】:

    看起来您没有任何东西将您的目标绑定到您的源。您正在使用 ON 子句有效地将目标表与其自身进行比较。

    不妨试试这样的:

    var assetNumber = "";
    var serialNumber = "";
    var assetType = "";
    var model = "";
    var toCube = "";
    var comments = "";
    
    if(IsPost && Validation.IsValid()){
        assetNumber = Request.Form["assetNumber"];
        serialNumber = Request.Form["serialNumber"];
        assetType = Request.Form["assetType"];
        model = Request.Form["model"];
        toCube = Request.Form["toCube"];
        var currentTime = DateTime.Now;
        comments = Request.Form["comments"];
    
        var db = Database.Open("Assets");
        var insertCommand = 
        @"MERGE Assets AS Target 
          USING (SELECT @0 as assetNumber, @1 as serialNumber) AS Source
          ON (Target.assetNumber = Source.assetNumber AND Target.serialNumber = Source.serialNumber)
            WHEN MATCHED THEN 
                UPDATE SET
                    AssetNumber=@0,
                    SerialNumber=@1,
                    AssetType=@2,
                    Model=@3,
                    Location=@4,
                    DateModified=@5,
                    Comments=@6                                      
            WHEN NOT MATCHED THEN 
                INSERT (AssetNumber, SerialNumber, AssetType, Model, Location, DateModified, Comments), 
                VALUES (@0, @1, @2, @3, @4, @5, @6)";
        db.Execute(insertCommand, assetNumber, serialNumber, assetType, model, toCube, currentTime, comments);
        Response.Redirect("~/AssetLookup");
    }
    

    我对这个不是 100%,因为我不太熟悉 Razor 或通过代码运行查询(我通常坚持存储过程),但听起来你想比较传入的资产和序列号到实际在表中,而您之前拥有的不会那样做。

    【讨论】:

    • 如果这是 Sql Server,这将是正确的,但从堆栈跟踪异常来看,很明显 Sql Server Compact Edition 不支持 MERGE。
    • 即使这对 CE 不起作用(我的错,不知道这是一个问题!)首先知道我的 MERGE 语句有什么问题是非常有帮助的。谢谢!
    猜你喜欢
    • 2011-04-14
    • 1970-01-01
    • 2022-12-21
    • 2016-03-25
    • 2017-06-24
    • 2016-01-03
    • 1970-01-01
    • 2012-08-05
    • 2022-12-03
    相关资源
    最近更新 更多