這樣做批次更新對嗎?(觀念問題) |
尚未結案
|
nachi
初階會員 ![]() ![]() 發表:40 回覆:116 積分:31 註冊:2003-02-26 發送簡訊給我 |
若底下為借書的procedure,那每借一本書就執行此procedure一次,假設執行了n次,那當我下batchupdate時,是不是就會把這n筆借書記錄一一更新???
procedure tform4.borrow_book(borrow_nu: string); begin with datamodule3 do begin adoquery1.active:=true; adoquery1.Close; adoquery1.SQL.Add('insert into 借閱記錄(姓名,借書,日期,還書情形)values(:bname,:bbook,:bdate,:bstate)'); adoquery1.Parameters.ParamByName(':bname').Value:=adoquery3.fieldbyname('姓名').AsString; adoquery1.Parameters.ParamByName(':bbook').Value:=adoquery2.fieldbyname('書名').AsString; adoquery1.Parameters.ParamByName(':bdate').Value:=AnsiReplaceText(FormatDateTime('eee,mm,dd', monthcalendar1.Date), ',', '/'); adoquery1.Parameters.ParamByName(':bstate').Value:=false; end; end; |
Justmade
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
我沒用過 ADO 也跑來答,哈哈哈。 應該不是罷 @@" UpdateBatch 是給你的 ADOTable 或 RequestLive 的 ADOQuery Edit / Insert / delete 先不存回數據庫待你 ADODataSet.UpdateBatch 時一次過將所有變更存回的。 若使用 Update Statement 是直接存回的與 Batch Update Mode 無關 不過即使不論 Batch Update Mode, 你的程式有大問題和可以改善效率的地方耶.... 下回繼續....< > -----------------------------------
第二回 : 我打字慢怕每次都遲貼所以採取兩段式答題,第一段先針對問題作答,第二段補充參考資料< > 大問題 :
你不Clear SQL 一直 Add 資料庫太笨不會看的啦 :P 改善效率 :
既然 SQL 一樣最好先設定好,然後程式開始時修便 ADOQuery.Prepare;
之後只是改 Param 及 ExecSQL, 這樣效率會比較好啊 發表人 - Justmade 於 2003/05/16 22:32:37
|
nachi
初階會員 ![]() ![]() 發表:40 回覆:116 積分:31 註冊:2003-02-26 發送簡訊給我 |
|
Justmade
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
batchupdate 只在修改 ADODataSet 內的數據有效,就像是
ADOQuery1.Edit;
ADOQuery1.FieldByName('姓名').Value := Edit1.Text;
ADOQuery1.FieldByName(.......
ADOQuery1.Post;
這類的修改新增移除才有效,因為資料都記在 Memory 裡,到你 UpdateBatch 時才一次過自動產生 SQL 更新進數據庫 但你若自己執行 SQL Statement , SQL Statment 不是在你的程式執行的而是直接傳到數據庫執行的,試問你的程式又甚能 Batch Update 它呢? 若你想將這個 Procedure 完成執行 n 次沒問題才更新否則便全部不更新,方法又二 : 1. 使用 Transaction,中間出問題便 rollback 全成功才 commit;
2. 用這個 procedure 來做一個一次 update 多個記錄的 SQL 最後才 給 ADOQuery1 來執行
a) 設個變數 = 'insert into 借閱記錄(姓名,借書,日期,還書情形)values '
b) 每次執行這個變數加上 '(所有值),'
c) 最後減去最後的 ','
d) 傳給 ADOQuery1.SQL 並 ExecSQL 修正
既然 SQL 一樣最好先設定好,然後程式開始時便先 ADOQuery1.Prepare;
之後只是改 Param 及 ExecSQL, 這樣效率會比較好啊
|
sryang
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
引言: batchupdate 只在修改 ADODataSet 內的數據有效,就像是 ADOQuery1.Edit; ADOQuery1.FieldByName('姓名').Value := Edit1.Text; ADOQuery1.FieldByName(....... ADOQuery1.Post; 這類的修改新增移除才有效,因為資料都記在 Memory 裡,到你 UpdateBatch 時才一次過自動產生 SQL 更新進數據庫 但你若自己執行 SQL Statement , SQL Statment 不是在你的程式執行的而是直接傳到數據庫執行的,試問你的程式又甚能 Batch Update 它呢? 若你想將這個 Procedure 完成執行 n 次沒問題才更新否則便全部不更新,方法又二 : 1. 使用 Transaction,中間出問題便 rollback 全成功才 commit; 2. 用這個 procedure 來做一個一次 update 多個記錄的 SQL 最後才 給 ADOQuery1 來執行 a) 設個變數 = 'insert into 借閱記錄(姓名,借書,日期,還書情形)values ' b) 每次執行這個變數加上 '(所有值),' c) 最後減去最後的 ',' d) 傳給 ADOQuery1.SQL 並 ExecSQL 修正 既然 SQL 一樣最好先設定好,然後程式開始時便先 ADOQuery1.Prepare; 之後只是改 Param 及 ExecSQL, 這樣效率會比較好啊ADO 可以一次執行多個 SQL 敘述 再者,若只是要執行insert、update、delete等 SQL 敘述,建議使用 TADOCommand,比較節省資源 多個SQL一起執行範例: ADOCommand1.CommandText := 'insert into TableA (F1, F2) values (1, ''AAA'');' 'insert into TableA (F1, F2) values (2, ''BBB'');' 'insert into TableA (F1, F2) values (3, ''CCC'');' 'insert into TableA (F1, F2) values (4, ''DDD'');' 'insert into TableA (F1, F2) values (5, ''EEE'');' 'insert into TableA (F1, F2) values (6, ''FFF'')'; ADOCommand1.Execute; SQL 指令的總長度在 8k 以內的話,就可以一起執行,否則需要分批 而且這樣只會有一次的網路 round-trip (若分批的話,是分批的次數) 加油喔,喵~
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/ |
chih
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:48 回覆:1186 積分:639 註冊:2002-04-02 發送簡訊給我 |
|
nachi
初階會員 ![]() ![]() 發表:40 回覆:116 積分:31 註冊:2003-02-26 發送簡訊給我 |
|
Justmade
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
引言: ADO 可以一次執行多個 SQL 敘述 再者,若只是要執行insert、update、delete等 SQL 敘述,建議使用 TADOCommand,比較節省資源 多個SQL一起執行範例: ADOCommand1.CommandText := 'insert into TableA (F1, F2) values (1, ''AAA'');' 'insert into TableA (F1, F2) values (2, ''BBB'');' 'insert into TableA (F1, F2) values (3, ''CCC'');' 'insert into TableA (F1, F2) values (4, ''DDD'');' 'insert into TableA (F1, F2) values (5, ''EEE'');' 'insert into TableA (F1, F2) values (6, ''FFF'')'; ADOCommand1.Execute; SQL 指令的總長度在 8k 以內的話,就可以一起執行,否則需要分批 而且這樣只會有一次的網路 round-trip (若分批的話,是分批的次數)沒用過 ADO 果然差些,我就沒想起 ADOCommand 不過我想總是 一句 insert statement 插入所有記錄比較好罷 ? 因為 1. SQL 比較短,傳輸快 2. 數據庫只執行一句statement , 速度快 3. 若中間某筆資料有問題, 一句 SQL statement 能一貫處理不會執行了部份後才發現問題 ? 只是我的想法若不對歡迎指正 若有一堆不同的 SQL command, 使用 ADOCommand 真的會很好用。 |
nachi
初階會員 ![]() ![]() 發表:40 回覆:116 積分:31 註冊:2003-02-26 發送簡訊給我 |
|
chih
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:48 回覆:1186 積分:639 註冊:2002-04-02 發送簡訊給我 |
你應該是要放在儲存Button裡面的吧,所以你可以考慮sryang及Justmade所述,我看你的畫面並沒有很複雜,應該沒有需要批次的功能吧,其實如果需要的話可以把你寫的程式中adoquery1用另外一各Query來下你原來寫的語法回寫資料就可以了,試試看吧
|
nachi
初階會員 ![]() ![]() 發表:40 回覆:116 積分:31 註冊:2003-02-26 發送簡訊給我 |
|
Justmade
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
我是說在你這個 Case 用我上面第二個提議應會較好,不是說用 ADOCommand ADOCommand1.CommandText :=
'insert into 借閱記錄 (姓名, 書名) values (1, ''AAA'');'
+'insert into 借閱記錄 (姓名, 書名) values (2, ''BBB'');'
ADOCommand1.Execute; ADOQuery1.SQL.Text :=
'insert into 借閱記錄 (姓名, 書名) values (1, ''AAA''), (2, ''BBB'');'
ADOCommand1.ExecSQL; 那個較短? 而且 ADOCommand 雖只用一個 Connection 但到了數據庫還是要一句句執行的若第二句出問題第一句已更新到數據庫了。
但用我提議的只有一個 SQL Statement 只執行一次較快且若有問題應整體不會被更新。 所以要看你甚樣用了。
var Form4 : TForm4; zSQL : String; procedure tForm4.SaveButtonClick(Sender : TObject); var i : integer; begin zSQL := 'insert into 借閱記錄(姓名,借書,日期,還書情形) values '; for i := 0 to .... do begin .... borrow_book(..); end; zSQL := copy(zSQL, 1, Length(zSQL) -1) // delete the trailing , with datamodule3 do begin AdoQuery1.SQL.Text := zSQL; AdoQuery1.ExecSQL; end; end; procedure tform4.borrow_book(borrow_nu: string); begin zSQL := zSQL '(' QuotedStr(adoquery3.fieldbyname('姓名').AsString) ',' QuotedStr(adoquery2.fieldbyname('書名').AsString) ',' QuotedStr(AnsiReplaceText(FormatDateTime('eee,mm,dd', monthcalendar1.Date), ',', '/')) ',false),' end; |
chih
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:48 回覆:1186 積分:639 註冊:2002-04-02 發送簡訊給我 |
另外放一各Query放在datamodule3上面,如果Databse跟執行檔在同一各目錄下,這各Query完全不用設定屬性..
procedure tform4.borrow_book;//我改為這樣 begin with datamodule3 do begin Query1.Close; Query1.SQL.Add('insert into 借閱記錄(姓名,借書,日期,還書情形)values(:bname,:bbook,:bdate,:bstate)'); Query1.Parameters.ParamByName(':bname').Value:=adoquery3.fieldbyname('姓名').AsString; Query1.Parameters.ParamByName(':bbook').Value:=adoquery2.fieldbyname('書名').AsString; Query1.Parameters.ParamByName(':bdate').Value:=AnsiReplaceText(FormatDateTime('eee,mm,dd', monthcalendar1.Date), ',', '/'); Query1.Parameters.ParamByName(':bstate').Value:=false; Query1.ExecSQL; Query1.Close; end; end;TRY TRY SEE PS:你這段語法我並沒有去check可不可以Run..你自己試吧.. |
nachi
初階會員 ![]() ![]() 發表:40 回覆:116 積分:31 註冊:2003-02-26 發送簡訊給我 |
|
nachi
初階會員 ![]() ![]() 發表:40 回覆:116 積分:31 註冊:2003-02-26 發送簡訊給我 |
justmade兄...下面是我對你程式的解讀 這行執行一次:
zSQL := 'insert into 借閱記錄(姓名,借書,日期,還書情形) values '; 底下放在儲存鈕:
zSQL := copy(zSQL, 1, Length(zSQL) -1) // delete the trailing ,
with datamodule3 do
begin
AdoQuery1.SQL.Text := zSQL;
AdoQuery1.ExecSQL;
end; 每借一本書執行一次:
procedure tform4.borrow_book(borrow_nu: string);
begin
zSQL := zSQL + '(' + QuotedStr(adoquery3.fieldbyname('姓名').AsString) + ',' +
QuotedStr(adoquery2.fieldbyname('書名').AsString) + ',' +
QuotedStr(AnsiReplaceText(FormatDateTime('eee,mm,dd', monthcalendar1.Date), ',', '/')) +
',false),'
end; 我在想我是否解讀錯誤,因為儲存後只能記錄到最後借閱的那一本書,之前的書都沒記錄到
|
nachi
初階會員 ![]() ![]() 發表:40 回覆:116 積分:31 註冊:2003-02-26 發送簡訊給我 |
|
Justmade
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
沒看見你昨天的 post 所以沒覆,對不起 那個方法是每一次 Save 做 一句 SQL 一次過儲存所有記錄
這句SQL 分兩大部份,第一部份是說明 insert 的 Table 和 欄位,之後便是每筆的資料 第一部份只需一次第二部份每個記錄要一次 雖然你說
zSQL := 'insert into 借閱記錄(姓名,借書,日期,還書情形) values ';
只執行一次,但看你的結果好像是每次借一本書這句都被重覆執行了,這樣才會只記下最後一筆 你最好可以在最後的 save button 檢視一下 zSQL 是否包含所有資料,或在
zSQL := 'insert into 借閱記錄(姓名,借書,日期,還書情形) values ';
設 Break point 看是否被重覆執行了
|
sryang
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
引言: 沒用過 ADO 果然差些,我就沒想起 ADOCommand 不過我想總是 一句 insert statement 插入所有記錄比較好罷 ? 因為 1. SQL 比較短,傳輸快 2. 數據庫只執行一句statement , 速度快 3. 若中間某筆資料有問題, 一句 SQL statement 能一貫處理不會執行了部份後才發現問題 ? 只是我的想法若不對歡迎指正 若有一堆不同的 SQL command, 使用 ADOCommand 真的會很好用。1. 一個封包如果以 TCP/IP 來說,可以傳送 1K 的資料,一個 SQL 敘述要寫到 1K 實在是不容易。所以,一次一個 SQL 來傳送並不會比一批一起傳送來得快。 2. 一個或一批 SQL 敘述送到 DBMS 之後,會經過語法檢查、compile 等動作,如果每次送一個 SQL 敘述,這樣語法檢查和 compile 的動作會多出許多 3. 在這樣的場合,通常是配合著 Transaction 一起執行,所以有錯誤還是能即時發現。 加油喔,喵~
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/ |
Justmade
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:94 回覆:1934 積分:2030 註冊:2003-03-12 發送簡訊給我 |
我想你有點誤會我的對比了,我的對比是
1. 你說的用 ADOCommands 整合多個 insert Statement 作一次性的傳輸
Vs
2. 用一句 insert statement 整合多個記錄的更新作一次性的傳輸更新 而不是對用多句 Statement 作多次性的更新。 我同意你的說法,用 ADOCommands 絕對比分多次每次一個 insert Statement 好。但若可以做到一句 insert statement 就做到了一個 command 數十個 insert statment 的同樣功效,不是更好嗎?
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |