还是关于FDBatchMove时,是否允许两个表字段不一致或update的问题

秋天之落叶 2019-06-28 11:58:41
这是firedac自带的实例:
问题:
假如A数据表 (对应qryLoaded):a,b字段;B数据表(对应qryMoved):a,c字段。如果A-->B时,需要update A.b后再对应B.c字段,
1、FDBatchMove允许这样吗?
2、在什么位置应该如何写代码?


// DB table -> DB table
procedure TfrmMain.btnTabToTabMoveClick(Sender: TObject);
begin
CloseQueries;

with TFDBatchMoveDataSetReader.Create(FDBatchMove) do begin
DataSet := qryLoaded;
Optimise := False;
end;

with TFDBatchMoveDataSetWriter.Create(FDBatchMove) do begin
DataSet := qryMoved;
Optimise := False;
end;
FDBatchMove.Execute;

// show data in dbgrid
qryLoaded.Open;
qryMoved.Open;
end;
...全文
1504 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
秋天之落叶 2019-10-12
  • 打赏
  • 举报
回复
论坛 你在还是关于FDBatchMove时,是否允许两个表字段不一致或update的问题的回帖已被管理员删除 10分钟前
你在还是关于FDBatchMove时,是否允许两个表字段不一致或update的问题的回帖已被管理员删除,原因是:政治

-------------那贴是政治了?管理员威武!
秋天之落叶 2019-07-01
  • 打赏
  • 举报
回复
引用 20 楼 xiaoxiangqing 的回复:
现在还在用bcb6.0

专业的人士都不愿意升级,我是业余爱好,喜欢新鲜玩意,精不精通不是我的追求,反正也是玩呢,哈哈
xiaoxiangqing 2019-07-01
  • 打赏
  • 举报
回复
现在还在用bcb6.0
秋天之落叶 2019-06-29
  • 打赏
  • 举报
回复
也就是说,如果reader的select a,c as b from testexecl.[sheet1$]和write的 select a,b from testsql对应了,使用mode的update时,它会自动关联1=1和2=2,将b值修改为c?也就是sheet1的查询字段决定了sql表中的修改字段?
我再去试一下,哈哈
秋天之落叶 2019-06-29
  • 打赏
  • 举报
回复
捣鼓了一晚上,也没有什么进展,倒是给弄的晕头转向,谁能给一个实例看看?

我想实现 update B set B.c=A.b from A,B where A.a=B.a

假如A数据表 (对应qryLoaded):a,b字段;B数据表(对应qryMoved):a,c字段。如果A-->B时,需要update A.b后再对应B.c字段,
BlueStorm 2019-06-29
  • 打赏
  • 举报
回复
我的例子中使用了指定表名的方法,可以不用在WriteSQL填写update语句
BlueStorm 2019-06-29
  • 打赏
  • 举报
回复
如果你需要进一步定制化update,可以在FDBatchMoveSQLWriter.WriteSQL中填写update语句,详情你可看一下F1帮助
BlueStorm 2019-06-29
  • 打赏
  • 举报
回复
不需要写update语句,fdbatchmove会自动产生
秋天之落叶 2019-06-29
  • 打赏
  • 举报
回复
太奇妙了,execl中要使用IIF(IsNull(天数), 0, 天数),终于又搞定一个问题。
下一个问题:fdbatchmove+fdconnection的事物没有起到作用。
秋天之落叶 2019-06-29
  • 打赏
  • 举报
回复
引用 7 楼 BlueStorm 的回复:
[ReadSQL = 'select a, c as b from [Sheet1$]'
INSERT INTO Test VALUES (1, '实例'), (2, '看看')

没看美明白,是不是漏了关键代码?
update+where语句怎么写?还是不用写,直接设置mode为update后就能匹配?全数据集直接匹配?
BlueStorm 2019-06-29
  • 打赏
  • 举报
回复
BlueStorm 2019-06-29
  • 打赏
  • 举报
回复

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
  FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.ODBC,
  FireDAC.Phys.ODBCDef, FireDAC.VCLUI.Wait, FireDAC.Phys.MSSQL,
  FireDAC.Phys.MSSQLDef, Vcl.StdCtrls, FireDAC.Phys.ODBCBase, Data.DB,
  FireDAC.Comp.Client, FireDAC.Comp.BatchMove, FireDAC.Comp.BatchMove.SQL,
  FireDAC.Comp.BatchMove.DataSet;

type
  TForm1 = class(TForm)
    FDBatchMoveSQLReader: TFDBatchMoveSQLReader;
    FDBatchMoveSQLWriter: TFDBatchMoveSQLWriter;
    FDBatchMove: TFDBatchMove;
    FDConnectionExcel: TFDConnection;
    FDConnectionSQL: TFDConnection;
    FDPhysMSSQLDriverLink: TFDPhysMSSQLDriverLink;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  FDBatchMove.GuessFormat;
  FDBatchMove.Execute;
end;

end.

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 214
  ClientWidth = 421
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 168
    Top = 160
    Width = 75
    Height = 25
    Caption = #26356#26032
    TabOrder = 0
    OnClick = Button1Click
  end
  object FDBatchMoveSQLReader: TFDBatchMoveSQLReader
    Connection = FDConnectionExcel
    ReadSQL = 'select a, c as b from [Sheet1$]'
    Left = 53
    Top = 136
  end
  object FDBatchMoveSQLWriter: TFDBatchMoveSQLWriter
    Connection = FDConnectionSQL
    TableName = 'Test'
    Left = 343
    Top = 136
  end
  object FDBatchMove: TFDBatchMove
    Reader = FDBatchMoveSQLReader
    Writer = FDBatchMoveSQLWriter
    Mode = dmUpdate
    Mappings = <>
    LogFileName = 'Data.log'
    Left = 183
    Top = 24
  end
  object FDConnectionExcel: TFDConnection
    Params.Strings = (
      
        'ODBCDriver=Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb' +
        ')'
      'DataSource=Excel Files'
      'Database=D:\Test.xlsx'
      'User_Name=admin'
      
        'ODBCAdvanced=DefaultDir=D:\;DriverId=1046;MaxBufferSize=2048;Max' +
        'ScanRows=8;PageTimeout=5;ReadOnly=1;SafeTransactions=0;Threads=3' +
        ';UserCommitSync=Yes'
      'DriverID=ODBC')
    LoginPrompt = False
    Left = 53
    Top = 80
  end
  object FDConnectionSQL: TFDConnection
    Params.Strings = (
      'DriverID=MSSQL'
      'OSAuthent=Yes'
      'Server=LocalHost'
      'Database=TestDB')
    Connected = True
    LoginPrompt = False
    Left = 343
    Top = 80
  end
  object FDPhysMSSQLDriverLink: TFDPhysMSSQLDriverLink
    Left = 343
    Top = 24
  end
end

USE TestDB;
GO

DROP TABLE Test
CREATE TABLE Test (a INTEGER PRIMARY KEY, b NVARCHAR(16))  --必须有primary key
INSERT INTO Test VALUES (1, '实例'), (2, '看看')

SELECT * FROM Test
秋天之落叶 2019-06-29
  • 打赏
  • 举报
回复
呵呵,虽然办法笨,但还是可以用,解决了累加问题,主要是不会使用readersql和writesql 。
open(ODBC+execl files)后,select 中不支持相关函数问题还没有解决,例如select ianull(a,0),cast(b as integer) from [test]。

FDConnection1.Close;
FDConnection1.Open();

FDConnection2.Close;
FDConnection2.Open();

FDQuery3.Close;
FDQuery3.Open('select * from [test]');

FDQuery2.Close;
FDQuery2.Open('select a,(c+' + FDQuery3.FieldByName('b').AsString + ') as b from [test$]');

FDBatchMoveDataSetReader1.DataSet := FDQuery2;
FDBatchMoveDataSetReader1.Optimise := False;

FDQuery3.Close;
FDQuery3.Open('select * from test');

FDBatchMoveDataSetWriter1.DataSet := FDQuery3;
FDBatchMoveDataSetWriter1.Optimise := False;

FDBatchMove1.Execute;
BlueStorm 2019-06-29
  • 打赏
  • 举报
回复
writesql :='update B set b = :b where a = :a'
秋天之落叶 2019-06-29
  • 打赏
  • 举报
回复
借机吐槽一下,firedac得到的表名如果是汉字,会用 · 号,不知道如何去掉,只能自己处理,这点不好,不如ADO的结果。大家也是这么处理的吗?
FDConnection1.GetTableNames('', '', '', str, [osMy, osOther, osSystem],
[tkTable, tkTempTable, tkLocalTable], False);

for i := 0 to str.count - 1 do
begin
if Pos('`', str[i]) <> 0 then
str[i] := ReplaceStr(str[i], '`', '');
end;
ComboBox40.Items := str;
秋天之落叶 2019-06-29
  • 打赏
  • 举报
回复
果然如此,万分感谢,这下解决一个大问题,省的使用FTP了,数据表可以直接通过客户端整理并导入到远程服务器了。
不过这种设计思路确实挺奇怪的,move时能自动耦合匹配,好想和以前的控件操作理念不一样,哈哈。

另外,请问一句,FDBatchMoveSQLWriter.WriteSQL中填写update语句时,这个语句对testsql表起作用吗?是update更新批量前的记录,还是更新批量后的记录?是不是可以写成 update B set B.c=A.b from A,B where A.a=B.a 这样子?没测试,回头试一试。
秋天之落叶 2019-06-28
  • 打赏
  • 举报
回复
或者说,FDBatchMove允不允许 A表的数据 update 到 B(B表已经存在数据,根据条件把A表的数值修改到B表)表中可不可以?
我琢磨了一下,字段不同可以 as 对应字段,但 update 字段好像不太符合要求。
到目前我还是没有搞懂FDBatchMove的拷贝原理?
reader--qryLoaded(这里是赋值吗?)--Writer--qryMoved(这是时保存吗?)
秋天之落叶 2019-06-28
  • 打赏
  • 举报
回复
引用 4 楼 BlueStorm 的回复:
至于你说的想Update B表的数据,可以用下面的dmAppendUpdate或dmUpdate:

哇塞,忘了还有mode,我说update怎么总是提示错误,原来还是insert。
多谢,我去试一试。
BlueStorm 2019-06-28
  • 打赏
  • 举报
回复
至于你说的想Update B表的数据,可以用下面的dmAppendUpdate或dmUpdate:
BlueStorm 2019-06-28
  • 打赏
  • 举报
回复
另一个解决方法就是设置FDBatchMov.Mappings, 设置源表的字段名称和目的表的字段名称的对应关系,不过我觉得这个不够灵活,更麻烦一点。
加载更多回复(1)

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧