Você está na página 1de 10

uniDac update multi-table record

January 08, 2018 22:27:06 wszysystem reading number: 268 more


Personal classification: uniDac
Copyright statement: This article is an original article of the blogger and may not be reproduced without the permission of the blo
gger. Https://blog.csdn.net/wszysystem/article/details/79007967

For data sets that get data from multiple tables, only one table is updatable by default. Y
ou should specify the name of the table to update in the UpdatingTable property, otherw
ise the table for the first field in the field list will be updated. If the SetFieldsReadOnly op
tion is set to True (by default), unused fields in the automatically generated update SQL
statement will be marked as read-only. Using Oracle, PostgreSQL, and odbcbased-base
d complex query providers (using multiple tables, synonyms, DBLinks, aggregate fields),
we recommend keeping the ExtendedFieldsInfo option.

If the Insert / Post, Update, or RefreshRecord operation has affected multiple records, U
niDAC will throw an exception. To suppress such an exception, you should set the Strict
Update option to False.

For more flexible control over data modification, you can populate the update SQL state
ment. They are represented by the SQLInsert, SQLUpdate, SQLDelete, and SQLRefres
h attributes and are automatically executed in the Insert / Post, Edit / Post, Delete, and R
efresh operations. At design time, you can generate a default update SQL statement in t
he SQL Generator tab of the component editor. The generated statement can be modifie
d according to your needs. However, if an update query is dynamically generated for ea
ch record, only the changed values are sent to the server.

This feature is not sufficient for some special cases. It can be extended using the TUniU
pdateSQL component. TUniUpdateSQL allows a separate TUniSQL / TUniQuery TUniSt
oredProc to update each operational component.

The above is a section of the uniDac help file.

The application context is as follows : a sales schedule, the field design is as follows: docum
ent number: D11_1, this field is the Primary Key of the schedule, billing date: D11_2, item num
ber: D11_3. Note that there is no product name in this table, but when it is displayed to the o
perator, it is necessary to display the product name. Otherwise, just look at the product num
ber. How do you know what it is? This product name is stored in the product file table B12, a
nd is associated with the LEFT JOIN through the sales table D11_3 and the product file table f
ield B12_1.

When I was doing this DEMO myself, I found some problems. First, I used a uniQuery to e
xecute a multi-table query, and then inserted a new record row, I found that only the table sp
ecified in the multi-table was updated, but other tables could not be displayed. As shown bel
ow:

As you can see, data such as name and specifications are not displayed.

I tried it for a long time, but I still used the previous ideas and solved this problem.
First, use another uniQuery control to do the insert and update operations. The uniQuery co
ntrol connects to another uniConnection. Then submit the data through this uniConnection
. (Because if two uniQuery connections are the same uniConnection, one will be closed after
one commits the data). Finally, turn the first uniQuery off and then back on. It can be achieve
d.
code show as below:
With A01F, D11F do
begin
try
if not A01F.uniConn_Do.InTransaction then
A01F.uniConn_Do.StartTransaction;
UniQ_Do.Close;
UniQ_Do.SQL.Text:='select * from D11 where D11_1=''''';
UniQ_Do.Open;
For i := 1 to StrToInt(D11F.eD11_22.Text) do
begin
UniQ_Do.Append;
UniQ_Do.FieldByName('D11_1').AsString:=D11F.eD11_1.Text;
UniQ_Do.FieldByName('D11_6').AsDateTime:= Now;
UniQ_Do.FieldByName('D11_8').AsString:=FieldByName('B12_1').AsString;
UniQ_Do.FieldByName('D11_10').AsString:=D11F.eD11_10.Text;
UniQ_Do.FieldByName('D11_22').AsInteger:=StrToInt(D11F.eD11_22.Text);
UniQ_Do.Post;
end;
A01F.uniConn_Do.Commit;
uniQ_D11.Close;
uniQ_D11.Open;
except
on e: Exception do
begin
A01F. uniConn_Do.Rollback;
ShowMessage('Error in submitting data! Error code: '+#13+e.Message);
end;
end;
end;

Reference materials:
1, solve the problem of multiple table display of ClientDataSet, single table update. Coo
l
Https://www.rxyj.org/item-v2-30110-2.html
2, uniDac help file

Solve the problem of multiple table display of


ClientDataSet, single table update. Cool
Author: Anonymous Published: 2013-03-10 22:06:21 Comments: [closed] Print this article

When displaying data in a table, in order to make the user see more clearly, it is often n

ecessary to display the data in a table with an associated statement. However, there is no suc
h field in the actual corresponding table, which is displayed by the keyword JOIN. There is a
problem. When updating with ApplyUpdates of TCLIENTDATASET, the update is often unsuc
cessful. After many experiments, I finally got it. For example: a department table, the field de
sign is as follows: Department number: DepartCode, this field is the Primary Key department
name of the department table: DepartName department manager number: ManagerCode N
ote that there is no manager name in this table, but when displayed to the user, It is necessa
ry to display the name, otherwise you only look at the job number. How do you know who it
is? This name is stored in the personnel file table, and is associated with the ManagerCode of
the department table and the ID field of the personnel file table by the LEFT JOIN. The displa
y form is as follows:

To update or delete selected records, use CLIENTDATASET.POST; CLIENTDATASET.Apply


Updates(0); this update is not successful. Also need to do the following: First, modify the two
properties of PROVIDER corresponding to ClientDataSet A. Change ResolveToDataSet from T
RUE to FALSE B. Change UpdateMode from upWhereAll to upWhereKeyOnly Second, Provid
er's BeforeUpdateRecord event: procedure TWZGL.BuMen_DSPBeforeUpdateRecord(Sender:
TObject;

SourceDS: TDataSet; DeltaDS: TCustomClientDataSet;

UpdateKind: TUpdateKind; var Applied: Boolean);

Var

i: Integer;

Begin

Inherited;

For i:= 0 to DeltaDS.RecordCount-1 do

Begin

DeltaDS.FieldByName('DepartCode').ProviderFlags:=DeltaDS.FieldByName('DepartCode'
).ProviderFlags + [pfInKey]; //DepartCode is the main keyword //The following fields are asso
ciated fields and do not need to be modified.

DeltaDS.FieldByName('FaDepName').ProviderFlags:=[];

DeltaDS.FieldByName('JlName').ProviderFlags:=[];

DeltaDS.FieldByName('AddTrueName').ProviderFlags:=[];

DeltaDS.FieldByName('EditTrueName').ProviderFlags:=[];
End;

End; Then use CLIENTDATASET.POST; CLIENTDATASET.ApplyUpdates(0); compile and ru


n. Wow, God, actually succeeded.

Related Reading

SQL gets all the table names of the database, the information of the fields

Use the following statement to get all the table names, field names, etc. of the database, you can add
it to the program, store it in a separate table, you can do some control on the program USE database name
GOSELECT table name = CASE a.colorder WHEN 1 THEN c.name ELSE '' END, sequence number = a.colorder,
field name = a.name, ID = CASE COLUMNPROPERTY(a.id,a.name,'IsIdentity') WHEN 1 THEN '√' ELSE '' END ,
primary key = CASEWHEN EXISTS ( SELECT * FROM sysobjects WHERE xtype='PK'AND name IN (SELECT
[name] FROM sysindexes WHERE id=a.idAND indid IN (SELECT indid FROM sysindexkeys WHERE
id=a.idAND colid IN (SELECT colid FROM syscolumns WHERE id=a.id

Using cxDBPivotGrid as a pivot table in XE2

PivotTable functionality in spreadsheets is useful for flexible analysis and statistics. Now you can
achieve the same pivoting functionality with DELPHI XE2 combined with the cxDBPivotGrid control. The
steps are as follows: First, drag the cxDBPivotGrid control to the FORM, then add a ADOQUERY and
DATASOURCE, the result is as shown in Figure 2. Set the connection string of ADOQUERY1. Since it is just an
operation, set the SQL property of ADOQUERY1 to static, directly in SQL. Enter the SQL query statement in
the attribute, and set its ACTIVE to TRUE, set the DATASET attribute of DATASORUCE1 to ADOQUERY1, and
set the DATASOURCE of cxDBPivotGrid to DATASORUCE1. Here, you can modify the appearance of
cxDBPivotGrid. No discussion here. 4. Double-click cxDBPivotGrid1, open the following dialog box and select
the FIELDS tab. Click ADD. The fields added here will be used in the PivotTable to display...

Considerations for the RecordCount property of UniDAC


September 22, 2013 15:06:32 Taxuewuhen Reads: 1219 More
Personal classification: UniDAC
UniDAC has always been used as a database query component, and the general way of writin
g is this:

1 UniQuery_sqlite.close;
2 UniQuery_sqlite.SQL.Clear;
UniQuery_sqlite.SQL.Add('SELECT * FROM TABLE');
3 try
4 UniQuery_sqlite.Open;
5 except
6 { TODO : 异常捕获 }
7 end;
8 //循环出所有记录
9 fori := 0to UniQuery_sqlite.RecordCount - 1do
10 begin
11 //....
12 UniQuery_sqlite.Next;
13 end;
14
Suddenly I found a problem today. It is clear that there are nearly a hundred records in the d
atabase, but only 25 are detected. The code is checked carefully. There is no problem. Then I
checked the properties of UniDAC UniQuery and found that there is such a property: FetchR
ows, and The default is 25! It must be the problem here. I found this property in the help to
help explain the following: It is

obvious that this property is for performance consideration. Since the default setting is 25, it
is definitely the best setting, or it is not changed, so I seek other solutions. The method, onlin
e search for such an explanation:
If you set the QueryRecCount option to True, TUniTable executes SELECT COUNT() query a

utomatically when you open the table, and assigns the correct value to the RecordCount

property.
So, I tried to set the QueryRecCount property to true, the problem is solved, showmessage a
recordcount, no longer 25, is already the correct number of rows. In order to find an authorit
ative explanation, I also searched the help documentation, which is explained as follows:

In particular, this sentence: Used for TCustomDADataSet to perform additional query to get t
he record count for this SELECT, so the RecordCount property reflects the actual number of r
ecords.

-------------------------------------------------- ----------------------------------------------

The above method did not find a place, my solution:

UniQryTest.Close;
UniQryTest.SQL.Text := 'select * from tb_system_user';

// UniQryTest.FetchingAll; After commenting, the d


efault is to load 25 records each time. Uncomment
all reads
UniQryTest.DisableControls;
UniQryTest.Open;
UniQryTest .EnableControls;

Unidac uses TuniQuery control to insert and update data


January 07, 2018 22:20:44 wszysystem reading number: 496 more
Personal classification: uniDac
Copyright statement: This article is an original article of the blogger and may not be reproduced without the permission of the blo
gger. Https://blog.csdn.net/wszysystem/article/details/78998271

First, the uniQuery control connects to a uniConnection control, and the transaction pro
perty is the default. Connect uniQuery with a table wwGrid.

First, the insertion operation

Code:

Try

If not A01F.uniConn_Do.InTransaction then


A01F.uniConn_Do.StartTransaction;

With uniQ_D11 do

Begin

Append;
FieldByName('D11_1').AsString:=eD11_1.Text;
FieldByName('D11_2').AsString:=FormatDateTime('yymmdd',date)+FieldByName('
B13_2').AsString+format('%.3d ',[i]);
FieldByName('D11_3').AsInteger:=i;
FieldByName('D11_4').AsString:=eD11_4.Hint;
FieldByName('D11_5').AsDateTime:=eD11_5.Date;
FieldByName(' D11_6').AsDateTime:=Now;
FieldByName('D11_8').AsString:=FieldByName('B13_2').AsString;
FieldByName('D11_10').AsString:=eD11_10.Text;
FieldByName('D11_22').AsInteger :=StrToInt(eD11_22.Text);
Post;

End;

A01F.uniConn_Do.Commit;
except
on e: Exception do
begin
A01F.uniConn_Do.Rollback;
ShowMessage('Error in new record! Error code: '+#13+e.Message);
exit;
end;
end;

Inserting the operation directly with the above code is basically no problem.

Second, update the data

The operation of updating the data is cumbersome. I modified it directly in the table ww
Grid and I didn't succeed at first. I checked a few of the only information and got it.

According to the online information, when modifying data in the wwGrid table, the uniQu
ery control will automatically call the edit method. The post method is automatically calle
d when the record line changes. So you don't have to write these two methods in the co
de.

The main points are:

1. Set the CachedUpdates property to True during the design period . The network s
ays that the runtime settings are invalid. I have not tried it.

2. Set the UpdatingTable and KeyFields properties.

3. Finally, submit the data using ApplyUpdates.


Modify the data before the code:

UpdatingTable:='D11';
KeyFields:='D11_1, D11_2';

After modifying the data, the code:

With uniQ_D11 do

Begin

Try
if not A01F.uniConn_Do.InTransaction then
A01F.uniConn_Do.StartTransaction;
ApplyUpdates;
ShowMessage('Data has been saved!');
except
on e: Exception do
begin
A01F.uniConn_Do.Rollback;
ShowMessage('An error occurred while submitting parameters! Error code :'+#13+
e.Message);
end;
end;
end;

To complete these two operations, the reference materials are:

1, unidac's help files;

2, "UniDac Foundation" dish translation

3, delphi xe use TuniQuery in unidac to save data error solution


http://blog.csdn.net/rznice/article/details/7735740

4, uniDAC usage summary


Use unidac
April 28, 2011 17:11:00 beiguofengguang reading number: 1319 tags: oracleserverdatabaseweb more
Personal classification: delphi

1. Connection mode: There are two connection modes for using unidac, non-direct co
nnection and direct connection mode. When using Direct Connect mode, the client does
not need to install the oracle client, which is very convenient.

When using Direct Connect mode, the properties of TUniConnection are similar to the g
eneral connection oracle, except that its Server property is changed to:

TUniConnection.Server :='IP:Port:SID'; For example:

TUniConnection.Server :='192.168.1.1:1521:WEB';

The server property of the indirect mode is directly set to the SID.

2. When using TUniConnection to connect to the database, you need to have a corre
sponding provider, otherwise the connection cannot be created correctly. In a unit with a
TUniConnection, you only need to drag and drop a provider control based on the selecte
d provider name.

Você também pode gostar