DBAdvGrid Show Decimal numbers - mysql

I have mysql table and DBAdvGrid,
decimal numbers of mysql column are shown like 950, 450, 555.45
I would like to be always shown 2 digits after point. like 950.00
I tried event of dataset 'AfterOpen'
TFloatField(MyDs.FieldByName('Price')).DisplayFormat := '0.00';
but did not helps
any help would appreciate.

you can try (use the Dataset direct)
works with mysql and Zeos
(MyDs.FieldByName('Price') as TFloatField).DisplayFormat := '#####0.00';
to get what you want.
More information look here.
Delphi's Database Architecture
UPDATE
About the test
procedure TForm1.Button1Click(Sender: TObject);
begin
ZQuery1.Open;
end;
procedure TForm1.ZQuery1AfterOpen(DataSet: TDataSet);
begin
if CheckBox1.Checked then
(ZQuery1.FieldByName('gebuehr') as
TFloatField).DisplayFormat := '#####0.00';
end;
Field gebuehr Transl.(gebuehr == fee)
Without AfterOpen
With AfterOpen

Related

Duplicate problem in MySQL with autoincrement id

I have an issue with my database.
Table structure is:
Table name: sales
sale_id (autoincrement)
date (datetime)
total (decimal)
etc.
I have 2 computers, one is "the server" and the other is "the client", when I Insert in "sales" sometimes the database saves more than 1 record, it's an issue kind of random because one day could be normal just save 1 record as is but other day could save 2 or more duplicates.
My code is:
qry1.SQL.Text := 'SELECT * FROM sales '
+ 'WHERE sale_id = 1';
qry1.Open;
qry1.Insert;
qry1.FieldByName('date').AsDateTime := Date;
qry1.FieldByName('total').AsFloat := total;
qry1.Post;
saleId := qry1.FieldByName('sale_id').AsInteger;
qry1.Close;
// Code to save sale details using saleId.
I'm using Delphi 10.3 + ZeosLib 7.2.6-stable + MySQL 8.0
I opened the ports in the server so I have a direct connection to MySQL, I don't know what could be happening
Hope you can help me
Update----
Thanks for your kind answers,
#nbk Yes, I did it already.
#A Lombardo I used "where" to get just 1 record and then I use the query to insert the new one similar to use TTable but instead of load the hole table I just get one record and I can insert (qry.Insert),
#TheSatinKnight not only I get two records, sometimes I get 3 or more, but makes sense probably the keayboard is not working well and could send "enter" key more than once.
#fpiette, I will do ti right now.
I will keep you posted.
There are better ways to accomplish an insert than to open a TZTable and inserting on that open table.
As another approach, drop 2 TZQuery (NOT TZTable) on your form (which I'll assume is TForm1 - change as appropriate).
Assuming the name is ZQuery1 and ZQuery2.
Set its connection property the same as your TZTable, so it uses the same connector.
Set ZQuery1.SQL property to 'Insert into sales (date, total) values (:pdate, :ptotal)' //(w/o quotes)
Set ZQuery2.SQL property to 'select last_insert_id() as iddb'
now add the Function below to your form's Private delcaration
TForm1 = class(TForm)
ZQuery1: TZQuery; //added when dropped on form
ZQuery2: TZQuery;
private
{ Private declarations }
function AddNewSale(SaleDate: TDateTime; Total: Double): Integer; //add this line
public
{ Public declarations }
end;
and then add the following code to your form's methods
var
Form1: TForm1;
implementation
{$R *.dfm}
function TForm1.AddNewSale(SaleDate: TDateTime; Total: Double): Integer;
begin
ZQuery1.ParamByName('pdate').AsDateTime := SaleDate;
ZQuery1.ParamByName('ptotal').AsFloat := Total;
ZQuery1.ExecSQL; //*Execute* the Insert - Only "open" SQL that returns a result set
//now the record has been added to your DB
if ZQuery1.RowsAffected = 1 then //check to ensure it was inserted
begin
ZQuery2.Open;
try
Result := ZQuery2.FieldByName('iddb').AsInteger;
finally
ZQuery2.Close;
end;
end
else
result := -1;//indicate error by returning negative value
end;
now in the place you want to insert the record, simply call this function:
var
ReturnValue: Integer;
begin
ReturnValue := AddNewSale(Date, total);
if ReturnValue < 0 then
//error happened
else
begin
//Everything worked
end;
end;
Thanks again for all your kind answers.
At the end the problem was keyboard, It had a problem with "Enter" key, so when you pressed it, it send more than one pulsation so #TheSatinKnigh your approach was correct
#fpiette I created the log file and I figured out as you said the request had been executed twice or more.
I know maybe it is a silly thing for a programmer because I was disabling the button to late, sorry for that
#A Lombardo thanks for you code I like it better than mine I will use it

Can't show fractional part as .0 when value is a whole number

Here's the case:
uses
System.JSON;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
dd:Double;
aJsonObj:TJSONObject;
begin
dd := 100.0;
aJsonObj := TJSONObject.Create(TJSONPair.Create('DecimalValue',TJSONNumber.Create(dd)));
ShowMessage(aJsonObj.ToString);
end;
which shows
{"DecimalValue":100}
What I need is
{"DecimalValue":100.0}
I've tried to change JsonFormatSettings but I couldn't find a way to add the fractional part.
One of TJSONNumber constructors accepts a raw string value that will be used in resulting JSON string without further processing. It allows you to pre-format the value yourself:
procedure TForm1.Button1Click(Sender: TObject);
var
dd: Double;
aJsonObj: TJSONObject;
begin
dd := 100.0;
aJsonObj := TJSONObject.Create(
TJSONPair.Create('DecimalValue', TJSONNumber.Create(FormatFloat('0.0###', dd, GetJSONFormat))));
try
ShowMessage(aJsonObj.ToString);
finally
aJsonObj.Free;
end;
end;
Using the above snippet the value shows as:
{"DecimalValue":100.0}
You can even create 'whatever' as number:
aJsonObj := TJSONObject.Create(TJSONPair.Create('DecimalValue', TJSONNumber.Create('whatever')));
to get this (invalid) JSON:
{"DecimalValue":whatever}
Side note: you are responsible for releasing root JSON objects you create as they have no parent object to manage their lifetime. Use try..finally to Free the root object when you're done with it as you can see in the first code snippet. Too bad that the documentation itself tempts you not to cleanup.

How to get this function to work in Oracle 11G - PL/SQL

I'm new with PL/SQL I have a assignment where I need to make a function. The assignment is as follows:
> "Create a function 'afdeling_van:'
> - this function accepts a medewerkernummer(employee number) as argument
> - give the afdelingnummer(department number) from the medewerkernummer(employee number) back"
So I need to create a function with a parameter that returns a number. After that I probably need to add some code to make it return a medewerker(employee) number back.
I got pretty stuck with this one as I am really new to PL/SQL. What I do have at the moment is this:
declare
procedure afdeling_van(p_persoon in medewerkers.mnr%type)--table name with column name
is
begin
select med.mnr
from medewerkers med;
where mnr = p_persoon;
end afdeling_van;
begin
afdeling_van(10);
end;
It's not working for me. I have tried different solutions. But as I lack experience and I cannot find the solution or information that I need on the web. I am trying it to ask here
one other thing. I think it's similair to my problem. In the previous assignment I made a procedure instead of a function. The procedure is as follows:
declare
v_medewerker varchar2(50) := ontsla_med();
procedure ontsla_med(p_medewerkers in medewerkers.naam%type)
is
begin
delete from medewerkers
where naam = p_medewerkers;
end ontsla_med;
begin
ontsla_med('');
dbms_output.put_line('Medewerker: ' || v_medewerker || 'verwijdert uit medewerker, inschrijven en uitvoeringen bestand.' );
exception
when no_data_found then
dbms_output.put_line('Medewerker bestaat niet/ is al verwijderd.');
end;
/
this works except for the last dbms_output.put_line. If I remove the output line, then it will work and with the output line, it won't.
I hope my question is not too vague.
Thanks in advance.
You need to create a function instead of a procedure, and you've got a semi-colon in the wrong place. Try something like:
declare
nReturned_value MEDEWERKERS.AFDELINGNUMMER%TYPE;
FUNCTION afdeling_van(p_persoon in medewerkers.mnr%type) --table name with column name
RETURN MEDEWERKERS.AFDELINGNUMMER%TYPE
is
nAFDELINGNUMMER MEDEWERKERS.AFDELINGNUMMER%TYPE;
begin
select med.AFDELINGNUMMER
INTO nAFDELINGNUMMER
from medewerkers med
where mnr = p_persoon;
RETURN nAFDELINGNUMMER ;
end afdeling_van;
begin
nReturned_value := afdeling_van(10);
DBMS_OUTPUT.PUT_LINE('nReturned_value = ' || nReturned_value);
end;
Edit
In your second example, I don't believe that the line v_medewerker varchar2(50) := ontsla_med(); will compile. ontsla_med is a procedure rather than a function, and because procedures don't return anything they can't be used in an assignment statement.
However, v_medewerker is only used in the DBMS_OUTPUT line which you say causes a problem - thus, it may be that the compiler is eliminating the variable because it's not used if the DBMS_OUTPUT line is removed, thus eliminating the problem. Try changing the declaration to v_medwerker varchar2(50) := 'Hello'; and see if that helps.

Cant retrieve error from procedure in PL/SQL

I'm starting to work with PL/SQL and learning how to write procedures and exceptions but I cant seem to grasp how to show an error. The procedure is a simple one, its only supposed to do simple math as you can see below:
create or replace
procedure get_simple_math
(n_num1 in number,
n_num2 in number,
n_answer out number,
n_err_code out number,
n_err_msg out varchar2)
as
begin
n_answer := (n_num1 / n_num2);
dbms_output.put_line('Answer is '||n_answer);
n_err_code := 0;
exception
when others
then
n_err_code := SQLCODE;
n_err_msg := 'Error in get_simple_math '||SQLERRM;
raise_application_error (-20002,n_err_msg);
end get_simple_math;
As you can see its nothing fancy, but I cant for the life of me get the block to run:
set serveroutput on
declare
n_answer number := 0;
n_err_code number;
n_err_msg varchar2;
begin
get_simple_math(10,5,n_answer);
end;
I'm assuming I need to declare the variables that are set to out, which is why they are there. I also tried adding them to the procedure execute like:
get_simple_math(10,5,n_answer,n_err_code,n_err_msg);
But that didn't seem to do the trick, so I am just looking for some help in solving this problem. Thanks in advance.
Run this and you'll get your answer:
declare
n_answer number := 0;
n_err_code number;
--> n_err_msg varchar2; -- Incorrect
n_err_msg varchar2(300); -- Correct
begin
--> get_simple_math(10,5,n_answer); -- Incorrect call to proc...
get_simple_math(10,5,n_answer, n_err_code, n_err_msg); -- add out parameters
end;
/
General suggestion for the procedure part: use substr - optional:
n_err_msg := 'Error in get_simple_math '||substr(SQLERRM, 1, 250);

function return varray error

I keep getting a error when i run this code, What wrong with the code?
create or replace function f_vars(line varchar2,delimit varchar2 default ',')
return line_type is type line_type is varray(1000) of varchar2(3000);
sline varchar2 (3000);
line_var line_type;
pos number;
begin
sline := line;
for i in 1 .. lenght(sline)
loop
pos := instr(sline,delimit,1,1);
if pos =0 then
line_var(i):=sline;
exit;
endif;
string:=substr(sline,1,pos-1);
line_var(i):=string;
sline := substr(sline,pos+1,length(sline));
end loop;
return line_var;
end;
LINE/COL ERROR
20/5 PLS-00103: Encountered the symbol "LOOP" when expecting one of
the following:
if
22/4 PLS-00103: Encountered the symbol "end-of-file" when expecting
one of the following:
end not pragma final instantiable order overriding static
member constructor map
Stack Overflow isn't really a de-bugging service.
However, I'm feeling generous.
You have spelt length incorrectly; correcting this should fix your first error. Your second is caused by endif;, no space, which means that the if statement has no terminator.
This will not correct all your errors. For instance, you're assigning something to the undefined (and unnecessary) variable string.
I do have more to say though...
I cannot over-emphasise the importance of code-style and whitespace. Your code is fairly unreadable. While this may not matter to you now it will matter to someone else coming to the code in 6 months time. It will probably matter to you in 6 months time when you're trying to work out what you wrote.
Secondly, I cannot over-emphasise the importance of comments. For exactly the same reasons as whitespace, comments are a very important part of understanding how something works.
Thirdly, always explicitly name your function when ending it. It makes things a lot clearer in packages so it's a good habit to have and in functions it'll help with matching up the end problem that caused your second error.
Lastly, if you want to return the user-defined type line_type you need to declare this _outside your function. Something like the following:
create or replace object t_line_type as object ( a varchar2(3000));
create or replace type line_type as varray(1000) of t_line_type;
Adding whitespace your function might look something like the following. This is my coding style and I'm definitely not suggesting that you should slavishly follow it but it helps to have some standardisation.
create or replace function f_vars ( PLine in varchar2
, PDelimiter in varchar2 default ','
) return line_type is
/* This function takes in a line and a delimiter, splits
it on the delimiter and returns it in a varray.
*/
-- local variables are l_
l_line varchar2 (3000) := PLine;
l_pos number;
-- user defined types are t_
-- This is a varray.
t_line line_type;
begin
for i in 1 .. length(l_line) loop
-- Get the position of the first delimiter.
l_pos := instr(l_line, PDelimiter, 1, 1);
-- Exit when we have run out of delimiters.
if l_pos = 0 then
t_line_var(i) := l_line;
exit;
end if;
-- Fill in the varray and take the part of a string
-- between our previous delimiter and the next.
t_line_var(i) := substr(l_line, 1, l_pos - 1);
l_line := substr(l_line, l_pos + 1, length(l_line));
end loop;
return t_line;
end f_vars;
/