2

是否可以使用以下约束执行插入或更新:

  1. 项目中使用了Dapper
  2. 主键是自动递增正数
  3. 新插入的数据可能没有PK 值(或值为0
  4. 数据需要在新插入的行上有 PK 值。
  5. 查询是按程序生成的,最好对其进行概括

就像是 :

int newId = db.QueryValue<int>( <<insert or update>>, someData );

我已经阅读了不同的解决方案,最好的解决方案似乎是这个

merge tablename as target
using (values ('new value', 'different value'))
    as source (field1, field2)
    on target.idfield = 7
when matched then
    update
    set field1 = source.field1,
        field2 = source.field2,
        ...
when not matched then
    insert ( idfield, field1, field2, ... )
    values ( 7,  source.field1, source.field2, ... )

  1. 它似乎在第三个约束上失败了
  2. 它不保证返回新生成的 id。

由于第五个约束(或偏好),存储过程似乎过于复杂。

有哪些可能的解决方案?谢谢!

4

1 回答 1

3

如果您的表具有自动增量字段,则在插入记录时无法为该字段分配值。好的,你可以,但这通常是个坏主意:)

使用 T-SQLMERGE语句,您可以将所有值放入源表中,包括默认的无效标识值,然后将插入子句编写为:

when not matched then
    insert (field1, field2, ...)
    values (source.field1, source.field2, ...)

: 并使用输出子句获取插入的标识值:

OUTPUT inserted.idfield

也就是说,我认为您可能会使 SQL 代码生成稍微复杂化,尤其是对于具有大量字段的表。UPDATE生成 distinct和查询通常会更好INSERT……尤其是如果您有某种方法可以跟踪对象的更改,以便您只能更新更改的字段。

假设您正在使用 MS SQL,您可以SCOPE_IDENTITY()在语句之后使用函数INSERT来获取复合语句中记录的标识字段的值:

INSERT INTO tablename(field1, field2, ...)
VALUES('field1value', 'field2value', ...);
SELECT CAST(SCOPE_IDENTITY() AS INT) ident;

当您执行此 SQL 语句时,您将在单个列中返回一个带有插入标识的结果集。然后,您的db.QueryValue<int>调用将返回您所追求的值。

对于标准整数自动增量字段,上述内容很好。对于其他字段类型,或更一般的情况,尝试将SCOPE_IDENTITY()结果转换为VARCHAR(MAX)并将结果字符串值解析为您的身份列期望的任何类型 - GUID 等。

在一般情况下,在你的db课堂上试试这个:

public string InsertWithID(string insertQuery, params object[] parms)
{
    string query = insertQuery + "\nSELECT CAST(SCOPE_IDENTITY() AS VARCHAR(MAX)) ident;\n";
    return this.QueryValue<string>(insertQuery, parms);
}

和/或:

public int InsertWithIntID(string insertQuery, params object[] parms)
{
    string query = insertQuery + "\nSELECT CAST(SCOPE_IDENTITY() AS INT) ident;\n";
    return this.QueryValue<int>(query, parms);
}

这样,您只需准备插入查询并调用适当的InsertWithID方法来获取结果标识值。这应该能满足你的第五个约束条件:)

于 2013-04-05T06:03:18.157 回答