【问题标题】:SQL- Insert into table only if the primary key value isn't already in the tableSQL-仅当主键值不在表中时才插入表中
【发布时间】:2016-04-08 01:33:39
【问题描述】:

如果我有一张桌子:

 Table A
 Column1(Primary Key) | Column2 | Column3

我如何确保在插入新行时,如果具有该主键的行已经存在,它不会插入新行?

我当前的 c# 代码和 SQL 命令:

string sqlConnectionString = ConfigurationManager.ConnectionStrings["blah"].ConnectionString;

string cmdString = "INSERT INTO TableA (Column1,Column2,Column3) VALUES (@val1, @val2, @val3)";

using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
    using (SqlCommand comm = new SqlCommand())
    {
        comm.Connection = conn;
        comm.CommandText = cmdString;
        comm.Parameters.AddWithValue("@val1", x);
        comm.Parameters.AddWithValue("@val2", y);
        try
        {
            conn.Open();
            comm.ExecuteNonQuery();
        }
        Catch(SqlException e)
        {
            // do something with the exception
            // don't hide it
        }
    }
}

由于 Column1 被指定为主要,这是否会自动处理?

编辑:

我在使用 WHERE 下面的 SQL 命令时遇到错误,有什么想法吗?

"INSERT INTO TableA (Column1,Column2) VALUES (@val1, @val2) WHERE 不存在(从 TableA 中选择 1,其中 Column1 = @val1)"

【问题讨论】:

  • 添加WHERE NOT EXISTS (SELECT 1 FROM TableA WHERE Column1 = @val1)
  • 为什么我们不能自动生成
  • 没有我可以使用的 UNIQUE/DISTINCT 标签吗?我必须在一个全新的查询上使用 WHERE NOT EXISTS 吗?
  • 您是否调查了使用 MERGE 指令而不是 INSERT 的解决方案?

标签: c# sql-server


【解决方案1】:

正如@tdelepine 建议的那样。您可以在命令中使用合并方法。这是一个简单的例子。对于您的使用,您只需要摆脱“When Matched Then”子句。我在存储过程中经常使用这种方法来进行添加或更新。

MERGE [dbo].[TableName] AS tar
USING (SELECT @Key As UserKey) AS src
ON (tar.[KeyColumn] = src.UserKey)
WHEN MATCHED THEN
    UPDATE SET [ValueColumn] = @Value
WHEN NOT MATCHED BY TARGET THEN
    INSERT ([KeyColumn], [ValueColumn])
    VALUES (@Key, @Value);

【讨论】:

    【解决方案2】:

    如果您使用存储过程但不是必需的,会更容易。

    如果主键已经存在但其他值都更新了,是否要更新其他列?

    MERGE TableA with (holdlock) AS target
        USING (SELECT @val1, @val2, @val3) AS source (value1, value2, value2)
        ON (target.Column1 = source.value1)
        WHEN MATCHED THEN 
            UPDATE SET
                Column2 = source.value2,
                Column3 = source.value3
    WHEN NOT MATCHED THEN
        INSERT (Column1, Column2, Column3)
        VALUES (source.value1, source.value2, source.value3);
    

    您可以在不合并的情况下执行此操作。当您的输入是表值参数或来自另一个表的 SELECT 时,这更有用。它允许您在单个操作中执行其中的一些操作。您还可以在插入时使用 OUTPUT INTO 子句来返回实际上是新的和插入的主键。

    【讨论】:

      【解决方案3】:

      无需事先检查。如果主键存在,则第二次插入将失败。只需捕获该错误条件,以便在尝试复制时采取任何有意义的操作。

      这是明智的,因为 (a) 它避免了竞争条件,并且 (b) 请求宽恕比许可更容易通常是一种好的编程理念(通常会导致代码更简洁)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-03
        • 2012-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多