【问题标题】:Add and update values in settings table在设置表中添加和更新值
【发布时间】:2018-04-13 14:37:15
【问题描述】:

我需要使用 ADO 在 SQL Server 的用户设置表中添加/更新一些值。值可能已经存在,如果存在则更新键的值,如果键不存在,则为用户添加它,在设置表中可能存在也可能根本不存在。

与数据库表匹配的我的用户设置模型:

public class UserSettingsModel
{
    public string UserId { get; set; }
    public string Key { get; set; }
    public string Value { get; set; }
}

我将如何获取现有设置:

public static List<UserSettingsModel> GetUserSettings(string userId)
{
    List<UserSettingsModel> settings = new List<UserSettingsModel>();

    using (SqlConnection c = ConnectVRS())
    {
        SqlCommand cmd = new SqlCommand(@"
                SELECT    SettingKey
                        , SettingValue
                FROM    UserSettings
                WHERE   UserId = @UserId
            ", c);

        cmd.Parameters.Add("@UserId", SqlDbType.VarChar).Value = userId;

        using (SqlDataReader dr = cmd.ExecuteReader())
        {
            while (dr.Read())
            {
                settings.Add(new UserSettingsModel()
                {
                    UserId = userId,
                    Key = dr[0].ToString(),
                    Value = dr[1].ToString()
                });
            }
        }
    }

    return settings;
}

现在,我需要添加和更新设置的方法。我可以遍历传入的值并对每个项目执行查询,但我似乎记得有更好的方法?可能能够将所有传入的值堆叠到一个查询中吗?在查询中检查并添加/更新?感谢所有帮助。


AddUpdate 的附加代码:

public static void AddUpdateUserSettings(List<UserSettingsModel> userSettings)
{
    DataService.LogAudit("", "Add/Update User Settings");

    using (SqlConnection c = ConnectVRS())
    {
        SqlCommand cmd = new SqlCommand(@"
            CREATE TABLE #TempSettings ( UserId VarChar(128), SettingKey VarChar(100), SettingValue Text );

            INSERT INTO #TempSettings ( UserId, SettingKey, SettingValue ) VALUES ('Connie', 'two', 'four')

            INSERT INTO UserSettings
            SELECT UserId, SettingKey, SettingValue FROM #TempSettings 
            WHERE SettingKey NOT IN(
                SELECT UserSettings.SettingKey FROM UserSettings
                    INNER JOIN #TempSettings ON UserSettings.UserId = #TempSettings.UserId)

            UPDATE s
                SET s.SettingValue = t.SettingValue
            FROM UserSettings s
                INNER JOIN #TempSettings t ON s.UserId = t.UserId AND s.SettingKey = t.SettingKey

            DROP TABLE #TempSettings
        ", c);

        cmd.ExecuteNonQuery();
    }
}

【问题讨论】:

标签: c# sql .net ado.net sql-server-2016


【解决方案1】:

您可以使用 MERGE 语句,但对于像这样的简单事情来说它是一种过度杀伤力。

您可以将所有值插入临时表#TempSetting

那你就可以了

INSERT INTO UserSettings
SELECT .... FROM #TempSettings 
WHERE SettingKey NOT IN(
SELECT UserSettings.SettingKey FROM UserSettings
INNER JOIN #TempSettings ON 
UserSettings.SettingKey = #TempSettings.SettingKey)


UPDATE UserSettings
SET UserSettings.SettingValue= #TempSettings.SettingValue FROM UserSettings
INNER JOIN #TempSettings ON 
UserSettings.SettingKey = #TempSettings.SettingKey

【讨论】:

  • 我不得不将 Inner Join 向下移动,因为它出现错误,但在 SSMS 中测试时查询效果很好。谢谢!现在,只是围绕我需要如何填充临时表。上面添加的临时代码。
  • @ConnieDeCinkoCS 您可以执行 n 次插入,也可以只执行 Values(id, key, val), (id2, key2, val2), (i3, key3, val3)。基本上将所有设置插入临时表,然后将其合并。由于临时表仅在当前会话/事务中可见,因此您不必担心竞争条件问题,也不必最终删除它(Sql server 会为您完成)
  • 遇到问题,因为 UserId 和 SettingKey 是复合主键。想我可能只需要在表中添加一个标识列,这样我就可以将它传递到我的 NOT IN 中。
  • @ConnieDeCinkoCS 只是在 ON 子句中进行过滤。如果你能提供完整的表格结构,我也许可以帮助你
猜你喜欢
  • 1970-01-01
  • 2017-07-18
  • 1970-01-01
  • 2013-05-20
  • 2016-02-17
  • 2013-12-09
  • 2017-08-30
  • 2015-11-14
  • 1970-01-01
相关资源
最近更新 更多