How can I call a procedure declared inside another procedure? - stored-procedures
I have a doubt regarding procedures in Db2. I created a stored procedure using "CREATE PROCEDURE", and inside that I have another which is declared using "DECLARE PROCEDURE". But, this procedure created by declare, cannot be called using "CALL".
When I try to run the procedure, Db2 returns:
[Code: -440, SQL State: 42884] DB2 SQL Error: SQLCODE=-440,
SQLSTATE=42884,
SQLERRMC=DMTLDBR.SP_DASH_CALENDARIO.PROCURA_DIA_UTIL_POST_DIA1;PROCEDURE,
DRIVER=4.25.1301
How should I call the declared procedure? (PROCURA_DIA_UTIL_POST_DIA1)
Code:
create or replace PROCEDURE "SP_DASH_CALENDARIO" (IN P_MES INTEGER)
BEGIN
------
DECLARE SQLSTATE CHAR(5) DEFAULT ' ';
DECLARE V_ANO_MES DECIMAL(6);
DECLARE V_ID_DIA ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_DIADIA.ID_DIA;
DECLARE V_VAL_REAL_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_VAL_TONVNEMA ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONVNEMA;
DECLARE V_VAL_FAT357_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_FAT357;
DECLARE V_VAL_PERDA_FAT_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_PERDA;
DECLARE V_SUM_VAL_REAL_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_REAL_CAL;
DECLARE V_SUM_VAL_TONVNE_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONVNE_CAL;
DECLARE V_SUM_VAL_TONLIQUIDO_ZBCL_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONLIQUIDO_ZBCL_CAL;
DECLARE V_SUM_VAL_TONLIQUIDO_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONLIQUIDO_CAL;
DECLARE V_SUM_VAL_FAT357_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_FAT357_CAL;
DECLARE V_VAL_TONLIQUIDO_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONLIQUIDO_CAL;
DECLARE V_VAL_TONVNE_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONVNE_CAL;
DECLARE V_VAL_TONLIQUIDO_ZBCL_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONLIQUIDO_ZBCL_CAL;
DECLARE V_VAL_PLANO_FAT_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_PLANEJ_MAN.VAL_PLANO;
DECLARE V_VAL_PLANO ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_PLANEJ_MAN.VAL_PLANO;
DECLARE V_TOTAL_PLANO_DESOVA_SEMANAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_PLANEJ_MAN.TOTAL_PLANO_DESOVA_SEMANAL;
DECLARE V_ID_DIASEMANA ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_DIADIA.ID_DIASEMANA;
DECLARE V_FLG_HOLIDAY ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_DIADIA.FLG_HOLIDAY;
DECLARE V_IND_LEGENDA DECIMAL(1);
DECLARE V_VARIANTE ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_PRODVARIANTE.ID_VARIANTE;
DECLARE V_VAL_PERDA ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_VAL_DESOVA ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_VAL_UHT ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_VAL_SUCO ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_VAL_REQ ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_TONLIQUIDO;
DECLARE V_FAT_UHT ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_FAT357;
DECLARE V_FAT_REQ ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_FAT357;
DECLARE V_ID_DIA_INI ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_DIADIA.ID_DIA;
DECLARE V_ID_DIA_FIM ANCHOR DATA TYPE TO DMTLDBR.TB_DIM_DIADIA.ID_DIA;
DECLARE FLAG_DIA_UTIL BOOLEAN;
DECLARE V_SUM_VAL_TONVNEMA_CAL ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_DASH_CALENDARIO.VAL_TONVNEMA_CAL;
DECLARE V_SUM_VAL_FAT357 ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_FAT357;
DECLARE V_SUM_VAL_ABATIMENTOREPORTADO ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_ABATIMENTOREPORTADO;
DECLARE V_SUM_VAL_ICMSZFMREPORTADO ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_ICMSZFMREPORTADO;
DECLARE V_PROC ANCHOR DATA TYPE TO DMTLDBR.TB_TMP_LOG_EXECUTION_PROC.SYNCPOINT_PROC;
SET V_PROC = 'SP_DASH_CALENDARIO';
-- =========================================================================================================
-- P R O C P R O C U R A _ D I A _ U T I L _ P O S T _ D I A 1
--
-- OBTEM O PRIMEIRO DIA ÚTIL DO MÊS (QUE NÃO SEJA DOMINGO NEM FERIADO)
--
-- =========================================================================================================
BEGIN
DECLARE PROCEDURE PROCURA_DIA_UTIL_POST_DIA1(IN P_ID_MES INTEGER)
BEGIN
DECLARE V_ACHOU DECIMAL(1) DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND BEGIN END;
SET V_ID_DIA = NULL;
L1: LOOP -- (LP01)
BEGIN -- (BE02.)
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' BEGIN END;
SELECT MIN(ID_DIA) INTO V_ID_DIA
FROM DMTLDBR.TB_DIM_DIADIA
WHERE ID_MES = P_ID_MES
AND ID_DIASEMANA <> 1 -- DOMINGO
AND FLG_HOLIDAY = 0;
END; -- (BE02.)
IF SQLSTATE = '00000' THEN
LEAVE L1;
--SET V_ACHOU = 1;
END IF;
END LOOP L1; -- (LP01.)
END;
END;
CALL DMTLDBR.PROCURA_DIA_UTIL_POST_DIA1(201909);
END
A Compound SQL (compiled) statement requires strict order of declarations / statements inside.
For example:
--#SET TERMINATOR #
CREATE OR REPLACE PROCEDURE TEST_LOCAL(P_I INT)
BEGIN
-- SQL-variable-declarations
DECLARE L_I INT;
-- DECLARE-CURSOR-statements
DECLARE C1 CURSOR FOR VALUES 1;
-- procedure-declaration
DECLARE PROCEDURE TEST_LOCAL_NESTED(P_J INT) BEGIN END;
-- handler-declarations
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;
-- SQL-procedure-statements
CALL TEST_LOCAL_NESTED(P_I);
END#
Briefly for each BEGIN END block:
1-st: all SQL-variable-declarations
2-nd: all DECLARE-CURSOR-statements
3-rd: all procedure-declaration
4-th: all handler-declarations
All SQL-procedure-statements come afterwards only. These statements may contain nested BEGIN END blocks, where the same strict declaration / statement rules apply.
You have more than one mistake in the code shown in the question.
You are using a local procedure, that is the name for a procedure declared inside another procedure.
Local-Procedures work fine when used correctly.
Some suggestions to allow successful compilation:
the declare procedure must appear before any executable statements or new block in the calling procedure.
Move the statement SET V_PROC = 'SP_DASH_CALENDARIO' so that it appears
before the CALL to the local procedure (or anywhere within the main procedure block AFTER
all declarations (including after declaring the local procedure).
Additionally, remove the BEGIN (and matching END) on the line before DECLARE PROCEDURE.
You want all the declares to appear before any executable statement or new begin-end block.
the local procedure name must be unqualified both on the DECLARE and on the CALL
but you are using a qualifier on your CALL statement which will prevent Db2 from finding the local procedure.
The last part of your procedure will then look something like below:
...snip...
DECLARE V_SUM_VAL_ICMSZFMREPORTADO ANCHOR DATA TYPE TO DMTLDBR.TB_FATO_VENDASDIARIO.VAL_ICMSZFMREPORTADO;
DECLARE V_PROC ANCHOR DATA TYPE TO DMTLDBR.TB_TMP_LOG_EXECUTION_PROC.SYNCPOINT_PROC;
-- =========================================================================================================
-- P R O C P R O C U R A _ D I A _ U T I L _ P O S T _ D I A 1
--
-- OBTEM O PRIMEIRO DIA ÚTIL DO MÊS (QUE NÃO SEJA DOMINGO NEM FERIADO)
--
-- =========================================================================================================
DECLARE PROCEDURE PROCURA_DIA_UTIL_POST_DIA1(IN P_ID_MES INTEGER)
BEGIN
DECLARE V_ACHOU DECIMAL(1) DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND BEGIN END;
SET V_ID_DIA = NULL;
L1: LOOP -- (LP01)
BEGIN -- (BE02.)
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' BEGIN END;
SELECT MIN(ID_DIA) INTO V_ID_DIA
FROM DMTLDBR.TB_DIM_DIADIA
WHERE ID_MES = P_ID_MES
AND ID_DIASEMANA <> 1 -- DOMINGO
AND FLG_HOLIDAY = 0;
END; -- (BE02.)
IF SQLSTATE = '00000' THEN
LEAVE L1;
--SET V_ACHOU = 1;
END IF;
END LOOP L1; -- (LP01.)
END;
SET V_PROC = 'SP_DASH_CALENDARIO';
CALL PROCURA_DIA_UTIL_POST_DIA1(201909);
END#
Related
Why "=" operator results True when comparing varEmpty with a zero evalued varInteger?
Why does the = operator results True when comparing a varEmpty Variant variable with a zero evalued varInteger Variant variable? var V1 : Variant; V2 : Variant; begin V2 := 0; if(V1 = V2) then ShowMessage('V1 = V2') else ShowMessage('V1 <> V2'); end; This code produces the following output: V1 = V2 Does the equality operator = only checks the value part of Variant variables?
In order to make a comparison, the empty variant is converted to an integer. According to the variant type conversion rules, the unassigned (empty) variant is converted to 0. Hence the expression returns true.
Lua / Initialize table with inline function code but assign value not function
I have this Lua code to initialize a table: table = { a = 1; b = myfunc(); c = function () <some code> end; } After this table.c has type function and I have to use table.c() in a print statement with the .. operator to get the result. But I would like to just use table.c instead. Is there a way that I can get the return value of the function assigned to table.c so the type is not function without having to define a function outside of the table?
If you wanted table.c to contain the return value of the function, then you should have assigned it the return value of the function. You instead assigned it the function itself. To get the return value of a function, you must call that function. It's really no different from b. myfunc is a function; myfunc() is calling that function and storing its return value. But, due to Lua's grammar, calling a function that you are defining requires that you need to wrap the function constructing expression in (), then call it: c = (function () <some code> end)(); This of course will only contain the value of that function at the time that the table is constructed.
How to handle bidirectional pin (inout) in a verilog task
I want to use a bidirectional data bus in my controller.Here's the code module controller ( clk, data_out); // Port Declaration input clk; inout [7:0] data_out; reg [7:0] a; reg [7:0] b; wire [7:0] c; // data should write to data_out (data_out act as output) task write; input c; begin assign data_out = a; data_out <= c; end endtask // data should read from data_out (data_out act as input) task read; output b; begin assign data_out = 8'bz; b <= data_out; end endtask endmodule when I compile this i'm getting an error saying LHS in procedural continuous assignment may not be a net: data_out. it's says there is an error in assign data_out = a; and assign data_out = 8'bz; I know assign should be done in always or initial block but in a task using those blocks are useless/give eroor Then, how we can change directions of the bus in side a task??
You shouldn't use assign in initial and always blocks. I don't get why you necessarily want it in task? Simply use assign alone. Assinging value to bidirectional port needs a flag that specifies what action- read or write- should be done. Syntax is like: assign bidir_port = [flag] ? a : 1'bz;
Pass class to record
I want define constant with records where one variable is class. And receive error: [DCC Error] usample.pas(18): E2026 Constant expression expected Class and record declaration in Unit1: type TParentClass = class (TObject) function Call(s: string) : boolean; end; type TMyRecord = record s: string; c: TParentClass; //or TClass end; And Unit2 with Child Class and record: type TChildClass = class (TParentClass); procedure two; var: class_var: TChildClass; const rec_var : array[0..1] of TMyRecord = ( (s : ''; c : class_var) //Error with class_var. ); UPD: I want to fill record with Class and in unit1 search functions in this Class. Its a team project. UPD2: const class_var: TChildClass = nil; Same error.
Because as the compiler says, you have to put a constant in there, but you defined class_var as a variable. Change class_var to be declared as a constant, not a variable. But this cannot actually be done: const class_var = TParentClass; is not allowed. And const class_var : TClass = TParentClass; is not a real constant and you cannot use it inside another constant declaration.
In your latest update you ask why this does not compile: const class_var: TChildClass = nil; rec_var: TMyRecord = (s: ''; c: class_var); The reason that does not compile is that class_var is not a true constant. You can write it like this: rec_var: TMyRecord = (s: ''; c: nil); because nil is a true constant. I'm struggling to get a handle on what you are really trying to do, but my instincts tell me that a constant is not what you need. I think you are going to need to use variables that are initialized at startup.
You cannot define a const with a field initialized to the content of a variable. The compiler needs to evaluate consts at compile time, ie when class_var does not even have a location, never mind any content. Forget this idea. If you can, declare rec_var as a variable and load it up at runtime.
Lambda Expressions in Delphi Prism/Oxygene
I have been experimenting with Lambda expressions in Oxygene. Very simple recursive lambda expression to calculate a fibonacci number : var fib : Func<int32, int32>; fib := n -> iif(n > 1, fib(n - 1) + fib(n - 2), n); fib(3); When I run this code I get a nullreferenceexception. Any ideas as to what I'm doing wrong?
You aren't doing anything wrong. If anything, the compiler should warn you about using fib, an unassigned variable, inside the body of the lambda. However the compiler ought to be capturing fib as a location, so that when the assignment completes and the delegate is later invoked, fib is properly assigned and recursion should work as expected. The most obvious possible reason for the failure is that Prism isn't capturing locations, but values, which would be grossly unintuitive and at odds with every other closure implementation in non-pure languages. For example, try this code in JavaScript (contrary to Craig's assertion in the comments to this post, JavaScript also captures locations, not values): <html> <head> <script language='javascript'> function main() { var x = 1; var f = function() { return x; }; alert(f()); x = 2; alert(f()); } </script> </head> <body> <input type=button onclick="javascript:main()"></input> </body> </html> The alert boxes after you click on the button show 1 and 2 respectively, while following Prism/Oxygene semantics they would show 1 both times.
Steve: The issue has apparently been addressed in Delphi Prism 2010. The following code sample works in the official release. var fib : Func<int32, int32>; fib := n -> iif(n > 1, fib(n - 1) + fib(n - 2), n); var i := fib(9); //1,1,2,3,5,8,13,21,34 MessageBox.Show(i.ToString); The MessageBox shows the value 34. In response to Jeroen's question, this code was run in the original, official release build, 3.0.21.661.
as a temporary workaround you can use: var f := new class(f: Tfib := nil); f.f := method(n : Int32): Int32 begin if n > 1 then Result := f.f(n-1) + f.f(n-2) else Result := n; end; f.f(3);
Prism handles the capture of local variables differently then native Delphi or C#. In those 2 all references in your code of those locals will be mapped to fields of the compiler generated class that will hold your anonymous method. In prism, these locals stay ordinary locals, yet the fields of this hidden fields are set when you instantiate the anonymous method. One way to get a recursive lambda, would be to use a reference type to hold the lambda for you. All of this sounds much more complicated then it really is. 2 methods of accomplishing your goal: 1) var fib := new class(Call : Func<Integer, Integer> := nil); fib.Call := n -> iif(n > 1, fib.Call(n - 1) + fib.Call(n - 2), n); var x := fib.Call(3); 2)When you do not want to have a reference to this wrapper, you can do it like so: var fib : Func; with fibWrapper := new class(Call : Func<Integer, Integer> := nil) do begin fibWrapper.Call := n -> iif(n > 1, fibWrapper.Call(n - 1) + fibWrapper.Call(n - 2), n); fib := fibWrapper.Call; end; btw, the reason behind Prism not following C# here, is that for threading and loop, this reusing of captured vars makes for hard weird runtime problems. In Prism, captures are really captured the moment you assign the anonymous method or lambda. Which has a certain immuatble touch to it... Cheers, Robert
Does the same apply to Anonymous Methods? I'm guessing it does, but can't quite figure out the syntax to get this to run var f : Tfib; f := method(n : Int32): Int32 begin if n > 1 then Result := f(n-1) + f(n-2) else Result := n; end; Edit It does. var f := new class(call : TFib := nil); f.call := method(n : Int32): Int32 begin if n > 1 then Result := f.call(n-1) + f.call(n-2) else Result := n; end;