How to use declared variable to create a json element - json

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.

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.

I Getting error when run this below query : RETURN statements in scalar valued functions must include an argument

I am getting this error message
RETURN statements in scalar valued functions must include an argument
when run this query:
create function gender(#gender nvarchar(40))
returns nvarchar(40)
as
begin
(select name,cast(DOB as date) as DOB from datenames where gender = #gender)
return
end
The write way to create a function in mysql for your example is as follows:
DELIMITER \\
create function gender(Igender nvarchar(40))
returns nvarchar(40)
begin
DECLARE customerLevel NVARCHAR(40);
IF EXISTS (select name,cast(DOB as date) as DOB from datenames where gender = Igender) THEN
SET customerLevel = 'SOMETHING1';
ELSE
SET customerLevel = 'SOMETHING2';
END IF;
RETURN (customerLevel);
end
No need to as
No need to # before input
You need to return something.
Don't forget to use DELIMITER.
If you use phpmyadmin and has problem with nvarchar read this post: Unrecognize data type nvarchar in database or simply change it to to varchar.

How can i pass multiple values to an array parameter function

i need your help.....how can i pass multi values into single parameter in a function?
The values 'AAA 1','BBB 2', 'CCC 3' 'DDD 4' are to be passed to the same parameter "v_type", the values will be sent based on the selection from the drop down in the front end screen. The user can select one or more values from the list and those values should be passed to the procedure which in turn will be passed to the WHERE clause of the SELECT statement inside the procedure.
My function is somenthing like this:
Example
CREATE OR REPLACE FUNCTION FN_GET_ROWS
(v_date_ini IN DATE,
v_date_end IN DATE,
v_type IN VARCHAR2
)
RETURN TEST_TABTYPE
AS
V_Test_Tabtype Test_TabType;
BEGIN
SELECT TEST_OBJ_TYPE(DATE, NAME, ALERT)
BULK COLLECT INTO V_Test_TabType
FROM (select date, name, alert
from Table
where DATE BETWEEN v_date_ini AND v_date_end
AND Alert in (select REGEXP_SUBSTR (v_type, '[^,]+', 1, level)
from dual
connect by level <= length(regexp_replace(v_type,'[^,]*'))+1)
);
RETURN V_Test_TabType;
END;
Searching internet i found that maybe an Varray works but i dont know how to assign it to the variable :type with the parameters that the user selects on the screen.
I create this types on database, how can i used it? i'm kind a new in plsql.
CREATE TYPE alert_obj AS OBJECT (type_alert VARCHAR2(60));
CREATE TYPE alert_varray_typ AS VARRAY(100) OF alert_obj;
Thanks for your help
Emanuel.
I dont know, if I really understand your problem. But I think, that there is more solutions.
You can use string of VARCHAR2 as parameter and after that parse it with function like that:
PROCEDURE p_parse_into_array (
lv_str IN VARCHAR2,
lt_table IN OUT sys.dbms_debug_vc2coll,
lv_splitter IN VARCHAR2)
IS
ln_position NUMBER := 0;
ln_position_2 NUMBER;
ln_i NUMBER := 1;
BEGIN
ln_position_2 := INSTR(lv_str,lv_splitter,1,1);
WHILE ln_position_2 != 0
LOOP
lt_table.extend(1);
lt_table(ln_i) := SUBSTR(lv_str,ln_position+1,ln_position_2-ln_position-1);
ln_position := INSTR(lv_str,lv_splitter,1,ln_i);
ln_position_2 := INSTR(lv_str,lv_splitter,1,ln_i+1);
ln_i := ln_i + 1;
END LOOP;
END;
where lv_str is string to parse, lt_table is table of varchar(2000) and lv_splitter is character to split (, . ; - etc) and this function return values into lt_table, which you can use in you select menu.
Second solution is to use varray as you say, but there you need to use dynamic sql with command:
execute immediate 'select * from dual where some_value in (select * from table('||my_varray_table||'));
And other solution is to use nested table. It´s your choice, which of this solution you prefer :)

Where is the error in this stored procedure

DELIMITER //
CREATE PROC InserimentoValori()
BEGIN
DECLARE #caratteri varchar(30);
set #caratteri = 'abcdefghijklmnopqrstuvwxyz',
DECLARE x INT DEFAULT 1;
WHILE x <=100 DO
INSERT INTO Persona(nome,cognome,eta) VALUES((SELECT #caratteri = substring(#caratteri +1),(SELECT #caratteri = sebstring(#caratteri +1),(SELECT floor(rand() * 99) AS randNum));
SET x = x+1;
END WHILE
END //
DELIMITER ;
I want to create a stored procedure that insert random values into the table.
Thanks
There are a couple of errors.
We don't "declare" user defined variables in MySQL. Just SET them.
If you want to DECLARE a variable within a procedure, that needs to be a procedure variable.
A user defined variable has a name that starts with the # character. A procedure variable cannot start with a # character.
So, a line like this is an error:
DECLARE #foo ...
If you want to use a user defined variable, remove that line. If you want to use a procedure variable, remove the # from the beginning of the variable name (and make that same change everywhere you want to reference the procedure variable foo.)
And SEBSTRING is not the name of a MySQL provided function.
Also, a boolean expression in a SELECT list of a query will return 0, 1 or NULL.
For example:
SELECT #caratteri = substring(#caratteri +1)
That expression is comparing the value on the left side of the = with the value on the right, and is going to return 1 if they are equal, or 0 if the aren't, or NULL if either of the values is NULL.
To perform an assignment to a user defined variable in a SELECT statement, use the Pascal-style := operator.
(If you meant to do an assignment, the design makes it look like you are gogin to lop off the first character each time through the loop; that's eventually going to be an empty string, if we loop enough times. You may want to think about leaving the string static. Consider incrementing integer values, and use those as arguments in SUBSTRING function. And you can use the MOD operator to get the integer value to "wrap".)

mysql: joining two strings in one variable

so I wrote a procedure that should join two strings in one variable and then store it in the DB. the procedure works fine when i run it but it doesn't store the variable in the db. instead it stores it as 0.
this is the code I used
select memFname, memLname into fn, ln from member where memberid = memid;
SET v_name := fn || ' ' || ln ;
insert into profile(memberid, fullName) values (memid, v_name);
fn, ln, and v_name are variables of type varchar. memid is a variable of type integer.
am I missing something here?
I'm using a trigger to call the procedure.
Trigger code
DELIMITER $$
create trigger prof_name
after insert on member
for each row
begin
call profile_fullname(new.memberid);
END $$;
DELIMITER ;
member table structure:
memberid integer,
memfname varchar,
memlname varchar.
profile table structure:
profid integer,
memberid integer.
By default, the || operator in MySQL is a logical operator. You are using it as a concat, which is why I thought you were using Oracle. As a logical operator, it will convert each argument to a logical expression, which has a value of 0 or 1. Obviously, it is converting them to 0s, which is why you are getting 0 in the table. The alternative would be 1, which isn't any more interesting.
The right solution is to use concat() instead of ||. You can also set the system variable PIPES_AS_CONCAT to use || as you want to, but that would normally only be set if you were trying to make code portable between databases.
Here are examples:
update profile
set fullName = (select concat(memFname, ' ', memLname) from member m where m.memberid = memid)
where profile.memberid = memid;
If you actually want an insert, it looks something like this:
insert into profile(memberid, fullname)
select memid, concat(memFname, ' ', memLname)
from member m
where m.memberid = memid;