POSTGRESQL
Case Background -There is a table named MasterSIM to which details are to be added usin.csv file via Nodered.
CREATE OR REPLACE PROCEDURE "master_SIMs".simiccidlink1(IMEI bigint, iccid text, phonenumber bigint, apn text, "Operator" text, isesim boolean, ism2m boolean, mdi bigint, imsi integer)
LANGUAGE 'plpgsql' AS
$BODY$
declare
-- retval text
begin
if (length(IMEI) = 15) then
if (master_packs.luhn_verify(IMEI) is True) then
update "master_SIMs".list SET "ICCID" = iccid, "phoneNumber" = phonenumber, "APN" = apn, "operator" = "Operator", "isESIM" = isesim, "isM2M" = ism2m, "MDI" = mdi, "IMSI" = imsi where IMEI = "serialNumber";
end if;
end if;
end;
$BODY$;
CALL "master_SIMs".simiccidlink1(352277818466409, 'iccid1', '8018466080', 'apn1', 'operator1', '0', '0', 123456789987653, 12354);
select * from "master_SIMs".list;
error I am getting is -
ERROR: procedure master_SIMs.simiccidlink1(unknown, unknown, unknown, unknown, integer, integer, integer, integer, bigint) does not exist
LINE 2: CALL "master_SIMs".simiccidlink1('iccid1', '8018466080', 'ap...
^
HINT: No procedure matches the given name and argument types. You might need to add explicit type casts.
SQL state: 42883
Character: 7
I am new to this - please GUIDE.
I have tried all possible ways to fix it.
Related
I need to develop some kind of function in a informix db, in order to split one string into multiple rows for example:
Column1
one,two,three,four
And my expected result is:
column1
one
two
three
four
What i was thinking is to create a function, that splits the string into multiple rows. My actual code is the next one :
create function split(text_splitted varchar(100), separator char(1))
returning varchar(100)
define splitted_word varchar(100);
define current_val char(1);
define start, cont integer;
let start = 0;
let splitted_word = "";
let current_val = "";
for cont = 0 to length(text_splitted)
let current_val = substr(text_splitted, cont, 1);
if current_val = separator then
let splitted_word = substr(text_splitted, start, cont - start);
let start = cont + 1;
return splitted_word with resume;
end if;
end for;
end function
If you execute the next statement, works find:
execute function split('hello.my.name.is', '.');
And the result is:
hello
my
name
this is perfect, but my problem is that when you launch a query with this function, and the function returns more than one row an error is raised. What i have been google, is that i need to create an aggregate function but i am not able to build this function. I am new in this kind of developing....
Here is the little documentation i found: http://www.pacs.tju.edu/informix/answers/english/docs/dbdk/is40/extend/04aggs3.html
Thanks!
In oracle DB, I created a custom type in a package and i guess this type is similar to integer array.
create or replace PACKAGE mypackage AS
TYPE custom1 is table of integer index by binary_integer;
END mypackage;
Used type in procedure IN param and expecting out param to be size of IN param.
CREATE OR REPLACE PROCEDURE MYPROCEDURE( param1 in mypackage.custom1, count1 out integer) IS
begin
count1 := param.count();
END MYPROCEDURE
Now I want to call above procedure,for this I should prepare mypackage.custom1.
Please help me in constructing mypackage.custom1 and call above procedure.
You have some errors in your code;
CREATE OR REPLACE PACKAGE mypackage AS
TYPE custom1 IS TABLE OF INTEGER
INDEX BY BINARY_INTEGER;
END mypackage;
CREATE OR REPLACE PROCEDURE MYPROCEDURE(param1 IN mypackage.custom1, count1 OUT INTEGER) IS
BEGIN
count1 := param1.COUNT();
END MYPROCEDURE;
To call your procedure, you simply need to define two variables and call the procedure with them; for example, in an anonymous block:
declare
v mypackage.custom1;
n number;
begin
select 1
bulk collect into v
from dual connect by level <= 5;
--
MYPROCEDURE(v, n);
dbms_output.put_line('n= ' || n);
end;
n= 5
The same way, you can build your stored procedures, packages, ... to call your procedure.
Executing above procedure with list of integers passing to custom type
SET SERVEROUTPUT = ON;
declare
v mypackage.custom1;
n number;
begin
v(0) := 10;
v(1) := 12;
v(2) := 14;
v(3) := 16;
--
MYPROCEDURE(v, n);
dbms_output.put_line('n= ' || n);
end;
output :
n = 4
Here is the JDBC code to invoke above procedure
String procedure = "call MYPROCEDURE(?, ?)";
CallableStatement callableStatement = con.prepareCall(procedure);
ArrayDescriptor ad = ArrayDescriptor.createDescriptor("mypackage.custom1", con);
ARRAY arr = new ARRAY(ad, con, new Integer[]{1,2,3,4});
callableStatement.setArray(1, arr);
callableStatement.registerOutParameter(2, Types.INTEGER);
final boolean execute = callableStatement.execute();
System.out.println("No of entries :" + callableStatement.getObject(2));
output :
No of entries : 4
So i have a tool that call procedure.
Tool looks like that:
call Attach_test('select TTID from alerts.status where Class in (73000,8891) and to_int(TTID) > 0 and ServerSerial in ($selected_rows.Serial)',[ $selected_rows.Serial ]); flush iduc;
it should get TTID (that field have only one of many selected alarms ) and array of server serials of selected alarms.
Then all this data is transfered to SQL procedure that looks like:
declare
tempservser integer; k integer;
begin
for k = 1 to array_len(serserial) do
begin
set tempservser = serserial[k];
update alerts.status set ParentTT = parentttid, TTFlag = 2 where ServerSerial = tempservser and TTID = '' ;
end;
end
Parameters:
in parentttid Char(11)
in serserial array of Integer
And here comes the trouble - procedure do nothing. There is no errors or something but there is no update on selected alarms.
I want it to work like this - you select many alarms with only one that have TTID, run this tool that set ParentTT = TTID on every other of selected alarms.
OS ver. 8.1
Sorry for my english
I figured out how to do it:
Tool
call AttachSelectedToTTID([ $selected_rows.Serial ],[ $selected_rows.ParentTT ]);
flush iduc;
Procedure
declare
tempservser integer; k integer;n integer;partt char(15);
begin
for n = 1 to array_len(ttid) do
begin
if (ttid[n] != '' ) then
set partt = ttid[n];
end if;
end;
for k = 1 to array_len(serserial) do
begin
set tempservser = serserial[k];
update alerts.status set ParentTT = partt,TTFlag = 2 where Serial = tempservser and TTID = '';
end;
end
Parameters:
in ttid array of Char(15)
in serserial array of Integer
I wanted to know the Informix 4gl command to split a variable
such as
lv_var = variable01;variable02
into
lv_var01 = variable01
lv_var02 = variable02
Is there something in Informix 4gl that can do this.
In python I could do
lv_array = lv_var.split(";")
and use the variables from the array
It's possible with classic Informix 4gl with something like this...
define
p_list dynamic array of char(10)
main
define
i smallint,
cnt smallint,
p_str char(500)
let p_str = "a;b;c;d"
let cnt = toarray(p_str, ";")
for i = 1 to cnt
display p_list[i]
end for
end main
function toarray(p_str, p_sep)
define
p_str char(2000),
p_sep char(1),
i smallint,
last smallint,
ix smallint,
p_len smallint
let ix = 0
let p_len = length(p_str)
# -- get size of array needed
for i = 1 to p_len
if p_str[i] = p_sep then
let ix = ix + 1
end if
end for
if ix > 0 then
# -- we have more then one
allocate array p_list[ix + 1]
let ix = 1
let last = 1
for i = 1 to p_len
if p_str[i] = p_sep then
let p_list[ix] = p_str[last,i-1]
let ix = ix + 1
let last = i + 1
end if
end for
# -- set the last one
let p_list[ix] = p_str[last, p_len]
else
# -- only has one
allocate array p_list[1]
let ix = 1
let p_list[ix] = p_str
end if
return ix
end function
Out:
a
b
c
d
Dynamic array support requires IBM Informix 4GL 7.32.UC1 or higher
There isn't a standard function to do that. One major problem is returning the array. I'd probably write a C function to do the job, but in I4GL, it would look like:
FUNCTION nth_split_field(str, c, n)
DEFINE str VARCHAR(255)
DEFINE c CHAR(1)
DEFINE n INTEGER
...code to find nth field delimited by c in str...
END FUNCTION
What you'll find is that the products that have grown to superceed Informix 4GL over the years such as FourJs Genero will have built-in methods that have been added to simplify the Informix 4GL developers life.
So something like this would do what you are looking for if you upgraded to Genero
-- Example showing how string can be parsed using string tokenizer
-- New features added to Genero since Informix 4gl used include
-- STRING - like a CHAR but length does not need to be specified - http://www.4js.com/online_documentation/fjs-fgl-manual-html/?path=fjs-fgl-manual#c_fgl_datatypes_STRING.html
-- DYNAMIC ARRAY like an ARRAY but does not need to have length specified. Is also passed by reference to functions - http://www.4js.com/online_documentation/fjs-fgl-manual-html/?path=fjs-fgl-manual#c_fgl_Arrays_010.html
-- base.StringTokenizer - methods to split a string - http://www.4js.com/online_documentation/fjs-fgl-manual-html/?path=fjs-fgl-manual#c_fgl_ClassStringTokenizer.html
MAIN
DEFINE arr DYNAMIC ARRAY OF STRING
DEFINE i INTEGER
CALL string2array("abc;def;ghi",arr,";")
-- display result
FOR i = 1 TO arr.getLength()
DISPLAY arr[i]
END FOR
-- Should display
--abc
--def
--ghi
END MAIN
FUNCTION string2array(s,a,delimiter)
DEFINE s STRING
DEFINE a DYNAMIC ARRAY OF STRING
DEFINE delimiter STRING
DEFINE tok base.StringTokenizer
CALL a.clear()
LET tok = base.StringTokenizer.create(s,delimiter)
WHILE tok.hasMoreTokens()
LET a[a.getLength()+1] = tok.nextToken()
END WHILE
-- a is DYNAMIC ARRAY so has been pased by reference and does not need to be explicitly returned
END FUNCTION
Following is my Function created in PostgreSQL
CREATE OR REPLACE FUNCTION funcInsert(iacid int,islno int,idate date) RETURNS int AS
$$
declare id_val int;
BEGIN
INSERT INTO GTAB83 (acid,slno,orderdte) VALUES (iacid,islno,idate) RETURNING orderid into id_val;
return id_val;
END;
$$
LANGUAGE 'plpgsql';
and my code to execute the above function using vb.net is
Dim myCmd As PgSqlCommand = New PgSqlCommand("funcInsert", Myconnstr)
myCmd.CommandType = CommandType.StoredProcedure
myCmd.Parameters.Add("iacid", PgSqlType.Int).Value = cboCust.SelectedValue
myCmd.Parameters.Add("islno", PgSqlType.Int).Value = txtOrderNO.Text
myCmd.Parameters.Add("idate", PgSqlType.Int).Value = txtDate.Text
myCmd.ExecuteScalar()
trans.Commit()
the error is
You need to create the command with a SELECT statement.
Dim myCmd As PgSqlCommand = New PgSqlCommand("SELECT funcInsert(#iacid, #islno, #idate)", Myconnstr)