sqlserver数据表的varchar列自动去除内容末尾的空白字符

问题描述
今天有用户反应我们写的程序保存到数据库再读出来之后就会出现空格减少的情况。通过与用户交流发现,他要保存的数据类似于“012345678901234567890123456789      012345678901234567890123456789”,我们的程序逻辑是如果一个字符串过长,就把它拆分为多条记录进行存储,于是上面这个字符串被拆分为两个字符串:
1)“012345678901234567890123456789   “
2)“   012345678901234567890123456789”
注意,原字符串中有六个空格,拆分时正好在中间拆分,所以第一个子字符串后面有三个空格,而第二个子字符串开头有三个空格。
保存到数据库时,保存字符串的数据库表列类型为varchar,保存到数据库然后再读出来之后,发现这两个字符串变成了下面的形式:
1)“012345678901234567890123456789“
2)“   012345678901234567890123456789”
第一个子字符串最后的空格没有了。
问题定位
一开始以为是自己程序写的有问题,于是在数据保存和数据读取的时候分别下断点,然后查看字符串长度,结果发现,保存到数据库之前,字符串最后的空格还存在,但从数据库中读出来之后最后的空格就没有了。
我们的程序是用C#写的,与数据库的操作使用的是Linq To SQL,上面的测试完了之后,就怀疑会不会是Linq在保存到数据库的时候进行了处理。然后就用sqlserver客户端直接操作数据库进行测试,发现直接操作数据库也会存在类似的最后空格消息的问题。
于是确定应该是sqlserver的问题。
问题解决方案
sqlserver是微软出的数据库软件,不太可能犯这种错误,所以很可能是sqlserver的设置导致出现这种问题。于是在网上搜索解决方案,搜索词类似于“sqlserver varchar auto trim”这种,找到了参考文献1-4。
参考文献中介绍的比较详细,这里就不细说原理了,主要是与sqlserver中的ANSI_PADDING命令有关系。参考文献4中介绍说这个命令只在创建表时生效,后面就不再改动,并且该命令只影响varchar,不会用nvarchar类型造成影响。
于是有了下面几种解决方法:
1)将数据库表列的类型由varchar改为nvarchar
2)重新创建表,创建表的同时设置ANSI_PADDING的值,但是如果表中有数据,这种方法就不是很好
3)写程序处理,例如写入数据库之前把字符串变为base64编码,从数据库中读出来时再解码。这种方法也存在一个历史数据的问题,因为历史数据没有编码,可以设置一个标志位或者标志字符串标识一下保存在数据库中的数据是否经过编码,这种做法稍微麻烦一些,但不会对数据库造成更改。
我最终采用的是第三种方法,就是在保存到数据库之前检查字符串末尾是否为空格,如果是空格,就加一个标志字符串( 要保证用户的输入中肯定不会出现标志字符串),从数据库中读出来后检查字符串结尾是否有标志字符串,如果有则将标志字符串去除。这种做法虽然麻烦,但是不用修改数据库,对历史数据也没有影响,可以暂时解决问题。
但是最好的解决方法是以后建数据库表时将varchar类型的列变为nvarchar,这样才能一劳永逸的解决问题。
参考文献
[1]http://techygypo.blogspot.jp/2011/06/auto-trimming-whitespace-removal-in-sql.html
[2]http://www.sqlines.com/sql-server/ansi_padding
[3]https://msdn.microsoft.com/en-us/library/ms187403.aspx
[4]http://stackoverflow.com/questions/1571180/auto-trim-database-entries
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值