How to set a JSONB value to null - postgresql

I'm trying to update a bunch of jsonb values to null. Here's an example of what i'm trying to do and i'm getting the error below.
How can I set first-name to null in this case?
UPDATE users
SET
fields = fields || '{"first-name": NULL}'
WHERE user_id = 1;
ERROR: invalid input syntax for type json
LINE 3: fields = fields || '{"first-name": NULL}'
^
DETAIL: Token "NULL" is invalid.
CONTEXT: JSON data, line 1: {"first-name": NULL...

Use jsonb_set:
UPDATE users
SET
fields = jsonb_set(fields, '{first-name}', 'null')
WHERE user_id = 1;

If you want the null value inside the JSONB, then it must be a JSON null value, not an SQL NULL value. JSON null must be spelled in lower case.

Related

SQL Error [22P02]: ERROR: invalid input value for enum tableName.date_unit: ""

I got this error when I try to get the list of all rows on my table. This only happens because I include one of the column in the SELECT. The column itself is an enum column and I wanna use COALESCE for the column in case it meets a null value.
This is a simplication of my code
SELECT id,
user_id,
coalesce(date_unit, '') date_unit
FROM table_name
WHERE user_id = $1
I got this error when I try to run it
SQL Error [22P02]: ERROR: invalid input value for enum table_name.date_unit: ""
This is the error when I run it using SQLX On Golang
Pq: invalid input value for enum table_name.date_unit: \"\"
date_unit itself is an enum which has restricted values. It only accepts day and month as value in the table. But lots of rows have null value in date_unit.
I wanna convert it to "" or empty string if date_unit value is null.
Is there a problem with the COALESCE with enum values? How should I use COALESCE to work with what I wanna do?
The answer is found in the comment section of the question.
To officiate it, as date_unit is not a string type, it cannot be returned when querying (invalid data type). As such, when querying, we should convert date_unit to string type.
This can be done using the query:
SELECT id,
user_id,
COALESCE(date_unit::text, '')
FROM table_name
WHERE user_id = $1
SELECT id,
user_id,
coalesce(date_unit, '')
FROM table_name
WHERE user_id = $1

How to check JSONB has a field in root?

I try this:
select * from "User" where "partnerData" -> 'name' != NULL
partnerData is a JSONB. I would see those rows, does not have the name field in JSON.
You can't use <> (or != or any other operator) to check for NULL values, you need to use IS NULL. Using -> also returns a jsonb value which might be the literal null not the SQL NULL value. So you should use ->> to return a text value (which would then be a SQL NULL)
select *
from "User"
where "partnerData" ->> 'name' IS NULL
Note that this doesn't distinguish between a JSON value that contains the key name but with a value of NULL and a JSON value that does not contain the key at all.
If you only want to check if the key exists (regardless of the value - even if it's a JSON null), use the ? operator.
where "partnerData" ? 'name'

Update column with input from a VALUES expression without explicit type cast

I'm trying to update a nullable date column with NULL and for some reason Postgres takes NULL as text and gives the below error
UPDATE tbl
SET
order_date = data.order_date
FROM
(VALUES (NULL, 100))
AS data(order_date,id)
WHERE data.id = tbl.id
And the error shows:
[42804] ERROR: column "order_date" is of type date but expression is
of type text
Hint: You will need to rewrite or cast the expression.
I can fix this by explicitly converting NULL to date as below:
NULL::date
But, Is there a way to achieve this without explicit type conversion?
You can avoid the explicit cast by copying data types from the target table:
UPDATE tbl
SET order_date = data.order_date
FROM (
VALUES
((NULL::tbl).order_date, (NULL::tbl).id)
(NULL, 100)
) data(order_date, id)
WHERE data.id = tbl.id;
The added dummy row with NULL values is filtered by WHERE data.id = tbl.id.
Related answer with detailed explanation:
Casting NULL type when updating multiple rows

How do I check if a column is NULL using rust-postgres? [duplicate]

This question already has an answer here:
How to handle an optional value returned by a query using the postgres crate?
(1 answer)
Closed 5 years ago.
I am using the rust-postgres library and I want to do a SELECT and check if the first column of the first row is NULL or not.
This is how I get my data:
let result = connection.query(
r#"
SELECT structure::TEXT
FROM sentence
WHERE id = $1
"#,
&[&uuid]
);
let rows = result.expect("problem while getting sentence");
let row = rows
.iter()
.next() // there's only 1 result
.expect("0 results, expected one...");
The only simple way I found to figure it out is the following code:
match row.get_opt(0) {
Some(Ok(data)) => some data found,
Some(Err(_)) => the column is null,
None => out of bound column index
}
Unfortunately, it seems that Some(Err(_)) is the executed path for any kind of SQL/database error, and not only if the retrieved column is NULL.
Which condition should I use to check that the column is NULL ?
If all you need to know is whether the column is NULL, you could try changing your query to:
SELECT COUNT(1) FROM sentence WHERE id = $1 AND structure IS NOT NULL
with or without the NOT.
If you want to make the logic simpler so any error is an actual error, I'd consider changing the select value to something like:
COALESCE( structure::TEXT, ''::TEXT ) AS "structure"
so it should never be NULL. That should work as long as an empty string isn't a valid non-NULL value for that column.
Otherwise, I may have misunderstood your problem.

Zend: Problems defining select option with NULL value for submission to INT MySQL field

I have a database field defined as INT with NULL Allowed. The data submitted to this field is produced by a select form element whos values are defined using addMultiOption and addMultiOptions in combination e.g.
$selectData = $dataModel->getPairs();
$updateForm->getElement('type_id')->addMultiOption(NULL, '- Not Selected -');
$updateForm->getElement('type_id')->addMultiOptions($selectData);
The problem is that the NULL I'm trying to assign to the "- Not Selected -" option is being converted to an empty string at some point and MySQL is throwing an error because an empty string is an incorrect integer value.
How can I modify this such that the NULL arrives at the MySQL insert as a NULL?
Regards,
Nick
EDIT: See Daniel Gadawski's answer below. Below is the final result.
$selectData = $dataModel->getPairs();
$updateForm->getElement('type_id')->addFilter(new Zend_Filter_Null());
$updateForm->getElement('type_id')->addMultiOption('', '- Not Selected -');
$updateForm->getElement('type_id')->addMultiOptions($selectData);
This allows the value NULL to be written to a MySQL Integer field with NULL Allowed.
Add Zend_Filter_Null to this field:
$updateForm->getElement('type_id')->addFilter(new Zend_Filter_Null());
Then just retrieve data from this form using $updateForm->getValues() and the empty strings will be replaced by null values.