Checking if a value is a decimal in an input - stored-procedures

I'm learning SQL using SQLAnywhere which I believe uses a fairly standard SQL syntax
My problem is I have created a table MatchRecord with an Id as char(4) NOT NULL, a score as decimal and a pins as decimal.
now I want to create a procedure insert_scores to insert values into the table
I have got so far as :
create procedure insert_scores(IN play_id char(4), IN play_score decimal(5, 2),
IN no_pins decimal(5, 2), OUT a_message varchar(40))
begin
if substr(play_id, 1, 1)in (Upper('M','F', 'J'
then
if isnumeric(substr(play_id 2, 3)) = 1
then
if isnumeric(play_score) = 1
then
if isnumeric(no_pins) = 1
then
insert into MatchRecord(id, score, pins)
values(play_id, play_score, no_pins);
set a_message = 'Entry successful';
else
set a_message = 'Number of pins must be decimal ie, 1.6 ';
end if;
else
set a_message = 'Score must be decimal ie, 9.4 ';
end if;
else
set a_message = 'ID number must be in range 000 to 999 ';
end if;
else
set a_message = 'First character of ID must be M, F of J':
end if;
end
this works fine apart for any accidental insertion of a character in either of the decimal values, whereupon the system throws an error, it seems to check the table type before it reads the if statement,
I have tried isnumeric(string(play_score)) = 1 but still the same error.
Is there any way of checking that the number passed in play_score and no_pins is a decimal before the first if statement?

You could try to transform your number into a string and then check if there is a dot in the string. Something like this could do the trick.
DECLARE #number_is_ok BIT
SET #number_is_ok = CASE charindex('.', CAST(play_score as CHAR))
WHEN 0 THEN 0
ELSE 1
END
You could do then a simple check if the number is decimal or not and then continue with the corresponding logic.
IF #number_is_ok = 1 ...

Related

What does a "for i, v" loop do?

I understand, "for i, v" loops for tables, i is the index, and v is the value, but what does this script do? I do not think this has anything to do with tables, but the only type of for table loops I know in ROBLOX script is the first one I mentioned; "for i, v" loops, which loop through tables.
randomVariable = 1
for i = 1, randomVariable do
(random script)
end
This is a numeric loop statement.
for controlValue = startValue, endValue, stepValue do
-- for body
end
It goes from startValue until it reaches endValue, after running body code, controlValue is increased by stepValue. If controlValue is higher or equals to endValue the loop stops. If stepValue is not provided, it equals to 1.
It's equivalent to this code:
local controlValue = startValue
if not stepValue then stepValue = 1 end -- if no stepValue it equals to 1
while controlValue < endValue do
-- for body
controlValue = controlValue + stepValue
end
There are a few different ways to loop in Lua.
while variable < number do
repeat stuff until variable == number
for key, value in pairs do
for index, value in ipairs do
for i = 1, number do
i = 1 is the initial condition.
It usually begins at one, then loops through items in a table.
So you can think of it as an index in that regard.
where the randomVariable you mentioned would be #tab
however, you could set that initial condition to be larger, then count down.
for i = #tab, 1, -1 do
the third, optional argument is called "step size"
and it's the amount that initial condition is changed, after completing each loop. it defaults to 1, so it's not needed, most of the time.
so to step through all the even numbers in a table it would be
for i = 2, #tab, 2 do
Further reading: https://www.tutorialspoint.com/lua/lua_loops.htm

How can a Lua function return nil, even if the returned value is not nil inside the function?

I have created a function that (pseudo)randomly creates a table containing numbers. I then loop this function until at least correct result is found. As soon as I've confirmed that at least one such result exists, I stop the function and return the table.
When I create tables containing small values, there are no issues. However, once the random numbers grow to the range of hundreds, the function begins to return nil, even though the table is true the line before I return it.
local sort = table.sort
local random = math.random
local aMin, aMax = 8, 12
local bMin, bMax = 200, 2000
local function compare( a, b )
return a < b
end
local function getNumbers()
local valid = false
local numbers = {}
-- Generate a random length table, containing random number values.
for i = 1, random( aMin, aMax ) do
numbers[i] = random( bMin, bMax )
end
sort( numbers, compare )
-- See if a specific sequence of numbers exist in the table.
for i = 2, #numbers do
if numbers[i-1]+1 == numbers[i] or numbers[i-1] == numbers[i] then
-- Sequence found, so stop.
valid = true
break
end
end
for i = 1, #numbers-1 do
for j = i+1, #numbers do
if numbers[j] % numbers[i] == 0 and numbers[i] ~= 1 then
valid = true
break
end
end
end
if valid then
print( "Within function:", numbers )
return numbers
else
getNumbers()
end
end
local numbers = getNumbers()
print( "Outside function:", numbers )
This function, to my understanding, is supposed to loop infinitely until I find a valid sequence. The only way that the function can even end, according to my code, is if valid is true.
Sometimes, more often than not, with large numbers the function simply outputs a nil value to the outside of the function. What is going on here?
You're just doing getNumbers() to recurse instead of return getNumbers(). This means that if the recursion gets entered, the final returned value will be nil no matter what else happens.
In the else case of the if valid then, you are not returning anything. You only return anything in the valid case. In the else case, a recursive call may return something, but then you ignore that returned value. The print you see is corresponding to the return from the recursive call; it isn't making it out the original call.
You mean to return getNumbers().

Count Field Crystal Report

I have some view from database
here the view
select main.processId,
main.departmentname as DepartmentName,
dpaudit.DropdownlistName DdlAudit,
main.PICForAudit,
main.DateOfAudit,
main.ReferenceDetail,
main.finding as Finding,
CASE dpfinding.DropdownlistName WHEN 'RFI' THEN 'X' ELSE '' END AS IsRFi,
CASE dpfinding.DropdownlistName WHEN 'Minor NC' THEN 'X' ELSE '' END AS IsMinor,
CASE dpfinding.DropdownlistName WHEN 'Major NC' THEN 'X' ELSE '' END AS IsMajor,
iird.description as Description,
CASE spdl.DropdownlistName WHEN 'High Priority' THEN 'X' ELSE '' END AS High,
CASE spdl.DropdownlistName WHEN 'Medium Priority' THEN 'X' ELSE '' END AS Medium,
CASE spdl.DropdownlistName WHEN 'Low Priority' THEN 'X' ELSE '' END AS Low,
bc.DropdownlistName as RootCause,
iird.CorrectiveActionPlan,
iird.picResponsibilityName,
iird.TargetDateCompletion,
pos.positionname as Position
from SheAuditMain main
join IncidentInvestigationRecommendationDescription iird on main.ProcessId = iird.PIDSource
join SheProgramsDropdownlistMenu spdl on spdl.dropdownlistcode = iird.priority
join SheProgramsDropdownlistMenu dpaudit on main.TypeOfAudit = dpaudit.DropdownlistCode
join SheProgramsDropdownlistMenu dpfinding on main.TypeOfFinding = dpfinding.DropdownlistCode
join SheProgramsDropdownlistMenu bc on bc.dropdownlistcode = iird.basiccause
join vwusrposOs pos on iird.picResponsibility = pos.positionid
and then i want to create report using crystal report so the report look like this
https://ibb.co/eq924T
as we can see count of the priority [L,M,H]
isn't correct,
i do some code for that
first, i add running total field from each field [L,M,H]
and then i write code in formula
example for formula field for field high, because low and med is the same
Local numberVar i := 0;
Local numberVar TotalHigh := 0;
for i := 0 to {#RTotalHigh} - 1 do <{#RTotalHigh} coming from running total
(
if ({VwCheckPrior.High} = 'X') then
TotalHigh := TotalHigh + 1
else
0
);
TotalHigh
how do i display the correct calculation ?
[sorry for the image, i forgot my account before]
I think you should use NULL instead off empty string ('') in that CASE, because when you use empty string it will be count in total

Value can't be assigned to a host variable because it's not in range data type

CREATE PROCEDURE ADMINIST.STUDENT_CUSTOM_PROCEDURE1 (
IN p_id INTEGER,
IN p_maths INTEGER,
IN p_science INTEGER,
Out p_obtain_marks INTEGER,
out p_percentage decimal(3,2),
out p_status char(4)
)
P1: BEGIN
DECLARE p_total INTEGER;
SET p_total = 200;
SET p_obtain_marks = p_maths + p_science;
SET p_percentage = ((p_obtain_marks * 100)/p_total);
IF (p_percentage > 35) THEN
SET p_status = 'PASS';
ELSE
SET p_status = 'FAIL';
END IF;
insert into ADMINIST.STUDENT_RESULT values(p_id, p_maths, p_science, p_obtain_marks, p_percentage, p_status);
END P1
I got Error code:
SQLCODE=-304, SQLSTATE=22003
The DEC/DECIMAL data type is different than assumed. The data type information can be found in the DB2 manual under CREATE TABLE:
"DECIMAL(precision-integer, scale-integer) or DEC(precision-integer, scale-integer)
For a decimal number. The first integer is the precision of the number; that is, the total number of digits; it may range from 1 to 31. The second integer is the scale of the number; that is, the number of digits to the right of the decimal point; it may range from 0 to the precision of the number.
If precision and scale are not specified, the default values of 5,0 are used. The words NUMERIC and NUM can be used as synonyms for DECIMAL and DEC."
So in your case, to hold percentages, change the variable declaration:
out p_percentage decimal(5,2),
I got this answer by casting value into dacimal.
SET p_percentage = DECIMAL(((p_obtain_marks * 100)/p_total),3,2);
Thanks Henrik Loeser and Alex.

Verilog Code for specific kind of counter (Problems)

Good afternoon people, i'm trying to code in Verilog a structure than can store up to 64 different 8bit numbers (64X8), which is only allowed to store numbers greater than 125 and bellow or equal to 250. When it is writing (or not), it can show the maximum current stored value (VAL_MAX) as well as it's position (POS_MAX). When not writing (EN_WR ==0) i simply put in POS_RD the position that i want, in order to see what number is stored there, and when the memory is full (NR_ST = 64) it replaces the oldest stored numbers with the new ones, one by one. I currently have the code but there are some issues:
1st - When the memory is full and for eg. i have 250 in the 2nd position, the output will be
VAL_MAX= 250 ; POS_MAX=1. When a bunch of new numbers come, that maximum should be replaced with the 2nd highest stored value and must show it's position, but the memory isn't showing a new Max Value.
2nd - When i want to see the number stored in the 1st position (POS_RD = 0) the output VAL_RD (used to read the stored numbers) is "X" and not the stored number, i don't know if it is saving or not.
The code is:
module Bloco(VAL_SENSOR, EN_WR, POS_RD, NR_ST, VAL_MAX, POS_MAX, VAL_RD, segundo, clk);
parameter MEM_SIZE = 64;
parameter MEM_WIDTH = 8;
parameter ADDR_SIZE = 5;
input[MEM_WIDTH - 1:0] VAL_SENSOR;
input[5:0] POS_RD;
input EN_WR,segundo,clk;
output[6:0] NR_ST;
output[MEM_WIDTH - 1:0] VAL_MAX;
output[ADDR_SIZE :0]POS_MAX;
output[MEM_WIDTH - 1:0]VAL_RD;
reg[MEM_WIDTH - 1:0] ram[MEM_SIZE - 1:0]; // C , L
reg[MEM_WIDTH - 1:0] VAL_RD;
reg[MEM_WIDTH - 1:0] val_max = 0; //necessita de variavel so por causa do valor inicial
reg[ADDR_SIZE :0] POS_MAX = 0;
reg[ADDR_SIZE :0] POS_MAX2 = 0;
reg[ADDR_SIZE + 1:0] NR_ST_COUNTER = 0; //addr_size + 1 because it needs to count from zero to the number of values
reg[ADDR_SIZE :0] POS_POINTER = 0;
assign VAL_MAX = val_max;
assign NR_ST = NR_ST_COUNTER;
always # (posedge clk)
begin
if(EN_WR) //Caso esteja habilitado o sistema de armazenamento
begin
if(segundo)
begin
if(VAL_SENSOR > 125 && VAL_SENSOR <= 250) //Se for um numero abaixo de 250 unid. luminosas e acima de 125
begin //Escrita
if(POS_POINTER == POS_MAX)
POS_MAX <= POS_MAX2;
else
ram[POS_POINTER] <= VAL_SENSOR;
if(NR_ST_COUNTER < 64) //atualizar Contador de Valores guardados
NR_ST_COUNTER = NR_ST_COUNTER + 1;
if(VAL_SENSOR > val_max) //atualizar MAX
begin
POS_MAX <= POS_POINTER;
val_max <= VAL_SENSOR;
end
else //ver se encaixa no segundo maior POS_MAX2
begin
if(VAL_SENSOR > ram[POS_MAX2]) //nao precisa guardar o valor
POS_MAX2 <= POS_POINTER;
end
POS_POINTER <= POS_POINTER + 1;
end
end
end
else
VAL_RD <= ram[POS_RD];
end
endmodule
.
NOTE = The input "segundo" is like EN_WR, but it's only used after 10 clock cycles (it will be linked to a Counter).
Thank you.
To answer your questions:
1) The reason you are likely not seeing the second highest value in your memory appear on VAL_MAX when the current max is overridden is because you never change val_max register to contain the value of ram[POS_MAX2], ie the second highest value. However, as you do not have an ordered data structure and do not store any more than the second highest value (and do not search the memory for the second highest value), you cannot reliably keep finding the next highest value when the current highest is removed/overridden. You might need to rethink alot of how you are doing this if you need to always have the current highest value in the memory being output on VAL_MAX.
2) Position 0 is not being written to the first time you write to the memory; thus you are getting the default value of the memory, ie 'x. Here way:
if(POS_POINTER == POS_MAX)
POS_MAX <= POS_MAX2;
else
ram[POS_POINTER] <= VAL_SENSOR;
In the above lines, you only put values in the memory if the current position is not equal to the position of the current highest value. The first time you write (ie, to position 0), POS_POINTER and POS_MAX are at their initial values of 0, thus equal. So, ram[0] never gets updated as it is only executed if POS_POINTER and POS_MAX are not equal (which in this case, they are equal). If you were to write to position 0 a second time, you might be able to write to it as the value of POS_MAX might have changed. Note also, that you sometimes update the write pointer POS_POINTER even if you dont write there, as in the example above (even through ram[0] wasnt written to, you will still update POS_PONTER to be 1).
As mentioned in #1, depending on your requirements, you might not have the right structures here to meet them. If you always need to have the highest value in the memory output on VAL_MAX and always have the old value ejected, you might need to make old of those operations do a search, or store and update all the needed meta data.

Resources