How to check for null values in a row? - postgresql

I want the rows in which there is at least one column with a null value. I've tried to use a row expression like:
SELECT *
FROM <table>
WHERE <table> IS NULL
But it does not work. Is my query incorrect or?
PS I am using version 13.4

You can reference the table alias in the WHERE clause. The condition where the_table is not null would return the rows where all columns are not null.
The opposite of that (where at least one column is null) can be achieved by negating the expression:
select *
from the_table
where not (the_table is not null);
Looks a bit strange, but it's not the same as the_table is null - which is never true, as the reference to the table (alias) refers to an existing row. And if a row exists the the "whole row" can't be null.
This:
with the_table (col1, col2, col3) as (
values
(1,null,null),
(null,2,null),
(null,3,4),
(5,6,7)
)
select *
from the_table
where not (the_table is not null);
returns:
col1 | col2 | col3
-----+------+-----
1 | |
| 2 |
| 3 | 4

to check if the value is not null, you use the IS NOT NULL operator
value IS NOT NULL
The expression returns true if the value is NULL or false if it is not.

You need to mention your column name in the search.
SELECT * FROM <table_name> WHERE <column_name> IS NULL;
For more than one columns:
SELECT * FROM <table_name> WHERE <column1_name> IS NULL OR <column2_name> IS NULL;

Related

Replace Infinity values in a PostgreSQL numeric[] array field

I have a table in a PG 14 database having a column containing Infinity values in numeric[] arrays as follow:
SELECT id, factors_list FROM mytable ORDER BY id ASC LIMIT 2;
id | factors_list
---+-------------
1 | {Infinity,1,2.91825,2.2911174796669,1.58367915763394,1.96345397169765,1.41599564744287}
2 | {Infinity,1,1.0625,2.114,4.25,2.18021276595745}
The data type of this column is ARRAY (numeric[]) and the length of the array is variable (with some records being NULL):
SELECT column_name, data_type FROM information_schema.columns WHERE
table_name = 'mytable' AND column_name = 'factors_list';
column_name | data_type
----------------+-----------
factors_list | ARRAY
In order to restore this database table into an older (<14) PG database, I need to replace all Infinity values by any valid number, let's say 99999999.
How could I achieve that in an efficient way? (I have roughly 200'000 rows)
This simple update statement should do the job:
UPDATE mytable
SET factors_list = array_replace(factors_list, 'Infinity', 99999999)
WHERE TRUE;

add Exists operator in a union sql query

I have two tables that am using union to combine the result-set of them my problem here is Each SELECT statement within UNION must have the same number of columns and data types, I don't have the same number of columns so am creating null columns
select
d.deal_id as order_id,
EXISTS(select * from table1 c where d.user_id = c.user_id) as IsUser, --this returns boolean value
from table 1 c
union
select
cast(o.id as varchar) as order_id,
coalesce('No_user'::text,'0'::text) as IsUser, --i get an error :UNION types boolean and character varying cannot be matched
from table2 o
how can I create a null column in table2 that matches the boolean data type of the table1
how can I create a null column in table2 that matches the boolean data type of the table1
By putting NULL into the SELECT list of the second query.
Generally (in SQL) the datatype for the column is dictated by the first query in the union set and other queries must match. You don't need column aliases for subsequent queries either, but they may help make a query more readable:
select
d.deal_id as order_id,
EXISTS(select * from table1 c where d.user_id = c.user_id) as IsUser, --this returns boolean value
from table 1 c
union
select
cast(o.id as varchar) as order_id,
null --IsUser
from table2 o
If you have a case where the type of the column in the first query is different to what you want in the output, you cast the first column:
select 1::boolean as boolcol
UNION
select true
This will ensure that the column is boolean, rather than giving a "integer and bool cannot be matched". Remember also that, should you need to, NULL can be cast to a type, e.g. select null::boolean as bolcol

Set the value of a column to its default value

I have few existing tables in which I have to modify various columns to have a default value.
How can I apply the default value to old records which are NULL, so that the old records will be consistent with the new ones
ALTER TABLE "mytable" ALTER COLUMN "my_column" SET DEFAULT NOW();
After modifying table looks something like this ...
Table "public.mytable"
Column | Type | Modifiers
-------------+-----------------------------+-----------------------------------------------
id | integer | not null default nextval('mytable_id_seq'::regclass)
....
my_column | timestamp(0) with time zone | default now()
Indexes:
"mytable_pkey" PRIMARY KEY, btree (id)
Is there a simple to way to have all columns which are currently null and also which have a default value to be set to the default value ?
Deriving from insert into:
For clarity, you can also request default values explicitly, for individual columns or for the entire row:
INSERT INTO products (product_no, name, price) VALUES (1, 'Cheese', DEFAULT);
INSERT INTO products DEFAULT VALUES;
I just tried this, and it is as simple as
update mytable
set my_column = default
where my_column is null
See sqlfiddle
Edit: olaf answer is easiest and correct way of doing this however the below also is viable solution for most cases.
For a each column it is easy to use the information_schema and get the default value of a column and then use that in a UPDATE statement
UPDATE mytable set my_column = (
SELECT column_default
FROM information_schema.columns
WHERE (table_schema, table_name, column_name) = ('public', 'mytable','my_column')
)::timestamp
WHERE my_column IS NULL;
Note the sub-query must by typecast to the corresponding column data type .
Also this statement will not evaluate expressions as column_default will be of type character varying it will work for NOW() but not for expressions like say (NOW()+ interval ' 7 days')
It is better to get expression and validate it then apply it manually

postgres array field with select in condition

I have a POSTGRES field with 2 fields - integer arrayfield and integer field.
CREATE TABLE test.public.polls (
"id" serial NOT NULL,
field_1 _int4,
field_2 int4 NOT NULL,
PRIMARY KEY ("id")
);
and the values are
1) Now I need to check if any of the field value {1,2,3} is in the field_1
something like this -
select * from test.public.polls
where field_1 = ANY ('{1,2,3}'::int[])
but this throws an error
operator does not exist: integer[] = integer
2) Need to check if any of the id values = {2,3,4} is in the field_1
select * from test.public.polls
where field_1 = array(id)
not sure what should be the syntax for this.
Since your field_1 seems to be an array then following should work (this is called overlapping):
select *
from yourtable
where field_1 && '{1,2,3}'::int[]
For the second part it seems like you'd like to aggregate id column and check whether any value from the aggregated set exists within field_1:
select *
from yourtable
where field_1 && (select array_agg(id) from yourtable)
Use overlap operator &&
SELECT *
FROM polls
WHERE '{1,2,3}' && field_1
Here is a SQLFiddle

PostgreSQL - check if a row is completely filled in

I've seen questions for checking if a row merely exists, But I haven't seen anything (on SO or elsewhere) about whether or not all the data is filled in.
I was hoping that SELECT true FROM myTable WHERE name='myRow' AND * IS NOT NULL; would work, but it doesn't.
What wildcard will work in place of the asterisk, if there is one? Will I have to put in each column name into the query individually?
You can indeed reference the whole row, but not using *, but by using the table name:
SELECT true
FROM myTable
WHERE name='myRow'
AND myTable IS NOT NULL;
The IS NOT NULL operator on a row value returns true if all columns of the row are not null.
The following statement:
with mytable (col1, col2, col3) as (
values
(1,null,null),
(null,1,null),
(null,null,1),
(1,1,1)
)
select *
from mytable
where mytable is not null;
will return:
col1 | col2 | col3
-----+------+-----
1 | 1 | 1
The opposite btw. is not true. where mytable is null will not return anything because a row is by definition never null (because then it wouldn't exist). To find rows where at least one column is null you would need to use where not (mytable is not null)
A similar problem is described here: https://dba.stackexchange.com/q/143959/1822