Stored procedure for updating values dynamically in db2 table - stored-procedures

I am trying to update the values of a table dynamically, using stored procedure. My stored procedure is as follows,
CREATE OR REPLACE PROCEDURE Update
(
IN ID1 BIGINT,
IN SOURCE1 VARCHAR(100),
IN NAME1 VARCHAR(100)
)
DYNAMIC RESULT SETS 2
LANGUAGE SQL
BEGIN
UPDATE MessageTable
SET SOURCE=SOURCE1,
NAME=NAME1
WHERE ID=ID1;
END
When I try to pass the value for ID1 and SOURCE1 alone, the values are not getting updated. When I pass all the three values, they are getting updated properly. My requirement is even if I pass two values it should get updated. I tried giving DEFAULT NULL for the arguments. Since the fields are declared NOT NULL, it was not working. Could someone help to overcome this. The stored procedure should work even if I pass single value. Thanks in advance.

You could use COALESCE:
UPDATE MessageTable
SET SOURCE = COALESCE(SOURCE1, SOURCE),
NAME = COALESCE(NAME1, NAME)
WHERE ID = ID1;
When NAME1 is NULL then the original NAME will be preserved.

You could check with IF or another statement whether all arguments have non-NULL values and then switch to either an UPDATE statement that sets one or two column values.

Related

How to write a stored procedure in DB2 to perform UPDATE / DELETE operation by passing Dynamic values?

I want to write a stored procedure in DB2 database for UPDATE and DELETE operations.
I am able to do that by directly providing values in procedure, but I want to do it by passing dynamic values.
My Table Structure is -
create table emp2 (int_1 int, char_1 char(10))
Below is my stored procedure for UPDATE operation which I am able to run but, its not behaving as per expectations. Changes are not reflecting in DB even after passing correct parameters while calling stored procedure.
CREATE OR REPLACE PROCEDURE "DB2INST1"."UPDATE_1" (IN int_1 int, IN
char_1 char(10)) SPECIFIC UPDATE_1
LANGUAGE SQL
DYNAMIC RESULT SETS 1
BEGIN
update emp2 set char_1=char_1 where int_1=int_1;
END;
This is the my stored procedure for DELETE operation which I am able to run successfully, but it's deleting all rows from the database table instead of deleting a single row:
CREATE OR REPLACE PROCEDURE "DB2INST1"."DELETE_1" (IN int_1 int)
SPECIFIC DELETE_1
LANGUAGE SQL
DYNAMIC RESULT SETS 1
BEGIN
delete from emp2 where int_1=int_1;
END;
Please provide me syntax for creating stored procedure for UPDATE and DELETE operations by passing dynamic values in a DB2 database.
The problem is that you don't qualify your columns and parameters having the same names.
According to the References to SQL parameters, SQL variables, and global variables:
Names that are the same should be explicitly qualified. Qualifying a
name clearly indicates whether the name refers to a column, SQL
variable, SQL parameter, row variable field, or global variable. If
the name is not qualified, or qualified but still ambiguous, the
following rules describe whether the name refers to a column, an SQL
variable, an SQL parameter, or a global variable:
If the tables and views specified in an SQL routine body exist at the time the routine is created, the name is first checked as a column
name. If not found as a column, it is then checked as an SQL variable
in the compound statement, then checked as an SQL parameter, and then,
finally, checked as a global variable.
That is, the following statements changing all the table rows obviously are equivalent:
update emp2 set char_1 = char_1 where int_1 = int_1;
--and
update emp2 e set e.char_1 = e.char_1 where e.int_1 = e.int_1;
What you need is to rewrite this statement to the following, if you want to use the same column and parameter names (the routine name UPDATE_1 is used here for the parameter qualification).
update emp2 set char_1 = UPDATE_1.char_1 where int_1 = UPDATE_1.int_1
fiddle

How pass TEXT data type to stored procedure in hana

I'm writing a simple stored procedure for my Hana database, its behavior is to update a table and return the updated element. Here the code:
CREATE OR REPLACE PROCEDURE "UpdateTbl" (in _id integer, in formula text) AS
BEGIN
UPDATE "MyTable" SET "formula" = formula, WHERE "id" = _id;
SELECT "id", "formula" FROM "MyTable" WHERE "id" = _id;
END;
The problem i'm facing is that I cannot specify a TEXT input parameter in stored procedures.
A possible workaround could be to use NVARCHAR instead.
In this way, I can correctly create the stored procedure, but when I run it with 'dummy' value in the NVARCHAR field, i got this error
Error: (dberror) [7]: feature not supported: "Database"."UpdateTbl": ... : Unregistered function name: "to_text
It seems that it cannot convert NVARCHAR in TEXT.
So, there is a way to force the conversion of this kind of parameter in TEXT?
If not, there is a way I'm not considering to pass TEXT parameter as input (other data types, for instance)?
Thnaks in advance
this simple example works as expected when using NVARCHAR or NCLOB as procedure parameter type
DROP TABLE t1;
CREATE TABLE t1 (i int, t text fast preprocess off);
INSERT INTO t1 values(3,'');
INSERT INTO t1 values(4,'');
CREATE OR REPLACE PROCEDURE p1 (in i int, in t nclob) AS
BEGIN
UPDATE t1 SET t = :t WHERE i = :i;
--SELECT i,t FROM t1 where i = :i;
END;
CALL p1(3,'bob went to london');
CALL p1(4,'nancy moved to berlin');
SELECT * FROM t1 WHERE CONTAINS(*,'go',linguistic);
please provide your column properties

Postgres function returns custom data set

Is there a way to create postgres stored function (using plpgsql to be able to set input parameters) that returns a custom data set?
I've tried to do something like this according to official manual:
CREATE FUNCTION extended_sales(p_itemno int)
RETURNS TABLE(quantity int, total numeric) AS $$
BEGIN
RETURN QUERY SELECT quantity, quantity * price FROM sales
WHERE itemno = p_itemno;
END;
$$ LANGUAGE plpgsql;
but result is an array with only one column which contains type (quantity, total), but I need to get two column array with 'quantity' column and 'total' column.
At a guess you're running:
SELECT extended_sales(1);
This will return a composite type column. If you want it expanded, you must instead run:
SELECT * FROM extended_sales(1);
Also, as #a_horse_with_no_name notes, a PL/pgSQL function is completely unnecessary here. Presumably this is a simplified example?
In future please include:
Your PostgreSQL version; and
The exact SQL you ran and the exact output you got

Informix procedure — how to return an empty table?

I need to create an Informix procedure to return a table with rows if I found some value and an empty table if no value found.
I know how to return a table with rows, but I don't know how to return the empty table; can anyone help?
CREATE row type AType (
id VARCHAR(255),
name VARCHAR(255)
);
CREATE PROCEDURE getmeasurement (p_date DATETIME YEAR TO SECOND)
RETURNING MULTISET(AType NOT NULL);
DEFINE AType_TABLE MULTISET (AType NOT NULL);
DEFINE v_id VARCHAR(255);
DEFINE v_name VARCHAR(255);
....
IF( FoundValue ) THEN
-- INSERT INTO TABLE
INSERT INTO TABLE (AType_TABLE) VALUES (ROW(v_id,v_name)::AType);
ELSE
// how to initial a AType_TABLE instance with empty records.
END IF
....
RETURN AType_TABLE;
END PROCEDURE;
Despite what it says in the SQL Syntax Manual, SPL (Stored Procedure Language) procedures can return collection types (COLLECT, SET, MULTISET or LIST). I've reported a documentation bug against that — which misled me earlier this week.
I'm not able to get this procedure to compile under Informix 11.70.FC6 on Mac OS X 10.7.5, but the error it comes up with is:
SQL -9905: [Internal] No extended type information for domain.
I've run into various issues trying various variants of the above code. You can't have a WHERE clause on a DELETE from a multiset, it seems (different error message). You can also run into problems if you rollback the creation of the type and then try again.
However, I was able to test it with a pre-release of 11.70.FC8 on Linux (RHEL 5, x86/64) and got the desired output:
CREATE ROW TYPE IF NOT EXISTS AType
(
id VARCHAR(255),
name VARCHAR(255)
);
CREATE PROCEDURE getmeasurement (p_date DATETIME YEAR TO SECOND)
RETURNING MULTISET(AType NOT NULL);
DEFINE AType_TABLE MULTISET(AType NOT NULL);
DEFINE v_id VARCHAR(255);
DEFINE v_name VARCHAR(255);
LET v_id = "Polynomial - " || p_date;
LET v_name = "Euclid's Geometry of the Plane";
INSERT INTO TABLE (AType_TABLE) VALUES(ROW(v_id, v_name)::AType);
IF 1 = 1 THEN
-- how TO initial a AType_TABLE instance WITH empty records.
DELETE FROM TABLE(AType_TABLE);
END IF
RETURN AType_TABLE;
END PROCEDURE;
EXECUTE PROCEDURE getmeasurement(CURRENT);
ROLLBACK;
The output was:
MULTISET{}
which is an empty multiset. If you don't insert something into the multiset first, the delete fails. This is a trifle odd.
Summary
You may be OK with Informix 11.70.xC7; it may work on some other versions too. But there are likely to be a lot of versions of Informix where it does not work.

basic stored procedure (update column value)

I have a basic table that looks like the following:
SQL> desc comments
Name Null? Type
---------------------------------------
COMMENT_ID NOT NULL NUMBER
POST_ID NOT NULL NUMBER
USER_ID NOT NULL NUMBER
MESSAGE NOT NULL VARCHAR2(2500)
MESSAGE_TIME NOT NULL TIMESTAMP(6)
UPVOTES NOT NULL NUMBER
What I'd like to do is have a stored procedure be called that would increment the upvotes. This seems to make the most sense because I don't want to pass in anything other than the comment_id and post_id.
I think I should be doing something like this (please excuse syntax, I haven't messed with stored procedures in a long long time)
CREATE OR REPLACE procedure proc_upvote_comment (comment_id NUMBER , post_id NUMBER)
BEGIN
SELECT UPVOTES FROM COMMENTS
WHERE COMMENTS.COMMENT_ID = proc_upvote_comment.comment_id
AND COMMENTS.POST_ID = proc_upvote_comment.post_id;
//Call an update
END;
/
But I just don't seem to know the missing piece here. I've tried looking at
http://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_packages.htm#i1007682
http://docs.oracle.com/cd/B12037_01/server.101/b10759/statements_6009.htm
And a few other places on the site - but I'm just missing something.
Any help in the right direction would be great
Is there any reason this is not working for you:
CREATE OR REPLACE procedure proc_upvote_comment (comment_id NUMBER , post_id NUMBER)
AS
BEGIN
UPDATE COMMENTS
SET UPVOTES = UPVOTES + 1
WHERE COMMENTS.COMMENT_ID = proc_upvote_comment.comment_id
AND COMMENTS.POST_ID = proc_upvote_comment.post_id;
END;
Remember that SQL works with sets ;)
You probably just want
CREATE OR REPLACE procedure proc_upvote_comment (p_comment_id NUMBER , p_post_id NUMBER)
AS
BEGIN
UPDATE comments
SET upvotes = upvotes + 1
WHERE comment_id = p_comment_id
AND post_id = p_post_id;
END;
/
Generally, you want to have a naming convention to differentiate parameters from column names. I prefer using the p_ prefix for parameters and the l_ prefix for local variables but there are other conventions. If you don't do this and you use the same name for a column and for a parameter, the SQL statement will resolve identifiers first using the name of the column and then using the name of the parameter. Resorting to prefixing the name of the stored procedure to provide scope resolution works but it's rather cumbersome.

Resources