Is there a way in sql to, by default bring back values regardless of if they are true or false?
for example I have a column, 'Mandatory' which datatype is a bit.
Is there a way to bring back records where the column 'Mandatory' is either true or false or null?
something like
Select * From Table Where Mandatory = .... etc
select * from Table
where mandatory is null or mandatory in (0,1)
If the mandatory is a bit, this code is definitely true. There is no other possibility.
Let me assume you are using SQL Server -- because it supports bit but not boolean.
You can use:
where mandatory = 1
or
where mandatory = 'true'
resolved by doing this
ISNULL(Mandatory,0) =
CASE
WHEN #Mandatory = 0 THEN 0
WHEN #Mandatory = 1 THEN 1
WHEN #Mandatory = 2 THEN ISNULL(Mandatory,0)
essentially saying that when 2 is inputted, it will bring back all values for true, false and null. works very well
The question is how to run a binary logic into trinary logic.
Binary = There are distinct, actual values: in regards to this question the values [True] or [False]
Trinary = There are distinct, actual values plus unknown values: in regards to this question the values [ True | False | NULL ]
It is not possible to include unknown values in a single WHERE condition. Instead it has to be checked separately:
WHERE mandatory IN (0, 1) -- check whether TRUE or FALSE against bit
OR mandatory IS NULL -- also include UNKNOWN
This approach is better than using a function as a function in a WHERE condition can (and will) lead more often than not to performance losses.
Related
I have a SQL table that has a bit column named "Split".
I need to create a stored procedure that receives a parameter named WithSplit of type bit.
If WithSplit is false then I need to get all the records that have the "Split" column equal to false.
If WithSplit is true, then I need to get the records having the "Split" column value either true or false.
That is , if WithSplit is false then get only the records where split=withsplit, else get all records.
How should this be achieved?
I have found the answer:
(Split = #WithSplit or #WithSplit = case when #WithSplit =1 then 1 end)
I understand that SQL uses three valued logic but I am having trouble understanding how to use this in practice, especially why TRUE || NULL = True and FALSE && NULL = False instead of evaluating to null.
Here are the three valued truth tables that apply to SQL Server:
I found a couple explanations of three valued logic online but I cannot find any real code examples of this in use. Can someone show me a code example using three valued logic to help me understand this a little better?
An example of TRUE || NULL = True would be
declare #x as int = null;
if 1=1 or #x/1=1
print 'true'
An example of FALSE && NULL = False would be
declare #x as int = null;
if not(1=2 and #x/1=1)
print 'false'
True && NULL is neither True or False. It's just NULL.
Whether that will evaluate as True, False, or an Error in a boolean expression depends on what happens on your system when you evaluate NULL by itself as a boolean. Sql Server will do everything it can to avoid choosing, but when forced you'll pretty much never see a positive (True) result.
Generally speaking from a user standpoint, you don't want a Boolean expression to evaluate to NULL.
Writing SQL typically involves writing queries to explicitly avoid NULL values in Boolean expressions. IMX, developers would consider using three valued logic intentionally would be considered an abuse of three valued logic. A properly written query should handle NULLs and understand them. You don't write them in such a way that they happen to work right when something is NULL. Usually this involves COALESCE() or IS NULL or IS NOT NULL somewhere.
It is, however, vital that you understand the logic, because NULLs exist and are unavoidable for most real-world data.
For example, let's say I'm working on a table of students. The table has First, Middle, and Last name fields. I want to know the list of students that don't have a middle name. Now, some applications will store an empty string, '', and some applications will store a NULL value, and some applications might do both (and some RDBMSs like Oracle treat empty strings as NULLs). If you were unsure, you could write it as:
SELECT *
FROM Student
WHERE MiddleName = ''
OR MiddleName IS NULL;
The other common scenario is when you're OUTER JOINing to another table. Let's say you're comparing the paychecks for teachers. You have a table for Checks, and a table for CheckDetail. You want to know how much teachers pay for Benefits. Your report needs to list all teachers, even if they're contractors who don't pay for benefits because they don't get any:
SELECT Check.Employee_Id,
SUM(CheckDetail.Amount) AS BenefitsDeductions
FROM Check
LEFT JOIN CheckDetail
ON Check.Id = CheckDetail.CheckId
AND CheckDetail.LineItemType = 'Benefits'
GROUP BY Check.Employee_Id;
You run your report, and you notice that your contractor teachers show NULL for BenefitsDeductions. Oops. You need to make sure that shows up as a zero:
SELECT Check.Employee_Id,
COALESCE(SUM(CheckDetail.Amount),0) AS BenefitsDeductions
FROM Check
LEFT JOIN CheckDetail
ON Check.Id = CheckDetail.CheckId
AND CheckDetail.LineItemType = 'Benefits'
GROUP BY Check.Employee_Id;
So you try that, and it works. No NULL values! But... a few days later, your users report that teachers who used to be contractors are showing up with 0s even though they're paying for benefits now. You've got to COALESCE before the SUM to keep those amounts:
SELECT Check.Employee_Id,
SUM(COALESCE(CheckDetail.Amount,0)) AS BenefitsDeductions
FROM Check
LEFT JOIN CheckDetail
ON Check.Id = CheckDetail.CheckId
AND CheckDetail.LineItemType = 'Benefits'
GROUP BY Check.Employee_Id;
Finding these kinds of corner cases and exceptions is what writing SQL is all about.
The code example by user4955163 is a great visualization of this, however I just wanted to step back in to address the first segment of the question:
...especially why TRUE || NULL = True and FALSE && NULL = False instead
of evaluating to null...
TRUE || NULL = True
This is because the or operator will short-circuit if one operand is already known to be true. No matter what the second operand is (even if unknown, ie. "NULL"), it wouldn't make the expression false since we already know the other operand is true. or only needs one operand to be true, to evaluate to true.
FALSE && NULL = False
This is because the and operator will short-circuit if one operand is already known to be false. No matter what the second operand is (even if unknown, ie. "NULL"), it wouldn't make the expression true since we already know the other operand is false. and needs both operands to be true to evaluate to true.
To use a nullable variable you just need to check NULL conditions (using IS NULL) before checking the value.
e.g. IF #a IS NOT NULL AND #a = 1
I have a bit column on a table in a SQL Server 2012 database.
I am trying to retrieve all the rows where this bit column is either NULL or NOT TRUE.
This query does not bring back what it should: (returns 0 rows)
Select *
from table
where bit_column_value <> 1
This query brings back the correct rows:
Select *
from table
where bit_column_value IS NULL
Now, I'd be happy to use the second query, but my issue is that, in a similar query for another table, the reverse of the above is true, where the first way works, but the second way does not!
Could someone assist in explaining what the difference is in the above? I have specifically updated the relevant bit columns to be NULL and this does not change the results. (Thought maybe there was a difference between "Empty" and Null values.
Thanks in advance for any explanations.
The reason <> doesn't work is that SQL treats NULL as unknown - it doesn't know what NULL is supposed to mean, so it evaluates both = and <> on a NULL value as UNKNOWN (which is treated as false in a where clause or join condition). For more info, read this: Why does NULL = NULL evaluate to false in SQL server.
If there's an index on it, using the ISNULL function will mean the index can't be used, so to
ensure the query can use the index just use OR:
SELECT *
FROM TableName
WHERE
bit_column_value IS NULL OR bit_column_value = 0
your best bet would be to write the query as such:
SELECT
*
FROM
table
WHERE
ISNULL(bit_column_value, 0) = 0
This should return all the NULL and FALSE records.
Without seeing your table structure and data, I cannot really comment on why you are getting different results from your 2 queries.
MSDN says that the BIT type can store values 0, 1 or NULL. (The fact that a BIT value is NULL must be stored separately from the bit value itself, since the bit values can be compressed so that 8 BIT values are stored in a byte.)
Remember that a condition in a WHERE clause selects a row when the condition is TRUE. For most binary predicates (conditions), if you compare NULL with some value, the result is NULL or UNKNOWN (not TRUE). So, for example, if the value in a column is NULL, then column = 0 evaluates to NULL or UNKNOWN, and so does column <> 0.
Looking at your queries:
SELECT * FROM table WHERE bit_column_value <> 1
Where the value in the bit_column_value column is 1, the condition is FALSE so the row is not returned; where the value is 0, the condition is TRUE so the row is returned; and where the value is NULL, the condition is also NULL or UNKNOWN so the row is not returned.
SELECT * FROM table WHERE bit_column_value IS NULL
According to the SQL standard, the IS [NOT] NULL predicate, and the related IS [NOT] {TRUE|FALSE|UNKNOWN} predicates, are slightly different. The IS NULL test returns TRUE if the tested value is NULL; otherwise, they return FALSE (and never return UNKNOWN). The IS [NOT] {TRUE|FALSE|UNKNOWN} tests are similar; they return TRUE if the value is of the specified type and FALSE otherwise (not UNKNOWN). For example:
Column IS TRUE IS FALSE IS UNKNOWN IS NOT TRUE IS NOT FALSE IS NOT UNKNOWN
FALSE FALSE TRUE FALSE TRUE FALSE TRUE
TRUE TRUE FALSE FALSE FALSE TRUE TRUE
NULL FALSE FALSE TRUE TRUE TRUE FALSE
So, in your second query, only the rows where the bit_column_value value is NULL (which is separate from both 0 and 1) will be selected — not the TRUE, nor the FALSE.
I am trying to retrieve all the rows where this bit column is either NULL or NOT TRUE.
Try writing the query directly from your specification:
SELECT * FROM table WHERE bit_column_value IS NULL OR bit_column_value IS NOT TRUE
SELECT * FROM table WHERE bit_column_value IS NULL OR bit_column_value = FALSE
SELECT * FROM table WHERE bit_column_value IS NULL OR bit_column_value <> TRUE
SELECT * FROM table WHERE bit_column_value IS NOT TRUE
Given the truth table above, query 4 would yield the result you want — with the major caveat that I'm not certain that MS SQL Server supports the IS [NOT] {TRUE|FALSE|UNKNOWN}. Judging from MSDN on Predicates, the IS [NOT] {TRUE|FALSE|UNKNOWN} predicates are not supported (but I might have missed the correct part of the manual). If that's correct, you need to use one of query 2 or 3.
(There are some extra complications with these predicates when the value is not a simple column but is a row value. However, that's not relevant to your question or problem; doubly not since MS SQL Server does not seem to support them.)
Please check your table data, if it's contain value = 0 ?
SQL Bit data type can only have value either 0, 1 or NULL, if you insert other value, it's considered to 1 (Exception : If you insert 'False' it will became 0, 'True' will became 1).
For example :
insert into t1 values (1),(2),(1),(3),(-1),(0),(NULL),('false'),('true')
The result :
1, 1, 1, 1, 1, 0, NULL, 0, 1
I think this is because that all the data have NULL values in this column. So:
Select *
from table
where bit_column_value <> 1;
Won't give you the result. Since NULL is unknown. And this:
Select *
from table
where bit_column_value IS NULL;
Will give you the result you are looking for.
But you have a misconception of representing true and false using the bit data type.
You are representing false as NULL, 0 is empty and true is any other value. The bit data types works as #IswantoSan explained in his answer; It should be 0 or 1 or NULL:
0 is false,
1 is true,
NULL is empty.
Therefore to get:
true values use the where bit_column_value = 1.
false values use the where bit_column_value = 0.
NULL or empty where bit_column_value IS NULL.
NULL or not true:where bit_column_value IS NULL or bit_column_value = 0`.
The other thing to note is that NULL and empty are two different things, they are not the same. In case of the BIT data type empty is NULL not 0, because 0 is supposed to be false. But consider a string data type like VARCHAR for example then the empty string '' is totally different from the NULL value.
In SQL , why does 10/NULL evaluate to NULL (or unknown) ? Example :
if((10/NULL) is NULL)
DBMS_OUTPUT.PUT_LINE("Null.");
However , 1 = NULL being a COMPARISON is considered as FALSE. Shouldn't 10/NULL also be considered as FALSE ?
I am referring to SQL only . Not any DBMS in particular. And it might be a duplicate but I didn't know what keywords to put in search for this query.
Shouldn't 10/NULL also be considered as FALSE?
No, because:
Any arithmetic expression containing a null always evaluates to null. For example, null added to 10 is null. In fact, all operators (except concatenation) return null when given a null operand.
Emphasis mine, taken from the Oracle manual: http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements005.htm#i59110
And this is required by the SQL standard.
Edit, as the question was for RDBMS in general:
SQL Server
When SET ANSI_NULLS is ON, an operator that has one or two NULL expressions returns UNKNOWN
Link to the the manual:
MySQL
An expression that contains NULL always produces a NULL value unless otherwise indicated in the documentation for a particular function or operator
Link to the manual
DB2
if either operand can be null, the result can be null, and if either is null, the result is the null value
Link to the manual:
PostgreSQL
Unfortunately I could not find such an explicit statement in the PostgreSQL manual, although I sure it behaves the same.
Warning: The "(except concatenation)" is an Oracle only and non-standard exception. (The empty string and NULL are almost identical in Oracle). Concatenating nulls gives null in all other DBMS.
1 = null is not null. It is actually unknown. As well as any other null operation.
The equality predicate 1 = NULL evaluates to NULL. But NULL in a boolean comparison is considered false.
If you do something like NOT( 1 = NULL ), 1 = NULL evaluates to NULL, NOT( NULL ) evaluates to NULL and so the condition as a whole ends up evaluating to false.
Oracle has a section in their documentation on handling NULL values in comparisons and conditional statements-- other databases will handle things in an very similar manner.
10/something means that you are counting how much "something" will be in 10
in this case you're counting how much "nothing" will be in 10 - that's infinity, unknown..
1 = NULL is false because one does not equal nothing
The NULLIF function accepts two parameters. If the first parameter is equal to the second parameter, NULLIF returns Null. Otherwise, the value of the first parameter is returned.
NULLIF(value1, value2)
NVL
The NVL function accepts two parameters. It returns the first non-NULL parameter or NULL if all parameters are NULL.
also check this conditional outcomes:
This "null equals UNKNOWN truth value" proposition introduces an inconsistency into SQL 3VL. One major problem is that it contradicts a basic property of nulls, the property of propagation. Nulls, by definition, propagate through all SQL expressions. The Boolean truth values do not have this property. Consider the following scenarios in SQL:1999, in which two Boolean truth values are combined into a compound predicate. According to the rules of SQL 3VL, and as shown in the 3VL truth table shown earlier in this article, the following statements hold:
( TRUE OR UNKNOWN ) → TRUE
( FALSE AND UNKNOWN ) → FALSE
However, because nulls propagate, treating null as UNKNOWN results in the following logical inconsistencies in SQL 3VL:
( TRUE OR NULL ) → NULL ( = UNKNOWN )
( FALSE AND NULL ) → NULL ( = UNKNOWN )
The SQL:1999 standard does not define how to deal with this inconsistency, and results could vary between implementations. Because of these inconsistencies and lack of support from vendors the SQL Boolean datatype did not gain widespread acceptance. Most SQL DBMS platforms now offer their own platform-specific recommendations for storing Boolean-type data.
Note that in the PostgreSQL implementation of SQL, the null value is used to represent all UNKNOWN results and the following evaluations occur:
( TRUE OR NULL ) → TRUE
( FALSE AND NULL ) → FALSE
( FALSE OR NULL ) IS NULL → TRUE
( TRUE AND NULL ) IS NULL → TRUE
I have an SQL server database that I am querying and I only want to get the information when a specific row is null. I used a where statement such as:
WHERE database.foobar = NULL
and it does not return anything. However, I know that there is at least one result because I created an instance in the database where 'foobar' is equal to null. If I take out the where statement it shows data so I know it is not the rest of the query.
Can anyone help me out?
Correct syntax is WHERE database.foobar IS NULL. See http://msdn.microsoft.com/en-us/library/ms188795.aspx for more info
Comparison to NULL will be false every time. You want to use IS NULL instead.
x = NULL -- always false
x <> NULL -- always false
x IS NULL -- these do what you want
x IS NOT NULL
Read Testing for Null Values, you need IS NULL not = NULL
Is it an SQL Server database?
If so, use IS NULL instead of making the comparison (MSDN).