Recursive stored procedure in HSQLDB - recursion

is it possible to create recursive stored procedure in HSQLDB ?
I wrote the following one to update a record and recursively all the parent records:
CREATE PROCEDURE updateFolderTotals(IN p_id VARCHAR(32), IN p_size BIGINT, IN p_files INT, IN p_folders INT)
MODIFIES SQL DATA
BEGIN ATOMIC
DECLARE l_parentid VARCHAR(32);
UPDATE folders
SET tot_files = tot_files + p_files,
tot_size = tot_size + p_size ,
tot_folders = tot_folders + p_folders
WHERE id = p_id;
SELECT parentid INTO l_parentid FROM folders WHERE id = p_id;
IF (l_parentid IS NOT NULL) THEN
CALL updateFolderTotals(l_parentid,p_size,p_files,p_folders);
END IF;
END;
but I get the following error:
user lacks privilege or object not found: UPDATEFOLDERTOTALS / Error Code: -5501 / State: 42501
In HyperSQL User Guide I've found some info (see Recursive Routines in HyperSQL User Guide) but it seems it is supported for funtions only.
Thank you in advance for support.

You can create recursive procedures following the same guidelines. First create the procedure with a simple body that throws an exception. You need to specify the SPECIFIC name of the procedure:
CREATE PROCEDURE updateFolderTotals(IN p_id VARCHAR(32), IN p_size BIGINT, IN p_files INT, IN p_folders INT)
SPECIFIC updateFolderTotals_1 MODIFIES SQL DATA
SIGNAL SQLSTATE '45000'
Then alter the created procedure with the full body:
ALTER SPECIFIC ROUTINE updateFolderTotals_1
BEGIN ATOMIC
DECLARE l_parentid VARCHAR(32);
UPDATE folders
SET tot_files = tot_files + p_files,
tot_size = tot_size + p_size ,
tot_folders = tot_folders + p_folders
WHERE id = p_id;
SELECT parentid INTO l_parentid FROM folders WHERE id = p_id;
IF (l_parentid IS NOT NULL) THEN
CALL updateFolderTotals(l_parentid,p_size,p_files,p_folders);
END IF;
END;

Related

how can i call stored procedure from the function in mariadb?

i want to get count of no.of rows present in table which i pass at runtime to a function.
i have created a procedure and function to execute dynamic queries. function will not allow dynamic query because i am calling procedure from function.
that procedure having dynamic query.
///////procedure///////
CREATE PROCEDURE bizopsgolddev.`test1`(tbnm varchar(100))
begin
declare sql_text varchar(200);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SELECT CONCAT(sql_text, ' is not valid');
END;
set sql_text=concat('select count(*) from ',tbnm);
SET #SQL := sql_text;
PREPARE stmt FROM #SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
end;
//////function//////
DROP FUNCTION IF EXISTS xyz;
CREATE FUNCTION `xyz`(tname varchar(100)) RETURNS int(11)
begin
declare val int;
call test1(tname);
return 1;
end;
if i execute this //select xyz('axpdc')// it should return rows count
can any one tell me how can i get count by passing table name to function(in mariadb only)
As I understand the question, the solution would be a function that returns the row count of a table with it's name passed to the function as a parameter.
I think this could be done by querying the information_schema database in MariaDB. A function could look like this:
CREATE DEFINER = 'yourUsername'#'192.168.%'
FUNCTION testDataBase.fn_GetRowCount(tableName VARCHAR(128))
RETURNS int(11)
BEGIN
-- This could be a parameter if need it to be.
DECLARE databaseName varchar(40) DEFAULT 'testDataBase';
DECLARE result int DEFAULT -1;
SELECT t.TABLE_ROWS INTO result
FROM information_schema.TABLES t
WHERE t.TABLE_NAME = tableName
AND t.TABLE_SCHEMA = databaseName;
RETURN result;
END
In order for this to work the user mentioned as the definer must have read privilege to the TABLES table in the information_schema database, otherwise you might get an error (tbh, I don't know if this is necessary).
There is a lot of useful information to be grabbed from the information_schema database.

Forms 6i if record exists then update

I need to create select statement in post_insert trigger. Is it possible if yes then how?
I want to check another table records if it exists then it will update it otherwise insert as new record. Please help.
My block code is that i want to run
DECLARE
EXSIST_TYPE varchar2(50);
EXSIST_NAME varchar2(50);
EXSIST_COMPANY VARCHAR2(100);
BEGIN
SELECT PRO_TYPE, PRO_NAME, COMPANY_NAME INTO EXSIST_TYPE, EXSIST_NAME ,EXSIST_COMPANY FROM STOCK;
IF
:PURCHASE_DETAIL.PRO_TYPE <> EXSIST_TYPE AND
:PURCHASE_DETAIL.PRO_NAME <> EXSIST_NAME AND
:PURCHASE_DETAIL.COMPANY_NAME <> EXSIST_COMPANY THEN*/
IF
:PURCHASE.RADIO_TYPE = 'PURCHASE' THEN
INSERT INTO STOCK(
PRO_TYPE ,
PRO_NAME ,
COMPANY_NAME ,
QUANTITY ,
PURCHASE_RATE,
SALE_RATE ,
RACK_NUM
)
VALUES
(
:PURCHASE_DETAIL.PRO_TYPE,
:PURCHASE_DETAIL.PRO_NAME,
:PURCHASE_DETAIL.COMPANY_NAME,
:PURCHASE_DETAIL.QUANTITY,
:PURCHASE_DETAIL.PRICE,
:PURCHASE_DETAIL.SALE_PRICE,
:PURCHASE_DETAIL.RACK_NUM
);
END IF;
ELSIF
:PURCHASE_DETAIL.PRO_TYPE = EXSIST_TYPE AND
:PURCHASE_DETAIL.PRO_NAME = EXSIST_NAME AND
:PURCHASE_DETAIL.COMPANY_NAME = EXSIST_NAME THEN
IF
:PURCHASE.RADIO_TYPE = 'PURCHASE' THEN
UPDATE STOCK SET
STOCK.QUANTITY = STOCK.QUANTITY+:PURCHASE_DETAIL.QUANTITY
WHERE
STOCK.PRO_TYPE = :PURCHASE_DETAIL.PRO_TYPE AND
STOCK.PRO_NAME = :PURCHASE_DETAIL.PRO_NAME AND
STOCK.COMPANY_NAME= :PURCHASE_DETAIL.COMPANY_NAME;
ELSIF
:PURCHASE.RADIO_TYPE = 'PRCH_RETURN' THEN
UPDATE STOCK SET
STOCK.QUANTITY = STOCK.QUANTITY-:PURCHASE_DETAIL.QUANTITY
WHERE
STOCK.PRO_TYPE = :PURCHASE_DETAIL.PRO_TYPE AND
STOCK.PRO_NAME = :PURCHASE_DETAIL.PRO_NAME AND
STOCK.COMPANY_NAME = :PURCHASE_DETAIL.COMPANY_NAME;
END IF;
END IF;
END;
You never said what happened when you ran that code.
Anyway: requirement you mentioned ("if it exists then it will update it otherwise insert") looks like an excellent candidate for a MERGE statement (also called upsert, as a combination of UPdate and inSERT).
As Forms 6i is an old piece of software, I'm pretty much sure that MERGE can't directly be used there. However, if the underlying database is at least 9i, MERGE will work - create a stored procedure that contains MERGE, and pass form items' values as parameters.
Here's an example (taken from here; have a look for more examples. I'm lazy to create my own code):
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);

Error in syntax of define a trigger in SQLite

In a table as below:
CREATE TABLE "active_mtrs"
(
"mtr_ID" INTEGER PRIMARY KEY NOT NULL,
"status" INTEGER,
"NIrSTime" DATETIME,
"NIrETime" DATETIME
)
I defined a trigger as:
CREATE TRIGGER "main"."replace1"
AFTER INSERT ON "active_mtrs" FOR EACH ROW
BEGIN
DECLARE #NIrSTime DATETIME;
DECLARE #NIrETime DATETIME;
DECLARE #mtr_ID INTEGER DEFAULT 0;
SELECT #mtr_ID = mtr_ID FROM INSERTED;
SELECT #NIrSTime = NIrSTime,#NIrETime = NIrETime
FROM subscriber
WHERE mtr_ID = #mtr_ID;
UPDATE active_mtrs
SET NIrSTime = #NIrSTime,
NIrETime = #NIrETime
WHERE mtr_ID = #mtr_ID;
END
where subscriber is another table in this database.
But I get an error:
[ near "DECLARE": syntax error ]
Exception Name: NS_ERROR_FAILURE
Exception Message: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE)
What is my problem?
Your problem is that you are trying to use a different SQL dialect in SQLite.
You cannot use DECLARE; you have to look up the values directly:
CREATE TRIGGER main.replace1
AFTER INSERT ON active_mtrs
FOR EACH ROW
BEGIN
UPDATE active_mtrs
SET (NIrSTime, NIrETime) =
(SELECT NIrSTime, NIrETime
FROM subscriber
WHERE mtr_ID = NEW.mtr_ID)
WHERE mtr_ID = NEW.mtr_ID;
END;

calling stored procedure with linq

I am new to Linq server.
I have a stored procedure in my databse that retuens count number.
select COUNT(*) from tbl_WorkerUsers
where WorkerCode=#Wcode
when I run it directly in my database it returns 1.
exec checkWorkerCodeAvailibility 100000312
but when I run it in c# code it always returns null.
WorkerDataContext Wkc = new WorkerDataContext();
int? result = Wkc.checkWorkerCodeAvailibility(Int32.Parse(Wcode)).Single().Column1;
what's wrong?
Define your Stored Procedure like this:
CREATE PROCEDURE [dbo].[checkWorkerCodeAvailibility]
#Wcode int = 0
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Result INT
SELECT #Result = COUNT(*) FROM tbl_WorkerUsers WHERE WorkerCode=#Wcode
RETURN #Result
END
You can then access this using the following code:
int result = db.checkWorkerCodeAvailibility(Int32.Parse(WCode));

Best way to insert values multiple times from data layer to stored procedure?

Hi
I have DAL Layer, from where invoking a stored procedure to insert values into the table.
E.g.:-
CREATE PROCEDURE [dbo].[DataInsert]
#DataName nvarchar(64)
AS
BEGIN
INSERT INTO
table01 (dataname)
VALUES
(#dataname)
END
Now as requirement changed, per client request i have to add values 5 times. So what is the best practice?
Do i call this Stored Procedure 5 times from my DAL?
or
Pass all the values (may be comma separated) to storedprocedure in one go and then let the stored procedure add it for 5 times?
BTW. Its not always 5 times. It is changeable.
You could create a user-defined table type;
CREATE TYPE [dbo].[SomeInfo] AS TABLE(
[Id] [int] NOT NULL,
[SomeValue] [int] NOT NULL )
Define your stored proc as such;
CREATE PROCEDURE [dbo].[AddSomeStuff]
#theStuff [SomeInfo] READONLY
AS
BEGIN
INSERT INTO SOMETABLE ([...columns...])
SELECT [...columns...] from #theStuff
END
Then you'll need to create a datatable (called table below) that matches the schema and call the stored proc as so;
var cmd = new SqlCommand("AddSomeStuff", sqlConn) {CommandType = CommandType.StoredProcedure};
var param = new SqlParameter("#theStuff", SqlDbType.Structured) {Value = table};
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
btw this proc works - I've just written and tested it see results below!
CREATE PROCEDURE [dbo].[DataInsert]
#DataName nvarchar(max) AS
BEGIN
DECLARE #pos SMALLINT, #str VARCHAR(max)
WHILE #DataName <> ''
BEGIN
SET #pos = CHARINDEX(',', #DataName)
IF #pos>0
BEGIN
SET #str = LEFT(#DataName, #pos-1)
SET #DataName = RIGHT(#DataName, LEN(#DataName)-#pos)
END
ELSE
BEGIN
SET #str = #DataName
SET #DataName = ''
END
INSERT INTO table01 VALUES(CONVERT(VARCHAR(100),#str))
END
END
GO
then run it: -
EXEC #return_value = [dbo].[DataInsert]
#DataName = N'five, bits, of, your, data'
*rows from table01: *
five
bits
of
your
data
(5 row(s) affected)
I'd either call your proc repeatedly(that would be my choice), or else you could use XML to pass in a list of values as a single parameter.
http://support.microsoft.com/kb/555266
Instead of fancy SQL code that is difficult to maintain and is not scalable, I would simply go to invoking your stored procedure multiple times.
If performance or transactional behavior is an issue, you can consider to send the commands in a single batch.
You talked about 5 insert. If the number of record to insert is much greater, you could consider bulk insert as well.

Resources