I am trying to get data from SQLite database table, but i cannot get more than 50 rows. Is there a limitation of 50 rows?
My code looks like that:
unit Unit1;
interface
uses
FireDAC.Stan.Def, FireDAC.DApt, FireDAC.Phys.SQLite, FireDAC.VCLUI.Wait, FireDAC.Comp.Client, FireDAC.Stan.Async;
type
TRaportas = record
Pradzia: TDateTime;
Pabaiga: TDateTime;
Trukme: Integer;
idPriezastis: Integer;
Priezastis: string;
idVieta: Integer;
Vieta: string;
Komentaras: string;
end;
procedure TForm1.btnRaportasClick(Sender: TObject);
var
sqlConn: TFDConnection;
query: TFDQuery;
prastovuRec: array of TRaportas;
i: Integer;
begin
dbVieta := edt2.Text;
sqlConn := TFDConnection.Create(nil);
//sqlConn.Connected := False;
sqlConn.DriverName := 'SQLITE';
sqlConn.Params.Values['DataBase'] := dbVieta;
query := TFDQuery.Create(nil);
query.Connection := sqlConn;
query.SQL.Text := 'SELECT * FROM Prastovos WHERE ID >= :_ID';
query.ParamByName('_ID').Value := StrToIntDef(edt3.Text, 656);
sqlConn.Open();
query.Open();
SetLength(prastovuRec, query.RowsAffected);
edt4.Text := IntToStr(query.RowsAffected);
for i := 0 to query.RowsAffected - 1 do
begin
with mRaportas do
begin
Pradzia := query.FieldByName('Pradzia').AsDateTime;
Pabaiga := query.FieldByName('Pabaiga').AsDateTime;
Trukme := query.FieldByName('Trukme').AsInteger;
idPriezastis := query.FieldByName('IDpriezastis').AsInteger;
Priezastis := query.FieldByName('Priezastis').AsString;
idVieta := query.FieldByName('IDvieta').AsInteger;
Vieta := query.FieldByName('Vieta').AsString;
Komentaras := query.FieldByName('Komentaras').AsString;
end;
prastovuRec[i] := mRaportas;
query.Next;
end;
query.Close;
query.DisposeOf;
sqlConn.Close;
sqlConn.Free;
end;
There is a lot of mistakes and misunderstandings inyour code. To simplify, I'm just going to fix your code to make it work. Study the differences yourself.
unit Unit1;
interface
uses
FireDAC.Stan.Def, FireDAC.DApt, FireDAC.Phys.SQLite, FireDAC.VCLUI.Wait, FireDAC.Comp.Client,
FireDAC.Stan.Async, FireDAC.Stan.Option;
type
TRaportas = record
Pradzia: TDateTime;
Pabaiga: TDateTime;
Trukme: Integer;
idPriezastis: Integer;
Priezastis: string;
idVieta: Integer;
Vieta: string;
Komentaras: string;
end;
var
prastovuRec: array of TRaportas;
procedure TForm1.Button7Click(Sender: TObject);
var
sqlConn: TFDConnection;
query: TFDQuery;
mRaportas: TRaportas;
i: Integer;
begin
sqlConn := TFDConnection.Create(nil);
query := TFDQuery.Create(nil);
try
sqlConn.DriverName := 'SQLITE';
sqlConn.Params.Values['DataBase'] := edt2.Text;
query.Connection := sqlConn;
query.FetchOptions.Mode := fmAll; // essential if you want to use RecordCount
query.SQL.Text := 'SELECT * FROM Prastovos WHERE ID >= :_ID';
query.ParamByName('_ID').Value := StrToIntDef(edt3.Text, 656);
query.Open();
edt4.Text := IntToStr(query.RecordCount);
SetLength(prastovuRec, query.RecordCount);
i := 0;
while not query.Eof do
begin
mRaportas := Default(TRaportas); // not necessary if you assign all record fields
mRaportas.Pradzia := query.FieldByName('Pradzia').AsDateTime;
mRaportas.Pabaiga := query.FieldByName('Pabaiga').AsDateTime;
mRaportas.Trukme := query.FieldByName('Trukme').AsInteger;
mRaportas.idPriezastis := query.FieldByName('IDpriezastis').AsInteger;
mRaportas.Priezastis := query.FieldByName('Priezastis').AsString;
mRaportas.idVieta := query.FieldByName('IDvieta').AsInteger;
mRaportas.Vieta := query.FieldByName('Vieta').AsString;
mRaportas.Komentaras := query.FieldByName('Komentaras').AsString;
prastovuRec[i] := mRaportas;
Inc(i);
query.Next;
end;
query.Close;
finally
query.Free;
sqlConn.Free;
end;
end;
No, there is no special limit.
But you have a WHERE clause in your query. It is likely that which limits the result set. Check the value you use.
Related
I am trying to code a trigger with PL/SQL, where I want to show different messages when an error happens. The problem is when It should show more than one message.
That is my code
create or replace trigger Restrictionns
BEFORE INSERT ON numbers FOR EACH ROW
DECLARE
v_message varchar2(500);
v_error boolean;
v_type number;
BEGIN
v_message := '';
v_error := false;
v_type := -20000;
IF LENGTH(:new.number) > 6 THEN
v_message := v_message || '{The length number can't be bigger than 6}';
v_error := true;
v_type := -20001;
END IF;
IF :new.number > 9 or :new.number< 0 THEN
v_message := v_message || '{The number must be beetween 0 and 9}';
v_error := true;
v_type := -20002;
END IF;
IF :new.number < 0 THEN
v_message := v_message || '{The number can't be negative)}';
v_error := true;
v_type := -20003;
END IF;
IF v_error = true THEN
RAISE_APPLICATION_ERROR(v_type,v_message)
END IF;
END;
/
For example if INSERT a negative number it should show two messages, the error -20002 and -20003... but it only shows the last one. What is the way to show all error messages when they happens?
i am trying to call the procedure my_package.procedure_test like bellow:
declare
v_counter BINARY_INTEGER := 1;
a tbl_familles;
v_mytable tbl_familles;
begin
PK_SOA_Famille_Test.get_famille('zz','zz', v_mytable);
while v_counter <= v_mytable.count
loop
Dbms_Output.Put_Line(v_mytable(v_counter).nom);
v_counter := v_counter + 1;
end loop;
end;
But i get the exception:
ORA-06531: reference to uninitialized collection
The Package definition:
CREATE OR REPLACE Package PK_SOA_Famille_Test as
PROCEDURE get_famille
(num_ass IN VARCHAR2, num_indd IN VARCHAR2,
OutTableParam OUT tbl_familles);
end PK_SOA_Famille_Test;
The Procedure body:
CREATE OR REPLACE PACKAGE BODY PK_SOA_Famille_Test AS
PROCEDURE get_famille
(num_ass IN VARCHAR2, num_indd IN VARCHAR2, OutTableParam OUT tbl_familles) IS
v_counter number := 0;
Cursor C_typ_famille
(
num_ass varchar2 ,num_indd varchar2
) Is
SELECT nom, prenom, num_imm ,num_ind ,nat_int ,dat_naiss, num_cin, der_stat, der_sit, datsit, indpere, indmere
from typ_famille
where (num_imm = num_ass AND num_ind = num_indd) ;
C2 C_typ_famille%ROWTYPE;
BEGIN
IF num_indd is null then
for EmpCursor in
(select nom,prenom,num_imm ,num_ind, nat_int, dat_naiss, num_cin, der_stat, der_sit, datsit, indpere, indmere
from typ_famille
where num_imm = num_ass)
loop
v_counter := v_counter + 1;
OutTableParam(v_counter).nom := EmpCursor.nom;
OutTableParam(v_counter).prenom := EmpCursor.prenom;
OutTableParam(v_counter).num_imm := EmpCursor.num_imm;
OutTableParam(v_counter).num_ind := EmpCursor.num_ind;
OutTableParam(v_counter).nat_int := EmpCursor.nat_int ;
OutTableParam(v_counter).dat_naiss := EmpCursor.dat_naiss;
OutTableParam(v_counter).num_cin := EmpCursor.num_cin;
OutTableParam(v_counter).der_stat := EmpCursor.der_stat;
OutTableParam(v_counter).der_sit := EmpCursor.der_sit;
OutTableParam(v_counter).datsit := EmpCursor.datsit;
OutTableParam(v_counter).indpere := EmpCursor.indpere;
OutTableParam(v_counter).indmere := EmpCursor.indmere;
end loop;
END IF ;
END get_famille;
END PK_SOA_Famille_Test;
/
I have also created the types rec_famille as an object and tbl_familles as a table of rec_famille in schema level.
When num_indd is NOT NULL then PK_SOA_Famille_Test.get_famille effectively does nothing. This leaves OutTableParam uninitialized. You could have an ELSE in your IF-statement with OutTableParam := tbl_familles(); as EJ Egyed suggested.
Additionally, looping through a cursor to fill a collection is a waste: you should use BULK COLLECT instead.
CREATE OR REPLACE PACKAGE BODY pk_soa_famille_test IS
PROCEDURE get_famille(num_ass IN VARCHAR2,
num_indd IN VARCHAR2,
outtableparam OUT) IS
BEGIN
IF num_indd IS NULL THEN
SELECT nom,
prenom,
num_imm,
num_ind,
nat_int,
dat_naiss,
num_cin,
der_stat,
der_sit,
datsit,
indpere,
indmere
BULK COLLECT
INTO outtableparam
FROM typ_famille
WHERE num_imm = num_ass;
ELSE
outtableparam := tbl_familles;
END IF;
END get_famille;
END pk_soa_famille_test;
I have following pl/SQL block for getting records from record type,and i am using object of record as array.It gives wrong number or types of argument error where i initialize array.kindly give me written solution for initializing object of record as array.
DECLARE
TYPE loc IS RECORD (
loc_id number(4),
str_add VARCHAR2(40),
p_code VARCHAR2(12),
city VARCHAR2(30),
st_pro VARCHAR2(25),
c_id CHAR(2),
Oper varchar2(1));
--names namesarray;
--loc_rec loc IS VARRAY(8);
type loc_rec IS VARRAY(8) OF loc;
total number(4);
tot number(3);
loc_id1 number(4);
i number(2);
begin
i:=1;
loc_rec(1).loc_id:=1;
loc_rec(1).str_add:='chikhli';
loc_rec(1).p_code:='396521';
loc_rec(1).city:='chikhli';
loc_rec(1).st_pro:='Gujarat';
loc_rec(1).c_id:='G1';
loc_rec(1).Oper:='I';
loc_rec(2).loc_id:=2;
loc_rec(2).str_add:='chikhli';
loc_rec(2).p_code:='396521';
loc_rec(2).city:='chikhli';
loc_rec(2).st_pro:='Gujarat';
loc_rec(2).c_id:='G1';
loc_rec(2).Oper:='U';
loc_rec(3).loc_id:=3;
loc_rec(3).str_add:='chikhli';
loc_rec(3).p_code:='396521';
loc_rec(3).city:='chikhli';
loc_rec(3).st_pro:='Gujarat';
loc_rec(3).c_id:='G1';
loc_rec(3).Oper:='D';
--names := --namesarray(loc_rec.loc_id,loc_rec.str_add,loc_rec.p_code,
--loc_rec.city,loc_rec.st_pro,loc_rec.c_id,loc_rec.Oper);
LOOP
--total := names.count;
if loc_rec(i).Oper='I' then
insert into locations values(loc_rec(i).loc_id,
loc_rec(i).str_add,
loc_rec(i).p_code,
loc_rec(i).city,
loc_rec(i).st_pro,
loc_rec(i).c_id
);
dbms_output.put_line('Record Inserted Successfully');
elsif loc_rec(i).Oper='D' then
delete from locations where location_id=loc_rec(i).loc_id;
dbms_output.put_line('Record deleted Successfully');
if(sql%NOTFOUND) then
dbms_output.put_line('Input location ID Not Found');
end if;
elsif loc_rec(i).Oper='U' then
update locations
set
street_address=loc_rec(i).str_add,
postal_code=loc_rec(i).p_code,
city=loc_rec(i).city,
state_province=loc_rec(i).st_pro,
country_id=loc_rec(i).c_id
where location_id=loc_rec(i).loc_id;
dbms_outt.put_line('Record Updated Successfully');
if(sql%NOTFOUND) then
insert into locations values(loc_rec(i).loc_id,
loc_rec(i).str_add,
loc_rec(i).p_code,
loc_rec(i).city,
loc_rec(i).st_pro,
loc_rec(i).c_id
);
end if;
else
dbms_output.put_line('Kindly give proper Input: I:insert U:update D:delete');
end if;
commit;
i:=i+1;
END LOOP;
end;
/
There are several things wrong with your code.
You haven't declared a variable to hold your array
You haven't initialized the collection
You haven't extended the collection to hold a new row
dbms_outt.put_line... typo; I think you mean dbms_output.put_line
You're not looping through the collection correctly - you've more or less coded an infinite loop, except eventually you'll run out of items in your collection and will end up with a subscript out of range error eventually.
Your code should be something like:
declare
type loc is record (loc_id number (4),
str_add varchar2 (40),
p_code varchar2 (12),
city varchar2 (30),
st_pro varchar2 (25),
c_id char (2),
oper varchar2 (1));
--names namesarray;
--loc_rec loc IS VARRAY(8);
type loc_varray is varray (8) of loc;
total number (4);
tot number (3);
loc_id1 number (4);
loc_rec loc_varray := loc_varray();
begin
loc_rec.extend;
loc_rec (1).loc_id := 1;
loc_rec (1).str_add := 'chikhli';
loc_rec (1).p_code := '396521';
loc_rec (1).city := 'chikhli';
loc_rec (1).st_pro := 'Gujarat';
loc_rec (1).c_id := 'G1';
loc_rec (1).oper := 'I';
loc_rec.extend;
loc_rec (2).loc_id := 2;
loc_rec (2).str_add := 'chikhli';
loc_rec (2).p_code := '396521';
loc_rec (2).city := 'chikhli';
loc_rec (2).st_pro := 'Gujarat';
loc_rec (2).c_id := 'G1';
loc_rec (2).oper := 'U';
loc_rec.extend;
loc_rec (3).loc_id := 3;
loc_rec (3).str_add := 'chikhli';
loc_rec (3).p_code := '396521';
loc_rec (3).city := 'chikhli';
loc_rec (3).st_pro := 'Gujarat';
loc_rec (3).c_id := 'G1';
loc_rec (3).oper := 'D';
--names := --namesarray(loc_rec.loc_id,loc_rec.str_add,loc_rec.p_code,
--loc_rec.city,loc_rec.st_pro,loc_rec.c_id,loc_rec.Oper);
for i in loc_rec.first..loc_rec.last
loop
--total := names.count;
if loc_rec (i).oper = 'I'
then
insert Into Locations
Values (Loc_Rec (I).Loc_Id,
Loc_Rec (I).Str_Add,
Loc_Rec (I).P_Code,
Loc_Rec (I).City,
Loc_Rec (I).St_Pro,
Loc_Rec (I).C_Id);
dbms_output.put_line ('Record Inserted Successfully');
elsif loc_rec (i).oper = 'D'
then
delete from locations
where location_id = loc_rec (i).loc_id;
dbms_output.put_line ('Record deleted Successfully');
if (sql%notfound)
then
dbms_output.put_line ('Input location ID Not Found');
end if;
elsif loc_rec (i).oper = 'U'
then
UPDATE locations
SET street_address = loc_rec (i).str_add,
postal_code = loc_rec (i).p_code,
city = loc_rec (i).city,
state_province = loc_rec (i).st_pro,
country_id = loc_rec (i).c_id
WHERE location_id = loc_rec (i).loc_id;
dbms_output.put_line ('Record Updated Successfully');
if (sql%notfound)
then
insert into locations
values (loc_rec (i).loc_id,
loc_rec (i).str_add,
loc_rec (i).p_code,
loc_rec (i).city,
loc_rec (i).st_pro,
loc_rec (i).c_id);
end if;
else
dbms_output.put_line (
'Kindly give proper Input: I:insert U:update D:delete');
end if;
commit;
end loop;
end;
/
my problem is that the table that my user will be loading, i'm not sure what they columns will be so how do define these unknown elements (columns), and also what they will be defined as (e.g. asstring, asinteger,asreal) etc
(I use SQLlite)
So here's my code
procedure TFrmsearchpage.btnloadClick(Sender: TObject);
var
con:tfdconnection;
loadquery:tfdquery;
i:integer;
j:integer;
row:integer;
col1,col2,col3,col4, col5, col6, col7 : string;
begin
con:=tfdconnection.Create(nil);
loadquery:=tfdquery.Create(con);
loadquery.Connection:=con;
con.DriverName:='SQL';
con.Open('DriverID=SQLite;Database='+Dir+'/Stock_V5;');
loadquery.SQL.Text:='SELECT * FROM ' + edtdatabasename.Text; //' Con Column';
loadquery.Open;
if loadquery.Eof then
ShowMessage('not exists')
else
ShowMessage('exists');
for i := 0 to sgdproduct.RowCount do
for j := 0 to sgdproduct.ColCount do
sgdproduct.Cells[i,j]:='';
showmessage(loadquery.SQL.Text);
Sgdproduct.colcount:=7;
sgdproduct.fixedcols:=0;
for i := 0 to 3 do
sgdproduct.colwidths[i]:=100;
sgdproduct.cells[0,0] := 'Col1'; //?
sgdproduct.cells[1,0] := 'Col2'; //?
sgdproduct.cells[2,0] := 'Col3';
sgdproduct.cells[3,0] := 'Col4'; //?
sgdproduct.cells[4,0] := 'Col5'; //?
sgdproduct.cells[5,0] := 'Col6'; //?
sgdproduct.cells[6,0] := 'Col7'; //?
row:=1;
while not loadquery.Eof do
begin
Col1:=query.FieldByName('Col1')//.As
Col2:=query.FieldByName('Col2')//.As
Col3:=query.FieldByName('Col3')//.As
Col4:=query.FieldByName('Col4')//.As
Col5:=query.FieldByName('Col5')//.As
Col6:=query.FieldByName('Col6')//.As
col7:=query.FieldByName('Col7')//.As
sgdproduct.Cells[0,row]:=Col1;
sgdproduct.Cells[1,row]:=Col2;
sgdproduct.Cells[2,row]:=Col3;
sgdproduct.Cells[3,row]:=Col4;
sgdproduct.Cells[4,row]:=Col5;
sgdproduct.Cells[5,row]:=Col6;
sgdproduct.Cells[6,row]:=Col7;
row:=row+1;
query.Next;
end;
end;
to give label in stringgrid based on Tdataset generated by your SQL, take a look at below code :
for i := 0 to DataSet.FieldCount - 1 do
begin
sgdproduct.cells[i,0] := DataSet.Fields[i].DisplayName;
end;
I have a function which concatinates the value for a cursor. Its now only concatinates 4 columns and that column name should be hardcoded. Is there a way to have a generic solution for this, such that if i pass a cursor it will automatically concatinate data regardless of column name and number of columns in 11g.
FUNCTION generateData(p_dataCursor IN SYS_REFCURSOR)
RETURN VARCHAR2 AS
-- ---------------------------------------------------------------------
crlf VARCHAR2(2) := chr(13)||chr(10);
lv_message VARCHAR2(32000);
BEGIN
FOR rec IN p_dataCursor
LOOP
lv_message := lv_message || rec.a||','||rec.b||','||rec.c||','||rec.d || crlf;
END LOOP;
RETURN lv_message;
END;
Since 11g Oracle built-in package DBMS_SQL provides function TO_CURSOR_NUMBER - "This function takes an OPENed strongly or weakly-typed ref cursor and transforms it into a DBMS_SQL cursor number."
Example code:
DECLARE
l_cursor SYS_REFCURSOR;
FUNCTION generateData(p_dataCursor IN SYS_REFCURSOR)
RETURN VARCHAR2 AS
curs SYS_REFCURSOR := p_dataCursor;
l_cursorid NUMBER;
l_column_count INTEGER;
l_describe_table DBMS_SQL.DESC_TAB;
l_numvar NUMBER;
l_ignore INTEGER;
l_value VARCHAR2(2000);
l_coma VARCHAR2(10);
crlf VARCHAR2(2) := chr(13)||chr(10);
lv_message VARCHAR2(32000);
BEGIN
l_cursorid := dbms_sql.to_cursor_number( curs );
dbms_sql.describe_columns( l_cursorid, l_column_count, l_describe_table );
FOR i IN 1..l_column_count LOOP
dbms_sql.define_column(l_cursorid, i, l_value, 2000);
END LOOP;
LOOP
IF DBMS_SQL.FETCH_ROWS(l_cursorid)>0 THEN
l_coma := '';
FOR i IN 1..l_column_count LOOP
dbms_sql.column_value(l_cursorid, i, l_value);
lv_message := lv_message || l_coma || l_value;
l_coma := ',';
END LOOP;
lv_message := lv_message || crlf;
ELSE
EXIT;
END IF;
END LOOP;
dbms_sql.close_cursor( l_cursorid );
RETURN lv_message;
END;
BEGIN
open l_cursor FOR 'SELECT 1 as A, 2 AS B, 3 AS C, 4 AS D FROM DUAL UNION ALL SELECT 1 as A, 2 AS B, 3 AS C, 4 AS D FROM DUAL';
dbms_Output.put_Line(generateData(l_cursor));
END;
/