How to use % in oracle for calculation - oracle

I have defined a logic where I want to use % percentage as a calculation but its giving me error while using.
Below is the logic.
ELSIF V_ANCHOR_NONANCHOR = 'Anchor'
THEN
v_STD_REVISED_AMT := (V_STANDRD_AMT - v_OD_Discount) - ((V_STANDRD_AMT - v_OD_Discount * 10%));
and the error is
Error(103,94): PLS-00103: Encountered the symbol "%" when expecting one of the following: ) , * & = - + < / > at in is mod remainder not rem => <an exponent (**)> <> or != or ~= >= <= <> and or like like2 like4 likec as between || member submultiset The symbol "%" was ignored.
Please suggest how to use it.
update
v_STD_REVISED_AMT := (V_STANDRD_AMT - v_OD_Discount) - ((V_STANDRD_AMT - v_OD_Discount * 0.1), (V_STANDRD_AMT - v_OD_Discount));
giving error as
Error(108,22): PLS-00412: list of values not allowed as argument to this function or procedure

I think you just want the multiplication by 0.1 which is 10/100 means 10% as follows:
(V_STANDRD_AMT - (v_OD_Discount * 0.1))
-- Update
The entire solution should be as follows:
v_STD_REVISED_AMT := (V_STANDRD_AMT - v_OD_Discount)
- CASE WHEN V_ANCHOR_NONANCHOR = 'Anchor'
OR (M2_DATE_COL_VARIABLE < DATE '2019-03-31'
AND M2_DATE_COL_VARIABLE > DATE '2016-07-13')
THEN (V_STANDRD_AMT - v_OD_Discount * 10%)
ELSE 0
END;

Related

SETFILTER - is not equal to (<>) not working NAV 90

I have been trying to make use of setfilter but it seems not working
FOR i := 1 TO ARRAYLEN(ItemGroupFilter) DO BEGIN
IF i <> ARRAYLEN(ItemGroupFilter) THEN BEGIN
IF ItemGroupFilter[i] <> '' THEN
IF ItemGroupString = '' THEN
ItemGroupString := '<>' + ('%' + FORMAT(i))
ELSE
ItemGroupString := ItemGroupString + ('|%' + FORMAT(i))
ELSE
ItemGroupString := ItemGroupString;
END ELSE BEGIN
IF ItemGroupFilter[i] <> '' THEN
IF ItemGroupString = '' THEN
ItemGroupString := '<>' + ('%' + FORMAT(i))
ELSE
ItemGroupString := ItemGroupString + ('|%' + FORMAT(i))
ELSE
ItemGroupString := ItemGroupString;
END;
END;
Item.RESET;
Item.SETFILTER("Item Group",ItemGroupString,ItemGroupFilter[1],ItemGroupFilter[2],ItemGroupFilter[3],ItemGroupFilter[4]);
As a result, only the first ItemGroupFilter[1] is doing the job. as from the OR (|) afterwards, it doesnt work
Message Values:
ItemGroupString = '<>%1|%2|%3|%4'
ItemGroupFilter[1] = '1'
ItemGroupFilter[2] = '2'
ItemGroupFilter[3] = '3'
ItemGroupFilter[4] = '4'
Found the solution. SETFILTER for <> should be as follows:
SETFILTER('<>%1&<>%2&<>%3&<>%4','1','2','3','4')
So my above ItemGroupString Variable consist of
ItemGroupString = '<>%1&<>%2&<>%3&<>%4'
Happy programming! :)

Get currently-running MLM name in Arden

How do I get the currently-running MLM name without the user name at the beginning? The special keyword THIS_MLM_NAME returns the name of the MLM in the format USERNAME-302364198::MLM_NAME_HERE, but I just want the MLM's name by itself.
I tried using SUBSTRING:
SUBSTRING 200 CHARACTERS
STARTING AT ((FIND "::" IN THIS_MLM_NAME) + 2)
FROM THIS_MLM_NAME;
But this just returns null. What am I doing wrong?
The problem is that THIS_MLM_NAME is not actually an Arden string. If you test THIS_MLM_NAME IS STRING you will get false. To fix that, convert it to a string with THIS_MLM_NAME AS STRING:
ThisMLMName := SUBSTRING 200 CHARACTERS
STARTING AT ((FIND "::" IN STRING (THIS_MLM_NAME AS String)) + 2)
FROM (THIS_MLM_NAME AS String);
Since there is no debugger in Sunrise Acute Care's implementation of Arden, I wrote the following MLM to help show information about variables (name the module MOD_VARIABLE_INFO or change the code to match the actual name):
// data slot
(Variable, Padding) := ARGUMENT;
Result := "";
IF NOT EXIST Padding THEN
Padding := "";
ENDIF;
CR := (13 FORMATTED WITH "%c") || Padding;
Delimiter := "";
MOD_VARIABLE_INFO := MLM 'MOD_VARIABLE_INFO';
IF Variable IS LIST THEN
Result := Result || "List(" || (COUNT Variable) || ") [" || CR || " ";
FOR Item IN Variable DO
Result := Result || Delimiter;
TempResult := CALL MOD_VARIABLE_INFO WITH Item, Padding || " ";
Result := Result || TempResult;
Delimiter := "," || CR || " ";
ENDDO;
Result := Result || CR || "]";
ELSEIF Variable IS STRING THEN
Result := Result || "String";
ELSEIF Variable IS NUMBER THEN
Result := Result || "Number";
ELSEIF Variable IS BOOLEAN THEN
Result := Result || "Boolean";
ELSEIF Variable IS NET_OBJECT THEN
Result := Result || ".Net Object";
ELSEIF Variable IS NULL THEN
Result := Result || "Null";
ELSEIF Variable IS OBJECT THEN
Result := Result || "Object {" || CR || " ";
FOR Attr IN (EXTRACT ATTRIBUTE NAMES Variable) DO
Result := Result || Delimiter || Attr || ": ";
Item := ATTRIBUTE Attr FROM Variable;
TempResult := CALL MOD_VARIABLE_INFO WITH Item, Padding || " ";
Result := Result || TempResult;
Delimiter := "," || CR || " ";
ENDDO;
Result := Result || CR || "}";
ELSE
Result := Result || "Unknown (" || Variable || ")";
ENDIF;
// logic slot
CONCLUDE True;
// action slot
RETURN Result;
While this MLM returns "Unknown" for THIS_MLM_NAME, it at least shows that it is not any of the native Arden data types nor is it a .Net data type.
In the Sunrise MLM Editor, you can see what is going on in the underlying Lisp by syntax checking the MLM, then clicking on the "Syntax Check MLM" tab, selecting "Function Definition" then looking at the code in the lower right pane. Search for THIS_MLM_NAME and you will find (SETQ THIS_MLM_NAME 'USERNAME-302364198::MLM_NAME). From this you can see that the variable has been set to a plain quoted/unevaluated lisp expression rather than a string, which would look like (SETQ THIS_MLM_NAME "USERNAME-302364198::MLM_NAME").

What's wrong with this Pascal syntax?

I can't understand what's going on here. Can you give me a hand? This is the problematic code:
While not EOF(Archi) do begin
index:= index + 1;
Read(Archi, Alumno[index]);
Promes[index] := (Alumno[index].nota1 + Alumno[index].nota2) / 2;
if Promes[index] >= 6 then begin
alguPromo := true;
PromosIndex := PromosIndex + 1;
Promos[PromosIndex]:= Alumno[index];
end;
else begin
if Promes[index] > 4 then cantiRecu:= cantiRecu + 1;
else begin
LibresIndex += 1;
Libres[LibresIndex] := Alumno[index];
end;
end;
end;
The compiler marks error in the line 10 of this code (else begin). The error is:
Fatal: Syntax error, ; expected but ELSE found.
If someone wants to tray compile here is the entire code: http://pastebin.com/dRg1Lguu
Note that in Pascal the semicolon is a separator, not a terminator. Sometimes this doesn't matter, but in some cases it does, particularly before an else. Your code should be:
while not EOF(Archi) do
begin
index:= index + 1;
Read(Archi, Alumno[index]);
Promes[index] := (Alumno[index].nota1 + Alumno[index].nota2) / 2;
if Promes[index] >= 6 then
begin
alguPromo := true;
PromosIndex := PromosIndex + 1;
Promos[PromosIndex] := Alumno[index]
end
else
begin
if Promes[index] > 4 then
cantiRecu:= cantiRecu + 1
else
begin
LibresIndex := LibresIndex + 1;
Libres[LibresIndex] := Alumno[index]
end
end
end
Note that I have re-formatted the code into a more conventional style which helps to make the program logic more easily understood and which also makes it more obvious where the semicolons are needed and where they are not.
Looks like problem in += operator

Can't seem to subract two numbers in a PLSQL function

The following function is intended to divide up a delimited CLOB into a string array:
FUNCTION SPLIT_CLOB(sText IN clob, sDel IN VARCHAR2 := ',') RETURN CLOB_ARRAY IS
nStartIdx PLS_INTEGER := 1;
nEndIdx PLS_INTEGER := 1;
oRet CLOB_ARRAY := CLOB_ARRAY();
BEGIN
IF sText IS NULL THEN RETURN oRet; END IF;
IF DBMS_LOB.getlength(sText) = 0 THEN RETURN oRet; END IF;
LOOP
nEndIdx := DBMS_LOB.INSTR(sText, sDel, nStartIdx);
IF nEndIdx > 0 THEN
oRet.Extend;
/* compiler error on this statement: */
oRet(oRet.LAST) := DBMS_LOB.SUBSTR(sText, (nEndIdx – nStartIdx), nStartIdx);
nStartIdx := nEndIdx + LENGTH(sDel);
ELSE
oRet.Extend();
oRet(oRet.LAST) := DBMS_LOB.SUBSTR(lob_loc => sText, offset => nStartIdx);
EXIT;
END IF;
END LOOP;
RETURN oRet;
END SPLIT_CLOB;
The line:
oRet(oRet.LAST) := DBMS_LOB.SUBSTR(sText, (nEndIdx – nStartIdx), nStartIdx);
throws PLS-00103 compiler errors. But if I change the call to:
oRet(oRet.LAST) := DBMS_LOB.SUBSTR(sText, 5, nStartIdx);
everything is fine. I've tried creating another variable to do the subtraction ahead of time, but ran into the same PLS-00103 error.
Have I lose my touch? Did I forget how to subtract two numbers or something?
Please help. Thanks.
EDIT
Okay, the WEIRDEST thing just happened... in the rest of this package, I know I was subtracting some PLS_INTEGERs somewhere else in a different function.... so I found such an example, then COPY & PASTE the minus sign found in my other function, and the thing compiles...
Thanks for your help...
Why not do the calculation before the
oRet(oRet.LAST) := DBMS_LOB.SUBSTR(sText, (nEndIdx – nStartIdx), nStartIdx);
eg
calcValue := nEndIdx – nStartIdx;
oRet(oRet.LAST) := DBMS_LOB.SUBSTR(sText, calcValue, nStartIdx);
"Operations involving patterns as parameters, such as COMPARE, INSTR, and SUBSTR do not support regular expressions or special matching characters (such as % in the LIKE operator in SQL) in the pattern parameter or substrings." http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lob.htm
I think you should calculate "nEndIdx – nStartIdx" outside the SUBSTR Function
Substr Ref. http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lob.htm#i999349

How to convert a string version value to a numerical value in Inno Setup Scripts?

I want to develop a setup package for conditionally upgrading an existing package. I want to check the existing software version against to-be-installed version. In order to do that, I have to compare the version strings.
How can I convert the string value to a numerical value in a Inno setup script?
RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\Blah blah', 'Version', version)
version = 'V1.R2.12';
numVersion := ??string_to_numerical_value??(version);
This is a little more tricky, as you would want to handle versions like 'V1.R2.12' and 'V0.R15.42' correctly - with the simple conversion in the other answer you would get 1212 and 1542, which would not compare the way you would expect.
You need to decide how big each part of the version number can be, and multiply the parts by that value to get a correct end number. Something like this:
[Code]
function string_to_numerical_value(AString: string; AMaxVersion: LongWord): LongWord;
var
InsidePart: boolean;
NewPart: LongWord;
CharIndex: integer;
c: char;
begin
Result := 0;
InsidePart := FALSE;
// this assumes decimal version numbers !!!
for CharIndex := 1 to Length(AString) do begin
c := AString[CharIndex];
if (c >= '0') and (c <= '9') then begin
// new digit found
if not InsidePart then begin
Result := Result * AMaxVersion + NewPart;
NewPart := 0;
InsidePart := TRUE;
end;
NewPart := NewPart * 10 + Ord(c) - Ord('0');
end else
InsidePart := FALSE;
end;
// if last char was a digit the last part hasn't been added yet
if InsidePart then
Result := Result * AMaxVersion + NewPart;
end;
You can test this with the following code:
function InitializeSetup(): Boolean;
begin
if string_to_numerical_value('V1.R2.12', 1) < string_to_numerical_value('V0.R15.42', 1) then
MsgBox('Version ''V1.R2.12'' is not as recent as version ''V0.R15.42'' (false)', mbConfirmation, MB_OK);
if string_to_numerical_value('V1.R2.12', 100) > string_to_numerical_value('V0.R15.42', 100) then
MsgBox('Version ''V1.R2.12'' is more recent than version ''V0.R15.42'' (true)', mbConfirmation, MB_OK);
Result := FALSE;
end;
Whether you pass 10, 100 or 1000 for AMaxVersion depends on the number and range of your version number parts. Note that you must not overflow the LongWord result variable, which has a maximum value of 2^32 - 1.
I haven't tried that (and my Pascal knowledge is a bit rusty), but something like the following should work:
function NumericVersion(s: String): Integer;
var
i: Integer;
s1: String;
begin
s1 := '';
for i := 0 to Length(s)-1 do
if (s[i] >= '0') and (s[i] <= '9') then
s1 := s1 + s[i];
Result := StrToIntDef(s1, 0);
end;
Please not that you'll have to play with the start and end value for i as I'm not sure whether it is zero-based or not (s[0] may contain the length of the string if it is a "Pascal String").
I've implemented two version strings (actually one string and one dword value) in the registry to overcome complexity.
displayversion="v1.r1.0"
version="10100" (=1*10^4 + 1*10^2 + 0*10^0)
That's simple. Though not an answer to this question, however one might think the other way around when faced with complexity, which could be avoided in a simpler way.

Resources