主题:请教: empty() 和 isblank() 的区别
coffeenight
[专家分:230] 发布于 2010-04-15 11:24:00
ywk1 字段是数值型
BLANK FIELDS ywk1 all &&先运行这条命令
?ISBLANK(ywk1) &&测试第一条纪录, 返回 .t.
?empty(ywk1) &&测试第一条纪录, 返回 .t.
UPDATE bscj SET ywk1=ywk1.ywk1 from ywk1 WHERE bscj.ksbh=ywk1.ksbh AND isblank(bscj.ywk1) &&更新 0 条纪录
UPDATE bscj SET ywk1=ywk1.ywk1 from ywk1 WHERE bscj.ksbh=ywk1.ksbh AND empty(bscj.ywk1) &&更新 95 条纪录
请问朋友们,两条命令几乎一样,为什么会有这样的区别啊?百思不得其解。
回复列表 (共6个回复)
沙发
coffeenight [专家分:230] 发布于 2010-04-15 11:36:00
又试着用了下面的命令
UPDATE bscj SET ywk1=ywk1.ywk1 from ywk1 WHERE bscj.ksbh=ywk1.ksbh AND not isblank(bscj.ywk1) &&更新 95 条纪录
居然可以正常更新,更是让我一头雾水。。。。
板凳
deadfoxer [专家分:300] 发布于 2010-04-15 12:03:00
数据型字段,不给输值时,有时会当作0来处理,这时候isblank()就返回.f.,当被当作blank对待时就返回.t.
所以,对于字符字段用isblank函数较好,对于数值型还是用empt()好,其实很多时候用empty()是明智的,因为对于字符型的空串值,对于数值型的0值和对于日期型的{//}值,它都会返回.t.
3 楼
coffeenight [专家分:230] 发布于 2010-04-15 13:05:00
那使用empty(),数值型字段有没有办法将 0 和 空值 区分出来
因为的有成绩是 0分卷,所以是 0分
而有的成绩是因为还没有录入,所以是空值
这是2种不同的情况
而且困惑的是,为什么同一字段使用函数测试出来的结果和使用命令得到的结果不一致。。。
如下:
?isblank(ywk1) && .t.
SELECT ywk1 FROM bscj WHERE ISBLANK(ywk1) && 返回空
4 楼
deadfoxer [专家分:300] 发布于 2010-04-15 13:48:00
你所说的空值对于数值型字段是不稳定的一种状态,具体怎么说我还没稿明白,但你说的空值不是null值.
不信你可试一下,比如说字段sz的值用blank fields(sz)命令来赋值,然后你用isblank(sz)检测时返回.t.,但你用? sz来在屏幕上显示其值时却是0,所以,如果你要表示成绩没有录入而不是0时,最好用null值表示.
5 楼
Ilikefox [专家分:5770] 发布于 2010-04-15 17:16:00
咦,还在这个问题上迷惑??
俺根据经验来告诉你,你就当这是个Bug,而且是个没人理会的Bug(至少大多数人都不理会它)。能不用就不用。
下面这句话是事实,从一本很有名的书上看来的(Hacker's Guide to Visual FoxPro X.0)
ISBLANK()这个函数历史悠久了,它是为了让FOX兼容很久很久以前的DBASE而保留的。
瞧!既然是为兼容性保留的,那就说明不必用它。
下面的话是俺主观臆造的
那时候还没有采用NULL这个表示未知数据的值。当一个字段要表示没有输入数据时,怎么办呢?比如一个字符字段,用一串空格表示这里没有数据?万一输入的就是一串空格呢?再比如数值型字段,用0表示没有输入数据吗?万一输入的就是0呢?
于是一个字段是不是“空”,全凭使用者主观决定,假如张三的数值型数据总是>0,张三可以主观认为0表示他没有输入数值(“空”),而李四可能需要0这样的数值,他不认为0表示“空”,假如他的数值数据总是非负数,李四可以用-1表示这个地方没有输入数据(“空”)。
这样一来有点乱套了,于是NULL这个怪异的数据后来被使用进来,专门用它表示“暂时没有输入数据”、“空数据”、“未知数据”等等意思。
这下OK了,张三和李四都用NULL表示没有输入数据,不再出现歧义。
如果大家都这样办,其实太好了。可惜许多人不习惯NULL,老狐狸于是在建表的时候,让你选择是否在某个字段使用NULL,结果(俺臆断)好多人并没有使用。
这就又回到了当初的情况,由使用者主观决定字段空不空。
先来看个例子:
create table tb1(fd1 N(3), fd2 C(10))
append blank
browse
现在,fd1字段是“空”的吗?fd2字段是“空”的吗?呵呵!看着空。
?fd1 &&显示0
?fd1+3 &&显示3
啊?有数据,是0 。它空不空?
?fd2 &&看不出来
?asc(fd2) &&显示32(空格的ascii码),即fd2里面是空格。
?len(fd2) &&显示10,哇,10个空格
它空不空?
你认为它空,它就空,你认为它不空,它就不空。
现在回到你的问题,一个成绩字段(数值型),并且0表示0分,并不表示 空值 ,你想区分它们。
要区别它们,古老的ISBLANK()函数起作用了。
?ISBLANK(fd1) &&.T.
可是刚才你发现fd1里面是0(尽管从浏览窗口看不到)
好,执行命令
replace fd1 with 0
?ISBLANK(fd1) &&.F.
哈哈,真管用,只要你不使用SQL命令,它就真管用。
可是
SELECT fd1 FROM tb1 WHERE ISBLANK(fd1) && 返回空
经验告诉我们,ISBLANK不适合用在SQL-SELECT命令中,换句话在SQL-SELECT中ISBLANK不能保证正确。很困惑吗?不必困惑,其实还有东西不适合用在SQL中。
比如一般情况下:
? "abc"="ab" && 得到.T.
replace fd2 with "abc"
select * from tb1 where alltrim(fd2)="ab" &&得到一条记录
现在
SET EXACT ON &&要求字符串比较必须严格相等
? "abc"="ab" && 得到.F.
select * from tb1 where alltrim(fd2)="ab" &&还是得到同样的一条记录
瞧,不会又困惑吧?这个倒是在帮助中明明白白说明了,SET EXACT不适用于SQL。只是这个ISBLANK没有在帮助中提出。
对于你的问题,解决办法两种,一种是对成绩字段使用NULL,这样用ISNULL()判断是否没有成绩。
另一种使用ISBLANK()判断,用在locate啊 scan啊这些语句中,并且避免在SQL中使用ISBLANK()。
6 楼
Ilikefox [专家分:5770] 发布于 2010-04-15 17:29:00
补充一点:
当我们习惯使用NULL值表示“空”时,就和ISBLANK()永别了。呵呵。
至于主贴标题“请教:empty()和 isblank()的区别”,就是帮助上唠叨的那些:
ISBLANK( ) 不同于 EMPTY( ) 和 ISNULL( )。例如,如果一个字符表达式包含计算为空的空格、制标符、回车符或换行符时,EMPTY( ) 返回真(.T.)。而一个表达式仅包含空串("")或空格时,ISBLANK( ) 才返回真(.T.)。
我来回复