SQL: Calling REPLACE() with a NULL replacement - sql

I've recently run into this behaviour and whilst I can work around it, I'm quite curious as to why it occurs. There doesn't seem to be much documentation explaining why this happens.
Consider the following two snippets:
SELECT REPLACE('hello world', 'world', NULL)
SELECT REPLACE('hello world', 'foobar', NULL)
Both of these examples return NULL.
I don't really understand either, but with the first one I can see how if there is indeed some caveat I'm unaware of with NULLs that this will cause the outcome we see.
But with the second example I'm completely stumped. Even if there is some strange NULL replacing behaviour, why is my string being manipulated at all? The replacement string is not found in the target string.

Read this:
https://learn.microsoft.com/en-us/sql/t-sql/functions/replace-transact-sql
It states that:
Returns NULL if any one of the arguments is NULL.

This is most certainly a result of the messed up NULL handlich in SQL Server. Everything you perform with NULL will result in NULL as well. Try SELECT 1 + NULL or 'abc' + NULL. Anyways, since you are working with a string, you should use the empty string '' instead of NULL.

Related

LIKE 'x%' works, but LIKE '%x' doesn't work on INT converted to STRING

I've found this strange behaviour and I searched but couldn't find anything about it.
I know that in my example I don't need to cast [affairenum] to STRING, but because of a specific syntax in Entity Framework this is how an Affairenum.Contains(), StartsWith() or EndsWith() ends up being generated.
Consider for example a table that contains an id (affaireid column) and numbers (affairenum column) with values from 1 to 5000000.
SELECT TOP (1000) [affaireid]
,[affairenum]
,STR(affairenum) AS string
FROM [dbo].[ULAffaire]
where STR(affairenum) LIKE N'%9'
Works and returns results. Same goes with N'%9%'.
SELECT TOP (1000) [affaireid]
,[affairenum]
,STR(affairenum) AS string
FROM [Ulysse].[dbo].[ULAffaire]
where STR(affairenum) LIKE N'9%'
Does not work and returns nothing. The difference here being LIKE N'9%', the equivalent of a StartsWith().
STR(affairenum) looks identical to affairenum, EndsWith() and Contains() both work normally, but this returns nothing.
I've tried with LOWER(), to no avail. Is the STR() method adding anything ? a space, some weird character ? Am I missing something silly ?
That is because str() left pads the results with spaces. The default is a length of 10 (see here).
I'm not a fan of using numbers as strings. But if you do so, explicit conversion should do what you want:
where cast(affairnum as varchar(255)) like '9%'
That is, str() is not a type conversion function. It is a string formatting function -- hence the presence of spaces where you might not expect them.
I should note that you don't even need to explicit convert the number to a string, so this works:
where affairnum like '9%'
However, I have such bad memories of hours and hours devoted to fixing problems in SQL code that used implicit conversion, so I cannot in good conscience propose implicit conversion to someone else.

replacing missing entires of variable 1 by non-missing values of variable 2 sql in googlebigquery (standard sql)

I am trying to create a new variable called STREET NAME which will take a value of ON_STREET_NAME if it is not null or OFF_STREET_NAME if ON_STREET NAME is null.
I tried using
ifnull(on_street_name, off_street_name)
and
coalesce(on_street_name, off_street_name)
but none seemed to work. Any advice?
Ok, i was able to experiment different things and found this to work. Having null and empty space works differently. Here is the solution.
coalesce(nullif(on_street_name,''),off_street_name) as street_name
It works like magic :)

SQL What does IF evaluate to for NULL

Hi this is a pretty basic question, but I am not able to find a definitive answer to it.
What does IF evaluate to for NULL in SQL ? What will happen in following code if fieldXYZ were NULL
IF fieldXYZ=SomeValue
//do something
ELSE
//do something else
Update:
I have found one result which suggests that NULL can be considered as falsy
https://technet.microsoft.com/en-us/library/ms182587(v=sql.110).aspx
First of all, I think your if..else statement is incomplete as you are not defining any expression for your column fieldXYZ. Generally, when you write an if..else statement, you would want to write an expression that compares your column value with something. You can explicitly check for null values if you want to handle them. Here is a gist of that syntax:
--This handles null check explicitly
IF fieldXYZ IS NOT NULL AND fieldXYZ = 'somevalue'
//do something
ELSE
//do something else
Also, if the fieldXYZ is passed a NULL value in the above statement, then the first condition is not met, so the else condition applies immediately in that scenario.Hope this helps!
(I am reluctant to answer my own question, but in absence of any solution, reposting my comment as answer)
Apparently the right way is to consider NULL as falsy.

SQLiteQueryBuilder.buildQuery not using selectArgs?

Alright, I'm trying to query a sqlite database. I was trying to be good and use the query method of SQLiteDatabase and pass in the values in the selectArgs parameter to ensure everything got properly escaped, but it wouldn't work. I never got any rows returned (no errors, either).
I started getting curious about the SQL that this generated so I did some more poking around and found SQLiteQueryBuilder (and apparently Stack Overflow doesn't handle links with parentheses in them well, so I can't link to the anchor for the buildQuery method), which I assume uses the same logic to generate the SQL statement. I did this:
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(BarcodeDb.Barcodes.TABLE_NAME);
String sql = builder.buildQuery(new String[] { BarcodeDb.Barcodes.ID, BarcodeDb.Barcodes.TIMESTAMP, BarcodeDb.Barcodes.TYPE, BarcodeDb.Barcodes.VALUE },
"? = '?' AND ? = '?'",
new String[] { BarcodeDb.Barcodes.VALUE, barcode.getValue(), BarcodeDb.Barcodes.TYPE, barcode.getType()},
null, null, null, null);
Log.d(tag, "Query is: " + sql);
The SQL that gets logged at this point is:
SELECT _id, timestamp, type, value FROM barcodes WHERE (? = '?' AND ? = '?')
However, here's what the documentation for SQLiteQueryBuilder.buildQuery says about the selectAgs parameter:
You may include ?s in selection, which
will be replaced by the values from
selectionArgs, in order that they
appear in the selection.
...but it isn't working. Any ideas?
The doc for SQLiteQueryBuilder.buildQuery also says, "The values will be bound as Strings." This tells me that it is doing the straight-forward thing, which is writing the SQL leaving the ? parameter markers in place, which is what you are seeing, and binding the selectArgs as input parameters.
The ? are replaced by sqlite when it runs the query, not in the SQL string. The first string in the array will go where you see the first ?, and so on, when the query actually executes. I would expect the logged SQL to still have the ? markers.
Probably, your query fails because you are quoting the ?. For example, don't use WHERE ID = '?', just use WHERE ID = ?, and make sure the selectArgs is a string that satisfies the query.
Two things:
The ? substitution will not be done at this point, but only when the query is executed by the SQLiteDatabase.
From what I've seen, ? substitution only works for the right side of comparison clauses. For example, some people have tried to use ? for the table name, which blows up. I haven't seen anyone try using ? for the left side of the comparison clause, so it might work -- I'm just warning you that it might not.

In how many languages is Null not equal to anything not even Null?

In how many languages is Null not equal to anything not even Null?
It's this way in SQL (as a logic language) because null means unknown/undefined.
However, in programming languages (like say, C++ or C#), a null pointer/reference is a specific value with a specific meaning -- nothing.
Two nothings are equivilent, but two unknowns are not. The confusion comes from the fact that the same name (null) is used for both concepts.
In VB6 the expression Null = Null will produce Null instead of True as you would expect.
This will cause a runtime error if you try to assign it to a Boolean, however if you use it
as the condition of "If ... Then" it will act like False. Moreover Null <> Null will also
produce Null, so:
In VB6 you could say that Null is neither equal to itself (or anything else), nor unequal!
You're supposed to test for it using the IsNull() function.
VB6 also has other special values:
Nothing for object references. Nothing = Nothing is a compile error. (you're supposed to compare it using "is")
Missing for optional parameters which haven't been given. It has no literal representation so you can't even write Missing = Missing. (the test is IsMissing(foo))
Empty for uninitialized variables. This one does test equal to itself although there's also a function IsEmpty().
... let me know if I've forgotten one
I remember being a bit disgusted with VB.
Oracle is this way.
SELECT * FROM dual WHERE NULL=null; --no rows returned
MySQL has a null-safe equality operator, <=>, which returns true if both sides are equal or both sides are null. See MySQL Docs.
In C#, Nullable<bool> has interesting properties with respect to logical operators, but the equality operator is the same as other types in that language (i.e., ((bool?)null == (bool?)null) == true).
To preserve the short-circuited behavior of the short-circuited logical operators, and to preserve consistency with the non-short-circuited logical operators, the nullable boolean has some interesting properties. For example: true || null == true. false && null == false, etc. This stands in direct contradiction with other three-valued logic languages such as ANSI SQL.
You can make ruby work that way:
class Null
def self.==(other);false;end
end
n=Null
print "Null equals nothing" if n!=Null
In SQL you would have to do something like:
WHERE column is NULL
rather than
WHERE column = NULL