如何自动拼接 Update语句,仅Update已修改的字段
来源:互联网 发布:ubuntu卸载nvidia驱动 编辑:程序博客网 时间:2024/06/10 23:50
我们通常使用update语句更新数据库记录,例如使用update user set username='001', nickname='Tom', age=18 where id = 1语句更新username、nickname或age字段的值。假设,我们只修改了username,并没有修改nickname和age,那么上面的sql就显得多余了,改成update user set username='001' where id = 1才算完美,即哪些字段发生了变化就更新哪些字段。
此外,SQL Server数据库中有触发器,可监控到字段值的变更,例如在表user上创建触发器
create trigger [dbo].[tr_user_update]on [dbo].[user]Afterupdateasdeclare @id int;select @id = id from inserted;if update(nickname) begin--some codeend;
如果使用update user set username='001', nickname='Tom', age=18 where id = 1语句,即便nickname和age的值与数据库中完全一样,也会触发 some code,但这并不是我们期望的。
所以执行update更新前,有必要检查哪些字段需发生了修改,尤其是需要记录表变更历史的情形。
本例中,笔者使用System.Reflection.PropertyInfo和DataRow检查发生更新的字段,并拼接要更新的Update SQL语句。
首先,按照表user创建User.cs类
class User{ // 参照用户表User的字段定义属性 // 不包括系统字段 // 仅包括用户会修改的字段 // 属性名必须和字段名一致 public string UserName { get; set; } public string NickName { get; set; } public string Password { get; set; } public string Email { get; set; } public string Phone { get; set; } public int Age { get; set; }}
其次,创建赋值函数InitEntity(DataRow, Obj)
public static Obj InitEntity<Obj>(System.Data.DataRow row, Obj entity) where Obj : new(){ if (entity == null) entity = new Obj(); // 取得entity的类型 Type type = typeof(Obj); // 取得entity的属性 System.Reflection.PropertyInfo[] props = type.GetProperties(); // 遍历entity属性集合,按照属性类型给其赋值。通过entity属性名从row中取得对应的值。 foreach (System.Reflection.PropertyInfo prop in props) { if (prop.PropertyType.FullName.Equals("System.Int32")) { prop.SetValue(entity , Convert.ChangeType(MyFuncLib.dtv(row, prop.Name, "0") , prop.PropertyType), null); } else if (prop.PropertyType.FullName.Equals("System.Decimal")) { prop.SetValue(entity , Convert.ChangeType(MyFuncLib.dtv(row, prop.Name, "0") , prop.PropertyType), null); } else if (prop.PropertyType.FullName.Equals("System.Double")) { prop.SetValue(entity , Convert.ChangeType(MyFuncLib.dtv(row, prop.Name, "0") , prop.PropertyType), null); } else if (prop.PropertyType.FullName.Equals("System.Boolean")) { prop.SetValue(entity , Convert.ChangeType(MyFuncLib.dtv(row, prop.Name, "false") , prop.PropertyType), null); } else if (prop.PropertyType.FullName.Equals("System.DateTime")) { if (MyFuncLib.dtv(row, prop.Name, null) != null) { prop.SetValue(entity , Convert.ChangeType(MyFuncLib.dtv(row, prop.Name, null) , prop.PropertyType), null); } } else { prop.SetValue(entity , MyFuncLib.dtv(row, prop.Name, string.Empty), null); } } return entity;}显示用户数据时,将数据保存在一个DataTable dt中
private void Form1_Load(object sender, EventArgs e){ // 初始化表时,读取数据 SqlConnection conn = new SqlConnection(); conn.ConnectionString = ""; conn.Open(); SqlDataAdapter adapter = new SqlDataAdapter(); adapter.SelectCommand.CommandText = "select * from user where id = 1"; adapter.Fill(dt); adapter = null; conn.Close();}
修改数据后,将变更存入dt的第一条记录newRow中。保存数据前从数据库中读取记录存入oldRow,然后比较oldRow和newRow差异,遇到差异时拼接Update SQL语句。
private void btnSave_Click(object sender, EventArgs e){ // 理论上只有一条记录值 if (dt.Rows.Count > 0) { // 模拟数据修改,直接修改dt.Rows[0] #region update row dt.Rows[0]["UserName"] = "001"; dt.Rows[0]["NickName"] = "Tom"; dt.Rows[0]["Password"] = "123456"; #endregion // 打开数据库 SqlConnection conn = new SqlConnection(); conn.ConnectionString = ""; conn.Open(); // 修改前读取数据库中的记录 DataTable dtTemp = new DataTable(); SqlDataAdapter adapter = new SqlDataAdapter(); adapter.SelectCommand.CommandText = "select * from user where id = 1"; adapter.Fill(dtTemp); DataRow oldRow = dtTemp.Rows[0]; adapter = null; // 当前数据库中的值 User oldItem = MyFuncLib.InitEntity(oldRow, new User()); // 可能已经发生修改的值 User newItem = MyFuncLib.InitEntity(dt.Rows[0], new User()); // 标识当前记录是否发生了修改 bool amended = false; // Update Sql StringBuilder sql = new StringBuilder(); sql.AppendLine("update user set modifiedDate = getDate()"); // 定义Update Command SqlCommand comdUpdate = new SqlCommand(); // 遍历User类属性 System.Reflection.PropertyInfo[] props = typeof(User).GetProperties(); foreach (System.Reflection.PropertyInfo prop in props) { // 排除id等系统字段 if (!prop.Name.Equals("id")) { // 仅当值发生修改时才拼接SQL语句 if (!prop.GetValue(oldItem, null).Equals(prop.GetValue(newItem, null))) { // 拼接Update语句 sql.AppendLine(string.Format(",[{0}] = @{0}", prop.Name)); // 同时添加参数 comdUpdate.Parameters.AddWithValue( string.Format("@{0}", prop.Name) , prop.GetValue(newItem, null).ToString()); // 只要有一个字段值发生了变化,就设置amended = true amended = true; // 此处可插入日志代码,用于对当前表变更历史的记录 } } } if (amended) { // 执行拼接的Update Sql comdUpdate.CommandText = sql.ToString(); comdUpdate.Connection = conn; comdUpdate.ExecuteNonQuery(); } // 关闭SQL连接 conn.Close(); }}
演示示例:下载
0 0
- 如何自动拼接 Update语句,仅Update已修改的字段
- Sql语句 update set 修改多项字段的格式
- Hibernate update 仅更新部分字段的实现方式
- 独特的deadlock(仅update语句也能造成死锁)
- sql update 触发器 获得被update的行的信息(某行的某字段被修改后,自动修改该行的另外一个字段)
- 如何修改数据:update
- Oracle 中用 update 语句更新date, timestamp字段的格式
- MySQL 替换某字段部分内容的UPDATE语句
- MySQL 替换某字段部分内容的UPDATE语句
- UPDATE语句的用法
- UPDATE 语句的语法错误
- 复杂的update语句
- update语句的语法
- update语句的书写
- Hibernate——update-只更新被修改的字段
- MySql如何用一句sql语句对某个字段进行处理后,再进行对字段进行修改?即update和select如何混合写?
- sql语句 字段update为null
- 两张表间的字段进行update
- Java 专业人士必备的书籍和网站列表
- eclipse 安装svn插件
- oracle ORA-01207:文件比控制文件更新 - 旧的控制文件
- 轻松搞定JSONP跨域请求
- 哈夫曼树
- 如何自动拼接 Update语句,仅Update已修改的字段
- 使用subversion管理iOS源代码
- JDK环境搭建及程序测试
- VC运行时库/MD、/MDd、/MT、/MTd说明
- LeetCode-62:Unique Paths
- 【HDU】-1237-简单计算器(栈)
- python 学习(六) for 循环语句
- Codeforces Round #293 (Div. 2) D. Ilya and Escalator(概率DP)
- 如何推广和宣传网站?