How to select empty paths with POSTGRES LTREE - postgresql

I have a simple table defined in Postgres, where I'm using LTREE, but some rows can have empty paths:
CREATE TABLE films (
id serial PRIMARY KEY,
title varchar(40) NOT NULL,
path ltree DEFAULT NULL
);
If I insert the following values into the table,
INSERT INTO films (title, path)
VALUES ('first', 'A'),('second', 'A.B'),('third', NULL);
then try to select the rows with empty paths,
SELECT * FROM films WHERE path=NULL;
I get empty rows:
id | title | path
----+-------+------
(0 rows)
How should I modify the query to return rows with empty paths? Thanks!

The result of comparison operation with at least one operand is NULL always returns NULL. Thus your predicate where path = null always returns null, but the to select a row the expression must return True. Use instead:
SELECT * FROM films WHERE path is NULL;

Related

Pass an array to a query in Postgres to check if a value is contained in the array

I have an array with some ids on the front-end and I'm writing a query to check if I can find any user with a user_id inside the array, the table is very simple:
CREATE TABLE user_accounts (
user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE,
name TEXT,
connector_type connector_type_enum NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
);
The array on the front-end is something like ["328hdgyas78g2", "3adhdayas7453"]
and here's the query:
SELECT *
FROM user_accounts
WHERE user_id IN $1
of course there's a syntax error, I have tried the following:
SELECT *
FROM user_accounts
WHERE user_id = ANY(ARRAY["328hdgyas78g2", "3adhdayas7453"])
but I get the following error:
ERROR: column "328hdgyas78g2" does not exist
How can I fix the query?
That's because the " is used to reference a column or table name. To reference a string you use the single '
You have a couple of options there
WHERE user_id = ANY(ARRAY['328hdgyas78g2', '3adhdayas7453'])
or
WHERE user_id = ANY('{328hdgyas78g2,3adhdayas7453}')
Also, good reference is this

Output Inserted.id equivalent in Postgres

I am new to PostgreSQL and trying to convert mssql scripts to Postgres.
For Merge statement, we can use insert on conflict update or do nothing but am using the below statement, not sure whether it is the correct way.
MSSQL code:
Declare #tab2(New_Id int not null, Old_Id int not null)
MERGE Tab1 as Target
USING (select * from Tab1
WHERE ColumnId = #ID) as Source on 0 = 1
when not matched by Target then
INSERT
(ColumnId
,Col1
,Col2
,Col3
)
VALUES (Source.ColumnId
,Source.Col1
,Source.Col2
,Source.Col3
)
OUTPUT INSERTED.Id, Source.Id into #tab2(New_Id, Old_Id);
Postgres Code:
Create temp table tab2(New_Id int not null, Old_Id int not null)
With source as( select * from Tab1
WHERE ColumnId = ID)
Insert into Tab1(ColumnId
,Col1
,Col2
,Col3
)
select Source.ColumnId
,Source.Col1
,Source.Col2
,Source.Col3
from source
My query is how to convert OUTPUT INSERTED.Id in postgres.I need this id to insert records in another table (lets say as child tables based on Inserted values in Tab1)
In PostgreSQL's INSERT statements you can choose what the query should return. From the docs on INSERT:
The optional RETURNING clause causes INSERT to compute and return value(s) based on each row actually inserted (or updated, if an ON CONFLICT DO UPDATE clause was used). This is primarily useful for obtaining values that were supplied by defaults, such as a serial sequence number. However, any expression using the table's columns is allowed. The syntax of the RETURNING list is identical to that of the output list of SELECT. Only rows that were successfully inserted or updated will be returned.
Example (shortened form of your query):
WITH [...] INSERT INTO Tab1 ([...]) SELECT [...] FROM [...] RETURNING Tab1.id

PostgreSQL query by string is filtering even the values where there are nulls.

I've created a table in PostgreSQL 9.5 as shown below and I added some data to it. However, when I try and query data by case insensitive search like !~* it removes even the null value rows. How can I do a query that will return all categories that are null and vegetables but not fruits?
CREATE TABLE temp
(
category character varying,
item character varying
);
INSERT INTO temp VALUES('Fruits', 'apple');
INSERT INTO temp VALUES('FRUITS', 'applE');
INSERT INTO temp(item) VALUES('Apple');
INSERT INTO temp(item) VALUES('BANANA');
INSERT INTO temp VALUES('Vegetables', 'Cabbage');
Query
Select * from temp where category !~* 'fruits'
Output
category item
-------- --------
Vegetables Cabbage
To deal with the null you can use is distinct from:
Select *
from temp
where lower(category) is distinct from 'fruits'
or if you do want the regular expression:
Select *
from temp
where category !~* 'fruits'
or category is null;
alternatively treat null as something else:
Select *
from temp
where coalesce(category, '') !~* 'fruits'

updating a varchar column with multiple select stmts

I have to update a VARCHAR column of a table by concatenating values from SELECT queries from another table. I have build a query like
UPDATE url SET VALUE = (SELECT id FROM ids WHERE identifier='site')':'(SELECT id FROM cids WHERE identifier='cid')
WHERE name='SToken:CToken'
AND tokenvalue LIKE (SELECT id FROM ids WHERE identifier='site');
Here value is VARCHAR.
How should I do this?

Ambiguous column in PostgreSQL UPSERT (writeable CTE) using one table to update another

I have a table called users_import into which I am parsing and importing a CSV file. Using that table I want to UPDATE my users table if the user already exists, or INSERT if it does not already exist. (This is actually a very simplified example of something much more complicated I'm trying to do.)
I am trying to do something very similar to this:
https://stackoverflow.com/a/8702291/912717
Here are the table definitions and query:
CREATE TABLE users (
id INTEGER NOT NULL UNIQUE PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE users_import (
id INTEGER NOT NULL UNIQUE PRIMARY KEY,
name TEXT NOT NULL
);
WITH upsert AS (
UPDATE users AS u
SET
name = i.name
FROM users_import AS i
WHERE u.id = i.id
RETURNING *
)
INSERT INTO users (name)
SELECT id, name
FROM users_import
WHERE NOT EXISTS (SELECT 1 FROM upsert WHERE upsert.id = users_import.id);
That query gives this error:
psql:test.sql:23: ERROR: column reference "id" is ambiguous
LINE 11: WHERE NOT EXISTS (SELECT 1 FROM upsert WHERE upsert.id = us...
^
Why is id ambiguous and what is causing it?
The RETURNING * in the WITH upsert... clause has all columns from users and all columns from the joined table users_import. So the result has two columns named id and two columns named name, hence the ambiguity when refering to upsert.id.
To avoid that, use RETURNING u.id if you don't need the rest of the columns.