SQL IsNull function - sql

I saw a sql code using the isNull function in the where clause, similar like below:date>isNull(date1,date2)
Can someone explain what this means?
Many Thanks!
Michelle

declare #date1 datetime = null
declare #date2 datetime = getdate()
select isNull(#date1,#date2)
IsNull will return the first one going left to right that is not null
If #date1 is not null, it will return #date1.
If #date1 is null, then it will return #date2.
For more details the docs are pretty good:
https://learn.microsoft.com/en-us/sql/t-sql/functions/isnull-transact-sql?view=sql-server-ver16

To explain the ISNULL function is not necessary because there are lots of documentations about it, just google and read them. One of them is linked in the other answer.
Necessary is - at least in my opinion - to point that using such a function is in many cases bad practice.
Why that? There are two big disadvantages of that function:
The function is a non standard function. This means it is provided in some DBMS like for example SQL Server DB, but it is missing in some others like for example Oracle DB. Using non standard SQL when Standard SQL is possible makes no sense to me. Often, people change the DBMS, so each usage of non standard SQL produces effort to rewrite these queries or commands.
The ISNULL function only accepts one value which should be checked and replaced if NULL. This means it must be use nested in case more arguments should be used. This can get very bad readable. What a sad implementation in my point of view.
How to get rid of these unpleasant limitations? Well, we can just use COALESCE. This is SQL-standard, will work on every DBMS and accepts a lot of arguments.
So we can just write things like
SELECT COALESCE(column1, column2, column3,...,0) FROM yourtable;
This will take the value of the first column of all columns that we write there which is NOT NULL. If all of those columns are NULL, then zero will be selected in this example. And we will very likely never have to rewrite this when we change the DBMS.
To be fair: There are some edge cases, so it can sometimes be better or even really necessary to use the ISNULL approach. I don't want to create the impression that function is not useful at all. But very often, people just use it because they saw it somewhere and didn't think out of the box.
So whenever there is no important reason why we should or must use ISNULL, I advice to use COALESCE instead.
See for example here a question about the differences if you want to know more: Question on SO

Related

SELECT ALL... in Oracle SQL

I was researching packages from DB, when I saw following query:
SELECT ALL TABLE1.CODE, nvl(TABLE1.EXPLANATION, '') as Explanation
FROM TABLE1;
I couldn't find what is the usage of ALL in SELECT statement, I know that using ALL in WHERE has meaning of AND.
Could you please clear this out for me?
As the documentation specifies:
ALL
Specify ALL if you want the database to return all rows selected, including all copies of duplicates. The default is ALL.
I don't recall off-hand if any other databases support SELECT ALL. I have never seen it used in the real world.
A bit late, but I would like to remark somthing on this topic:
Yes, its right that it is the standard for select statements but it makes a difference for other functions e.g. "count":
count (all <col>)
ignores NULL values, whereas
count (<col>)
includes NULL values.
[Remark: ORACLE SQL, see https://www.oracletutorial.com/oracle-aggregate-functions/oracle-count/]

SQL Parameterized Query with Names instead of Question Marks

Question:
Is there a way to use names instead of question marks for paramaterized queries? If so, can anyone suggest some material that explains how to do this/the syntax?
A bit more detail:
For example, if I have something like:
INSERT INTO inventory VALUES(?)
Is it possible to have something like this instead that does the exact same thing as the question mark:
INSERT INTO inventory VALUES("prices")
I tried checking to see if it would work myself before posting the question, but it didn't work. So, I thought I'd ask if it was possible.
I feel like if you have a really long query with, let's say 20 parameters, you don't want to have to count question marks to make sure you have enough parameters whenever you change something. Also, I think it might make the code a bit more readable (especially if you have a lot of parameters to keep track of).
I'm rather new to sql, so I am not sure if it makes much of a difference (for this question) if I add that I'm using postgresql.
Note:
There is a similar question here, but it didn't have an answer that was helpful
I suggest to encapsulate the big query in a function, where you can use parameter names.
One example (out of many):
PostgreSQL parameterized Order By / Limit in table function
You can even set default values and call the function with named parameters, etc.:
Functions with variable number of input parameters

Using cast on a view in a Derby database that has multiple columns

This question is a quick one. I know that you could say something like SELECT CAST(someColumn AS otherType) FROM myView, where myView is a view in a Derby database, but is it combinable with other statements in a SELECT statement? In other words, could I say something like SELECT columnA, CAST(columnB AS otherType), someOtherColumns FROM myView, or would you have to cast YOUR ENTIRE QUERY? //I have been looking online for something that might help, but with no examples of this. I have even tried this on w3schools.com, but it was complaining that the database is read-only (somehow, cast() was changing the database!). Otherwise, I have found no working examples where someone has done something like what I am asking here.
I have found an answer to that question: yes, you can say something like I have said above in Derby. Here is an example: http://www.ibm.com/developerworks/library/os-ad-trifecta6/ //although I still couldn't use those methods on a database on w3schools.com!
You do not have to cast the entire freaking table; you could just cast one column at a time! Heck, in Derby, you could say DOUBLE(23), and it would return something like 23.000000!
I don't know what either Derby or w3schools.com means, but you need to understand that CAST is a function and all functions have syntax that is particular to whatever environment you are in. Many functions follow ANSI standard syntax but many others do not, especially in database languages. It doesn't make sense to use a function "on an entire query".
Here is a link to the Derby version 10.10 documentation for your DOUBLE function, a function that creates a floating point value (which is why you see it displayed as "23.000000"). When you get to that page, scroll down to the functions described in the section labeled "Built-in functions". You'll also see the documentation for the CAST function as well.
And note that although I've never heard of Derby before today, having access to the documentation like this means I'd fell comfortable developing code for it if the need ever came up.
In other words, always consult the documentation for the correct version of the database you are using!

When using GETDATE() in many places, is it better to use a variable?

By better, I mean does it improve performance by some non-marginal amount?
That is to say, each time I call GETDATE(), what amount of work does the server do to return that value?
If I'm using GETDATE() in many places in a stored procedure, should I instead be creating a variable to store the date of the transaction?
declare #transDate datetime = GETDATE()
Bench-marking data would be fantastic.
EDIT I want to clarify: I'm interested mainly in the actual performance differences between these two possibilities, and whether or not it is significant.
[NOTE: If you are going to downvote this answer, please leave a comment explaining why. It has already been downvoted many times, and finally ypercube (thank you) explained at least one reason why. I can't remove the answer because it is accepted, so you might as well help to improve it.]
According to this exchange on Microsoft, GETDATE() switched from being constant within a query to non-deterministic in SQL Server 2005. In retrospect, I don't think that is accurate. I think it was completely non-deterministic prior to SQL Server 2005 and then hacked into something called "non-deterministic runtime constant" since SQL Server 2005". The later phrase really seems to mean "constant within a query".
(And GETDATE() is defined as unambiguously and proudly non-deterministic, with no qualifiers.)
Alas, in SQL Server, non-deterministic does not mean that a function is evaluated for every row. SQL Server really does make this needlessly complicated and ambiguous with very little documentation on the subject.
In practice the function call is evaluated when the query is running rather than once when the query is compiled and its value changes each time it is called. In practice, GETDATE() is only evaluated once for each expression where it is used -- at execution time rather than compile time. However, Microsoft puts rand() and getdate() into a special category, called non-deterministic runtime constant functions. By contrast, Postgres doesn't jump through such hoops, it just calls functions that have a constant value when executed as "stable".
Despite Martin Smith's comment, SQL Server documentation is simply not explicit on this matter -- GETDATE() is described as both "nondeterministic" and "non-deterministic runtime constant", but that term isn't really explained. The one place I have found the term , for instance, the very next lines in the documentation say not to use nondeterministic functions in subqueries. That would be silly advice for "nondeterministic runtime constant".
I would suggest using a variable with a constant even within a query, so you have a consistent value. This also makes the intention quite clear:
You want a single value inside the query. Within a single query, you can do something like:
select . . .
from (select getdate() as now) params cross join
. . .
Actually, this is a suggestion that should evaluate only once in the query, but there might be exceptions. Confusion arises because getdate() returns the same value on all different rows -- but it can return different values in different columns. Each expression with getdate() is evaluated independently.
This is obvious if you run:
select rand(), rand()
from (values (1), (2), (3)) v(x);
Within a stored procedure, you would want to have a single value in a variable. What happens if the stored procedure is run as midnight passes by, and the date changes? What impact does that have on the results?
As for performance, my guess is that the date/time lookup is minimal and for a query occurs once per expression as the query starts to run. This should not really a performance issue, but more of a code-consistency issue.
My suggestion would be to use a variable mainly because if you have a long-running process, the GetDate() value might be different between calls.
Unless you are only using the Date part of GetDate() then you will be sure you are always using the same value.
One reason to use a variable with getdate() or functions like suser_sname() is a huge performance difference if you are inserting rows, or if you are doing a GROUP BY. You will notice this if you insert large amount of rows.
I suffered this myself migrating 300GB of data to several tables.
I was testing on a couple of stored procedures using the GETDATE() function as a variable within an SP and I was having increase on IO reads and execution time due to the fact that query optimizer does not know what's the value to operate read this Stored Procedure Execution with Parameters, Variables, and Literals , with that said you can use the GETDATE() function in every single part of the SP as #Gordon Linoff mentioned its value does not change during execution or in order to avoid/remove the thinking that the value might change I did create a parameters this way:
CREATE PROC TestGetdate
(
#CurrentDate DATETIME = NULL
)
AS
SET CurrentDate = GETDATE()
.....
and then use the parameters as you see fit, you'll see good results
Any comments or suggestions are welcome.
I used
WHERE ActualDateShipped+30 > dbo.Today()
in combination with function below. Brought my query time from 13 seconds to 2 seconds. No prior answers in this post helped this problem in SQL 2008/R2.
CREATE FUNCTION [dbo].[Today]()
RETURNS date
AS
BEGIN
DECLARE #today date = getdate()
RETURN #today
End

Beginner SQL section: avoiding repeated expression

I'm entirely new at SQL, but let's say that on the StackExchange Data Explorer, I just want to list the top 15 users by reputation, and I wrote something like this:
SELECT TOP 15
DisplayName, Id, Reputation, Reputation/1000 As RepInK
FROM
Users
WHERE
RepInK > 10
ORDER BY Reputation DESC
Currently this gives an Error: Invalid column name 'RepInK', which makes sense, I think, because RepInK is not a column in Users. I can easily fix this by saying WHERE Reputation/1000 > 10, essentially repeating the formula.
So the questions are:
Can I actually use the RepInK "column" in the WHERE clause?
Do I perhaps need to create a virtual table/view with this column, and then do a SELECT/WHERE query on it?
Can I name an expression, e.g. Reputation/1000, so I only have to repeat the names in a few places instead of the formula?
What do you call this? A substitution macro? A function? A stored procedure?
Is there an SQL quicksheet, glossary of terms, language specification, anything I can use to quickly pick up the syntax and semantics of the language?
I understand that there are different "flavors"?
Can I actually use the RepInK "column" in the WHERE clause?
No, but you can rest assured that your database will evaluate (Reputation / 1000) once, even if you use it both in the SELECT fields and within the WHERE clause.
Do I perhaps need to create a virtual table/view with this column, and then do a SELECT/WHERE query on it?
Yes, a view is one option to simplify complex queries.
Can I name an expression, e.g. Reputation/1000, so I only have to repeat the names in a few places instead of the formula?
You could create a user defined function which you can call something like convertToK, which would receive the rep value as an argument and returns that argument divided by 1000. However it is often not practical for a trivial case like the one in your example.
Is there an SQL quicksheet, glossary of terms, language specification, anything I can use to quickly pick up the syntax and semantics of the language?
I suggest practice. You may want to start following the mysql tag on Stack Overflow, where many beginner questions are asked every day. Download MySQL, and when you think there's a question within your reach, try to go for the solution. I think this will help you pick up speed, as well as awareness of the languages features. There's no need to post the answer at first, because there are some pretty fast guns on the topic over here, but with some practice I'm sure you'll be able to bring home some points :)
I understand that there are different "flavors"?
The flavors are actually extensions to ANSI SQL. Database vendors usually augment the SQL language with extensions such as Transact-SQL and PL/SQL.
You could simply re-write the WHERE clause
where reputation > 10000
This won't always be convenient. As an alternativly, you can use an inline view:
SELECT
a.DisplayName, a.Id, a.Reputation, a.RepInK
FROM
(
SELECT TOP 15
DisplayName, Id, Reputation, Reputation/1000 As RepInK
FROM
Users
ORDER BY Reputation DESC
) a
WHERE
a.RepInK > 10
Regarding something like named expressions, while there are several possible alternatives, the query optimizer is going to do best just writing out the formula Reputation / 1000 long-hand. If you really need to run a whole group of queries using the same evaluated value, your best bet is to create view with the field defined, but you wouldn't want to do that for a one-off query.
As an alternative, (and in cases where performance is not much of an issue), you could try something like:
SELECT TOP 15
DisplayName, Id, Reputation, RepInk
FROM (
SELECT DisplayName, Id, Reputation, Reputation / 1000 as RepInk
FROM Users
) AS table
WHERE table.RepInk > 10
ORDER BY Reputation DESC
though I don't believe that's supported by all SQL dialects and, again, the optimizer is likely to do a much worse job which this kind of thing (since it will run the SELECT against the full Users table and then filter that result). Still, for some situations this sort of query is appropriate (there's a name for this... I'm drawing a blank at the moment).
Personally, when I started out with SQL, I found the W3 schools reference to be my constant stopping-off point. It fits my style for being something I can glance at to find a quick answer and move on. Eventually, however, to really take advantage of the database it is necessary to delve into the vendors documentation.
Although SQL is "standarized", unfortunately (though, to some extent, fortunately), each database vendor implements their own version with their own extensions, which can lead to quite different syntax being the most appropriate (for a discussion of the incompatibilities of various databases on one issue see the SQLite documentation on NULL handling. In particular, standard functions, e.g., for handling DATEs and TIMEs tend to differ per vendor, and there are other, more drastic differences (particularly in not support subselects or properly handling JOINs). If you care for some of the details, this document provides both the standard forms and deviations for several major databases.
You CAN refer to RepInK in the Order By clause, but in the Where clause you must repeat the expression. But, as others have said, it will only be executed once.
There are good answers for the technical problem already, so I'll only address some of the rest of your questions.
If you're just working with the DataExplorer, you'll want to familiarize yourself with SQL Server syntax since that's what it's running. The best place to find that, of course, is MSDN's reference.
Yes, there are different variations in SQL syntax. For example, the TOP clause in the query you gave is SQL Server specific; in MySQL you'd use the LIMIT clause instead (and these keywords don't necessarily appear in the same spot in the query!).