Cast from json to int not working? [duplicate] - json

This question already has answers here:
How to convert postgres json to integer
(3 answers)
Closed 8 months ago.
I need to somehow cast from json to int. I have made this func.:
CREATE OR REPLACE FUNCTION json2int(p_json json)
RETURNS integer AS
$BODY$DECLARE
v_json json;
--v_char character varying;
v_int integer;
BEGIN
SELECT p_json->'additionalData'->'id' INTO v_json;
--SELECT CAST(v_json as character varying) INTO v_char;
SELECT CAST(v_json as integer) INTO v_int;
RETURN v_int;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION json2int(json)
OWNER TO postgres;
I tried casting from json to int, that did't work. Then I tried casting from json to character varying to int, that also did't work. So I added:
CREATE CAST (json AS integer) WITH INOUT as implicit;
And now when I run my function as:
SELECT json2int('{"additionalData":{"id":"4","userType":"viewer"},"type":"wall"}');
I get this error:
ERROR: invalid input syntax for integer: ""4""
CONTEXT: SQL statement "SELECT CAST(v_json as integer)"
PL/pgSQL function json2int(json) line 8 at SQL statement
Can somebody help with this?

As hinted in the comments use ->> to have text then cast to int:
SELECT (p_json -> 'additionalData' ->> 'id')::int INTO v_int;

Related

Extracting key from json string having null value

I have following function
CREATE OR REPLACE FUNCTION public."test"(
_data text)
RETURNS integer
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
declare _sdate date:= null;
begin
select json_extract_path(_data:: json , 'sdate') into _sdate;
select _data:: json -> 'sdate' into _sdate;
END;
$BODY$;
I tried both way but it throws syntax error when sdate is null
I am calling like
select public."test"($${
"sdate":null
}$$)
but when I give sdate value it is working
select public."test"($${
"sdate":"2020-1-01"
}$$)
I also tried explicity parsing like
select _data:: json -> 'sdate'::date into _sdate;
But not working
You have many errors in your function. The first one being that you are not returning anything as you are missing a return statement.
Your expression: _data:: json -> 'sdate'::date is not working because the cast operator :: binds more strongly than the ->' operator and thus you are casting 'sdate'to a date, not the result of the->` operator.
You should also declare the function parameter as json, rather than casting it inside the function. And you need to use ->> to return the value as a text value because there is no direct cast from json to date.
You are casting the result to a date, but your function is declared to return integer which also doesn't match.
CREATE OR REPLACE FUNCTION public."test"(_data json)
RETURNS date --<< here
LANGUAGE plpgsql
stable
AS
$BODY$
declare
_sdate date := null;
begin
_sdate := (_data ->> 'sdate')::date;
return _sdate;
END;
$BODY$;
The way you formatted your code suggests that you think declare is needed for each variable. But declare starts a block that can contain multiple declarations. declarations, it's not something that needs to be repeated for each variable.

How to use declared variable to create a json element

I have a stored procedure, in this, I have declared a variable which holds a value from a select function. I need to use this value to create a json element, but it throws an exception
function jsonb_set(jsonb, unknown, character varying, boolean) does not exist
This is the function:
CREATE OR REPLACE FUNCTION test ( ) RETURNS
INTEGER AS $$
DECLARE
intent varchar;
BEGIN
select id into intent from customer;
UPDATE orders
SET data = jsonb_set(
data,
'{Items}', -- the array in which we operate
to_jsonb(
(WITH ar AS(
WITH temp AS(
SELECT data->'Items' AS items -- the array in which we operate
FROM orders
WHERE id = 1 -- the filtered order we are updating
)
SELECT jsonb_set(
jsonb_array_elements(items),
'{Quantity}', -- the new field we are adding
intent, -- this is where i need to replace the variable
true)
FROM temp)
SELECT (array_agg(ar.jsonb_set))
FROM ar)),
false)
WHERE id = 1;
return 0;
EXCEPTION WHEN others THEN
return 1;
END;
$$ LANGUAGE plpgsql;
Copying the snippet where I need to replace the variable:
SELECT jsonb_set(
jsonb_array_elements(items),
'{Quantity}', -- the new field we are adding
intent, -- this is where i need to replace the variable
true)
You have to explicitly cast intent to jsonb using CAST(intent AS jsonb) or intent::jsonb.
The reason it works with a string literal is that such literals are of the (internal) type unknown which can be transformed to most other types, but there is no implicit cast between character varying and jsonb, so you have to use an explicit one.

ERROR: cannot cast type integer to json in Postgresql

When I am trying to insert the record in tableA, i am getting the below error:
QUERY: insert into schemaname.tableB(col1, col2) values(....)
CONTEXT: PL/pgSQL function schemaname.funcA() line 5 at SQL statement
********** Error **********
ERROR: cannot cast type integer to json
SQL state: 42846
Context: PL/pgSQL function schemaname.funcA() line 5 at SQL statement
I have created following trigger which function when record gets committed:
CREATE CONSTRAINT TRIGGER trg_name
AFTER INSERT
ON schemaname.tableA
DEFERRABLE INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE schemaname.funcA();
In the below trigger function col1 is of integer type and col2 is of json type.
CREATE OR REPLACE FUNCTION schemaname.funcA()
RETURNS trigger AS
$BODY$
BEGIN
insert into schemaname.tableB(col1, col2) values(NEW.val1, json_build_object("abc", NEW.col2val1::json, "def", NEW.col2val2::json, "ghi", NEW.col2val3::json));
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Could you please help me what could be the cause of this error?
There is no cast from integer to json.
But since json_build_object accepts arguments of any type, you can solve the problem by removing the ::json casts in your trigger function.
By the way, using "abc" as a string constant is wrong – probably an error introduced while trying to obfuscate your code. You have to write '"abc"'.
CREATE OR REPLACE FUNCTION schemaname.funcA() RETURNS trigger AS $BODY$
BEGIN
insert into schemaname.tableB(col1, col2) values(NEW.col1, CAST('{"nameA" : ' ||'"'||NEW.nameA||'", ' || '"nameB" : '||'"'||NEW.nameB||'", ' ||'"nameC" : '||'"'||NEW.nameC||'", ' || '"nameD" : '||'"'||NEW.nameD||'"}' as json));
RETURN NEW;
END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100;

PostgreSQL Date Conversion Function

I have one challenge:
I have the following code in SQL Server and I want to move it to PostgreSQL DBMS.
I adapted it to PostgreSQL just like the following:
CREATE function public.SEMANA_ISO (fecha date) returns integer as $$
DECLARE
semana_ISO int= date_part ('week',fecha)+1
-date_part('week',CAST(date_part('year',fecha) as CHAR(4)) + '0104');
BEGIN
IF (semana_ISO=0)
THEN
semana_ISO=public.SEMANA_ISO(CAST(date_part('year',fecha)-1
AS CHAR(4)) + '12' + CAST(24 + date_part('day',fecha) AS CHAR(2)))+1;
ELSIF ((date_part('month',fecha)=12) AND ((date_part('day',fecha)-date_part('day',fecha))>=28))
THEN
semana_ISO=1;
END IF;
RETURN semana_ISO;
END;
$$ LANGUAGE plpgsql;
As you may see, I tried to make it look the most similar as in SQL Server is.
However when I try to run this function and test it:
Select public.SEMANA_ISO('28/12/2014');
The DMBS shows many errors:
ERROR: operator does not exist: character + unknown
LINE 2: ...rt('week',CAST(date_part('year',fecha) as CHAR(4)) + '0104')
HINT: No operator matches the name and type of the arguments. You may need to add explicit type casts.
QUERY: SELECT date_part ('week', date) +1
-date_part ('week', CAST (date_part ('year', date) as CHAR (4)) + '0104')
CONTEXT: PL / pgSQL function semana_iso (date) at line 5 during initialization of local variables in the statement block
What I try to do is the following.
From the following input date format: dd/mm/yyyy I want to use the function above to show it as the next output format:mm-dd-yyyy
I have thought in doing a simpler function that could receive the date in the format given (dd/mm/yyyy) and using the set datestyle = mdy statement change it in the body of the function and finally print it or return it.
What do you suggest folks?
Your help & time is always appreciated!
A guess you may need a Function like below
CREATE function a_date_conv (fecha date) returns text as $$
select to_char(fecha, 'mm-dd-yyyy');
$$ LANGUAGE sql;
select a_date_conv('08/10/2014')
Result
-------
10-08-2014

Named stored proc parameters and concatenation [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Cast integer and concatenate to varchar in TSQL
How do you call a stored procedure using named parameters that have more complex values. Here is a somewhat concocted example:
EXEC MyStoredProc #Param1='My name is: '+#Name
Or:
EXEC MyStoredProc #Param1=CONCAT('My name is: ',#Name)
I get an error trying to concatenate the literal string 'My name is: ' with the variable #Name. Parentheses do not help the matter any. Is this a limitation of T-SQL (i.e., when named parameters are used, the expression after the equal sign must be a single literal or variable)?
Thanks
One way
declare #Var1 varchar(50)
select #Var1 = 'My name is: '+#Name
EXEC MyStoredProc #Param1=#Var1
The same is true with functions as well
you can't do this
EXEC MyStoredProc #Param1=getdate()
you need to do
declare #Var1 datetime
select #Var1 = getdate()
EXEC MyStoredProc #Param1=#Var1