I am a beginner in Delphi, and I would like to show first and last name in the StatusBar instead of the username.
Here is my code:
procedure TForm1.Button1Click(Sender: TObject);
begin
with Login do
begin
active := false;
sql.Clear;
sql.Text := 'SELECT korisnicko, lozinka from operateri where korisnicko = ' + quotedstr(edtkorisnicko.Text) + ' and lozinka = ' + quotedstr(edtlozinka.Text);
active := true;
if Login.RecordCount <> 0 then
begin
form1.Hide();
form2.statusbar1.panels[0].text:= 'Korisnik: ' + edtKorisnicko.Text;
form2.showmodal();
end
else
begin
ShowMessage('Korisničko ime ili lozinka nisu validni!');
end;
end;
"Korisnicko or edtKorisnicko" standing for "username".
Given that your own answer shows the desired name is stored in the ime_prezime field of the database record you are searching for, you can simply retrieve that field in the very same SELECT query that is searching for the username/password, there is no need to run a 2nd query to get that field value separately, eg:
procedure TForm1.Button1Click(Sender: TObject);
begin
Login.Close;
Login.SQL.Text := 'SELECT ime_prezime from operateri where korisnicko = ' + QuotedStr(edtkorisnicko.Text) + ' and lozinka = ' + QuotedStr(edtlozinka.Text);
Login.Open;
Login.First;
if not Login.Eof then
begin
Form1.Hide();
Form2.StatusBar1.Panels[0].Text := 'Korisnik: ' + Login.FieldByName('ime_prezime').AsString;
Form2.ShowModal();
end
else
begin
ShowMessage('Korisničko ime ili lozinka nisu validni!');
end;
end;
There is answer. :)
procedure TForm1.Button1Click(Sender: TObject);
begin
with Login do
begin
active := false;
sql.Clear;
sql.Text := 'SELECT korisnicko, lozinka from operateri where korisnicko = ' + quotedstr(edtkorisnicko.Text) + ' and lozinka = ' + quotedstr(edtlozinka.Text);
active := true;
if Login.RecordCount <> 0 then
begin
active := false;
sql.Clear;
sql.Text := 'SELECT ime_prezime FROM operateri WHERE korisnicko = ' + quotedstr(edtkorisnicko.Text);
active := true;
form1.Hide();
form2.statusbar1.panels[0].text := 'Korisnik: ' + Login.FieldByName('ime_prezime').Text;
form2.showmodal();
end
else
begin
ShowMessage('Korisničko ime ili lozinka nisu validni!');
end;
end;
I'm tyring to write files for every cursor execution as shown in below sql. The data_payload column will have more than 1000 characters.
There is an exception at utl_file.put line.
If I use SUBRTR of 1000 characters, then the file writes successfully.
Is there any other alternate function to handle this?
SET SERVEROUTPUT ON
DECLARE
l_file_name VARCHAR2(100);
l_chr_payload VARCHAR2(4000);
fhandle utl_file.file_type;
CURSOR payload_cur IS
SELECT data_payload,
request_reference
FROM temp_tbl
WHERE message_type = 'ORDERCREATE'
AND ROWNUM < 2;
TYPE payload_typ IS
TABLE OF payload_cur%rowtype INDEX BY BINARY_INTEGER;
l_col_payload payload_typ;
BEGIN
OPEN payload_cur;
l_col_payload.DELETE;
FETCH payload_cur
BULK COLLECT INTO l_col_payload;
CLOSE payload_cur;
FOR i IN 1..l_col_payload.count LOOP
l_file_name := l_col_payload(i).request_reference
|| '_'
|| i
|| '.json';
dbms_output.put_line('l_file_name' || l_file_name);
fhandle := utl_file.fopen(
'TMP_DIR' -- File location
,
l_file_name -- File name
,
'w' -- Open mode: w = write.
);
l_chr_payload := substr(
l_col_payload(i).data_payload,
1,
1000
);
utl_file.put(
fhandle,
l_chr_payload
);
utl_file.fclose(fhandle);
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
dbms_output.put_line('ERROR: '
|| sqlcode
|| ' - '
|| sqlerrm);
RAISE;
END;
/
Assuming that temp_tbl.data_payload is a CLOB data type then you want to loop through the payload reading substring chunks (without needing to store the substrings in a temporary variable).
If you want to write more than 1024 characters at one time then you need to specify the 4th argument to UTL_FILE.FOPEN(location, filename, openmode, max_linesize) as the default is 1024.
Something like this (untested as I don't have your tables or a directory to write to):
DECLARE
l_index PLS_INTEGER := 0;
CURSOR payload_cur IS
SELECT data_payload,
request_reference
FROM temp_tbl
WHERE message_type = 'ORDERCREATE'
AND ROWNUM < 2;
TYPE payload_typ IS TABLE OF payload_cur%rowtype;
l_col_payload payload_typ;
BEGIN
OPEN payload_cur;
LOOP
-- In general, you should limit the number of rows you process at one time.
-- In your case this is not necessary due to the `ROWNUM < 2` filter.
FETCH payload_cur BULK COLLECT INTO l_col_payload LIMIT 10;
EXIT WHEN payload_cur%NOTFOUND;
FOR i IN 1..l_col_payload.count LOOP
l_index := l_index + 1;
DECLARE
l_file_name VARCHAR2(100);
c_amt CONSTANT PLS_INTEGER := 32000;
l_length PLS_INTEGER := COALESCE(dbms_lob.getlength(l_col_payload(i).data_payload),0);
l_offset PLS_INTEGER := 1;
l_fhandle utl_file.file_type;
BEGIN
l_file_name := l_col_payload(i).request_reference || '_' || l_index || '.json';
dbms_output.put_line('l_file_name' || l_file_name);
l_fhandle := utl_file.fopen('TMP_DIR', l_file_name, 'w', 32760);
WHILE ( l_offset <= l_length ) LOOP
utl_file.put(
l_fhandle,
dbms_lob.substr(l_col_payload(i).data_payload,c_amt,l_offset)
);
utl_file.fflush(l_fhandle);
l_offset := l_offset + c_amt;
END LOOP;
utl_file.fclose(l_fhandle);
END;
END LOOP;
END LOOP;
CLOSE payload_cur;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('ERROR: ' || sqlcode || ' - ' || sqlerrm);
RAISE;
END;
/
I'm currently trying to write a PL/SQL script that will gather information from my saleinv table that matches the serial number inputted by the user. Currently, my code is returning the error Error message is ORA-01422: exact fetch returns more than requested number of rows. If someone could explain to me how to fix the issue, it would be very appreciated. My code is below.
ACCEPT p_saleinv PROMPT 'Enter sales invoice number: '
VARIABLE g_output VARCHAR2(4000)
DECLARE
v_ABC NUMBER(4);
v_DEF EXCEPTION;
v_freightcost car.freightcost%TYPE;
v_totalcost car.totalcost%TYPE;
CURSOR saleinvoicelist IS
SELECT *
FROM saleinv
WHERE saleinv = '&p_saleinv';
BEGIN
SELECT COUNT(*)
INTO v_ABC
FROM saleinv
WHERE saleinv = '&p_saleinv';
SELECT freightcost,totalcost
INTO v_freightcost,v_totalcost
FROM car c, saleinv si
WHERE c.serial = si.serial
AND c.cname = si.cname;
IF v_ABC = '0' THEN
RAISE v_DEF;
ELSE
FOR v_saleinv IN saleinvoicelist LOOP
:g_output := :g_output||TRIM(v_saleinv.saleinv)||' ';
:g_output := :g_output||TRIM(v_saleinv.cname)||' ';
:g_output := :g_output||TRIM(v_saleinv.saledate)||' ';
:g_output := :g_output||TRIM(v_saleinv.serial)||' ';
:g_output := :g_output||TO_CHAR(v_freightcost,'122345.69')||CHR(10);
:g_output := :g_output||TO_CHAR(v_saleinv.tax,'12345.99')||' ';
:g_output := :g_output||TO_CHAR(v_saleinv.licfee,'123.76')||' ';
:g_output := :g_output||TO_CHAR(v_saleinv.commission,'1234.59')||' ';
:g_output := :g_output||TO_CHAR(v_totalcost,'123489.97')||CHR(10);
:g_output := :g_output||TO_CHAR(v_saleinv.totalprice,'12345.45')||' ';
END LOOP;
END IF;
EXCEPTION
WHEN v_DEF THEN
ROLLBACK WORK;
:g_output := 'Such data does not exist.';
WHEN OTHERS THEN
ROLLBACK WORK;
-- check error message
:g_output := 'Error'||CHR(10);
:g_output := :g_output||'Error code is '||SQLCODE||CHR(10);
:g_output := :g_output||'Error message is '||SQLERRM;
END;
/
PRINT g_output
Most likely cause of this error would be the below select
SELECT freightcost,totalcost
INTO v_freightcost,v_totalcost
FROM car c, saleinv si
WHERE c.serial = si.serial
AND c.cname = si.cname;
because you are selecting into variables the select can only return one row. I would assume that the serial number that you are using will return multiple rows from this select. You need to ensure that it returns a unique row.
Below SELECT INTO statement expects only a singluar output in the singular variable. You need to either handle exceptions or modifiy the code, if you expect more output then use FOR LOOP.
Hope below snippet helps.
ACCEPT p_saleinv PROMPT 'Enter sales invoice number: '
VARIABLE g_output VARCHAR2(4000)
DECLARE
v_ABC NUMBER(4);
v_DEF EXCEPTION;
v_freightcost car.freightcost%TYPE;
v_totalcost car.totalcost%TYPE;
CURSOR saleinvoicelist
IS
SELECT * FROM saleinv WHERE saleinv = '&p_saleinv';
BEGIN
SELECT COUNT(*) INTO v_ABC FROM saleinv WHERE saleinv = '&p_saleinv';
BEGIN
SELECT freightcost,
totalcost
INTO v_freightcost,
v_totalcost
FROM car c,
saleinv si
WHERE c.serial = si.serial
AND c.cname = si.cname;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
dbms_output.put_line('Too many rows fetched');
RETURN;
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('No rows fetched');
RETURN;
IF v_ABC = '0' THEN
RAISE v_DEF;
ELSE
FOR v_saleinv IN saleinvoicelist
LOOP
:g_output := :g_output||TRIM(v_saleinv.saleinv)||' ';
:g_output := :g_output||TRIM(v_saleinv.cname)||' ';
:g_output := :g_output||TRIM(v_saleinv.saledate)||' ';
:g_output := :g_output||TRIM(v_saleinv.serial)||' ';
:g_output := :g_output||TO_CHAR(v_freightcost,'122345.69')||CHR(10);
:g_output := :g_output||TO_CHAR(v_saleinv.tax,'12345.99')||' ';
:g_output := :g_output||TO_CHAR(v_saleinv.licfee,'123.76')||' ';
:g_output := :g_output||TO_CHAR(v_saleinv.commission,'1234.59')||' ';
:g_output := :g_output||TO_CHAR(v_totalcost,'123489.97')||CHR(10);
:g_output := :g_output||TO_CHAR(v_saleinv.totalprice,'12345.45')||' ';
END LOOP;
END IF;
EXCEPTION
WHEN v_DEF THEN
ROLLBACK WORK;
:g_output := 'Such data does not exist.';
WHEN OTHERS THEN
ROLLBACK WORK;
-- check error message
:g_output := 'Error'||CHR(10);
:g_output := :g_output||'Error code is '||SQLCODE||CHR(10);
:g_output := :g_output||'Error message is '||SQLERRM;
END;
/
with TdmBCElections.Create(Self) do
begin
with dmBCElections, qryParties do
begin
SQL.Clear;
if rgpParty.ItemIndex = 0 then
SQL.Text := 'SELECT StrConv(P_Surname, 3), StrConv(P_Names, 3) ' +
'FROM Parties WHERE P_Type = "HEAD"'
else
SQL.Text := 'SELECT StrConv(P_Surname, 3), StrConv(P_Names, 3) ' +
'FROM Parties WHERE P_Type = "TEACHER"';
Open;
while not Eof do
begin
cmbDetails.Items.Add(qryParties['StrConv(P_Surname, 3)'] + ', ' +
qryParties['StrConv(P_Names, 3)']);
Next;
end;
end;
end;
The code above gives me the following error message:
How do I call the table fields when StrConv is applied to them?
You can assign an alias to the fields:
with TdmBCElections.Create(Self) do
begin
with dmBCElections, qryParties do
begin
if rgpParty.ItemIndex = 0 then
SQL.Text := 'SELECT StrConv(P_Surname, 3) as ConvertedSurname, StrConv(P_Names, 3) as ConvertedNames ' +
'FROM Parties WHERE P_Type = "HEAD"'
else
SQL.Text := 'SELECT StrConv(P_Surname, 3) as ConvertedSurname, StrConv(P_Names, 3) as ConvertedNames ' +
'FROM Parties WHERE P_Type = "TEACHER"';
Open;
while not Eof do
begin
cmbDetails.Items.Add(qryParties['ConvertedSurname'] + ', ' +
qryParties['ConvertedNames']);
Next;
end;
end;
end;
Otherwise, you can use field indexes instead of names:
with TdmBCElections.Create(Self) do
begin
with dmBCElections, qryParties do
begin
if rgpParty.ItemIndex = 0 then
SQL.Text := 'SELECT StrConv(P_Surname, 3), StrConv(P_Names, 3) ' +
'FROM Parties WHERE P_Type = "HEAD"'
else
SQL.Text := 'SELECT StrConv(P_Surname, 3), StrConv(P_Names, 3) ' +
'FROM Parties WHERE P_Type = "TEACHER"';
Open;
while not Eof do
begin
cmbDetails.Items.Add(qryParties.Fields[0].AsString + ', ' + qryParties.Fields[1].AsString);
Next;
end;
end;
end;
Either way, I suggest you consider using a parameterized query instead:
SQL.Text := 'SELECT ... FROM Parties WHERE P_Type = :PType';
if rgpParty.ItemIndex = 0 then
Parameters.ParamByName('PType').Value := 'HEAD'
else
Parameters.ParamByName('PType').Value := 'TEACHER';
I'm using the script below in order to fetch JSON file from MongoDB, parse it and then insert it into Oracle table.
The script works fine in a sense that it inserts all values correctly into Oracle table. That includes the value Photo which is an image of base64 formate and it is much larger than 32KB.
The column Photo in the table Appery_Photos is of the type CLOB while column DecodedPhoto is of the type BLOB.
The problem lies in the line blobOriginal := base64decode1(Photo); which I used to decode the CLOB into BLOB. The function base64decode1 has been replaced with several functions (i.e. decode_base64 , base64DecodeClobAsBlob_plsql, base64decode , from_base64 & finally JSON_EXT.DECODE).
The result was the same for all of them. That is, the resultant BLOB object cannot be openned as an image in any of images editors (I'm using Oracle SQL Developer to download it).
I checked CLOB, and I could not find any newlines \n, nor could I find any spaces (only + signs found). Furthermore, I inserted CLOB value into the base64-image-converter and it displays the image correctly. In addition, I tried to encode the resultant BLOB in base64 back in order to further validate (using the opposite functions provided in the links above), the resultant base64 is not the same at all.
BEGIN
l_http_request := UTL_HTTP.begin_request('https://api.appery.io/rest/1/db/collections/Photos?where=%7B%22Oracle_Flag%22%3A%22Y%22%7D' , 'GET' , 'HTTP/1.1');
-- ...set header's attributes
UTL_HTTP.set_header(l_http_request, 'X-Appery-Database-Id', '53f2dac5e4b02cca64021dbe');
l_http_response := UTL_HTTP.get_response(l_http_request);
BEGIN
LOOP
UTL_HTTP.read_text(l_http_response, buf);
l_response_text := l_response_text || buf;
END LOOP;
EXCEPTION
WHEN UTL_HTTP.end_of_body THEN
NULL;
END;
l_list := json_list(l_response_text);
FOR i IN 1..l_list.count
LOOP
A_id := json_ext.get_string(json(l_list.get(i)),'_id');
l_val := json_ext.get_json_value(json(l_list.get(i)),'Photo');
dbms_lob.createtemporary(Photo, true, 2);
json_value.get_string(l_val, Photo);
dbms_output.put_line(dbms_lob.getlength(Photo));
dbms_output.put_line(dbms_lob.substr(Photo, 20, 1));
blobOriginal := base64decode1(Photo);
A_Name := json_ext.get_string(json(l_list.get(i)),'Name');
Remarks := json_ext.get_string(json(l_list.get(i)),'Remarks');
Status := json_ext.get_string(json(l_list.get(i)),'Status');
UserId := json_ext.get_string(json(l_list.get(i)),'UserId');
A_Date := json_ext.get_string(json(l_list.get(i)),'Date');
A_Time := json_ext.get_string(json(l_list.get(i)),'Time');
MSG_status := json_ext.get_string(json(l_list.get(i)),'MSG_status');
Oracle_Flag := json_ext.get_string(json(l_list.get(i)),'Oracle_Flag');
acl := json_ext.get_string(json(l_list.get(i)),'acl');
INSERT
INTO Appery_Photos
(
A_id,
Photo,
DecodedPhoto,
A_Name,
Remarks,
Status,
UserId,
A_Date,
A_Time,
MSG_status ,
Oracle_Flag,
acl
)
VALUES
(
A_id,
Photo,
blobOriginal,
A_Name,
Remarks,
Status,
UserId,
A_Date,
A_Time,
MSG_status ,
Oracle_Flag,
acl
);
dbms_lob.freetemporary(Photo);
END LOOP;
-- finalizing
UTL_HTTP.end_response(l_http_response);
EXCEPTION
WHEN UTL_HTTP.end_of_body THEN
UTL_HTTP.end_response(l_http_response);
END;
Any help is deeply appreciated.
I found that is not in the function I used in the base64 decoding. Instead, the value I have is not base64 encoded strings, but base64 encode dataURi's, something like
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAA
So I have to use something like: clobbase642blob( substr( Photo, instr( Photo, ',' ) + 1 ) )
The following script is inspired by Oracle Community answer
DECLARE
l_param_list VARCHAR2(512);
l_http_request UTL_HTTP.req;
l_http_response UTL_HTTP.resp;
l_response_text CLOB;
--l_response_text VARCHAR2(32767);
buf VARCHAR2(32767);
l_list json_list;
l_val json_value;
A_id VARCHAR2(100);
Photo CLOB;
A_Name VARCHAR2(100);
Remarks VARCHAR2(100);
Status VARCHAR2(100);
UserId VARCHAR2(100);
A_Date VARCHAR2(100);
A_Time VARCHAR2(100);
MSG_status VARCHAR2(100);
Oracle_Flag VARCHAR2(100);
acl VARCHAR2(100);
obj json_list;
blobOriginal BLOB := empty_blob();
clobInBase64 CLOB;
substring VARCHAR2(2000);
tmp BLOB;
n pls_integer := 0;
substring_length pls_integer := 2000;
------------------------------------------------------
FUNCTION clobbase642blob(
p_clob CLOB )
RETURN BLOB
IS
t_blob BLOB;
t_buffer VARCHAR2(32767);
t_pos NUMBER := 1;
t_size NUMBER := nls_charset_decl_len( 32764, nls_charset_id( 'char_cs' ) );
t_len NUMBER;
t_tmp raw(32767);
BEGIN
dbms_lob.createtemporary( t_blob, true );
t_len := LENGTH( p_clob );
LOOP
EXIT
WHEN t_pos > t_len;
t_buffer := REPLACE( REPLACE( SUBSTR( p_clob, t_pos, t_size ), chr(10) ), chr(13) );
t_pos := t_pos + t_size;
WHILE t_pos 0
LOOP
t_buffer := t_buffer || REPLACE( REPLACE( SUBSTR( p_clob, t_pos, 1 ), chr(10) ), chr(13) );
t_pos := t_pos + 1;
END LOOP;
t_tmp := utl_encode.base64_decode( utl_raw.cast_to_raw( t_buffer ) );
dbms_lob.writeappend( t_blob, utl_raw.length( t_tmp ), t_tmp );
END LOOP;
RETURN t_blob;
END;
------------------------------------------------------
BEGIN
-- service's input parameters
-- preparing Request...
l_http_request := UTL_HTTP.begin_request('https://api.appery.io/rest/1/db/collections/Photos?where=%7B%22Oracle_Flag%22%3A%22Y%22%7D' , 'GET' , 'HTTP/1.1');
-- ...set header's attributes
UTL_HTTP.set_header(l_http_request, 'X-Appery-Database-Id', '53f2dac5e4b02cca64021dbe');
l_http_response := UTL_HTTP.get_response(l_http_request);
BEGIN
LOOP
UTL_HTTP.read_text(l_http_response, buf);
l_response_text := l_response_text || buf;
END LOOP;
EXCEPTION
WHEN UTL_HTTP.end_of_body THEN
NULL;
END;
l_list := json_list(l_response_text);
FOR i IN 1..l_list.count
LOOP
A_id := json_ext.get_string(json(l_list.get(i)),'_id');
--deal with base64 URI photo >32KB
l_val := json_ext.get_json_value(json(l_list.get(i)),'Photo');
dbms_lob.createtemporary(Photo, true, 2);
json_value.get_string(l_val, Photo);
--dbms_output.put_line(dbms_lob.getlength(Photo));
--dbms_output.put_line(dbms_lob.substr(Photo, 20, 1));
blobOriginal := clobbase642blob( SUBSTR( Photo, 24 ) );
A_Name := json_ext.get_string(json(l_list.get(i)),'Name');
Remarks := json_ext.get_string(json(l_list.get(i)),'Remarks');
Status := json_ext.get_string(json(l_list.get(i)),'Status');
UserId := json_ext.get_string(json(l_list.get(i)),'UserId');
A_Date := json_ext.get_string(json(l_list.get(i)),'Date');
A_Time := json_ext.get_string(json(l_list.get(i)),'Time');
MSG_status := json_ext.get_string(json(l_list.get(i)),'MSG_status');
Oracle_Flag := json_ext.get_string(json(l_list.get(i)),'Oracle_Flag');
acl := json_ext.get_string(json(l_list.get(i)),'acl');
INSERT
INTO Appery_Photos
(
A_id,
Photo,
DecodedPhoto,
A_Name,
Remarks,
Status,
UserId,
A_Date,
A_Time,
MSG_status ,
Oracle_Flag,
acl
)
VALUES
(
A_id,
Photo,
blobOriginal,
A_Name,
Remarks,
Status,
UserId,
A_Date,
A_Time,
MSG_status ,
Oracle_Flag,
acl
);
dbms_lob.freetemporary(Photo);
END LOOP;
-- finalizing
UTL_HTTP.end_response(l_http_response);
EXCEPTION
WHEN UTL_HTTP.end_of_body THEN
UTL_HTTP.end_response(l_http_response);
END;
/
It is Base64 or HexBinary...
This works for HexBinary
function DESERIALIZE_HEX_BLOB(P_SERIALIZATION CLOB)
return BLOB
is
V_BLOB BLOB;
V_OFFSET INTEGER := 1;
V_AMOUNT INTEGER := 32000;
V_INPUT_LENGTH NUMBER := DBMS_LOB.GETLENGTH(P_SERIALIZATION);
V_HEXBINARY_DATA VARCHAR2(32000);
begin
if (P_SERIALIZATION is NULL) then return NULL; end if;
DBMS_LOB.CREATETEMPORARY(V_BLOB,TRUE,DBMS_LOB.CALL);
while (V_OFFSET <= V_INPUT_LENGTH) loop
V_AMOUNT := 32000;
DBMS_LOB.READ(P_SERIALIZATION,V_AMOUNT,V_OFFSET,V_HEXBINARY_DATA);
V_OFFSET := V_OFFSET + V_AMOUNT;
DBMS_LOB.APPEND(V_BLOB,TO_BLOB(HEXTORAW(V_HEXBINARY_DATA)));
end loop;
return V_BLOB;
end;
--
And could probably be modified to handle Base64 without too much trouble.