Behaviour of NOT LIKE with NULL values
About NULL
'anything' NOT LIKE NULL
yields NULL
, not TRUE
.
And only TRUE
qualifies for filter expressions in a WHERE
clause.
Most functions return NULL
on NULL
input (there are exceptions). That's the nature of NULL
in any proper RDBMS.
If you desire a single expression, you could use:
AND (column_default LIKE 'nextval%') IS NOT TRUE;
That's hardly shorter or faster, though. Details in the manual.
Proper query
Your query is still unreliable. A table name alone is not unique in a Postgres database, you need to specify the schema name in addition or rely on the current search_path
to find the first match in it:
Related:
- How does the search_path influence identifier resolution and the "current schema"
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'hstore1'
AND table_schema = 'public' -- your schema!
AND (column_default IS NULL OR
column_default NOT LIKE 'nextval%');
Better, but still not bullet-proof. A column default starting with 'nextval' does not make a serial
, yet. See:
- Auto increment table column
To be sure, check whether the sequence in use is "owned" by the column with pg_get_serial_sequence(table_name, column_name)
.
I rarely use the information schema myself. Those slow, bloated views guarantee portability across major versions - and aim at portability to other standard-compliant RDBMS. But too much is incompatible anyway. Oracle does not even implement the information schema (as of 2015).
Also, useful Postgres-specific columns are missing in the information schema. For this case I might query the the system catalogs like this:
SELECT *
FROM pg_catalog.pg_attribute a
WHERE attrelid = 'table1'::regclass
AND NOT attisdropped -- no dropped (dead) columns
AND attnum > 0 -- no system columns
AND NOT EXISTS (
SELECT FROM pg_catalog.pg_attrdef d
WHERE (d.adrelid, d.adnum) = (a.attrelid, a.attnum)
AND d.adsrc LIKE 'nextval%'
AND pg_get_serial_sequence(a.attrelid::regclass::text, a.attname) <> ''
);
Faster and more reliable, but less portable.
The manual:
The catalog
pg_attrdef
stores column default values. The main
information about columns is stored inpg_attribute
(see below). Only
columns that explicitly specify a default value (when the table is
created or the column is added) will have an entry here.
'table1'::regclass
uses the search_path
to resolve the name, which avoids ambiguity. You can schema-qualify the name to overrule: 'myschema.table1'::regclass
.
Related:
- Find the referenced table name using table, field and schema name
- Get the default values of table columns in Postgres?
Does Oracle 'NOT LIKE' expression do not return NULL?
NULL is not matched with LIKE
. You have to explicitly ask for it with OR firstname IS NULL
Not equal != operator on NULL
<>
is Standard SQL-92; !=
is its equivalent. Both evaluate for values, which NULL
is not -- NULL
is a placeholder to say there is the absence of a value.
Which is why you can only use IS NULL
/IS NOT NULL
as predicates for such situations.
This behavior is not specific to SQL Server. All standards-compliant SQL dialects work the same way.
Note: To compare if your value is not null, you use IS NOT NULL
, while to compare with not null value, you use <> 'YOUR_VALUE'
. I can't say if my value equals or not equals to NULL, but I can say if my value is NULL or NOT NULL. I can compare if my value is something other than NULL.
Is SQL LIKE NULL valid syntax for all database?
Yes, LIKE NULL
is valid in all RDBMS. LIKE
is an operator followed by a string and a string can be null; so no problem.
Comparing a value to NULL
, no matter what operator (<
, <=
, =
, <>
, LIKE
, etc. - except for IS
which is especially made to compare with NULL
), results in UNKNOWN
. UNKNOWN
is not TRUE
, so the condition is not met in case of NULL
. And anyway, in case @firstName
contains NULL
, @firstName IS NULL
evaluates to TRUE
, so it doesn't even matter what LIKE @firstName
results in then (because @firstName IS NULL OR firstName LIKE @firstName
is TRUE
when at least one of the two conditions is TRUE
).
NOT IN with Nulls - unclear behaviour
First query returns no data because of comparing null values.
When you compare 2 values result could be
TRUE
if they equalsFALSE
if they're notUNKNOWN
if one or two of the values is null
So when you use not in
sql should compare your value glnfact
with all values of GLN
in the subquery and if all compares return FALSE
, then it returns TRUE
for the whole not in
clause. If one of the value of GLN
is null, comparing it with glnfact
returns UNKNOWN
so not in
clause is UNKNOWN
.
NOT Like or in an NVARCHAR field is also filtering out Null - SQL Server 2008
Then use IS NULL
+ OR <> N'Complete'
:
SELECT TOP (1) dbo.woo.woo_statuscode,
dbo.woo.woo_workcenterid
FROM dbo.woo
LEFT OUTER JOIN dbo.wke
ON dbo.woo.woo_recordid = dbo.wke.wke_woo_recordid
LEFT OUTER JOIN dbo.wko
ON dbo.woo.woo_workorderid = dbo.wko.wko_workorderid
WHERE ( dbo.wko.wko_workorderid = @WorkOrder )
AND (dbo.woo.woo_statuscode IS NULL OR dbo.woo.woo_statuscode <> N'Complete')
ORDER BY dbo.wke.wke_labstoptime DESC
Why you can't select null values with =
or <>
:
<>
is Standard SQL-92;!=
is its equivalent. Both evaluate for
values, whichNULL
is not --NULL
is a placeholder to say there is
the absence of a value.Which is why you can only use
IS NULL
/IS NOT NULL
as predicates
for such situations.This behavior is not specific to SQL Server. All standards-compliant
SQL dialects work the same way.
https://stackoverflow.com/a/5658472/284240
You can change this behaviour via SET ANSI NULLS OFF
.
Strange behaviour SQL on comparing null values
demo: db<>fiddle
SELECT *
FROM br
LEFT JOIN af
ON
br.col1 = af.col1
AND br.col2 = af.col2
AND COALESCE(br.col3, af.col3, br.col4, af.col4) IS NULL
The COALESCE() IS NULL
ensures that all elements in this function (all columns) are NULL
.
NULL values inside NOT IN clause
Query A is the same as:
select 'true' where 3 = 1 or 3 = 2 or 3 = 3 or 3 = null
Since 3 = 3
is true, you get a result.
Query B is the same as:
select 'true' where 3 <> 1 and 3 <> 2 and 3 <> null
When ansi_nulls
is on, 3 <> null
is UNKNOWN, so the predicate evaluates to UNKNOWN, and you don't get any rows.
When ansi_nulls
is off, 3 <> null
is true, so the predicate evaluates to true, and you get a row.
Related Topics
Ssdt Failing to Publish: "Unable to Connect to Master or Target Server"
SQL Server Permissions on Stored Procs with Dynamic SQL
SQL Injections with Prepared Statements
How to Write a Function in the H2 Database Without Using Java
Get Excel Sheet into Temp Table Using a Script
Equivalent Function to Stuff in SQL (Group_Concat in Myssql/Listagg in Oracle)
Is There a Simple Way to Query the Children of a Node
Select Databases Which Only Contain Specific Table
Split a Varchar in Db2 to Retrieve a Value Inside
Select Multiple Tables When One Table Is Empty in MySQL
How to Execute SQL Statements Saved in a Table with T-Sql
Xml Oracle:Multiple Child Node Extract
Sql: Error, Expression Services Limit Reached
How to Use Regular Expression in SQL Server
How to Use Elasticsearch to Get Join Functionality as in SQL
Sane/Fast Method to Pass Variable Parameter Lists to SQLserver2008 Stored Procedure
How to Insert Multiple Rows with a Foreign Key Using a Cte in Postgres