I am pulling down records with a stored procedure of customers that have a customer_id=5.
Now the procedure gets the data and shows it in the grid and I want to add a new record .
How can I make sure that when I add new record in the grid it has automatically the same customer_id ( 5 ) ?
I dont want to write it down all the time.I used to know this but I forgot.The DB is sql server.
You can set the DefaultExpression to the used ID for the field you want. For example for a UniDAC stored procedure object you can do (ParamCustID is the procedure input parameter, FieldCustID is the returned dataset field name):
var
CustID: Integer;
begin
CustID := 123;
UniStoredProc1.StoredProcName := 'MyProcedure';
UniStoredProc1.PrepareSQL;
UniStoredProc1.ParamByName('ParamCustID').AsInteger := CustID;
UniStoredProc1.Execute;
UniStoredProc1.FieldByName('FieldCustID').ReadOnly := True;
UniStoredProc1.FieldByName('FieldCustID').DefaultExpression := IntToStr(CustID);
end;
The above code will setup the field for assigning same value for every appended tuple, and makes it read only. Out of curiosity, the same task for FireDAC would go like this (for applying changes, there must be an explicit method call for updating field attributes):
var
CustID: Integer;
begin
CustID := 123;
FDStoredProc1.StoredProcName := 'MyProcedure';
FDStoredProc1.Prepare;
FDStoredProc1.ParamByName('#ParamCustID').AsInteger := CustID;
FDStoredProc1.Open;
FDStoredProc1.FieldByName('FieldCustID').ReadOnly := True;
FDStoredProc1.FieldByName('FieldCustID').DefaultExpression := IntToStr(CustID);
FDStoredProc1.UpdateAttributes;
end;
Related
I write datasnap application. I should know id of last uploaded record on server and after that upload new records from local db using cliendataset component.
I don't realise meaning of this code, what are there Parameters[0].Value, Parameters[1].Value and how it change correctly in order to return result from server:
FSelectCountryCommand.Parameters[0].Value.SetInt32();
FSelectCountryCommand.ExecuteUpdate;
Result := FSelectCountryCommand.Parameters[1].Value.GetInt32;
if I write manually random integer value, for example
result:=10; //FSelectCountryCommand.Parameters[1].Value.GetInt32;
then it works correctly and returns this value in ClientFormUnit.
My final goal is return result value(maxcountry_id) from Server to buttonclick procedure of ClientForm unit
Query on server:
select max(country_id) as maxcountry_id from country
ClientForm unit:
procedure Tclient.buttonCountryClick(Sender: TObject);
var c:integer;
begin
c:=Clientmodule1.ServerMethods1Client.SelectCountry;
Clientmodule1.lqCountry.close;
Clientmodule1.lqCountry.Params[0].AsInteger:= c;
Clientmodule1.lqCountry.close;
end;
ClientClassesUnit:
function TServerMethods1Client.SelectCountry:Integer;
begin
if FSelectCountryCommand = nil then
begin
FSelectCountryCommand := FDBXConnection.CreateCommand;
FSelectCountryCommand.CommandType :=
TDBXCommandTypes.DSServerMethod;
FSelectCountryCommand.Text := 'TServerMethods1.SelectCountry';
FSelectCountryCommand.Prepare;
end;
FSelectCountryCommand.Parameters[0].Value.SetInt32();
FSelectCountryCommand.ExecuteUpdate;
Result := FSelectCountryCommand.Parameters[1].Value.GetInt32;
end;
ServerMethodUnit:
function TServerMethods1.SelectCountry:Integer;
begin
qCountry.close;
qCountry.Open;
Result:= qCountryMaxCountry_id.AsInteger;
end;
I tried use global variable but without success: it is seen only in project area, not in project group area.
SOLUTION
this code works fine:
FSelectCountryCommand.ExecuteUpdate;
Result := FSelectCountryCommand.Parameters[0].Value.GetInt32;
As I understand, as select query doesn't contain parameters therefore this operator:
FSelectCountryCommand.Parameters[0].Value.SetInt32();
is redundant.
if Length(idStrArray)>0 then
begin
with DataModule4.ADQueryTemp do
begin
Close;
SQL.Clear;
SQL.Add('SELECT id, pato, ftest, res FROM tbl ');
SQL.Add('WHERE id IN ('+idStrArray+')');
Open;
(rprMasterDataFish as Tfrxmasterdata).DataSet := frxDst_Multi;
(rprMasterDataFish as Tfrxmasterdata).DataSetName := 'Multi';
end;
end;
Hello,
I have TfrxDBDataset component. I can add fields from table like above. But i also want to add fields and values manually at runtime.
I have text file like this :
id note
1 sample
2 sample
I want to read this text file and insert note to frxDst_Multi. Is this possible ?
I dont want to create a new column as note in tbl. Because, i have too many mysql server.
Thanks in advice,
You can't add fields to a dataset while it is open, so you have to do it before
it is opened, either in code or using the TDataSet fields editor. If you are
doing it in code, you can add the field in the dataset's BeforeOpen
event.
The next problem is that is you don't want to field to be bound to the table the
dataset accesses, you need to add it as a calculated field and set its value
in the dataset's`OnCalcFields' event - see example below.
Ideally, the added field would be a TMemoField, but unfortunately a TMemoField
can't be a calculated field (FieldKind = ftMemo). So probably the best thing you can do is to make it a String field, but then you will need to
give it a fixed maximum size and truncate the field's value at that size when you calculate its value.
Btw, I don't know whether your TfrxDBDataset supports the fkInternalCalc fieldkind, but if it does, then you could try adding the note field as a TMemoField instead of a TStringField one.
The one thing I haven't been able to do is to load the field's value from
an external file because you haven't said in your q how to determine the
name of the file which is to be read.
Obviously, the IsNull check in the frxDst_MultiCalcFields event is to avoid the overhead of reloading the file if its contents have already been read.
const
NoteFieldSize = 4096;
procedure TForm1.AddNoteField;
var
NoteField : TField;
begin
if frxDst_Multi.FindField('Note') = Nil then begin
NoteField := TStringField.Create(frxDst_Multi);
NoteField.FieldName := 'Note';
NoteField.Size := NoteFieldSize;
NoteField.FieldKind := fkCalculated;
NoteField.DataSet := frxDst_Multi;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
frxDst_Multi.Open;
end;
procedure TForm1.frxDst_MultiCalcFields(DataSet: TDataSet);
var
S : String;
begin
if DataSet.FieldByName('Note').IsNull then begin
S := 'a note'; // replace by code to set the field value
DataSet.FieldByName('Note').AsString := Copy(S, 1, NoteFieldSize);
end;
end;
procedure TForm1.frxDst_MultiBeforeOpen(DataSet: TDataSet);
begin
AddNoteField;
end;
I have a TDataModule with 2 TADOQueries & 2 datasources: Master and Detail.
DataModule.DetailQuery.Datasource := MasterQueryDataSource;
I display the datasets from these queries in a separate form. A new instance of the form is created each time. The form has a MasterDbGridEh and a DetaildbGridEh bound to the master and the details datasource. When The user is finished with editing, the form is destroyed, the queries are closed. When the user needs to open the window next time, a new instance is created and the queries are activated.
When the form is invoked for the 1st time everythin works just fine.
But the second time I get this issue with the DetailsDbGridEh:
it displays the DataSet with the 1st row selected but I can't move up or down in the grid when I try to scroll. After appending a new row to the dataset the new row is not displayed.
The dataset AfterScroll event fires when I try to move up or down and the dataset is actually scrolled behind the scenes but the scroll and the changes are not displayed by the dbgrideh.
It seems that after first showing the dataset the dbgrid somehow loses touch to the datasource.
UPDATE
Structure of queries:
Datamodel consists of entities: ORDER, each order consists of several JOBS, each Job has several Participants.
So there are 3 queries: OrderEditQuery, JobEditQuery and JobParticipantsQuery;
JobEditQuery depends on OrderEditQuery and has parameter ORDER_ID which it takes from ORDEREDITQUERY
JobParticipantsQuery depends on JobEditQuery and has parameter JoB_ID which it takes from JobEditQuery.
When JobEditorForm is opened only one order is edited but the user is supposed to be able to navigate through and edit jobs of the order and through and edit participants of each job
CODE:
code in main form to invoke editor form:
with TJobEditorForm.Create(Self, orderID, // constructor
jobID, officeID) do
begin
ShowModal;
end;
Constructor:
constructor TJobEditorForm.Create(AOWner: TComponent; orderID: integer;
jobID: integer; officeID: integer);
begin
self.Create(AOwner);
_orderID := orderID;
_startingJobID := jobID;
_officeID := officeID;
end;
On form show:
procedure TJobEditorForm.FormShow(Sender: TObject);
begin
jobEditDataModule.ActivateQueries(_orderID, _officeID);
// jobEditdatamodule is the datamodule where the queries sit
end;
procedure TJobEditDataModule.ActivateQueries(orderID, officeID : integer);
begin
CloseQueries; // put this in to ensure that all queries are closed before they are reopened
// different auxiliary queries used for look up fields
Data.VID_ALL.Active := false;
Data.VID_ALL.Parameters.ParamValues['office'] := officeID;
Data.VID_ALL.Active := true;
Data.KOEF_ALL.Active := false;
Data.KOEF_ALL.Parameters.ParamValues['podr'] := officeID;
Data.KOEF_ALL.Active := true;
Data.Jobstatuses_All.Active := true;
Data.Attract_Channels_All.Active := true;
JobEditDataModule.Customers.Active := true;
EmployeeDataModule.Employees.Active := true;
// this is the query that gives me trouble
JobParticipantsQuery.Active := false;
// main query
OrderEditQuery.Parameters.ParamValues['orderID'] := orderID;
OrderEditQuery.Open;
OrderEditQuery.EnableControls;
// first details query. Dependent on OrderEditQuery (takes two params: officeID and OrderID. OrderID is taken from OrderEditQuery, on which JobEditQuery depends)
JobEditQuery.Active := false;
JobEditQuery.EnableControls;
JobEditDataModule.JobEditQuery.Parameters.ParamValues['officeID'] := officeID;
TDataUtils.EnsureActive( [ JobEditQuery ]);
JobEditQuery.EnableControls;
// JobPArticipantsQuery is details query dependent on JobEditQuery.
JobparticipantsQuery.DisableControls;
JobparticipantsQuery.EnableControls;
JobParticipantsQuery.Active := true;
JobparticipantsQuery.EnableControls;
end;
When the editor form is closed, the CloseQueries procedure is executed:
procedure TJobEditDataModule.CloseQueries;
begin
OrderEditQuery.DisableControls;
JobParticipantsQuery.DisableControls;
JobparticipantsQuery.DisableControls;
JobParticipantsQuery.Close;
JobEditQuery.Close;
OrderEditQuery.Close;
end;
I have 2 mdb linked. Original.mdb (not to be touched) and a copy.mdb
I've been using this for checking if tables exists:
function CheckIfTableExists(myTable : AnsiString): boolean;
var
x := Integer;
bTrue : boolean;
begin
f1.ADOConnection1.GetTableNames(f1.ListBox1.Items,False);
bTrue := false;
for x := 0 to f1.ListBox1.Items.Count -1 do
begin
if (f1.ListBox1.Items.Strings[x] = myTable) then
begin
bTrue := true;
end;
end;
if (bTrue = true) then
begin
Result := True;
end
else
Result := false;
end;
end;
I'm sure there is a better way to do this, but so far it worked nice for me.
Now I need to check if a LINK to another mdb table exist. Does anyone know how to do that?
I.Bagon
Every Access MDB file has a hidden table named MSysObjects which is basically a list of all objects in the MDB.
You can query this table to find out if an object with a given name exists in the MDB.
MSysObjects contains ALL objects in the MDB. Not only tables, but forms and records as well.
You can filter on the Type column to get only the tables:
Type = 1 --> local table
Type = 6 --> linked table
Given a nested TClientDataSet, how could I find the link field name on the detail TClientDataSet?
I'm copying data from one TClientDataSet to another (record by record) and I would like to automatically ignore the link field.
I could also copy the data using the TClientDataSet.Data property but I still would need to clear the link and key fields.
You can check the "DataSetField" property of the detail/nested dataset, or access the "NestedDataSet" property of the master dataset.
Sample code to get the "link" field name:
function GetCDSDLinkFieldName(cds: TClientDataSet): string;
var
i: Integer;
cdsDetail: TClientDataSet;
begin
Result := EmptyStr;
cdsDetail := nil;
if Assigned(cds.DataSetField) then
cdsDetail := cds;
if not Assigned(cdsDetail) and (cds.FieldCount > 0) then
begin
i := 0;
while not Assigned(cdsDetail) and (i < cds.FieldCount) do
begin
if cds.Fields[i].DataType = ftDataSet then
cdsDetail := TClientDataSet(TDataSetField(cds.Fields[i]).NestedDataSet);
Inc(i);
end;
end;
if Assigned(cdsDetail) then
Result := cdsDetail.DataSetField.FieldName;
end;
Invoking example:
procedure ...
begin
ShowMessage(GetCDSDLinkFieldName(cdsMaster));
ShowMessage(GetCDSDLinkFieldName(cdsDetail));
end;
P.S.: 2 years later I don't believe this answer will help the author of the question, but maybe can help others that search for the same subject.