Dan said:
NULL is not just a quirky empty.
Yes, that's what I'm saying:
myself said:
NULL has the meaning of an absence of values
I earlier said NULLs are blanks, and to me, that means the same, to VFP the blank concept even differs from empty and is closest to NULL but handles the value of fields as if they are empty(ß for numeric, .f. for bools, etc)
VFPs blank (as ISBLANK() returns) is a quirky empty, not NULL. It is almost meant the way NULL is meant, as ISBLANK() returns .T. for any field, that wasn't set in an INSERT or APPEND BLANK, but its value is the same as that of an empty field.
You have to know how to deal with NULLs, as NULL is "contageous". A NULL in an expression makes the whole expression NULL.
VFPs biggest weakness about NULL is executing an else branch, which treats NULL as FALSE:
Code:
Create Cursor nulltest (avalue int NULL)
Insert into nulltest Values (1)
Insert into nulltest Values (10)
Insert into nulltest Values (100)
Insert into nulltest Values (.null.)
Clear
Scan
If avalue>Pi()
? "avalue="+Transform(avalue)+" is > Pi"
Else
? "avalue="+Transform(avalue)+" is not > Pi"
EndIf
If avalue<Pi()
? "avalue="+Transform(avalue)+" is < Pi"
Else
? "avalue="+Transform(avalue)+" is not < Pi"
Endif
EndScan
That is by design, so keep in mind the ELSE branch doesn't state the IF expression is .F. (false) if the else branch executes you only know the IF expression is not .t. (not true). Other programming languages are strict about that and NULL gives you a NULL exception or no branch executes. It's not even wrong but has to be kept in mind.
NULL is handled as in database theory in SUM()s and AVG():
Code:
Create Cursor nulltest (avalue int NULL)
Insert into nulltest Values (1)
Insert into nulltest Values (10)
Insert into nulltest Values (100)
Insert into nulltest Values (.null.)
* notice avg is computed as 111/3:
Select Sum(avalue) as ntotal, Avg(avalue) as naverage, Count(*) as ncountall, Count(avalue) as ncountvalues from nulltest
Use
Create Cursor nulltest (avalue int NULL)
Insert into nulltest Values (1)
Insert into nulltest Values (10)
Insert into nulltest Values (100)
Insert into nulltest Values (0)
* notice avg is computed as 111/4:
Select Sum(avalue) as ntotal, Avg(avalue) as naverage, Count(*) as ncountall, Count(avalue) as ncountvalues from nulltest
As already said you have ISNULL() and NVL() to treat NULLs guiding IF what you actually want to test and handling NULL as a replacement value. And you CAN decide, if you know that's right, your new table doesn't have NULL in new columns. as I already said, rather extend a table and give fields a default, then only update rows with a match and you have that result. And if you only need that in a query result, I'd not query INTO TABLE, making it a permanent DBF file, but anyway you choose Tamar's NVL() expressions then are what prevents NULLs for you, too.
Bye, Olaf.
Olaf Doschke Software Engineering