線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1752
推到 Plurk!
推到 Facebook!

請問如何寫這個SQL語句?

答題得分者是:cashxin2002
mathewzhao
中階會員


發表:121
回覆:164
積分:67
註冊:2003-04-04

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-08-11 13:35:25 IP:219.145.xxx.xxx 未訂閱
各位先進好!  Q:統計從DateTimePicker所選定月份, 將Field2求總和,且Field1不為空‧  我是這樣寫的:      
 Decodedate(DateTimePicker1.Date,PYear,PMonth,PDay);
     ADOquery1.Close;
     ADOquery1.SQL.Clear;
     ADOQuery1.SQL.Add('Select sum(Field2) as SumField2 from Table1 where Field1 is Not Null and year(DateTime)=:sYear and  month(DateTime)=:sMonth');
     ADOquery1.Parameters.ParamByName('sYear').value:=PYear;
     ADOquery1.Parameters.ParamByName('sMonth').value:=PMonth;
     Adoquery1.Open;
 
執行時出現錯誤訊息: Invalid Variant type Conversion. (DB:Access ,Delphi5 )
cashxin2002
版主


發表:231
回覆:2555
積分:1937
註冊:2003-03-28

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-08-11 13:43:04 IP:63.84.xxx.xxx 未訂閱
您好﹒ 您的PYear和PMonth形態是否正确﹖須為字串形態﹗ 參考看看﹗ 努力,相信會獲得美麗! 忻晟 發表人 - cashxin2002 於 2003/08/11 13:47:46
------
忻晟
mathewzhao
中階會員


發表:121
回覆:164
積分:67
註冊:2003-04-04

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-08-11 15:11:33 IP:202.100.xxx.xxx 未訂閱
感謝前輩cashxin2002回應! PYear和PMonth的型別為Word 但修改後: ADOquery1.Parameters.ParamByName('sYear').value:=IntToStr(PYear); ADOquery1.Parameters.ParamByName('sMonth').value:=IntToStr(PMonth); 仍然出現相同的錯誤訊息.
cashxin2002
版主


發表:231
回覆:2555
積分:1937
註冊:2003-03-28

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-08-11 15:30:14 IP:63.84.xxx.xxx 未訂閱
引言: 感謝前輩cashxin2002回應! PYear和PMonth的型別為Word 但修改後: ADOquery1.Parameters.ParamByName('sYear').value:=IntToStr(PYear); ADOquery1.Parameters.ParamByName('sMonth').value:=IntToStr(PMonth); 仍然出現相同的錯誤訊息.
您好﹒ PYear和PMonth的值應該是您從DataTimePicker中得知的吧﹐如果沒有做轉形態的動作的話﹐應該是為DateTime的形態﹐所以﹐你應該用DateToStr函數﹒ 請參考您的另一篇發表﹐里面有提到一些相關的問題﹕ http://delphi.ktop.com.tw/topic.php?TOPIC_ID=35443 參考看看 努力,相信會獲得美麗! 忻晟
------
忻晟
sos_admin
版主


發表:121
回覆:697
積分:768
註冊:2003-07-23

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-08-11 15:37:51 IP:61.155.xxx.xxx 未訂閱
这样就可以了!    Decodedate(DateTimePicker1.Date,PYear,PMonth,PDay); ADOquery1.Close; ADOquery1.SQL.Clear; ADOQuery1.SQL.Add('Select sum(Field2) as SumField2 from table1 where (Field1 is not null) and year(datetime)=' inttostr(pyear) ' and month(datetime)=' inttostr(pmonth) ''); Adoquery1.Open;
mathewzhao
中階會員


發表:121
回覆:164
積分:67
註冊:2003-04-04

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-08-11 16:22:53 IP:219.145.xxx.xxx 未訂閱
感謝前輩cashxin2002的熱心回應! 前輩可能誤解這兩個問題了. 首先看一下今天的問題: PYear,PMonth是由Decodedate函式得到,即: Decodedate(DateTimePicker1.Date,PYear,PMonth,PDay); 再看Decodedate定義: Procedure DecodeDate(Date:TDateTime;var Year,Month,day:Word); 可知: PYear,PMonth不是DateTime形態,而是Word形態 昨天的問題是直接使用DateTimePicker1.Date,故仍為DateTime形態‧
ha0009
版主


發表:16
回覆:507
積分:639
註冊:2002-03-16

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-08-11 18:36:01 IP:61.30.xxx.xxx 未訂閱
你好: try it
with AdoQuery1.SQL do 
   Close;
   Clear;
   Add ('Select sum(Field2) as SumField2');
   Add ('From Table1');
   Add ('Where (Field1 is not Null) and (Year ([DateTime])=:sYear)) and (Month ([DateTime])=:sMonth))');
   Parameters.ParamByName('sYear').value:=PYear;
   Parameters.ParamByName('sMonth').value:=PMonth;
   Open;
end;
cashxin2002
版主


發表:231
回覆:2555
積分:1937
註冊:2003-03-28

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-08-11 18:38:38 IP:63.84.xxx.xxx 未訂閱
您好﹒ 剛才做了一下測試﹐程式碼如下﹕ var Month, Day, Year : Word; begin Decodedate(DateTimePicker1.Date,Year,Month,Day); Label4.Caption := IntToStr(Year); //小弟用這句來判斷是否能將[Year]成功轉成成字串 ADOQuery1.Close; ADOQuery1.SQL.Text := 'Select * From 訂單 Where Year(訂購日期)= :Year'; ADOQuery1.Parameters.ParamByName('Year').Value := IntToStr(Year); ADOQuery1.Open; end; 可以跑﹐沒有問題﹒ 但這里需要注意的現象是如果資料表中沒有符合的資料錄﹐就會出現[Invalid Variant type Conversion.]錯誤信息﹐所以請您用﹕ Try ... Except ... 來做例外處理﹐就不會有這個問題了﹒ 參考看看﹗ 努力,相信會獲得美麗! 忻晟
------
忻晟
sos_admin
版主


發表:121
回覆:697
積分:768
註冊:2003-07-23

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-08-11 18:50:09 IP:61.155.xxx.xxx 未訂閱
mathewzhao 兄:    其实您的题目已经有很多可选的解决方法了~
mathewzhao
中階會員


發表:121
回覆:164
積分:67
註冊:2003-04-04

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-08-11 19:49:09 IP:61.185.xxx.xxx 未訂閱
感謝各位前輩的熱心指點 !  晚輩覺得前輩cashxin2002找到了原因.  因為將:  'Select sum(Field2) as SumField2 from Table1 where Field1 is Not Null and year(DateTime)=:sYear and month(DateTime)=:sMonth'  中累積函式SUM換為Count就不會出現錯誤訊息,但換為Max亦會出現相同錯誤訊息. 這個可以通過前輩cashxin2002所說料表中有符合的料就會出現錯誤訊息得到解釋  但是晚輩不太明白:    1)在ADOquery1.open後,晚輩用  if adoquery1.isempty then  begin  showmeesage('Hello!');  end  在料表中有符合的料就應該出現'Hello!'提示訊息,而不應  出現[Invalid Variant type Conversion.]錯信息呀?     2)在Access幫助中提到:A Variant is a special data type that can contain any kind of data except fixed─length String data.  那麼,應該在 I'm passing a nil value or empty string to my SQL command,才會出現'Invalid Variant type Conversion'錯誤訊息呀,它怎會這時就跑出來了? 
cashxin2002
版主


發表:231
回覆:2555
積分:1937
註冊:2003-03-28

發送簡訊給我
#11 引用回覆 回覆 發表時間:2003-08-11 20:30:38 IP:63.84.xxx.xxx 未訂閱
您好﹗    把這一段完整的程式碼貼出來﹐大家幫您看看吧﹗ 努力,相信會獲得美麗! 忻晟
------
忻晟
mathewzhao
中階會員


發表:121
回覆:164
積分:67
註冊:2003-04-04

發送簡訊給我
#12 引用回覆 回覆 發表時間:2003-08-11 20:58:08 IP:219.145.xxx.xxx 未訂閱
Code如下,請各位先進指點! procedure TForm1.Button1Click(Sender: TObject); begin Decodedate(DateTimePicker1.Date,PYear,PMonth,PDay); DBGrid1.DataSource:=nil; ADOquery1.Close; ADOquery1.SQL.Clear; ADOQuery1.SQL.Add('Select sum(Field2) as SumField2 from Table1 where Field1 is Not Null and year(DateTime)=:sYear and month (DateTime)=:sMonth'); ADOquery1.Parameters.ParamByName('sYear').value:=PYear; ADOquery1.Parameters.ParamByName('sMonth').value:=PMonth; Adoquery1.Open; if adoquery1.isempty then begin showmessage('Hello!'); end else Edit1.Text:=ADOquery1.FieldByName('SumField2').value; DBGrid1.DataSource:=DataSource1; end; 發表人 - mathewzhao 於 2003/08/11 21:00:40
cashxin2002
版主


發表:231
回覆:2555
積分:1937
註冊:2003-03-28

發送簡訊給我
#13 引用回覆 回覆 發表時間:2003-08-12 00:06:41 IP:63.84.xxx.xxx 未訂閱
您好﹗    做了一些測試﹐發現有如下問題﹕
procedure TForm1.Button1Click(Sender: TObject);
begin
  Decodedate(DateTimePicker1.Date,PYear,PMonth,PDay);
  DBGrid1.DataSource:=nil;
  Try
  ADOquery1.Close;
  ADOquery1.SQL.Clear;
  ADOQuery1.SQL.Add('Select sum(Field2) as SumField2 from Table1 
  where Field1 is Not Null and year(DateTime)=:sYear and month
  (DateTime)=:sMonth');
  ADOquery1.Parameters.ParamByName('sYear').value:=PYear;
  ADOquery1.Parameters.ParamByName('sMonth').value:=PMonth;
  Adoquery1.Open;      if adoquery1.isempty then
    begin
      showmessage('Hello!');
    end
//Open之后﹐如果沒有資料符合查詢條件的話﹐紅色處的程式碼根本不會執行﹐
//出現的Invalid Variant type Conversion訊息不是發生在AfterOpen事件中﹐
//而是在Open与AfterOpen之間﹒而后就直接跳到Except之后執行ShowMessage
  else
    begin
      Edit1.Text:=ADOquery1.FieldByName('SumField2').value;
      DBGrid1.DataSource:=DataSource1;
      end;
  except
    ShowMessage('SQL語法錯誤!');
  end;
//只有存在符合查詢條件的資料時﹐藍色處的程式碼才會繼續執行﹒
end;
小弟稍改程式碼用Try...Except...End(橘色處)來做例外處理﹐除了使用ADOQuery1.Parameters屬性之外﹐還有直接使用組合字串的方法和直接指定查詢日期的方法﹐都會出現同樣的現象﹐不知道這是何原因﹒是否勞煩站長大大和其他的前輩﹑先進幫忙看一下﹐是Bug問題﹐還是Code的原理錯誤﹒ 感謝﹗ 努力,相信會獲得美麗! 忻晟 發表人 - cashxin2002 於 2003/08/12 00:16:27
------
忻晟
sos_admin
版主


發表:121
回覆:697
積分:768
註冊:2003-07-23

發送簡訊給我
#14 引用回覆 回覆 發表時間:2003-08-12 08:49:53 IP:61.155.xxx.xxx 未訂閱
adoquery1.isempty 是检测记录集是否为空,但是用聚焦sql查询是不可能返回一个空记录集的(但是他可以返回的一条不合法null记录,对于SumField2的必须asinteger强制将其转换成0,这样就不会出现异常了;而用value是一个variant 型是可以包含null的,所以会出现异常了。 >>);
mathewzhao
中階會員


發表:121
回覆:164
積分:67
註冊:2003-04-04

發送簡訊給我
#15 引用回覆 回覆 發表時間:2003-08-12 13:46:42 IP:61.150.xxx.xxx 未訂閱
sos admin前輩好! 晚輩有兩個問題想請教前輩: 1:聚集SQL查詢是指什麼?為什麼不可能返回一個空紀錄集? 2:'value是一個variant型',value是指: ADOquery1.Parameters...value:=‧‧‧ 中的value嗎,這個value不是字串型態嗎? 而且variant型可以包含NULL嗎? variant型別的資料結構在System.pas 定義: PVarData = ^TVarData; TVarData = packed record VType: Word; Reserved1, Reserved2, Reserved3: Word; case Integer of varSmallint: (VSmallint: Smallint); varInteger: (VInteger: Integer); varSingle: (VSingle: Single); varDouble: (VDouble: Double); varCurrency: (VCurrency: Currency); varDate: (VDate: Double); varOleStr: (VOleStr: PWideChar); varDispatch: (VDispatch: Pointer); varError: (VError: LongWord); varBoolean: (VBoolean: WordBool); varUnknown: (VUnknown: Pointer); varByte: (VByte: Byte); varString: (VString: Pointer); varAny: (VAny: Pointer); varArray: (VArray: PVarArray); varByRef: (VPointer: Pointer); end; 並不包括varNULL呀!
sos_admin
版主


發表:121
回覆:697
積分:768
註冊:2003-07-23

發送簡訊給我
#16 引用回覆 回覆 發表時間:2003-08-13 09:15:13 IP:61.155.xxx.xxx 未訂閱
聚集SQL查詢是指什麼? 简单的讲就是指类似于合计、统计纪录数量、分组查询等,将符合一组条件的纪录以一条纪录形式返回。    為什麼不可能返回一個空紀錄集?  比如说,让你统计一个班级学生人数;但是,这个班级没有任何学生! 请问,这个班级有多少人? 是NULL,还是0?我想你一定说是0,但是计算机认为是NULL.< > 如果您回答上面的问题,那么它至少会有一种结果[纪录]。< > 您不会不回答吧?如果不回答,那么一定ERROR
Justmade
版主


發表:94
回覆:1934
積分:2030
註冊:2003-03-12

發送簡訊給我
#17 引用回覆 回覆 發表時間:2003-08-13 09:50:25 IP:218.16.xxx.xxx 未訂閱
你肯定你在只有一個 ADOQuery 沒設事件沒其他元件也會出現該錯誤嗎 ? 我的感覺是你其他的 Code 出錯的 (如 ADOQueryAfterScroll 裡的) 因為即使回傳的 Sum(xxx) 是 null, 若你沒有去使用他,則應不會出現 Invalid Variant type Conversion 才對。 例如你有這行 : Edit1.Text := ADOQuery1.FieldByName('SumField2').Value; 當SumField2 是 Null (where 選不到資料)時便出錯,因為Edit1.Text 是 String 不能接受 Null 值。 你可改成 : Edit1.Text := ADOQuery1.FieldByName('SumField2').AsString; // Null 自動轉 '' 或 if ADOQuery1.FieldByName('SumField2').Value <> null then // 不是 Null 才設,可加上 else 清空 Edit1.Text := ADOQuery1.FieldByName('SumField2').Value;
Brian77
中階會員


發表:8
回覆:114
積分:94
註冊:2002-05-17

發送簡訊給我
#18 引用回覆 回覆 發表時間:2003-08-13 17:45:26 IP:61.61.xxx.xxx 未訂閱
我想問題點應該已經由幾位大大點出來了 在這裡提供一點除錯的技巧 像這個問題, 在 open 時發生錯誤, 可以先簡化程式, 以釐清錯誤點 先另外撰寫一小程式, 純綷只有 TADOQuery 和開檔的程式碼, 連 DateTimePicker 都可以先省略, 這樣可以測試 SQL 是否無誤 然後再檢查它是否使用了某些 事件, 或者和其它的物件連結了
mathewzhao
中階會員


發表:121
回覆:164
積分:67
註冊:2003-04-04

發送簡訊給我
#19 引用回覆 回覆 發表時間:2003-08-13 18:50:12 IP:61.150.xxx.xxx 未訂閱
感謝Justmade前輩的的回應! 首先回答前輩的問題:  1)在Adoquery1中沒設任何事件  2)如果在Form1如果只用:  Edit1,Button1,ADOquery1三個元件  在ADOquery1連接資料庫後,只增加下列Code,   
procedure TForm1.Button1Click(Sender: TObject);
   var
     Pyear,Pmonth,Pday:word;
   begin
     Decodedate(Date,PYear,PMonth,PDay);
     ADOquery1.Close;
     ADOquery1.SQL.Clear;
     ADOQuery1.SQL.Add('Select sum(Field2) as SumField2 from Table1 
where Field1 is Not Null and year(DateTime)=:sYear and month
(DateTime)=:sMonth');
     ADOquery1.Parameters.ParamByName('sYear').value:=PYear;
     ADOquery1.Parameters.ParamByName('sMonth').value:=PMonth;
     Adoquery1.Open 
     
     Edit1.Text:=ADOquery1.FieldByName('SumField2').value;
    end;
在沒選到資料時,仍然出現相同的錯誤訊息. 其次,將 Edit1.Text := ADOQuery1.FieldByName('SumField2').Value; 換為 Edit1.Text := ADOQuery1.FieldByName('SumField2').AsString; 後,就沒有出現錯誤訊息. 證明前輩下面兩個觀點是正確的: 1)即使回傳的Sum(xxx)是null,若有使用他,不會出現 Invalid Variant type Conversion . 2)錯誤的原因是:因Edit1.Text 是 String 不能接受 Null 值,當SumField2 是 Null時便出錯 另外,特別感謝前輩SOS admin和前輩Brian77的熱心指點,謝謝!
系統時間:2024-07-04 11:37:11
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!