全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1679
推到 Plurk!
推到 Facebook!

請問動態組成SQL字串做法..

 
kjwang
一般會員


發表:11
回覆:8
積分:3
註冊:2005-04-17

發送簡訊給我
#1 引用回覆 回覆 發表時間:2006-08-15 18:16:40 IP:210.201.xxx.xxx 訂閱

我想請教一個情況:
就是我想要動態組成SQL去Insert資料

程式裡已經 get 到一個字串內容是:
strField := 'Field0,Field1,Field2,Field3....';(視不同的Table欄位數不一定)

然後我再用TStringList的CommaText屬性get到各欄位的FieldName
節錄一段有疑問的Code如下:

slt := TStringList.Create;
slt.CommaText := strField;
x
x
x
strSQL := 'SELECT * FROM A';
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Add(strSQL);
Query1.Open
while not Query1.Eof do
begin
for i := 0 to slt.Count - 1 do
begin
strSQL := ' INSERT INTO bdbo.' strTable '(' strField ')' //strTable也是動態傳入的
' VALUES(''';
//下面這裡組Values的欄位值(問題點)
if i = 0 then
strSQL := strSQL Query1.FieldByName(slt[i]).AsString ''''
else
strSQL := strSQL ',''' Query1.FieldByName(slt[i]).AsString '''';
end;
Query2.Close;
Query2.SQL.Clear;
Query2.SQL.Add(strSQL);
Query2.Execute;
Query1.Next;
end;

實際Run下去才發現同一Record的值我沒辦法這樣一個Field一個Field分別Keep住它們的值,
而是比如有五個欄位,跑完for迴圈,我的SQL也只保有最近一個欄位的資料而已

不知道這樣的描述能理解嗎?有何更好的做法呢? 謝謝!!

帥氣銀行
一般會員


發表:13
回覆:40
積分:15
註冊:2005-05-31

發送簡訊給我
#2 引用回覆 回覆 發表時間:2006-08-16 15:19:39 IP:61.219.xxx.xxx 未訂閱
試著在跑迴圈時
用ShowMessage將Query2的SQL.Text秀出來看看
或是存成.TXT檔來檢查是否迴圈有問題


Query2應該呼叫ExecSQL來執行SQL
參考看看
menfox
一般會員


發表:1
回覆:10
積分:2
註冊:2006-08-14

發送簡訊給我
#3 引用回覆 回覆 發表時間:2006-08-16 18:48:00 IP:211.21.xxx.xxx 未訂閱

我用的方法是這樣的

1.寫一悜 procedure, 如下所示, 只要把你查出來的 Dataset (即你的 query1) 及 table name 傳進去即可! 當然還有一個 GenInsSQL 的 fucntion, 它才是主角!

procedure GenAllInsSQL(rsTblName : String; raDS : TClientDataSet) ;
function ExecuteSQL(rsInsertSQL : string) : Boolean;
var
lsSQL : String;
begin
try
with cdsUpdComm do
begin
close;
CommandText := EmptyStr;
CommandText := rsInsertSQL;
Execute;
end;
result := True;
except
result := False;
end;
end;

var
lsInsertSQL : string;
laList : TStringList;
begin
laList := TStringList.Create;
with raDS do
begin
first;
while not eof do
begin
lsInsertSQL := GenInsSQL(rsTblName, raDS);
if ExecuteSQL(lsInsertSQL) then
laList.Add(lsInsertSQL)
else
laList.Add('Error: ' lsInsertSQL);
next;
end;
Close;
end;
laList.SaveToFile('C:\' rsTblName '.sql');
FreeandNil(laList);
end;

它還會在 C:\ 目錄下產生一個 .sql 的檔案, 記錄所有產生的 Insert SQL command.

2.產生 insert SQL 的 function, 它是藉由直接 paser Dataset 中的 datafield 來自動產生 SQL (只缺 Table name, 所以要傳進來)

function GenInsSQL(rsTblName : String; raDS : TClientDataSet) : String;
var
laFld : TField;
liCt : Integer;
lsSQL, lsFStr, lsPStr, lsLStr, lsFldName : String;
lsValue : String;
begin
lsSQL := EmptyStr;
if raDS.Active then
begin
with raDS do
begin
lsLStr := EmptyStr;
lsFStr := EmptyStr;
lsPStr := EmptyStr;
for liCt := 0 to raDS.FieldCount - 1 do
begin
if liCt > 0 then
lsLStr := ',';

laFld := raDS.Fields[liCt];
lsFldName := laFld.FieldName;
lsFStr := lsFStr lsLStr lsFldName;

if (laFld.DataType = ftFloat) or (laFld.DataType = ftFMTBcd) or (laFld.DataType = ftInteger) then
lsValue := FloatToStr(laFld.AsFloat)
else if (laFld.DataType = ftString) or (laFld.DataType = ftMemo) or (laFld.DataType = ftDateTime) or (laFld.DataType = ftTimeStamp) then
begin
if (laFld.IsNull) then
lsValue := 'NULL'
else
lsValue := '''' StrReplace(strTrim(laFld.AsString),'''','''''') '''';
end
else if laFld.DataType = ftBlob then
begin
lsValue := 'NULL';
end;

lsPStr := lsPStr lsLStr lsValue;
end;
lsSQL := format('insert into %s ( %s ) values (%s);',[rsTblName,lsFStr,lsPStr]);
end;
end;
Result := lsSQL;
end;

程式你可能要稍微調整一下, 因為我是 third tier 的架構, 所以用 client dataset. 另外 paser Dataset 中的 datafield 會因為您的資料庫而有不同的 Data Type, 有可能須要調整! 基本上它已經可以是一個共用的 function 了! 希望對你有幫助!

------
Hi! It's Menfox!
kjwang
一般會員


發表:11
回覆:8
積分:3
註冊:2005-04-17

發送簡訊給我
#4 引用回覆 回覆 發表時間:2006-08-17 09:39:33 IP:210.201.xxx.xxx 訂閱

感謝諸位的回覆..啟發了我的想法....後來我用動態陣列的方式達到我的需要了...

kjwang
一般會員


發表:11
回覆:8
積分:3
註冊:2005-04-17

發送簡訊給我
#5 引用回覆 回覆 發表時間:2006-08-17 10:17:20 IP:210.201.xxx.xxx 訂閱

感謝諸位的回覆..啟發了我的想法....

後來我用動態陣列和判斷Query的DataType 來達到我的需要了...

系統時間:2024-05-19 15:12:16
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!