Comparing to a null string in PL/SQL - oracle

I am looking for a way to compare a string to a null string the optimal way.
If I do
IF(str1 <> str2) THEN
dbms_output.put_line('Strings are not equal');
END IF;
This gets ignored if str1 is NULL.
I know I can set a null string to something before comparing to make it work
str1 := NVL(str1, 'Empty');
IF(str1 <> str2) THEN
dbms_output.put_line('Strings are not equal');
END IF;
And that works but I wanted to see if there is a better way to handle null string comparisons

You didn't say whether the string you must compare (str1) may be null; nor what the result of the comparison should be if either string is null.
It very rarely (if ever) makes sense to consider a non-null string equal to null. Sometimes it does make sense to consider two null strings as equal (if you think of them as "empty strings" - idiotically, Oracle doesn't make the distinction, mandated by the SQL Standard, between the SQL concept of null, on the one hand, and the empty string concept on the other hand).
The condition below:
str1 = str2
returns TRUE if both strings are non-null and they are equal; it returns FALSE if both strings are non-null and they are different; and it returns UNKNOWN if at least one string is null.
The LNNVL operator (which takes a condition as its argument) returns FALSE when its argument is TRUE and it returns TRUE when its argument is either FALSE or UNKNOWN. So, the condition
lnnvl(str1 = str2)
returns FALSE when the strings are both non-null and equal, and TRUE in all other cases. If you must consider two null strings as "not equal", then this is the condition you need in your code.
If, on the other hand, you must view two null strings as equal, you can use
decode(str1, str2, 0) is not null
In the case above, DECODE returns 0 if str1 and str2 are both non-null and equal, and also when they are both null. (This is why DECODE is often used in exactly this kind of situation). It returns the default (which I didn't specify, so the function will return the "default" default value, which is NULL) in the remaining cases. DECODE will return non-NULL when str1 and str2 are "the same" - either as equal, non-null strings, or as both null.
Of course, the DECODE condition can also be written as
decode(str1, str2, 0) = 0
or even
decode(str1, str2, 0, 1) = 0
to make it more explicit. Some people (not me!) may prefer it that way.

What if str2 literally is 'Empty'? nvl(str1, 'Empty'); (which is what you mean by DECODE(str1, 'Empty') I assume (decode() needs at least three parameters so your original expression would fail)) will give you a false negative. Just use IS NULL.
IF str1 <> str2
OR str1 IS NULL
OR str2 IS NULL THEN
dbms_output.put_line('Strings are not equal');
END IF;

If either str1 or str2 can be NULL then you can use:
IF str1 <> str2
OR str1 IS NULL AND str2 IS NOT NULL
OR str1 IS NOT NULL AND str2 IS NULL
THEN
dbms_output.put_line('Strings are not equal');
END IF;
db<>fiddle here

Related

Search a string in VBScript to verify if contains a character

I am trying to see if a string contains a dot.
Set Root_Currency = Root_TaxDataSummary.SlvObject("Currency")
curr_val = InStr(Root_Currency,".")
If curr_val.exist Then
pass
else
fail
Is there anything wrong with the way I am going about this?
InStr returns an integer representing the position the searched text can be found in the string.
curr_val.exist won't work because the integer type doesn't have an exist method. Instead:
If curr_val > 0 Then
Or (if this is the only use of that variable):
If InStr(Root_Currency,".") > 0 Then
Lastly, because 0 is treated as False in VBScript, you don't need to include the equality. Either a position is found for the character or you get back a 0/false:
If InStr(Root_Currency,".") Then
InStr returns a 'simple' number (1 based index/position of needle in haystack, or 0 meaning 'not found', or Null meaning Null argument) not an object. So change your code to:
If curr_val Then
' found
Else
' not found
End If

Classic ASP InStr() Evaluates True on Empty Comparison String

I ran into an issue with the Classic ASP VbScript InStr() function. As shown below, the second call to InStr() returns 1 when searching for an empty string in a non empty string. I'm curious why this is happening.
' InStr Test
Dim someText : someText = "So say we all"
Dim emptyString : emptyString = ""
'' I expect this to be true
If inStr(1,someText,"so",1) > 0 Then
Response.write ( "I found ""so""<br />" )
End If
'' I expect this to be false
If inStr(1, someText, emptyString, 1) > 0 Then
Response.Write( "I found an empty string<br />" )
End If
EDIT:
Some additional clarification: The reason for the question came up when debugging legacy code and running into a situation like this:
Function Go(value)
If InStr(1, "Option1|Option2|Option3", value, 1) > 0 Then
' Do some stuff
End If
End Function
In some cases function Go() can get called with an empty string. The original developer's intent was not to check whether value was empty, but rather, whether or not value was equal to one of the piped delimited values (Option1,Option2, etc.).
Thinking about this further it makes sense that every string is created from an empty string, and I can understand why a programming language would assume a string with all characters removed still contains the empty string.
What doesn't make sense to me is why programming languages are implementing this. Consider these 2 statements:
InStr("so say we all", "s") '' evaluates to 1
InStr("so say we all", "") '' evaluates to 1
The InStr() function will return the position of the first occurrence of one string within another. In both of the above cases, the result is 1. However, position 1 always contains the character "s", not an empty string. Furthermore, using another string function like Len() or LenB() on an empty string alone will result in 0, indicating a character length of 0.
It seems that there is some inconsistency here. The empty string contained in all strings is not actually a character, but the InStr() function is treating it as one when other string functions are not. I find this to be un-intuitive and un-necessary.
The Empty String is the Identity Element for Strings:
The identity element I (also denoted E, e, or 1) of a group or related
mathematical structure S is the unique element such that Ia=aI=a for
every element a in S. The symbol "E" derives from the German word for
unity, "Einheit." An identity element is also called a unit element.
If you add 0 to a number n the result is n; if you add/concatenate "" to a string s the result is s:
>> WScript.Echo CStr(1 = 1 + 0)
>> WScript.Echo CStr("a" = "a" & "")
>>
True
True
So every String and SubString contains at least one "":
>> s = "abc"
>> For p = 1 To Len(s)
>> WScript.Echo InStr(p, s, "")
>> Next
>>
1
2
3
and Instr() reports that faithfully. The docs even state:
InStr([start, ]string1, string2[, compare])
...
The InStr function returns the following values:
...
string2 is zero-length start
WRT your
However, position 1 always contains the character "s", not an empty
string.
==>
Position 1 always contains the character "s", and therefore an empty
string too.
I'm puzzled why you think this behavior is incorrect. To the extent that asking Does 'abc' contain ''? even makes sense, the answer has to be "yes": All strings contain the empty string as a trivial case. So the answer to your "why is this happening" question is because it's the only sane thing to do.
It is s correct imho. At least it is what I expect that empty string is part of any other string. But maybe this is a philosophical question. ASP does it so, so live with it. Practically speaking, if you need a different behavior write your own Method, InStrNotEmpty or something, which returns false on empty search string.

Why is `?something` invalid?

?. is a string literal:
?. #=> "."
However, I failed to declare a variable with a name like that:
?some_var = 100 #=> Error
How is?something invalid when ?. is valid?
? cannot describe any string literal; it is valid only for a single character.
Even if ?something were a valid string literal (counter to fact),
?something = ...
will be assignment to a string, which does not make sense. You cannot assign a value to a string.
?a is the same as "a". So it is a value, which belongs on the right hand side of an assignment, not the left hand side. It is not a variable name.
The Syntax exists as a relic from Ruby <=1.9, where it was equivalent to "a".bytes[0] and ?d could be used to shave off one character of code golf. I haven't seen any legitimate use otherwise.

IsNull in sybase where clause

I am using vb6 front end and sybase as backend. Can I use IsNull in where clause OR I must use = NULL
SQLStr = "select distinct thrd_pty.id_thrd_pty, thrd_pty.name_thrd_pty, thrd_pty.nbr_tax_idtn " _
& "from thrd_pty, cntct_rltn, cntct " _
& "where cntct.id_cntct = '" & cntct(ColNum, CurThrdPty) & "' and cntct_rltn.id_super = cntct.id_cntct and cntct_rltn.name_super = 'cntct' and thrd_pty.id_thrd_pty = cntct_rltn.id_thrd_pty and cntct_rltn.dt_eff_end IsNull "
The usual syntax in Sybase is either AND cntct_rltn.dt_eff_end IS NULL (which is perfectly fine for your example) or ISNULL(cntct_rltn.dt_eff_end, 0) for the more complicated stuff where you want to replace null with a defined default value. But you can do any of the follownig in ASE 15:
Adaptive Server treats null values in different ways, depending on the operators that you use and the type of values you are comparing. In general, the result of comparing null values is UNKNOWN, since it is impossible to determine whether NULL is equal (or not equal) to a given value or to another NULL. The following cases return TRUE when expression is any column, variable or literal, or combination of these, which evaluates as NULL:
expression is null
expression = null
expression = #x where #x is a variable or parameter containing NULL. This exception facilitates writing stored procedures with null default parameters.
expression != n where n is a literal not containing NULL and expression evaluates to NULL. (source)
(uppercase is mine as a personal style preference)
As a side note, you can also use COALESCE() function to deal with NULL values, but in your use case it won't add anything useful.
Reference:
Testing column for NULL values at Sybase infocenter
ISNULL as a function
COALESCE
Use is null:
cntct_rltn.dt_eff_end is null
More info, here
EDIT:
cQ = "update var1 = null ".(can be) .cQ = "update var1 is null" ?????
– niru dyogi
If you are updating, you have to use the assignment operator =. You can use is null only when evaluating conditions (such as the one in the example you provided).

NULL literal in XPath

Is there a NULL literal in XPath 1.0 or 2.0?
My use case is that I have a conditional (if then else) XPath expression and I want to return NULL to signify a certain condition. I am afraid that returning an empty string might be ambiguous in my case as it could be a valid result of the other part of the if then else expression.
The empty sequence () can be used as such. It is also returned if there is no result for a path expression.
let $foo := "foo"
return
if ($foo = ("foo", "bar", "batz")) then
$foo
else
()
You can check for an empty sequence using
let $result := ()
return empty($result)
If you pass the result of the first XPath expression to your native code, you should be able to distinguish "NULL" from the empty string by having no results (empty sequence / "NULL") or having a result string (which could be empty).

Resources