以型態為nvarchar的欄位為條件無法查出想要資料 |
答題得分者是:aftcast
|
hungyulin
一般會員 發表:36 回覆:33 積分:13 註冊:2003-10-15 發送簡訊給我 |
使用MS SQL 2000
Staff 有個欄位為StaffName nvarchar(20) 用ADOQuery 來查詢資料時 ADOQuery1.Close; ADOQuery1.SQL.Clear; ADOQuery1.SQL.Add(' Select * from Staff where StaffName=:Staffname '); ADOQuery1.Parameters.ParamByName('StaffName').DataType:=ftWideString; //edStaffName:TTntEdit; ADOQuery1.Parameters.ParamByName('StaffName').Value:=edStaffName.Text; ADOQuery1.Open; 這樣的式子無法查出所要的資料,只要edStaffName中的資料有用到Unicode的字,Select 就會沒有資料。 請教該如何解決,謝謝! |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
StaffName=N:Staffname
===================引 用 hungyulin 文 章=================== 使用MS SQL 2000 Staff 有個欄位為StaffName nvarchar(20) 用ADOQuery 來查詢資料時 ADOQuery1.Close; ADOQuery1.SQL.Clear; ADOQuery1.SQL.Add(' Select * from Staff where StaffName=:Staffname '); ADOQuery1.Parameters.ParamByName('StaffName').DataType:=ftWideString; //edStaffName:TTntEdit; ADOQuery1.Parameters.ParamByName('StaffName').Value:=edStaffName.Text; ADOQuery1.Open;
這樣的式子無法查出所要的資料,只要edStaffName中的資料有用到Unicode的字,Select 就會沒有資料。 請教該如何解決,謝謝!
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
hungyulin
一般會員 發表:36 回覆:33 積分:13 註冊:2003-10-15 發送簡訊給我 |
===================引 用 aftcast 文 章=================== StaffName=N:Staffname ===================引 用 hungyulin 文 章=================== ADOQuery1.Close; ADOQuery1.SQL.Clear; ADOQuery1.SQL.Add(' Select * from Staff where StaffName=N:Staffname '); ADOQuery1.Parameters.ParamByName('StaffName').DataType:=ftWideString; //edStaffName:TTntEdit; ADOQuery1.Parameters.ParamByName('StaffName').Value:=edStaffName.Text; ADOQuery1.Open;
這樣的會出現錯誤 raised exceptino class EOldException with message '無效的資料行名稱N@P1。 |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
OK, 抱歉我很久沒用delphi,而且我也不用TADOQuery,而是用TADODataSet或是TADOCommand。但我很確定你的關鍵問題在 N 這個字元。
我換個方式來回好了,但你自己稍變化一下。 sql2000裡要select一個含nchar型別的語法應該是要這樣 Select * from Staff where StaffName=N'Aftcast' ; 我不知道用"取代"的方式該如何,但我通常是用字串相加,只要加成上面那樣的形式,那整個就會是對的。
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
hungyulin
一般會員 發表:36 回覆:33 積分:13 註冊:2003-10-15 發送簡訊給我 |
|
pedro
尊榮會員 發表:152 回覆:1187 積分:892 註冊:2002-06-12 發送簡訊給我 |
Hi
不好意思,我來插花一下 [code delphi] With AdoQuery1 do begin Sql.Clear; Sql.Add('Select * from Staff '); Sql.Add('where StaffName=N' QuotedStr('Aftcast')); end; [/code] ===================引 用 aftcast 文 章=================== Select * from Staff where StaffName=N'Aftcast' ; ===================引 用aftcast文 章=================== 對,我知道在SQL工具中這樣下語法是可以,就是不知道在Delphi中要怎麼作?? |
hungyulin
一般會員 發表:36 回覆:33 積分:13 註冊:2003-10-15 發送簡訊給我 |
===================引 用 pedro 文 章=================== Hi 不好意思,我來插花一下 [code delphi] With AdoQuery1 do begin Sql.Clear; Sql.Add('Select * from Staff '); Sql.Add('where StaffName=N' QuotedStr('Aftcast')); end; [/code] ===================引 用 pedro 文 章=================== Sql.Add('where StaffName=N' QuotedStr('綉')); |
pedro
尊榮會員 發表:152 回覆:1187 積分:892 註冊:2002-06-12 發送簡訊給我 |
|
hungyulin
一般會員 發表:36 回覆:33 積分:13 註冊:2003-10-15 發送簡訊給我 |
===================引 用 pedro 文 章=================== 您Delphi是什麼版本? 試試Sql.Add('where StaffName like N''¯tcast%''),不要使用QuotedStr看看 ===================引 用 hungyulin 文 章=================== 我是Delphi 5,因為需求不可使用Like一定要絕對值才行。 //edStaffName:TtntEdit; SQL.Add(' Select Area,GroupName,StaffName,MobilPhone,Phone1,Addr1 from Staff ' ' where StaffName=N''' edStaffname.Text ''' '); 用這樣也是不行。
|
pedro
尊榮會員 發表:152 回覆:1187 積分:892 註冊:2002-06-12 發送簡訊給我 |
問題是出在"綉、堃"這些字,經Delphi 5的TEdit是輸入不進去的, 而且一些含有Unicode的字元,也無法以TDBEdit顯示出來 加掛TNTWare Delphi Unicode Components 或裝Unicode補完計劃不知道有沒有幫助? 或許其他前輩有處理過這類問題,看看有沒有其它解法? ===================引 用 hungyulin 文 章=================== 我是Delphi 5,因為需求不可使用Like一定要絕對值才行。 //edStaffName:TtntEdit; SQL.Add(' Select Area,GroupName,StaffName,MobilPhone,Phone1,Addr1 from Staff ' ' where StaffName=N''' edStaffname.Text ''' '); 用這樣也是不行。
編輯記錄
pedro 重新編輯於 2011-04-01 04:29:19, 註解 無‧
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
謝謝petro幫忙,我再接手回來。
我一直使用ado tnt 元件,一直沒問題。唯一有差的是我用的是bcb,但我想只是語法上的不同吧? 1/ 請不要用 adoquery 這個元件,極強烈的建議不要用! 因為 微軟ado元件本來只有 adodataset,adocommand,adoconnection這三個。這個adoquery是borland自己把adodataset再進一步包的。 2/ tadoquery裡的sql這個屬性,它是TStrings,並不是WideString(即unicode)。所以 SQL.Add(' Select Area,GroupName,StaffName,MobilPhone,Phone1,Addr1 from Staff ' ' where StaffName=N''' edStaffname.Text ''' '); 也一定死! 我剛找到我2003年時寫的delphi程式加以修改… 參考一下吧 [code delphi] self.ADODataSet2.CommandText := 'Select Area,GroupName,StaffName,MobilPhone,Phone1,Addr1 from Staff where StaffName=N''' edStaffname.Text ''''; self.ADODataSet2.Open; while not self.ADODataSet2.Eof do begin edUnicode.Text = VarToWideStr(ADODataSet2['StaffName']); {自己加一個tnt的元件名叫edUnicode,這是為了讓你知道取法} label1.Caption = VarToStr(ADODataSet2['Addr1']); {自己加一個Label元件,用以告知你若不是unicode時是這樣取的} self.ADODataSet2.Next; [/code]
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2011-04-01 08:30:11, 註解 無‧
|
hungyulin
一般會員 發表:36 回覆:33 積分:13 註冊:2003-10-15 發送簡訊給我 |
===================引 用 aftcast 文 章=================== [code delphi]
{進不了迴圈,因為recordCount為0} edUnicode.Text = VarToWideStr(ADODataSet2['StaffName']); {自己加一個tnt的元件名叫edUnicode,這是為了讓你知道取法} label1.Caption = VarToStr(ADODataSet2['Addr1']); {自己加一個Label元件,用以告知你若不是unicode時是這樣取的} self.ADODataSet2.Next; [/code] ===================================================== 感謝Aftcast大大的幫忙,如上面所示在self.ADODataSet2.Open後還是進不了下面的迴圈,因為加入了那個where條件導致Select 後的RecordCount為0吧? 後來小弟只好用一個很笨的方法來作,把where條件拿掉,全部Select出來一筆一筆慢慢比對,目前資料不多還可以接受. [code delphi] self.ADODataSet2.CommandText := 'Select Area,GroupName,StaffName,MobilPhone,Phone1,Addr1 from Staff' self.ADODataSet2.Open; while not self.ADODataSet2.Eof do begin if ADODataSet2['StaffName']=edStaffName.Text then begin edUnicode.Text = VarToWideStr(ADODataSet2['StaffName']); {自己加一個tnt的元件名叫edUnicode,這是為了讓你知道取法} label1.Caption = VarToStr(ADODataSet2['Addr1']); {自己加一個Label元件,用以告知你若不是unicode時是這樣取的} Break; end; self.ADODataSet2.Next; end [/code]
編輯記錄
hungyulin 重新編輯於 2011-04-05 20:30:24, 註解 無‧
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
請改成如下再測看看? (語法若有錯請自改,我不熟,也沒太多時間去確認 :p ,會分成這麼多段是有原因的,所以請先照著做看看)
[code delphi] command : WideString; tail : WideString; command := 'Select Area,GroupName,StaffName,MobilPhone,Phone1,Addr1 from Staff where StaffName=N'''; command := command edStaffname.Text; {edStaffname是tnt元件喔!} tail = ''''; command := command tail; self.ADODataSet2.CommandText := command; [/code]
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2011-04-05 20:55:37, 註解 無‧
|
hungyulin
一般會員 發表:36 回覆:33 積分:13 註冊:2003-10-15 發送簡訊給我 |
|
cancer
高階會員 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
何必那麼麻煩?一行搞定。
ADOQuery1.Sql.Text := Format('Select * from Staff where StaffName=''%s''', [edStaffName.Text]); 我用 Delphi 2006,大量使用 TAdoDateSet 和 TAdoQuery,全部都用 Format() 來組出 Sql 指令,從來都沒有問題。 我的同事都喜歡用 Parameter,我卻不用,無他,一行能搞定,為什麼要多寫幾行? 我同事喜歡先設定一個 TAdoQuery 的 Sql 指令含參數,使用者傳入參數打開,看起來方便,但有兩個缺點。 1.這個 AdoQuery 不能拿來填其他 Sql 指令。 2.在看程式碼的時候,不知道這個 AdoQuery 是幹嘛的,因為指令不在原始碼裡面,每次看到一半都要到物件檢視器看一下才知道,程式碼分離導致程式難閱讀。 ================================== ADOQuery1.SQL.Add(' Select * from Staff where StaffName=:Staffname '); ADOQuery1.Parameters.ParamByName('StaffName').DataType:=ftWideString; //edStaffName:TTntEdit; ADOQuery1.Parameters.ParamByName('StaffName').Value:=edStaffName.Text;
===================引 用 hungyulin 文 章=================== 感謝Aftcast大大的幫忙,後來發現在ADODataSet上有一個Propertie叫作ParamCheck要設為False就可以了。 |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
Cancer 你好,
你的寫法很好,也很棒。只是唯一要注意的是… 當命令中有unicode時,千萬不要用 tadoquery !!! ,因為 微軟ado元件本來只有 adodataset,adocommand,adoconnection這三個。這個adoquery是borland自己把adodataset再進一步包的。ms 的那三個都是unicode的。 2/ TStrings,並不是WideString(即unicode)。所以 SQL.Add(' Select Area,GroupName,StaffName,MobilPhone,Phone1,Addr1 from Staff ' ' where StaffName=N''' edStaffname.Text ''' '); ===================引 用 cancer 文 章=================== 何必那麼麻煩?一行搞定。 ADOQuery1.Sql.Text := Format('Select * from Staff where StaffName=''%s''', [edStaffName.Text]); 我用 Delphi 2006,大量使用 TAdoDateSet 和 TAdoQuery,全部都用 Format() 來組出 Sql 指令,從來都沒有問題。 我的同事都喜歡用 Parameter,我卻不用,無他,一行能搞定,為什麼要多寫幾行? 我同事喜歡先設定一個 TAdoQuery 的 Sql 指令含參數,使用者傳入參數打開,看起來方便,但有兩個缺點。 1.這個 AdoQuery 不能拿來填其他 Sql 指令。 2.在看程式碼的時候,不知道這個 AdoQuery 是幹嘛的,因為指令不在原始碼裡面,每次看到一半都要到物件檢視器看一下才知道,程式碼分離導致程式難閱讀。 ================================== ADOQuery1.SQL.Add(' Select * from Staff where StaffName=:Staffname '); ADOQuery1.Parameters.ParamByName('StaffName').DataType:=ftWideString; //edStaffName:TTntEdit; ADOQuery1.Parameters.ParamByName('StaffName').Value:=edStaffName.Text;
===================引 用 hungyulin 文 章=================== 感謝Aftcast大大的幫忙,後來發現在ADODataSet上有一個Propertie叫作ParamCheck要設為False就可以了。
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
sryang
尊榮會員 發表:39 回覆:762 積分:920 註冊:2002-06-27 發送簡訊給我 |
Cancer 網友,請修改你的寫法,改成跟你同事一樣使用參數
不然哪天 SQL Injection 就找上你 如果我在 edStaffName 中輸入 「'; drop table Staff; --」一查詢你的 Staff 資料表馬上不見 假如你預先料想到這樣的狀況,而使用沒有權限刪除資料表的使用者登入資料庫 我輸入「'; update Staff set StaffName=''; --」一查詢你的 StaffName 也會全部變成空白 防止 SQL Injection 最重要,也最有效的,就是使用參數化查詢 ===================引 用 cancer 文 章=================== 何必那麼麻煩?一行搞定。 ADOQuery1.Sql.Text := Format('Select * from Staff where StaffName=''%s''', [edStaffName.Text]);
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/
編輯記錄
sryang 重新編輯於 2011-04-22 10:56:23, 註解 無‧
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
經sryang提起了 sql injection的情形後 (好久沒去想這個問題,一般是網頁才會考量,yang想好多:p),我進一步去了解 ADodataset 裡關於TParameters的部份。發現…
TAdoQuery裡的sql是不行的) 並 TAdoQuery裡的sql是不行的) 追一下輸出,發現大概是送出這樣的指令至 mssql exec sp_executesql N'select * from Customers where CustomerID = @P1', N'@P1 sql_variant', N'AROUT' 至此有完美的解法了。yeah! 謝謝sryang常常會引發我更深入去回憶、去想… :-) ===================引 用 sryang 文 章=================== Cancer 網友,請修改你的寫法,改成跟你同事一樣使用參數 不然哪天 SQL Injection 就找上你 如果我在 edStaffName 中輸入 「'; drop table Staff; --」一查詢你的 Staff 資料表馬上不見 假如你預先料想到這樣的狀況,而使用沒有權限刪除資料表的使用者登入資料庫 我輸入「'; update Staff set StaffName=''; --」一查詢你的 StaffName 也會全部變成空白 防止 SQL Injection 最重要,也最有效的,就是使用參數化查詢 ===================引 用 cancer 文 章=================== 何必那麼麻煩?一行搞定。 ADOQuery1.Sql.Text := Format('Select * from Staff where StaffName=''%s''', [edStaffName.Text]);
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |