如果我有桌子:
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被指定为主?
编辑:
我在下面的SQL命令中遇到错误,有什么想法?
“INSERT INTO TableA(Column1,Column2)VALUES(@ val1,@ val2)WHERE NOT EXISTS(从TableA中选择1,其中Column1 = @ val1)“
答案 0 :(得分:0)
正如@tdelepine建议的那样。您可以在命令中使用merge方法。这是一个简单的例子。对于您的使用,您只需要摆脱“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);
答案 1 :(得分:0)
无需事先检查。如果存在主键,则第二个插入将失败。只需捕获该错误条件,以便在尝试复制时采取任何有意义的操作。
这是明智的,因为(a)它避免了竞争条件,(b)它更容易要求宽恕而不是许可通常是一种很好的编程理念(通常会导致更清晰的代码)。
答案 2 :(得分:0)
如果您使用存储过程但不是必需的话,这会更容易。
如果主键已存在但其他值已更新,是否要更新其他列?
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子句以返回实际为新插入的主键。