赞
踩
A开发反馈sqlserver表中字段有空格,数据同步到pg后表关联报错,B开发反馈在sqlserver插入时没有带空格,查询时也没有用rtrim把空格去掉,但能正常查出数据。
由此引出几个关于sqlserver空格的问题:
众所周知CHAR(nchar类似)适合存储定长数据,不足长度的自动用空格填充,查看有问题的表字段恰好就是ncahr
create table test0815(a nchar(6))
insert into test0815 values('ABC')
insert into test0815 values('AB')
insert into test0815 values('A')
SELECT * FROM test0815;
把查询到的字符粘出来,明显后面是补了空格的
通常我们会用len来看字符串的字符数,但是,这个函数计数不包括最右端空格,以这个来看char字段的字符数很可能是错的。
这个字段实际有多少字符可以用DATALENGTH来看,但该函数返回的是字节数,如果是nchar等类型,需要除以2
对比一下两个函数:
LEN(string_expression)
:返回指定字符串表达式的字符数(中英文字符都计1),其中不包含尾随空格。
DATALENGTH(expression)
:返回指定字符串表达式的字节数。如果处理的是unicode字符串,则返回两倍的字符数。
DECLARE @Str1 NVARCHAR(50)='汉字abcd '
DECLARE @Str2 VARCHAR(50)='汉字abcd '
DECLARE @Str3 CHAR(50)='汉字abcd '
DECLARE @Str4 NCHAR(50)='汉字abcd '
SELECT LEN(@Str1), LEN(@Str2), LEN(@Str3), LEN(@Str4) -- 返回指定字符串表达式的字符数,其中不包含尾随空格
-- 和查询语句1比较:LEN()、DATALENGTH()的区别
-- 自身比较:NVARCHAR、VARCHAR、CHAR、NCHAR的区别
SELECT
DATALENGTH(@Str1), -- NVARCHAR(n):变长,每个字符占2个字节,n=[1,4000]
DATALENGTH(@Str2), -- VARCHAR(n):变长,unicode字符占2个字节,非unicode字符占1个字节,n=[1,8000]
DATALENGTH(@Str3), -- CHAR(n):定长,所占字节为定长n,n=[1,8000]
DATALENGTH(@Str4) -- NCHAR(n):定长,所占字节为定长n*2,n=[1,4000]
第三个问题是,如果字段中实际存储的是'A ',为什么B开发在查询条件中没有加上空格,也没有对a字段用rtrim去掉右端空格,但是能查出结果?
实际上我们可以测试出字段最后有没有空格对返回结果没有影响
SELECT a FROM test0815 where a='A'
SELECT a FROM test0815 where a='A '
SELECT a FROM test0815 where a='A '
反过来如果直接在a字段最右端插入空格,查询时对返回结果也没有影响(所以where条件里对a字段加rtim函数其实是多余的)
Oracle也一样
这是为什么?这其实跟ANSI/ISO SQL-92规范有关系,大部分关系型数据库都遵循该规范,这个规范里是怎么比较两个字符串是否相等的?
如果要比较'A'和'A '两个字符串,它先给'A'字符串最后补空格,补到两个字符串长度相等然后进行比较,此时就是'A '和'A '比较,所以它们当然是相等的,但是字段返回时,字段里存的是什么样就什么样,不会额外处理。
唯一的例外是用like去匹配字符串,此时就不会在末尾先补空格,因为like本身用于模式匹配,补空格实际违背了like的定义。
LINQ到实体比较字符串忽略空格 - IT屋-程序员软件开发技术分享社区
这个其实我们前面说过了,你先去掉sqlserver也会给补上,没有区别。如果a是个索引字段,还会让索引失效。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。