I'm getting
"ERROR: invalid input syntax for type numeric: "NOS-Numbers" "
while running query
Datatype:
quantity numeric(15,3)
query:
insert into report_data(quantity)
select case
when p.product= 'OUTRIGHT' then
case
when sum(convert_to_integer(p.qty,0)) > 0 then 'NOS-Numbers'
else to_number('')
end
else to_number('')
end
from product_details
please help to get this resolved.
You cannot store strings in a numeric colums, and storing display data is generally a bad idea. Use instead NULL for an unknown value, and convert this to a better displayable value when fetching. E.g.:
SELECT COALESCE(quantity, 'NOS-Numbers') FROM report_data;
will return 'NOS-Numbers' for NULL, and the value of quantity otherwise.
Related
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
Is it possible to use COALESCE (or any other way) to replace NULL values from a TIMESTAMP column with a string like 'N/A'?
In my SELECT statement I have a
CASE WHEN n.expiration_date::date IS NULL THEN 'N/A' ELSE n.expiration_date::date END
When I try this, I get this error, which makes sense:
invalid input syntax for type date: "N/A"
I found this blog post too about this problem. Is there a way around it?
All values of a CASE expression have to evaluate to the same data type.
If you really need the N/A, you need to convert the date to a character type:
CASE
WHEN n.expiration_date IS NULL THEN 'N/A'
ELSE n.expiration_date::date::text
END
Or if you want to have control over the format:
CASE
WHEN n.expiration_date IS NULL THEN 'N/A'
ELSE to_char(n.expiration_date, 'YYYY-MM-DD')
END
I have field that has up to 9 comma separated values each of which have a string value and a numeric value separated by colon. After parsing them all some of the values between 0 and 1 are being set to an integer rather than a numeric as cast. The problem is obviously related to data type but I am unsure what is causing it or how to fix it. The problem only exists in the case statement, the split_part function seems to be working perfect.
Things I have tried:
nvl(split_part(one,':',2),0) = COALESCE types text and integer cannot be matched
nvl(split_part(one,':',2)::numeric,0) => Invalid input syntax for type numeric
numerous other cast/convert variations
(CASE WHEN split_part(one,':',2) = '' THEN 0::numeric ELSE split_part(one,':',2)::numeric END)::numeric => runs but get int value of 0
When using the split_part function outside of case statement it does work correctly. However, I need the result to be zero for null values.
split_part(one,':',2) => 0.02068278096187390979 (expected result)
When running the code above I get zero but expect 0.02068278096187390979
Field "one" has the following value 'xyz: 0.02068278096187390979' before the split_part function.
EXAMPLE:
create table test(one varchar);
insert into test values('XYZ: 0.50000000000000000000')
select
one ,split_part(one,':',2) as correct_value_for_those_that_are_not_null ,
case
when split_part(one,':',2) = '' then null
else split_part(one,':',2)::numeric
end::numeric as this_one_is_the_problem
from test
However, I need the result to be zero for null values.
Your example does not deal with NULL values at all, though. Only addressing the empty string ('').
To replace either with 0 reliably, efficiently and without casting issues:
SELECT part1, CASE WHEN part2 <> '' THEN part2::numeric ELSE numeric '0' END AS part2
FROM (
SELECT split_part(one, ':', 1) AS part1
, split_part(one, ':', 2) AS part2
FROM test
) sub;
See:
Best way to check for "empty or null value"
Also note that all SQL CASE branches must agree on a common data type. There have been minor adjustments in the logic that determines the resulting type in the past, so the version of Postgres may play a role in corner cases. Don't recall the details now.
nvl()is not a Postgres function. You probably meant COALESCE. The manual:
This SQL-standard function provides capabilities similar to NVL and IFNULL, which are used in some other database systems.
I am joining the two tables using the query below:
update campaign_items
set last_modified = evt.event_time
from (
select max(event_time) event_time
,result
from events
where request = '/campaignitem/add'
group by result
) evt
where evt.result = campaign_items.id
where the result column is of character varying type and the id is of integer type
But the data in the result column contains digits(i.e. 12345)
How would I run this query with converting the type of the result(character) into id
(integer)
Well you don't need to because postgresql will do implicit type conversion in this situation. For example, you can try
select ' 12 ' = 12
You will see that it returns true even though there is extra whitespace in the string version. Nevertheless, if you need explicit conversion.
where evt.result::int = campaign_items.id
According to your comment you have values like convRepeatDelay, these obviously cannot be converted to int. What you should then do is convert your int to char!!
where evt.result = campaign_items.id::char
There are several solutions. You can use the cast operator :: to cast a value from a given type into another type:
WHERE evt.result::int = campaign_items.id
You can also use the CAST function, which is more portable:
WHERE CAST(evt.result AS int) = campaign_items.id
Note that to improve performances, you can add an index on the casting operation (note the mandatory double parentheses), but then you have to use GROUP BY result::int instead of GROUP BY result to take advantage of the index:
CREATE INDEX i_events_result ON events_items ((result::int));
By the way the best option is maybe to change the result column type to int if you know that it will only contain integers ;-)
I have a query with the below WHERE clauses
WHERE
I.new_outstandingamount = 70
AND ISNUMERIC(SUBSTRING(RA.new_stampernumber,7, 4)) = 1
AND (DATEDIFF(M,T.new_commencementdate, SUBSTRING(RA.new_stampernumber,7, 10)) >= 1)
AND RA.new_applicationstatusname = 'Complete'
AND I.new_feereceived > 0
AND RA.new_stampernumber IS NOT NULL
AND T.new_commencementdate IS NOT NULL
RA.new_stampernumber is a string value which contains three concatenated pieces of information of uniform length. The middle piece of info in this string is a date in the format yyyy-MM-dd.
In order to filter out any rows where the date in this string in not formatted as expected I do a check to see if the first 4 characters are numeric using the ISNUMERIC function.
When I run the query I get an error message saying
The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value.
The line that is causing this error to occur is
AND (DATEDIFF(M,T.new_commencementdate, SUBSTRING(RA.new_stampernumber,7, 10)) >= 1)
When I comment out this line I don't get an error.
What is strange is that if I replace
AND ISNUMERIC(SUBSTRING(RA.new_stampernumber,7, 4)) = 1
with
AND SUBSTRING(RA.new_stampernumber,7, 4) IN ('2003','2004','2005','2006','2007','2008','2009','2010', '2011', '2012','2013','2014','2015'))
the query runs successfully.
Whats even more strange is that if I replace the above working line with this
AND SUBSTRING(RA.new_stampernumber,11, 1) = '-'
I get the error message again. But if I replace the equals sign with a LIKE comparison it works:
AND SUBSTRING(RA.new_stampernumber,11, 1) LIKE '-'
When I remove the DATEDIFF function and compare the results of each of these queries they all return the same resultset so it is not being caused by different data being returned by the different clauses.
Can anyone explain to me what could be causing the out-of-range error to be thrown for some clauses and not for others if the data being returned is in fact the same for each clause?
Thanks,
Neil
Different execution plans.
There is no guarantee that the WHERE clauses are processed in particular order. Presumably when it works it happens to filter out erroring rows before attempting the cast to date.
Also ISNUMERIC itself isn't very reliable for what you want. I'd change the DATEDIFF expression to something like the below
DATEDIFF(M, T.new_commencementdate,
CASE
WHEN RA.new_stampernumber LIKE
'______[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%'
THEN SUBSTRING(RA.new_stampernumber, 7, 10)
END) >= 1 )