请教一个关于SQL语句更新的写法的问题

niuhejun 2015-06-03 09:53:11
遇到一个更新需求:

1.表里有四个字段。
2.更新的时候不确定要更新哪几个字段。有可能是全部,也有可能是某几个。

我想的解决方案:
1.定义一个实体类。里面是四个对应的数据库字段的属性。
2.SQL语句是拼接的,在拼接的时候逐个判断属性值是否为空,如果为空就不拼接对应字段。


遇到的问题以及疑问:
1.在拼接的时候Update语句主要拼接 Set之后和WHERE之前的部分,每一句都要带一个逗号,由于在拼接的时候不知道那个字段为空,所以只能是在拼接后的语句去处理这个逗号(拼接完后WHERE前多了一个逗号)
2.关于属性,int型的变量及其属性应该默认值就是0 ,那我应该怎么处理,赋值为0和不赋值(就是不更改当前字段)这个情况呢
3.关于属性,Datetime类型。默认值问题。如何判断datetime类型的变量对应的属性没赋值呢?

求指点,谢谢
...全文
493 25 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
hlm750908 2015-06-05
  • 打赏
  • 举报
回复
整体更新前需要获取一次旧值,我想楼主的意思是不想获取旧值,就可以更新,所以不关注的字段不要牵涉进来,18楼的答复符合你的需求
leeya66 2015-06-05
  • 打赏
  • 举报
回复
全部字段都更新啊,这个是最合理的
我叫小菜菜 2015-06-05
  • 打赏
  • 举报
回复
引用 23 楼 hlm750908 的回复:
整体更新前需要获取一次旧值,我想楼主的意思是不想获取旧值,就可以更新,所以不关注的字段不要牵涉进来,18楼的答复符合你的需求
不获取一次旧值,那么就有可能会出现update语句失败:因为无法指定where子句。 比如 {id:123,name:CC,sex:m} 如果不获取旧值,初始化将是{id:?,name:?sex:?},假设设置id=34,name=BB,请问这“id=34”依据是啥,为什么一定要是34,而不能是35,36?随意的话,那应该是insert,而不是update了~~ 上面所说的以对象为基本单位,就是这个原因。 当然,动态拼接sql语句的办法,可以应用于任何场合,而且拼接字符串本身不是难题,无论多么复杂的字符串都是肯定能拼接出来的。
一枚大帅哥 2015-06-04
  • 打赏
  • 举报
回复
引用 2 楼 skyandcode 的回复:
一般这种情况是全部字段都更新,你这里只有4个字段,如果有10个、20个字段呢? update只更新一条记录的多个字段不会有太大影响。 1.是要自己处理逗号 2.3. 对于值类型,你可以用可空类型,默认就是空
这个正解
qbilbo 2015-06-04
  • 打赏
  • 举报
回复
全部更新是指把你类中所有的属性都更新,而不是数据库表中的字段全更新。 把属性的数据类型设置成int?,datetime?是为了可以和数据库表中字段类型完全匹配。从而不用担心int不能为null之类的问题。也许你的问题2中更新字段个数不一致就是这个原因。 如果你更新字段个数不一致是由于业务逻辑引起的,比如在有些特定情况下不更新,那建议改进一下你的这个类。比如:用于更新的属性为只读与赋值属性分开,在赋值属性的set方法里,根据业务逻辑来设定如何更新用于写入数据库的属性。
wish907 2015-06-04
  • 打赏
  • 举报
回复
你难道就不能在拼的时候在加','之前先if(是否有值)不就好了,至于int 和datetime的时间,设一个不应该出现的值不就好了
我叫小菜菜 2015-06-04
  • 打赏
  • 举报
回复
引用 17 楼 xuzuning 的回复:
从数据库操作角度看,你的逻辑是行不通的 因为 update 是修改记录中原有的值,既然是发生了修改,那么改一个字段和改两个字段还是全改,开销是一样的。而全改时效率反而更高。 另外,如果带有 NOT NULL 属性的字段,insert 和 update 时如果不赋值,是通不过语法检查的 再说,判断属性值是否为空,如果为空就不拼接对应字段也是欠妥的,如果我就是想将原来的值删去呢?你这样不就删不掉了吗 当然你想拼装 update 也是可以的,但是表是固定了的,update 是活的有什么意义呢?徒劳的消耗资源 拼装 SQL 指令串,多在动态查询时使用。 构建时可将各子句 Add 到 List<string> 循环结束后再用 string.Join 连接成字符串。根本就不会出现多余的逗号问题 即便你不想改变你的思路和先用代码,也只需在拼装后用 SubString 截取一下
斑竹正解。 数据库的CURD操作以实体为最小单位,而对象也是面向对象编程的核心概念,这已经是面向对象编程的共识(我不知道是不是规范)。【压根就不确定要更新那个或者那几个字段呢】,你为什么要关心到底更新了哪些字段呢?你应该把思路从【应该更新哪些字段】上升到【应该更新哪个对象】。正是因为一个对象可能有几十个属性,所以才把它封装为一个对象,从而屏蔽属性细节,把更多的精力放在业务逻辑上,而不是耗费在这些字段中。 至于效率问题: 对象属性都是固定的,而时间主要耗费在资源初始化、网络延迟和数据传输。 资源初始化方面比如打开数据库、索引定位数据记录,这些都是相同的; 网络延迟是系统因素; 数据传输方面都是整个对象为参数,那么对象的所有属性都会初始化为默认值,多出来的只是某些字段的赋值操作,而赋值操作的时间复杂度通常都是O(1),所以算下来效率并不会影响很大,但是对于业务逻辑的处理影响之大简直无可估量。 关于空值问题和默认值问题的处理: 从数据库逆向工程生成实体定义,如果数据库中int/double数字类型允许为空,那么生成的实体类会把这些类型映射成可空类型(int、bool等这些类型不能表示数据库中的“Null” 。因此C#提供了“可空类型”这种语法,只要在类型后加?就构成了可空的数据类型,比如int?、bool?,这样int? i=null 就可以了。),其实就是实现了System.Nullable<T>接口的int和bool,当然double和其他类型都有相应的可空类型~
niuhejun 2015-06-04
  • 打赏
  • 举报
回复
引用 1 楼 zhi_ai_yaya 的回复:
用存储过程吧。
大哥,能详细解释下吗?存储过程不也得把要修改的所有参数传入吗?如果我只是想修改里面的一个两个,参数应该怎么赋值呢
niuhejun 2015-06-04
  • 打赏
  • 举报
回复
引用 3 楼 bbjiabcd 的回复:
把查询出来一条记录的所有字段修改后全部放进实体类中,更新的时候全部更新就好了。
如果一个记录有20个字段,难道为了更新里面的三四个字段,就要获取全部的数据付给实体类,在进行更新吗?我个人以为,为了更新四五个字段而更新全部的几十个字段,是不是得不偿失啊
niuhejun 2015-06-04
  • 打赏
  • 举报
回复
引用 3 楼 bbjiabcd 的回复:
把查询出来一条记录的所有字段修改后全部放进实体类中,更新的时候全部更新就好了。
如果一个记录有20个字段,难道为了更新里面的三四个字段,就要获取全部的数据付给实体类,在进行更新吗?我个人以为,为了更新四五个字段而更新全部的几十个字段,是不是得不偿失啊
EdsionWang 2015-06-04
  • 打赏
  • 举报
回复
int和DateTime你都可以给一些特殊值做初始值。比如int可以设一个负数,或者int.MaxValue(考虑你系统内不会出现的值)
qbilbo 2015-06-04
  • 打赏
  • 举报
回复
属性的类型改为:int?,datetime?就可以为null了。 这样所有字段一起更新应该也没问题了吧。
bbjiabcd 2015-06-04
  • 打赏
  • 举报
回复
把查询出来一条记录的所有字段修改后全部放进实体类中,更新的时候全部更新就好了。
skyandcode 2015-06-04
  • 打赏
  • 举报
回复
一般这种情况是全部字段都更新,你这里只有4个字段,如果有10个、20个字段呢? update只更新一条记录的多个字段不会有太大影响。 1.是要自己处理逗号 2.3. 对于值类型,你可以用可空类型,默认就是空
我叫小菜菜 2015-06-04
  • 打赏
  • 举报
回复
用存储过程吧。
gossipchat 2015-06-04
  • 打赏
  • 举报
回复
int,datetime建议定义为int?,datetime?可空类型,默认赋值为null
0802023028 2015-06-04
  • 打赏
  • 举报
回复
你都定义好了实体类,还不好拼SQL啊,直接写就OK,当然也可以写个扩展方法动态组装SQL
bbjiabcd 2015-06-04
  • 打赏
  • 举报
回复
引用 6 楼 niuhejun 的回复:
[quote=引用 3 楼 bbjiabcd 的回复:] 把查询出来一条记录的所有字段修改后全部放进实体类中,更新的时候全部更新就好了。
如果一个记录有20个字段,难道为了更新里面的三四个字段,就要获取全部的数据付给实体类,在进行更新吗?我个人以为,为了更新四五个字段而更新全部的几十个字段,是不是得不偿失啊[/quote] Java中Hibernate的原理就是我说的这样。我倒觉得你一个一个字段判断再拼接SQL更加得不偿失
smthgdin_020 2015-06-04
  • 打赏
  • 举报
回复
1.可以拼后再去掉逗号;也可以在已知更新字段的前提下,去控制最后一个字段的字符串。 2,3个问题,可以给你个思路,就是在实体里定义一个hashtable去保存哪些字段做了更新。 比如: private readonly Hashtable ChangeFlag = new Hashtable(); private string address; public virtual string Address { get { return address; } set { address= value; this.ChangeFlag ["Address"] = true; } } 这样,每当你给属性赋值,hashtable都会添加哪个属性已经变化需要update。 对于new出来的实体,判断是否给主键赋值,或者在构造函数里先清空以下hashtable就可以解决你得问题。
xuzuning 2015-06-04
  • 打赏
  • 举报
回复
从数据库操作角度看,你的逻辑是行不通的 因为 update 是修改记录中原有的值,既然是发生了修改,那么改一个字段和改两个字段还是全改,开销是一样的。而全改时效率反而更高。 另外,如果带有 NOT NULL 属性的字段,insert 和 update 时如果不赋值,是通不过语法检查的 再说,判断属性值是否为空,如果为空就不拼接对应字段也是欠妥的,如果我就是想将原来的值删去呢?你这样不就删不掉了吗 当然你想拼装 update 也是可以的,但是表是固定了的,update 是活的有什么意义呢?徒劳的消耗资源 拼装 SQL 指令串,多在动态查询时使用。 构建时可将各子句 Add 到 List<string> 循环结束后再用 string.Join 连接成字符串。根本就不会出现多余的逗号问题 即便你不想改变你的思路和先用代码,也只需在拼装后用 SubString 截取一下
加载更多回复(5)

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧