如何在SQL CE中防止重复插入?附SqlCeCommand代码咨询
关于SQL CE实现防重复插入的问题解答
嘿,我来帮你梳理下这个问题~首先你的代码里有两个关键问题:
- 拼写错误:
ON DUBLICATE应该是ON DUPLICATE - 核心问题:SQL Compact Edition(SQL CE)并不支持MySQL的
ON DUPLICATE KEY UPDATE语法,所以这段代码执行时肯定会抛出语法错误,没法实现你想要的防重复插入+更新的需求。
下面给你几种SQL CE支持的正确实现方式,根据你的场景选就行:
方法1:使用MERGE语句(推荐,原子操作)
SQL CE 3.5及以上版本支持MERGE语法,这是原子性的操作,能避免并发情况下的冲突问题。假设你的fpl_table中FLIGHT_ID是主键或者唯一键(用来判断重复的依据),可以这么写:
// 构建MERGE语句,根据FLIGHT_ID判断是否重复 string sql = @"MERGE INTO fpl_table AS target USING (SELECT @FLIGHT_ID AS FLIGHT_ID, @BPN_TIME AS BPN_TIME, @BPX_TIME AS BPX_TIME, @DAY_NB AS DAY_NB) AS source ON target.FLIGHT_ID = source.FLIGHT_ID WHEN MATCHED THEN UPDATE SET BPN_TIME = source.BPN_TIME, BPX_TIME = source.BPX_TIME, DAY_NB = source.DAY_NB WHEN NOT MATCHED THEN INSERT (FLIGHT_ID, BPN_TIME, BPX_TIME, DAY_NB) VALUES (source.FLIGHT_ID, source.BPN_TIME, source.BPX_TIME, source.DAY_NB);"; SqlCeCommand command = new SqlCeCommand(sql, connection); command.Parameters.AddWithValue("@FLIGHT_ID", format); command.Parameters.AddWithValue("@BPN_TIME", format1); command.Parameters.AddWithValue("@BPX_TIME", format2); command.Parameters.AddWithValue("@DAY_NB", format3); // 执行命令 command.ExecuteNonQuery();
方法2:先判断存在性再执行更新/插入(适合老版本SQL CE)
如果你的SQL CE版本低于3.5,不支持MERGE,可以先查询是否存在对应记录,再决定执行UPDATE还是INSERT。注意这种方法在高并发场景下可能出现竞态条件,最好配合事务使用:
// 先检查是否存在记录 string checkSql = "SELECT COUNT(*) FROM fpl_table WHERE FLIGHT_ID = @FLIGHT_ID"; SqlCeCommand checkCmd = new SqlCeCommand(checkSql, connection); checkCmd.Parameters.AddWithValue("@FLIGHT_ID", format); int count = (int)checkCmd.ExecuteScalar(); SqlCeCommand command; if (count > 0) { // 存在则更新 string updateSql = @"UPDATE fpl_table SET BPN_TIME = @BPN_TIME, BPX_TIME = @BPX_TIME, DAY_NB = @DAY_NB WHERE FLIGHT_ID = @FLIGHT_ID"; command = new SqlCeCommand(updateSql, connection); } else { // 不存在则插入 string insertSql = @"INSERT INTO fpl_table (FLIGHT_ID, BPN_TIME, BPX_TIME, DAY_NB) VALUES (@FLIGHT_ID, @BPN_TIME, @BPX_TIME, @DAY_NB)"; command = new SqlCeCommand(insertSql, connection); } // 添加参数 command.Parameters.AddWithValue("@FLIGHT_ID", format); command.Parameters.AddWithValue("@BPN_TIME", format1); command.Parameters.AddWithValue("@BPX_TIME", format2); command.Parameters.AddWithValue("@DAY_NB", format3); // 执行命令 command.ExecuteNonQuery();
方法3:TRY/CATCH捕获主键冲突(简单场景可用)
还可以尝试直接执行INSERT,如果因为主键/唯一键冲突报错(错误码2627),就执行UPDATE:
string insertSql = @"INSERT INTO fpl_table (FLIGHT_ID, BPN_TIME, BPX_TIME, DAY_NB) VALUES (@FLIGHT_ID, @BPN_TIME, @BPX_TIME, @DAY_NB)"; string updateSql = @"UPDATE fpl_table SET BPN_TIME = @BPN_TIME, BPX_TIME = @BPX_TIME, DAY_NB = @DAY_NB WHERE FLIGHT_ID = @FLIGHT_ID"; SqlCeCommand command = new SqlCeCommand(insertSql, connection); command.Parameters.AddWithValue("@FLIGHT_ID", format); command.Parameters.AddWithValue("@BPN_TIME", format1); command.Parameters.AddWithValue("@BPX_TIME", format2); command.Parameters.AddWithValue("@DAY_NB", format3); try { command.ExecuteNonQuery(); } catch (SqlCeException ex) { // 捕获主键/唯一键冲突错误(错误码2627) if (ex.Errors.Cast<SqlCeError>().Any(e => e.NativeError == 2627)) { command.CommandText = updateSql; command.ExecuteNonQuery(); } else { // 其他错误重新抛出 throw; } }
内容的提问来源于stack exchange,提问作者Fazka
相关产品推荐
相关产品推荐

