乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      SQL /數(shù)據(jù)庫(kù) 使用藍(lán)皮書(shū) 大富翁論壇-富翁筆記-

       diamond 2007-09-14
      KeyLife富翁筆記
      作者: archonwang
      標(biāo)題: SQL /數(shù)據(jù)庫(kù) 使用藍(lán)皮書(shū)
      關(guān)鍵字: SQL語(yǔ)句
      分類(lèi): 開(kāi)發(fā)經(jīng)驗(yàn)
      密級(jí): 公開(kāi)
      (評(píng)分:★★ , 回復(fù): 7, 閱讀: 17979) »»

         SQL語(yǔ)言由命令、子句、運(yùn)算和集合函數(shù)等構(gòu)成。在SQL中,數(shù)據(jù)定義語(yǔ)言DDL(用來(lái)建立及定義數(shù)據(jù)表、字段以及索引等數(shù)據(jù)庫(kù)結(jié)構(gòu))包含的命令有CREATE、DROP、ALTER;數(shù)據(jù)操縱語(yǔ)言DML(用來(lái)提供數(shù)據(jù)的查詢、排序以及篩選數(shù)據(jù)等功能)包含的命令有SELECT、INSERT、UPDATE、DELETE。

      一、SQL語(yǔ)句

      (1)Select 查詢語(yǔ)句
      語(yǔ)法:SELECT [ALL|DISTINCT]  <目標(biāo)列表達(dá)式> [AS 列名]
       [,<目標(biāo)列表達(dá)式> [AS 列名] ...] FROM <表名> [,<表名>…]
      [WHERE <條件表達(dá)式> [AND|OR  <條件表達(dá)式>...]
      [GROUP BY 列名 [HAVING <條件表達(dá)式>]]
      [ORDER BY 列名 [ASC | DESC]]
      解釋?zhuān)篬ALL|DISTINCT]   ALL:全部; DISTINCT:不包括重復(fù)行
      <目標(biāo)列表達(dá)式>  對(duì)字段可使用AVG、COUNT、SUM、MIN、MAX、運(yùn)算符等
      <條件表達(dá)式>  
      查詢條件  謂詞
      比較  =、>,<,>=,<=,!=,<>,
      確定范圍  BETWEEN AND、NOT BETWEEN AND
      確定集合  IN、NOT IN
      字符匹配  LIKE(“%”匹配任何長(zhǎng)度,“_”匹配一個(gè)字符)、NOT LIKE
      空值  IS NULL、IS NOT NULL
      子查詢  ANY、ALL、EXISTS
      集合查詢  UNION(并)、INTERSECT(交)、MINUS(差)
      多重條件  AND、OR、NOT
      <GROUP BY 列名>  對(duì)查詢結(jié)果分組
      [HAVING <條件表達(dá)式>]  分組篩選條件
      [ORDER BY 列名 [ASC | DESC]]  對(duì)查詢結(jié)果排序;ASC:升序 DESC:降序
      例1: select student.sno as 學(xué)號(hào), student.name as 姓名, course as 課程名, score as 成績(jī) from score,student where student.sid=score.sid and score.sid=:sid
      例2:select student.sno as 學(xué)號(hào), student.name as 姓名,AVG(score) as 平均分  from score,student where student.sid=score.sid and student.class=:class and (term=5 or term=6)  group by student.sno, student.name  having count(*)>0 order by 平均分 DESC
      例3:select * from score where sid like '9634'
      例4:select * from student where class in (select class from student where name='陳小小')

      (2)INSERT插入語(yǔ)句
      語(yǔ)法:INSERT INTO  <表名> [(<字段名1> [,<字段名2>, ...])]  VALUES (<常量1> [,<常量2>, ...])
      語(yǔ)法:INSERT INTO  <表名> [(<字段名1> [,<字段名2>, ...])] 子查詢
      例子:INSERT INTO  借書(shū)表(rid,bookidx,bdate)VALUES (edit1.text,edit2.text,date)
      例子:INSERT INTO score1(sno,name)  SELECT sno,name  FROM student  WHERE class=’9634’

      (3)UPDATE-SQL
      語(yǔ)法:UPDATE 〈表名〉
      SET 列名1 = 常量表達(dá)式1[,列名2 = 常量表達(dá)式2 ...]
       WHERE <條件表達(dá)式> [AND|OR  <條件表達(dá)式>...]
      例子:update score set credithour=4 where course='數(shù)據(jù)庫(kù)'

      (4)DELETE-SQL
      語(yǔ)法:DELETE FROM〈表名〉[WHERE <條件表達(dá)式> [AND|OR  <條件表達(dá)式>...]]
      例子:Delete from student where sid='003101'

      (5)CREATE TABLE
      CREATE TABLE | DBF TableName1 [NAME LongTableName] [FREE]
       (FieldName1 FieldType [(nFieldWidth [, nPrecision])]
         [NULL | NOT NULL]
         [CHECK lExpression1 [ERROR cMessageText1]]
         [DEFAULT eExpression1]
         [PRIMARY KEY | UNIQUE]
         [REFERENCES TableName2 [TAG TagName1]]
         [NOCPTRANS]
       [, FieldName2 ...]
         [, PRIMARY KEY eExpression2 TAG TagName2
      |, UNIQUE eExpression3 TAG TagName3]
         [, FOREIGN KEY eExpression4 TAG TagName4 [NODUP]
           REFERENCES TableName3 [TAG TagName5]]
         [, CHECK lExpression2 [ERROR cMessageText2]])
      | FROM ARRAY ArrayName

      (6)ALTER TABLE
      ALTER TABLE TableName1
       ADD | ALTER [COLUMN] FieldName1
         FieldType [(nFieldWidth [, nPrecision])]
         [NULL | NOT NULL]
         [CHECK lExpression1 [ERROR cMessageText1]]
         [DEFAULT eExpression1]
         [PRIMARY KEY | UNIQUE]
         [REFERENCES TableName2 [TAG TagName1]]
         [NOCPTRANS]

      (7)DROP TABLE
      DROP TABLE [路徑名.]表名

      (8)CREATE INDEX
      CREATE INDEX index-name ON table-name(column[,column…])
      例:CREATE INDEX uspa ON 口令表(user,password)

      (9)DROP INDEX
      DROP INDEX table-name.index-name|PRIMARY
      例:DROP INDEX 口令表.uspa

      二、在程序中使用靜態(tài)SQL語(yǔ)句
          在程序設(shè)計(jì)階段,將SQL命令文本作為T(mén)Query組件的SQL屬性值設(shè)置。

      三、在程序中使用動(dòng)態(tài)SQL語(yǔ)句
          動(dòng)態(tài)SQL語(yǔ)句是指在SQL語(yǔ)句中包含有參數(shù)變量的SQL語(yǔ)句(如:select * from student where class=:class),在程序中可以為參數(shù)賦值。給參數(shù)賦值的方法有:

          1、利用參數(shù)編輯器為參數(shù)賦值
          選中TQuery組件,在對(duì)象監(jiān)視器OI中點(diǎn)取Params項(xiàng),在彈出的參數(shù)編輯窗口中設(shè)置參數(shù)的值。
      例:SELECT bookidx AS 書(shū)號(hào),藏書(shū)表.bookname AS 書(shū)名, bdate AS 借書(shū)日期  FROM 借書(shū)表,藏書(shū)表 where 借書(shū)表.bookidx=藏書(shū)表.bookidx and rid=:rid

          2、在程序運(yùn)行中通過(guò)程序?yàn)閰?shù)賦值
        (1)根據(jù)參數(shù)在SQL語(yǔ)句中出現(xiàn)的順序,使用TQuery的Params屬性為參數(shù)賦值;

      例:在借書(shū)表中插入一條記錄
      with  Query1 do
      begin
         SQL.clear;
         SQL.add('Insert  Into  借書(shū)表(bookidx,rid,rdate)');
         SQl.add('Values(:bookidx,:rid,:rdate)');
         Params[0].AsString := bookidxEdit.Text;
         Params[1].AsString := ridEdit.Text;
         Params[2] .AsDate:=date;
         ExecSQL;
      End;

      (2)根據(jù)SQL語(yǔ)句中的參數(shù)名字,調(diào)用ParamByName方法為參數(shù)賦值;
      ParamByName('bookidx').AsString := bookidxEdit.Text;
      ParamByName('rid').AsString := ridEdit.Text;
      ParamByName('rdate') .AsDate:=date;
      ExecSQL;
      有:AsString 、AsSmallInt 、AsInteger 、AsWord 、AsBoolean 、AsFloat 、AsCurrency 、AsBCD 、AsDate 、AsTime 、AsDateTime轉(zhuǎn)換函數(shù)

      3、使用數(shù)據(jù)源為參數(shù)賦值
          把TQuery的DataSource屬性設(shè)置為另一個(gè)數(shù)據(jù)源(T DataSource名字),Delphi會(huì)把未賦值的參數(shù)與指定的數(shù)據(jù)源中的各字段相比較,并將匹配的字段的值賦給未賦值的參數(shù),可實(shí)現(xiàn)主表—明細(xì)表應(yīng)用。

      四、對(duì)TQuery返回的數(shù)據(jù)集進(jìn)行修改
          一般情況下,TQuery返回的數(shù)據(jù)集是只讀的,不能修改;
          對(duì)不包含集操作(如:SUM、COUNT)的單表SELECT查詢,設(shè)置TQuery的RequsetLive屬性為T(mén)rue,則可修改TQuery返回的數(shù)據(jù)集。

      var
        I: Integer;
        ListItem: string;
      begin
        for I := 0 to Query1.ParamCount - 1 do
        begin
          ListItem := ListBox1.Items[I];
          case Query1.Params[I].DataType of
            ftString:
              Query1.Params[I].AsString := ListItem;
            ftSmallInt:
              Query1.Params[I].AsSmallInt := StrToIntDef(ListItem, 0);
            ftInteger:
              Query1.Params[I].AsInteger := StrToIntDef(ListItem, 0);
            ftWord:
              Query1.Params[I].AsWord := StrToIntDef(ListItem, 0);
            ftBoolean:
              begin
                if ListItem = 'True' then
                  Query1.Params[I].AsBoolean := True
                else
                  Query1.Params[I].AsBoolean := False;
              end;
            ftFloat:
              Query1.Params[I].AsFloat := StrToFloat(ListItem);
            ftCurrency:
              Query1.Params[I].AsCurrency := StrToFloat(ListItem);
            ftBCD:
              Query1.Params[I].AsBCD := StrToCurr(ListItem);
            ftDate:
              Query1.Params[I].AsDate := StrToDate(ListItem);
            ftTime:
              Query1.Params[I].AsTime := StrToTime(ListItem);
            ftDateTime:
              Query1.Params[I].AsDateTime := StrToDateTime(ListItem);
          end;
        end;
      end;


      2003-11-25 9:59:00   
       2003-11-25 10:06:20    運(yùn)行期間對(duì)數(shù)據(jù)庫(kù)表的


      一、數(shù)據(jù)集表的打開(kāi)與關(guān)閉
        打開(kāi):設(shè)置數(shù)據(jù)集組件的Active屬性為T(mén)rue或調(diào)用數(shù)據(jù)集組件的Open方法
        關(guān)閉:設(shè)置數(shù)據(jù)集組件的Active屬性為False或調(diào)用數(shù)據(jù)集組件的Close方法

      二、創(chuàng)建數(shù)據(jù)庫(kù)應(yīng)用程序
      利用向?qū)?chuàng)建:使用Database菜單/Form Wizard選項(xiàng);
      創(chuàng)建主從表:設(shè)置從表的MasterSource、MasterField屬性;
      創(chuàng)建查詢表:使用TQuery組件;

      三、數(shù)據(jù)庫(kù)表記錄的定位
      使用TDBNavigator組件;
      調(diào)用數(shù)據(jù)集組件的First、Next、Prior、Last方法;
      數(shù)據(jù)集組件的EOF屬性(或BOF屬性)用來(lái)判斷記錄指針是否指向第一條記錄(或最后一條記錄);
      使用數(shù)據(jù)集的書(shū)簽BookMark(GetBookMark:獲得當(dāng)前記錄的BookMark記號(hào);GotoBookMark:從當(dāng)前記錄直接轉(zhuǎn)到指定BookMark的那條記錄;FreeBookMark:釋放某個(gè)BookMark)
      使用GotoKey、FindKey方法查找記錄進(jìn)行定位;

      四、數(shù)據(jù)庫(kù)表字段對(duì)象的使用

        (1)創(chuàng)建永久的字段對(duì)象
          雙擊或單擊再右擊TTable(TQuery)對(duì)象打開(kāi)字段編輯器,使用其彈出菜單增加字段對(duì)象、刪除字段對(duì)象、定義新的字段對(duì)象(字段編輯器的彈出菜單的New Fields選項(xiàng),可創(chuàng)建計(jì)算字段);

        (2)字段對(duì)象的屬性、方法、事件
          字段對(duì)象名:如Table1Name、Query1Sid
          屬性:Alignment(對(duì)齊方式)、Calculated(是否是從其它字段值計(jì)算得到)、DisplayLabel(顯示的標(biāo)題)、DisplayWidth(顯示的寬度)、DisplayFormat(顯示的格式)、EditMask(輸入的限制)、FieldName(字段名)、ReadOnly(是否只讀)、Visible(是否顯示)
          事件:OnChange(字段值發(fā)生變化時(shí)觸發(fā))、OnGetText(當(dāng)字段對(duì)象獲得字段值時(shí)觸發(fā))、OnSetText(當(dāng)字段對(duì)象被設(shè)置字段值時(shí)觸發(fā))、OnValiData(當(dāng)修改、插入、進(jìn)行有效性檢驗(yàn)時(shí)觸發(fā))

        (3)字段對(duì)象的類(lèi)型轉(zhuǎn)換
          有:AsString 、AsSmallInt 、AsInteger 、AsWord 、AsBoolean 、AsFloat 、AsCurrency 、AsBCD 、AsDate 、AsTime 、AsDateTime轉(zhuǎn)換函數(shù)
      如:Edit1.Text:=Table1Name.Value ;
      Table1Bdate.AsString:=DateToStr(DATE) ;

        (4)對(duì)字段對(duì)象的訪問(wèn)
          動(dòng)態(tài)字段對(duì)象的訪問(wèn):Table1.Fields[0]. DisplayLabel:= '學(xué)生編號(hào)'
      Table1.FieldByName('Sid'). DisplayLabel:= '學(xué)生編號(hào)' Table1.Fields[0].Assignment:=taCenter
      Edit1.Text:= Table1.FieldByName('Sid').AsString
          永久字段對(duì)象的訪問(wèn):Query1Sid.DisplayLabel:= '學(xué)生編號(hào)'  
      Query1Sid.DisplayWidth:= 12

      五、對(duì)數(shù)據(jù)庫(kù)表數(shù)據(jù)的操作方法

        (1)訪問(wèn)表中某一字段的數(shù)據(jù)的方法:
      Table1.FieldByName('bookidx').AsString
      Table1.Field[0].AsInteger
      Table1.Fieldvalues['bookidx']

        (2)數(shù)據(jù)庫(kù)表的一些屬性:
      當(dāng)前記錄號(hào):Table1.Recno
      記錄總數(shù):Table1.RecordCount
      得到表的字段名:Table1.GetFieldNames(ListBox1。Items)

        (3)數(shù)據(jù)維護(hù)的方法:
      Edit方法:把數(shù)據(jù)集設(shè)置為編輯狀態(tài);
      Append方法:把數(shù)據(jù)集設(shè)置為插入狀態(tài)(最后);
      Insert方法:把數(shù)據(jù)集設(shè)置為插入狀態(tài)(當(dāng)前記錄后);
      Post方法:把修改的記錄寫(xiě)回?cái)?shù)據(jù)集;
      Cancel方法:取消當(dāng)前的操作;
      Delete方法:刪除表中當(dāng)前記錄;
      AppendRecord方法:
      InsertRecord方法:table1.InsertRecord(['963409', NIL, NIL,'考試']);
      SetRecords方法:
      Abort方法:取消各種方法的調(diào)用;

        (4)輸入數(shù)據(jù)的合法性驗(yàn)證
          對(duì)數(shù)據(jù)庫(kù)表建立合法性驗(yàn)證機(jī)制(如在DBD設(shè)置表的Validity Check、Table Lookup、Referential Integrity等屬性);
        在字段編輯表Fields Editor(雙擊Ttable對(duì)象),選擇字段,編寫(xiě)其OnValidate事件,要求非空可設(shè)置其Required屬性為T(mén)rue;
        在程序中防止不合法輸入(如:使用TDBcombobox對(duì)象,TDBlookupcombobox對(duì)象);

      六、數(shù)據(jù)檢索
        (1)利用索引排序
          如:TABLE1.IndexName:='uspa'  或TABLE1.IndexFieldNames:='user_id'
        (2)使用GotoKey方法查找數(shù)據(jù)庫(kù)中的記錄
        要求查找字段建立了索引,非主索引要設(shè)置Ttable對(duì)象的IndexName屬性。
        調(diào)用SetKey方法,把要查找的Ttable對(duì)象置成查找模塊;
        把查找值送進(jìn)被查找的Field的查找緩沖區(qū);
        調(diào)用Ttable對(duì)象的GotoKey方法,測(cè)試該方法的返回值判斷查找是否成功;
        (3)使用FindKey方法查找數(shù)據(jù)庫(kù)中的記錄
          把查找值作為參數(shù)傳遞給FindKey函數(shù),允許有多個(gè)查找值,要求把要查找的多個(gè)字段的索引名賦給Ttable對(duì)象的IndexName屬性;
        (4)不精確查找
          GotoNearest方法
          FindNearest方法
        (5)使用Locate方法查找數(shù)據(jù)庫(kù)中的記錄(不用建索引)
          table1.locate(‘字段名1;字段名2’,VarArroyof([‘值1’,‘值2’]),[LoCaseInsensitive,LoPartialKey])
          LoCaseInsensitive:忽略大小寫(xiě);IoPartialKey:不精確查找
        (6)設(shè)定查找范圍的方法
          SetRangeStart、SetRangeEnd、EditRangeStart、EditRangeEnd、SetRange([Start Values],[End Value])、ApplyRange、CancelRange
        (7)用TQuery組件的動(dòng)態(tài)SQL語(yǔ)句進(jìn)行查找

      七、修改數(shù)據(jù)庫(kù)中的記錄
          在程序中對(duì)數(shù)據(jù)庫(kù)記錄進(jìn)行操作可按下列的步驟進(jìn)行:
        (1)移動(dòng)數(shù)據(jù)指針到要修改的記錄;
        (2)調(diào)用Edit方法將Ttable組件設(shè)置成編輯狀態(tài);
        (3)修改字段值;(Table1.Fieldvalues['字段名']:=值、Table1.Field[0].AsString:=值)
        (4)可用Nil對(duì)字段賦空值;
        (5)調(diào)用Post方法將修改后的記錄寫(xiě)入數(shù)據(jù)庫(kù);

      八、插入和刪除記錄
          刪除:移動(dòng)指針到相應(yīng)記錄處,調(diào)用Delete方法;
          插入:調(diào)用Insert、InsertRecord方法(當(dāng)前記錄處插入)或Append、InsertRecord方法(表的末尾插入);

       
       2003-11-25 10:11:12    動(dòng)態(tài)的添加PARADOX表的方法【王寒松】

      下面給出的函數(shù) AddMasterPassword 完成添加PARADOX表主口令的工作
      AddMasterPassword(Table1, 'MyNewPassword')
        procedure AddMasterPassword(Table: TTable; pswd: string);
        const
          RESTRUCTURE_TRUE = WordBool(1);
        var
          TblDesc: CRTblDesc;
          hDb: hDBIDb;
        begin
          {表打開(kāi)?表是獨(dú)占嗎?}
          if (Table.Active = False) or (Table.Exclusive = False) then
            raise EDatabaseError.Create('數(shù)據(jù)表必須在獨(dú)占方式才可以添加口令');
          {初始化表描述區(qū) }
          FillChar(TblDesc, SizeOf(CRTblDesc), 0);
          with TblDesc do
          begin
            { 把表名放到描述區(qū) }
            StrPCopy(szTblName, Table.TableName);
            { 把表類(lèi)型放到描述區(qū) }
            StrCopy(szTblType, szPARADOX);
            StrPCopy(szPassword, pswd);
            { 設(shè)置BPROTECTED為T(mén)RUE }
            bProtected := RESTRUCTURE_TRUE;
          end;
          { 從當(dāng)前的HANDLE里得到DATABASE的HANDLE }
          Check(DbiGetObjFromObj(hDBIObj(Table.Handle), objDATABASE, hDBIObj(hDb)));
          { 關(guān)閉表 }
          Table.Close;
          { 添加主口令到PARADOX表里}
          Check(DbiDoRestructure(hDb, 1, @TblDesc, nil, nil, nil, FALSE));
           {添加一個(gè)新口令到SESSION}
          Session.AddPassword(pswd);
          {重新打開(kāi)表 }
          Table.Open;
        end;
      添加副口令的辦法與此類(lèi)似

       
       2003-11-25 11:21:29    如何選擇一個(gè)好的數(shù)據(jù)庫(kù)【三大數(shù)據(jù)庫(kù)比較】

       
      【開(kāi)放性】

      SQL Server
          只能在windows 上運(yùn)行,沒(méi)有絲毫的開(kāi)放性,操作系統(tǒng)的系統(tǒng)的穩(wěn)定對(duì)數(shù)據(jù)庫(kù)是十分重要的。Windows9X系列產(chǎn)品是偏重于桌面應(yīng)用,NT server只適合中小型企業(yè)。而且windows平臺(tái)的可靠性,安全性和伸縮性是非常有限的。它不象unix那樣久經(jīng)考驗(yàn),尤其是在處理大數(shù)據(jù)量的關(guān)鍵業(yè)務(wù)時(shí).

      Oracle
          能在所有主流平臺(tái)上運(yùn)行(包括 windows)。完全支持所有的工業(yè)標(biāo)準(zhǔn)。采用完全開(kāi)放策略??梢允箍蛻暨x擇最適合的解決方案。對(duì)開(kāi)發(fā)商全力支持。

      DB2
          能在所有主流平臺(tái)上運(yùn)行(包括windows)。最適于海量數(shù)據(jù)。DB2在企業(yè)級(jí)的應(yīng)用最為廣泛,在全球的500家最大的企業(yè)中,幾乎85%以上用DB2數(shù)據(jù)庫(kù)服務(wù)器,而國(guó)內(nèi)到97年約占5%.


      【可伸縮性,并行性】

      SQL server
          并行實(shí)施和共存模型并不成熟。很難處理日益增多的用戶數(shù)和數(shù)據(jù)卷。伸縮性有限。

      Oracle
          平行服務(wù)器通過(guò)使一組結(jié)點(diǎn)共享同一簇中的工作來(lái)擴(kuò)展windownt的能力,提供高可用性和高伸縮性的簇的解決方案。如果windowsNT不能滿足需要, 用戶可以把數(shù)據(jù)庫(kù)移到UNIX中。

      DB2    
          DB2具有很好的并行性。DB2把數(shù)據(jù)庫(kù)管理擴(kuò)充到了并行的、多節(jié)點(diǎn)的環(huán)境.數(shù)據(jù)庫(kù)分區(qū)是數(shù)據(jù)庫(kù)的一部分,包含自己的數(shù)據(jù)、索引、配置文件、和事務(wù)日志。數(shù)據(jù)庫(kù)分區(qū)有時(shí)被稱(chēng)為節(jié)點(diǎn)或數(shù)據(jù)庫(kù)節(jié)點(diǎn)


      【安全性】

      SQL server
          沒(méi)有獲得任何安全證書(shū)。

      Oracle Server
          獲得最高認(rèn)證級(jí)別的ISO標(biāo)準(zhǔn)認(rèn)證。

      DB2
          獲得最高認(rèn)證級(jí)別的ISO標(biāo)準(zhǔn)認(rèn)證。


      【性能】

      SQL Server
          多用戶時(shí)性能不佳

      Oracle
          性能最高, 保持windowsNT下的TPC-D和TPC-C的世界記錄。

      DB2
          適用于數(shù)據(jù)倉(cāng)庫(kù)和在線事物處理,性能較高。


      【客戶端支持及應(yīng)用模式】

      SQL Server
          C/S結(jié)構(gòu),只支持windows客戶,可以用ADO,DAO,OLEDB,ODBC連接.

      Oracle
          多層次網(wǎng)絡(luò)計(jì)算,支持多種工業(yè)標(biāo)準(zhǔn),可以用ODBC,JDBC,OCI等網(wǎng)絡(luò)客戶連接

      DB2
          跨平臺(tái),多層結(jié)構(gòu),支持ODBC,JDBC等客戶


      【操作簡(jiǎn)便】

      SQL Server
          操作簡(jiǎn)單,但只有圖形界面.

      Oracle
          較復(fù)雜, 同時(shí)提供GUI和命令行,在windowsNT和unix下操作相同

      DB2
          操作簡(jiǎn)單,同時(shí)提供GUI和命令行,在windowsNT和unix下操作相同


      【使用風(fēng)險(xiǎn)】

      SQL server
          完全重寫(xiě)的代碼,經(jīng)歷了長(zhǎng)期的測(cè)試,不斷延遲,許多功能需要時(shí)間來(lái)證明。并不十分兼容早期產(chǎn)品。使用需要冒一定風(fēng)險(xiǎn)。

      Oracle
          長(zhǎng)時(shí)間的開(kāi)發(fā)經(jīng)驗(yàn),完全向下兼容。得到廣泛的應(yīng)用。完全沒(méi)有風(fēng)險(xiǎn)。

      DB2
          在巨型企業(yè)得到廣泛的應(yīng)用,向下兼容性好。風(fēng)險(xiǎn)小。

       
       2003-11-25 11:25:37    SQL查詢語(yǔ)句使用

      一、簡(jiǎn)單查詢
          簡(jiǎn)單的Transact-SQL查詢只包括選擇列表、FROM子句和WHERE子句。它們分別說(shuō)明所查詢列、查詢的表或視圖、以及搜索條件等。
          例如,下面的語(yǔ)句查詢testtable表中姓名為“張三”的nickname字段和email字段。
          SELECT nickname,email
          FROM testtable
          WHERE name='張三'

      (一)選擇列表
          選擇列表(select_list)指出所查詢列,它可以是一組列名列表、星號(hào)、表達(dá)式、變量(包括局部變量和全局變量)等構(gòu)成。

          1、選擇所有列
          例如,下面語(yǔ)句顯示testtable表中所有列的數(shù)據(jù):
          SELECT *
          FROM testtable
       
          2、選擇部分列并指定它們的顯示次序
          查詢結(jié)果集合中數(shù)據(jù)的排列順序與選擇列表中所指定的列名排列順序相同。
          例如:
          SELECT nickname,email
          FROM testtable
       
          3、更改列標(biāo)題
          在選擇列表中,可重新指定列標(biāo)題。定義格式為:
          列標(biāo)題=列名
          列名 列標(biāo)題
          如果指定的列標(biāo)題不是標(biāo)準(zhǔn)的標(biāo)識(shí)符格式時(shí),應(yīng)使用引號(hào)定界符,例如,下列語(yǔ)句使用漢字顯示列標(biāo)題:
          SELECT 昵稱(chēng)=nickname,電子郵件=email
          FROM testtable
       
          4、刪除重復(fù)行
          SELECT語(yǔ)句中使用ALL或DISTINCT選項(xiàng)來(lái)顯示表中符合條件的所有行或刪除其中重復(fù)的數(shù)據(jù)行,默認(rèn)為ALL。使用DISTINCT選項(xiàng)時(shí),對(duì)于所有重復(fù)的數(shù)據(jù)行在SELECT返回的結(jié)果集合中只保留一行。
       
          5、限制返回的行數(shù)
          使用TOP n [PERCENT]選項(xiàng)限制返回的數(shù)據(jù)行數(shù),TOP n說(shuō)明返回n行,而TOP n PERCENT時(shí),說(shuō)明n是表示一百分?jǐn)?shù),指定返回的行數(shù)等于總行數(shù)的百分之幾。
          例如:
          SELECT TOP 2 *
          FROM testtable
          SELECT TOP 20 PERCENT *
          FROM testtable

      (二)FROM子句
          FROM子句指定SELECT語(yǔ)句查詢及與查詢相關(guān)的表或視圖。在FROM子句中最多可指定256個(gè)表或視圖,它們之間用逗號(hào)分隔。
          在FROM子句同時(shí)指定多個(gè)表或視圖時(shí),如果選擇列表中存在同名列,這時(shí)應(yīng)使用對(duì)象名限定這些列所屬的表或視圖。例如在usertable和citytable表中同時(shí)存在cityid列,在查詢兩個(gè)表中的cityid時(shí)應(yīng)使用下面語(yǔ)句格式加以限定:

          SELECT username,citytable.cityid
            FROM usertable,citytable
            WHERE usertable.cityid=citytable.cityid
          在FROM子句中可用以下兩種格式為表或視圖指定別名:
          表名 as 別名
          表名 別名

          例如上面語(yǔ)句可用表的別名格式表示為:
          SELECT username,b.cityid
            FROM usertable a,citytable b
            WHERE a.cityid=b.cityid
         
          SELECT不僅能從表或視圖中檢索數(shù)據(jù),它還能夠從其它查詢語(yǔ)句所返回的結(jié)果集合中查詢數(shù)據(jù)。
          例如:
          SELECT a.au_fname+a.au_lname
            FROM authors a,titleauthor ta
              (SELECT title_id,title
                 FROM titles
                 WHERE ytd_sales>10000
              ) AS t
            WHERE a.au_id=ta.au_id
              AND ta.title_id=t.title_id
          此例中,將SELECT返回的結(jié)果集合給予一別名t,然后再?gòu)闹袡z索數(shù)據(jù)。

      (三)使用WHERE子句設(shè)置查詢條件
          WHERE子句設(shè)置查詢條件,過(guò)濾掉不需要的數(shù)據(jù)行。例如下面語(yǔ)句查詢年齡大于20的數(shù)據(jù):
          SELECT *
            FROM usertable
            WHERE age>20
       
          WHERE子句可包括各種條件運(yùn)算符:
          比較運(yùn)算符(大小比較):>、>=、=、<、<=、<>、!>、!<
          范圍運(yùn)算符(表達(dá)式值是否在指定的范圍):BETWEEN…AND…
                                                NOT BETWEEN…AND…
          列表運(yùn)算符(判斷表達(dá)式是否為列表中的指定項(xiàng)):IN (項(xiàng)1,項(xiàng)2……)
                                                      NOT IN (項(xiàng)1,項(xiàng)2……)
          模式匹配符(判斷值是否與指定的字符通配格式相符):LIKE、NOT LIKE
          空值判斷符(判斷表達(dá)式是否為空):IS NULL、NOT IS NULL
          邏輯運(yùn)算符(用于多條件的邏輯連接):NOT、AND、OR
       
          1、范圍運(yùn)算符例:age BETWEEN 10 AND 30相當(dāng)于age>=10 AND age<=30
          2、列表運(yùn)算符例:country IN ('Germany','China')
          3、模式匹配符例:常用于模糊查找,它判斷列值是否與指定的字符串格式相匹配??捎糜赾har、varchar、text、ntext、datetime和smalldatetime等類(lèi)型查詢。
          可使用以下通配字符:
          百分號(hào)%:可匹配任意類(lèi)型和長(zhǎng)度的字符,如果是中文,請(qǐng)使用兩個(gè)百分號(hào)即%%。
          下劃線_:匹配單個(gè)任意字符,它常用來(lái)限制表達(dá)式的字符長(zhǎng)度。
          方括號(hào)[]:指定一個(gè)字符、字符串或范圍,要求所匹配對(duì)象為它們中的任一個(gè)。
          [^]:其取值也[] 相同,但它要求所匹配對(duì)象為指定字符以外的任一個(gè)字符。
       
          例如:
          限制以Publishing結(jié)尾,使用LIKE '%Publishing'
          限制以A開(kāi)頭:LIKE '[A]%'
          限制以A開(kāi)頭外:LIKE '[^A]%'
         
          4、空值判斷符例WHERE age IS NULL
       
          5、邏輯運(yùn)算符:優(yōu)先級(jí)為NOT、AND、OR

      (四)查詢結(jié)果排序
          使用ORDER BY子句對(duì)查詢返回的結(jié)果按一列或多列排序。ORDER BY子句的語(yǔ)法格式為:
          ORDER BY {column_name [ASC|DESC]} [,…n]
          其中ASC表示升序,為默認(rèn)值,DESC為降序。ORDER BY不能按ntext、text和image數(shù)據(jù)類(lèi)型進(jìn)行排序。
          例如:
          SELECT *
            FROM usertable
            ORDER BY age desc,userid ASC
          另外,可以根據(jù)表達(dá)式進(jìn)行排序。

      二、聯(lián)合查詢
          UNION運(yùn)算符可以將兩個(gè)或兩個(gè)以上上SELECT語(yǔ)句的查詢結(jié)果集合合并成一個(gè)結(jié)果集合顯示,即執(zhí)行聯(lián)合查詢。UNION的語(yǔ)法格式為:
          select_statement
            UNION [ALL] selectstatement
              [UNION [ALL] selectstatement][…n]
          其中selectstatement為待聯(lián)合的SELECT查詢語(yǔ)句。
          ALL選項(xiàng)表示將所有行合并到結(jié)果集合中。不指定該項(xiàng)時(shí),被聯(lián)合查詢結(jié)果集合中的重復(fù)行將只保留一行。
          聯(lián)合查詢時(shí),查詢結(jié)果的列標(biāo)題為第一個(gè)查詢語(yǔ)句的列標(biāo)題。因此,要定義列標(biāo)題必須在第一個(gè)查詢語(yǔ)句中定義。要對(duì)聯(lián)合查詢結(jié)果排序時(shí),也必須使用第一查詢語(yǔ)句中的列名、列標(biāo)題或者列序號(hào)。
          在使用UNION 運(yùn)算符時(shí),應(yīng)保證每個(gè)聯(lián)合查詢語(yǔ)句的選擇列表中有相同數(shù)量的表達(dá)式,并且每個(gè)查詢選擇表達(dá)式應(yīng)具有相同的數(shù)據(jù)類(lèi)型,或是可以自動(dòng)將它們轉(zhuǎn)換為相同的數(shù)據(jù)類(lèi)型。在自動(dòng)轉(zhuǎn)換時(shí),對(duì)于數(shù)值類(lèi)型,系統(tǒng)將低精度的數(shù)據(jù)類(lèi)型轉(zhuǎn)換為高精度的數(shù)據(jù)類(lèi)型。
          在包括多個(gè)查詢的UNION語(yǔ)句中,其執(zhí)行順序是自左至右,使用括號(hào)可以改變這一執(zhí)行順序。例如:
          查詢1 UNION (查詢2 UNION 查詢3)

      三、連接查詢
          通過(guò)連接運(yùn)算符可以實(shí)現(xiàn)多個(gè)表查詢。連接是關(guān)系數(shù)據(jù)庫(kù)模型的主要特點(diǎn),也是它區(qū)別于其它類(lèi)型數(shù)據(jù)庫(kù)管理系統(tǒng)的一個(gè)標(biāo)志。
          在關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)中,表建立時(shí)各數(shù)據(jù)之間的關(guān)系不必確定,常把一個(gè)實(shí)體的所有信息存放在一個(gè)表中。當(dāng)檢索數(shù)據(jù)時(shí),通過(guò)連接操作查詢出存放在多個(gè)表中的不同實(shí)體的信息。連接操作給用戶帶來(lái)很大的靈活性,他們可以在任何時(shí)候增加新的數(shù)據(jù)類(lèi)型。為不同實(shí)體創(chuàng)建新的表,爾后通過(guò)連接進(jìn)行查詢。
          連接可以在SELECT 語(yǔ)句的FROM子句或WHERE子句中建立,似是而非在FROM子句中指出連接時(shí)有助于將連接操作與WHERE子句中的搜索條件區(qū)分開(kāi)來(lái)。所以,在Transact-SQL中推薦使用這種方法。
          SQL-92標(biāo)準(zhǔn)所定義的FROM子句的連接語(yǔ)法格式為:
          FROM join_table join_type join_table
            [ON (join_condition)]
          其中join_table指出參與連接操作的表名,連接可以對(duì)同一個(gè)表操作,也可以對(duì)多表操作,對(duì)同一個(gè)表操作的連接又稱(chēng)做自連接。
          join_type 指出連接類(lèi)型,可分為三種:內(nèi)連接、外連接和交叉連接。內(nèi)連接(INNER JOIN)使用比較運(yùn)算符進(jìn)行表間某(些)列數(shù)據(jù)的比較操作,并列出這些表中與連接條件相匹配的數(shù)據(jù)行。根據(jù)所使用的比較方式不同,內(nèi)連接又分為等值連接、自然連接和不等連接三種。
          外連接分為左外連接(LEFT OUTER JOIN或LEFT JOIN)、右外連接(RIGHT OUTER JOIN或RIGHT JOIN)和全外連接(FULL OUTER JOIN或FULL JOIN)三種。與內(nèi)連接不同的是,外連接不只列出與連接條件相匹配的行,而是列出左表(左外連接時(shí))、右表(右外連接時(shí))或兩個(gè)表(全外連接時(shí))中所有符合搜索條件的數(shù)據(jù)行。
          交叉連接(CROSS JOIN)沒(méi)有WHERE 子句,它返回連接表中所有數(shù)據(jù)行的笛卡爾積,其結(jié)果集合中的數(shù)據(jù)行數(shù)等于第一個(gè)表中符合查詢條件的數(shù)據(jù)行數(shù)乘以第二個(gè)表中符合查詢條件的數(shù)據(jù)行數(shù)。
          連接操作中的ON (join_condition) 子句指出連接條件,它由被連接表中的列和比較運(yùn)算符、邏輯運(yùn)算符等構(gòu)成。
          無(wú)論哪種連接都不能對(duì)text、ntext和image數(shù)據(jù)類(lèi)型列進(jìn)行直接連接,但可以對(duì)這三種列進(jìn)行間接連接。例如:
          SELECT p1.pub_id,p2.pub_id,p1.pr_info
            FROM pub_info AS p1 INNER JOIN pub_info AS p2
            ON DATALENGTH(p1.pr_info)=DATALENGTH(p2.pr_info)
       
          (一)內(nèi)連接
          內(nèi)連接查詢操作列出與連接條件匹配的數(shù)據(jù)行,它使用比較運(yùn)算符比較被連接列的列值。內(nèi)連接分三種:
          1、等值連接:在連接條件中使用等于號(hào)(=)運(yùn)算符比較被連接列的列值,其查詢結(jié)果中列出被連接表中的所有列,包括其中的重復(fù)列。
          2、不等連接: 在連接條件使用除等于運(yùn)算符以外的其它比較運(yùn)算符比較被連接的列的列值。這些運(yùn)算符包括>、>=、<=、<、!>、!<和<>。
          3、自然連接:在連接條件中使用等于(=)運(yùn)算符比較被連接列的列值,但它使用選擇列表指出查詢結(jié)果集合中所包括的列,并刪除連接表中的重復(fù)列。
          例,下面使用等值連接列出authors和publishers表中位于同一城市的作者和出版社:
          SELECT *
            FROM authors AS a INNER JOIN publishers AS p
            ON a.city=p.city
       
          又如使用自然連接,在選擇列表中刪除authors 和publishers 表中重復(fù)列(city和state):
          SELECT a.*,p.pub_id,p.pub_name,p.country
            FROM authors AS a INNER JOIN publishers AS p
            ON a.city=p.city
       
          (二)外連接
          內(nèi)連接時(shí),返回查詢結(jié)果集合中的僅是符合查詢條件( WHERE 搜索條件或 HAVING 條件)和連接條件的行。而采用外連接時(shí),它返回到查詢結(jié)果集合中的不僅包含符合連接條件的行,而且還包括左表(左外連接時(shí))、右表(右外連接時(shí))或兩個(gè)邊接表(全外連接)中的所有數(shù)據(jù)行。
          如下面使用左外連接將論壇內(nèi)容和作者信息連接起來(lái):
          SELECT a.*,b.* FROM luntan LEFT JOIN usertable as b
            ON a.username=b.username
       
          下面使用全外連接將city表中的所有作者以及user表中的所有作者,以及他們所在的城市:
          SELECT a.*,b.*
            FROM city as a FULL OUTER JOIN user as b
            ON a.username=b.username
       
          (三)交叉連接
          交叉連接不帶WHERE 子句,它返回被連接的兩個(gè)表所有數(shù)據(jù)行的笛卡爾積,返回到結(jié)果集合中的數(shù)據(jù)行數(shù)等于第一個(gè)表中符合查詢條件的數(shù)據(jù)行數(shù)乘以第二個(gè)表中符合查詢條件的數(shù)據(jù)行數(shù)。
          例,titles表中有6類(lèi)圖書(shū),而publishers表中有8家出版社,則下列交叉連接檢索到的記錄數(shù)將等于6*8=48行。
          SELECT type,pub_name
            FROM titles CROSS JOIN publishers
            ORDER BY type

       
       2003-11-25 11:31:30    SQL Server中Image Data Type的使用技巧 【國(guó)商網(wǎng)絡(luò)有限公司 蔣心武】

         MS SQL Server 是微軟公司推出的大型數(shù)據(jù)庫(kù)軟件,在NT平臺(tái)上擁有近一半的數(shù)據(jù)庫(kù)市場(chǎng),特別是在SQL Server 7.0推出后,其發(fā)展勢(shì)頭更加迅猛。SQL Server中Image數(shù)據(jù)類(lèi)型是用來(lái)存儲(chǔ)圖形的。在此我談?wù)勗鯓釉?、刪、改此類(lèi)型數(shù)據(jù)及在主頁(yè)中讀出此類(lèi)型數(shù)據(jù)。

          一、在表中添加圖形
          Image 數(shù)據(jù)類(lèi)型不同于其它數(shù)據(jù)類(lèi)型,不能用Insert 、Update的標(biāo)準(zhǔn)SQL語(yǔ)法進(jìn)行圖形的添加和修改。需用到SQL Server中的TEXTPTR 、WRITETEXT、UPDATETEXT等函數(shù)進(jìn)行圖形的添加和修改。

          首先假設(shè)在庫(kù)Im_Test中建立一張表Im_Info,此表中有兩個(gè)字段,分別為Pr_Id (INT),Pr_Info (IMAGE),用來(lái)存儲(chǔ)圖形編號(hào)及圖形信息。其語(yǔ)法如下:

       CREATE  TEALE  Im_Info  (
         Pr_Id  INT  NULL  ,
         Pr_Info  IMAGE  NULL
       )

          第一步往表中插入一條記錄,并初始化PR_INFO字段。其語(yǔ)法如下:

       INSERT  INTO  Im_Info  VALUES (1 ,0xFFFFFFFF)

          第二步往表中寫(xiě)入圖形信息。其語(yǔ)法如下:

                DECLARE @@ptrval varbinary(16)
                SELECT @@ptrval = TEXTPTR(Pr_Info)
         FROM Im_Info
           WHERE Pr_Id = 1
                WRITETEXT Im_Text.Im_Info  
                   @@ptrval  0x624fd543fd…..

          其中0x624fd543fd….. 為圖形的十六進(jìn)制數(shù)據(jù),可以通過(guò)C 、Java等工具獲得。注意在寫(xiě)入圖形信息前必須先將此數(shù)據(jù)庫(kù)的 'select into/bulkcopy' 屬性設(shè)置為 True ,其語(yǔ)法如下:

                sp_dboption Im_Test ,
                'select into/bulkcopy' ,True

          若想修改圖形數(shù)據(jù)可用UPDATETEXT函數(shù)修改,其語(yǔ)法如下:

                DECLARE @@ptrval varbinary(16)
                SELECT @@ptrval = TEXTPTR(Pr_Info)
            FROM Im_Info
         WHERE Pr_Id = 1
                UPDATETEXT Im_Text.Im_Info
                @@ptrval  0xaa31bcfe543fd…..

          二、在主頁(yè)中顯示圖形

          第一步建立數(shù)據(jù)源
          若想將加入的圖形顯示在主頁(yè)中,必須先建立數(shù)據(jù)源,打開(kāi)Windows 中的控制面板。通過(guò)ODBC 應(yīng)用程序,建立數(shù)據(jù)源(取名Im_Test)連接到Im_Test數(shù)據(jù)庫(kù)

          第二步編寫(xiě)程序
               < % @ LANGUAGE = VBScript % >
               < % Option Explicit % >
               < %
       Dim oConn    
       Dim oRs    
       Dim Pic    
       Dim PicSize    

       Response.Buffer = TRUE
       Response.ContentType = "image/gif"

       Set oConn = Server.CreateObject ("ADODB.Connection")
       oConn.Open "Im_Test",”sa”,””
       Set oRs = oConn.Execute("SELECT Pr_Info FROM Im_Info WHERE Pr_Id=1”)

       PicSize = oRs("Pr_Info").ActualSize
       Pic = oRs("Pr_Info ").GetChunk(PicSize)
       
       Response.BinaryWrite Pic
       Response.End
               % >

          此程序中先定義四個(gè)變量。然后設(shè)置屬性 Response.Buffer=TRU和Response.ContentType = "image/gif" ,再連接數(shù)據(jù)庫(kù)取出圖形,在加以顯示。  

       
       2003-11-25 11:41:44    深入SQL編程【關(guān)于存儲(chǔ)過(guò)程和索引】

        這里所指的SQL編程并不是那些在象ASP,PHP腳本語(yǔ)言里用的某個(gè)SQL語(yǔ)句,如果你是個(gè)程序員并在做DB C/S開(kāi)發(fā),我想你會(huì)很清楚的知道SQL編程是很復(fù)雜的,先拋開(kāi)嵌入語(yǔ)句,動(dòng)態(tài)執(zhí)行,高級(jí)函數(shù),表達(dá)試等這些不談單就解決性能問(wèn)題就很頭疼,下面就性能問(wèn)題給出一些解決放案.(以下程序均在NT+SP6 SQL SERVER 7下調(diào)試通過(guò))

      一,存儲(chǔ)過(guò)程
          我的一個(gè)朋友用VC/SQL SERVER做C/S項(xiàng)目開(kāi)發(fā),再開(kāi)發(fā)過(guò)程中他的程序雖順利執(zhí)行,但遇到了由于需要大批量插入數(shù)據(jù)而引出的性能問(wèn)題。他找到了我,雖然我沒(méi)有用過(guò)VC但很明顯在他程序中看出是在前臺(tái)用循環(huán)操作象后臺(tái)插入數(shù)據(jù)。這種方法再處理大批量數(shù)時(shí)無(wú)疑是不可取的,因編譯器并不會(huì)處理SQL語(yǔ)句而是通過(guò)ODBC傳輸?shù)胶笈_(tái),再在后臺(tái)解釋執(zhí)行。
          由此可見(jiàn)經(jīng)過(guò)以上幾步性能問(wèn)題以大打折扣,后我將他的程序段改為后臺(tái)SQL編程,用存儲(chǔ)過(guò)程實(shí)現(xiàn)。然后在前臺(tái)用VC調(diào)用,這樣一來(lái)問(wèn)題以得到完美的解決。改后程序如下:(遇到此類(lèi)問(wèn)題的朋友可參考解決)

      CREATE PROC usp_insert_temp
      @iCount VARCHAR(10),
      @Text VARCHAR(50),
      @price VARCHAR(15)

      AS

      DECLARE @iIndex INT
      DECLARE @pMoney FLOAT

      SET @iIndex=CONVERT(INT,@iCount)
      SET @pMoney=CONVERT(FLOAT,@price)

      BEGIN TRAN
      SELECT rygl_id,title,price
      INTO rygl_temp FROM rqk
      WHERE EXISTS
      (SELECT rygl_id
      FROM rygl
      WHERE rqk.rygl_id=rygl.rygl_id
      AND qty<30)
      ORDER BY title_id

      IF @@ERROR<>0
      ROLLBACK TRAN
      ELSE
      COMMIT TRAN

      WHILE @iIndex>0
      BEGIN
      BEGIN TRAN
      SET @pMoney=@pMoney+1.1111
      INSERT INTO rygl_temp(rygl_id,title,price)
      VALUES(@iIndex,@Text,CONVERT(SMALLMONEY,@pMoney))

      IF @@ERROR<>0 OR @@ROWCOUNT=0
      ROLLBACK TRAN
      ELSE
      COMMIT TRAN
      SET @iIndex=@iIndex-1
      END

      二,索引測(cè)試,比較
          合理的索引建立,運(yùn)用可很大幅度提高程序性能,以下是在工作當(dāng)中得出的經(jīng)驗(yàn),與大家共享。

      1,ORDER BY和GROPU BY
          如果用戶經(jīng)常選擇數(shù)據(jù)和使用ORDER BY和GROUP BY短語(yǔ),任何一種索引都有助于SELECT的性能提高。如果用戶選擇的是顧客并按其姓名分類(lèi),兩種索引都能快速檢索數(shù)據(jù)。但下面的一些因素會(huì)使用戶選擇使用某一種索引。

      2,返回范圍內(nèi)的數(shù)據(jù)
          列如,如果擁護(hù)希望返回在SMITH和TALBERT之間的所有顧客姓名,或者返回在日期“11/1/98”和“11/30/98”之間的訂貨量,并且用戶經(jīng)常做這類(lèi)事情,那么最好在該范圍所在的指定列使用聚類(lèi)索引。因聚類(lèi)索引已包含了經(jīng)過(guò)分類(lèi)排序的數(shù)據(jù),這對(duì)于在指定范圍內(nèi)檢索數(shù)據(jù)更為有效。聚類(lèi)索引只需找到要檢索的所有數(shù)據(jù)中的開(kāi)頭和結(jié)尾數(shù)據(jù)即可;而不象非聚類(lèi)索,必須在數(shù)據(jù)層專(zhuān)查找來(lái)字葉層的每一個(gè)數(shù)據(jù)項(xiàng)。

      3,列中有一個(gè)或極少的不同值
          在用戶表中的某些列中喊有極少不同值,列如狀態(tài)列中只包含INACVTIVE,ACVIVE或者TERMINATED。在這種情況下,在該列上使用任何類(lèi)型索引都是不明智的,原因很簡(jiǎn)單:如果用戶表包含了1500行大概有三分之一的行即500行在狀態(tài)列中含有ACTIVE。掃描整個(gè)表,如果不是更高效,至少也是同先在索引頁(yè)面中查找每個(gè)數(shù)據(jù)項(xiàng)而后尋找到包含ACTIVE狀態(tài)的行所在的數(shù)
      據(jù)頁(yè)面也相同的效率。下面這個(gè)列子創(chuàng)建了一個(gè)表,它在有很很多重復(fù)值的列上進(jìn)行索引,而該列具有很少的不同值。運(yùn)行該腳本可能要花幾分鐘。

      */

      DROP TABLE IndexTestTable
      CREATE TABLE IndexTestTable
      (
      Tid INT IDENTITY(1,1) NOT NULL,
      Status CHAR(10) NULL
      )

      GO

      SET IDENTITY_INSERT IndexTestTable ON
      DECLARE @intCount INT

      BEGIN TRAN
      SET @intCount=1
      WHILE @intCount<=1500
      BEGIN
      INSERT IndexTestTable(Tid,Status) VALUES(@intCount,'Active')
      SET @intCount=@intCount+3
      END

      SET @intCount=2
      WHILE @intCount<=1500
      BEGIN
      INSERT IndexTestTable(Tid,Status) VALUES(@intCount,'inactive')
      SET @intCount=@intCount+3
      END

      SET @intCount=3
      WHILE @intCount<=1500
      BEGIN
      INSERT IndexTestTable(Tid,Status) VALUES(@intCount,'Terminated')
      SET @intCount=@intCount+3
      END
      COMMIT TRAN

      SET IDENTITY_INSERT IndexTestTable OFF
      GO

      DUMP TRANSACTION pubs WITH NO_LOG
      GO

      CREATE INDEX inTableUniquesStatus
      ON IndexTestTable(Status)
      GO

      --不用索引查詢
      SELECT *
      FROM IndexTestTable WITH(index(0))
      WHERE Status='inactive'

      --用索引查詢
      SELECT *
      FROM IndexTestTable WITH(index(inTableUniquesStatus))
      WHERE Status='inactive'

      /*

          選中SHOW STATS I/O查看運(yùn)行結(jié)果會(huì)另人吃驚。第一個(gè)SELECT語(yǔ)句引起全表掃描幾乎不需要內(nèi)存操作(因?yàn)橹皇沁M(jìn)行插入,所有所有數(shù)據(jù)都在內(nèi)存中,并不需要進(jìn)行磁盤(pán)或物理讀操作)。第二個(gè)SELECT語(yǔ)句則需要執(zhí)行500個(gè)讀操作,這就證實(shí)了我們所說(shuō)的在這種情況下,使用任何類(lèi)型索引都是不明智的。

      4,
          以上舉列說(shuō)明了在何種情況下不應(yīng)使用索引,現(xiàn)在咱們?cè)俜催^(guò)來(lái)看看當(dāng)索引列中
      不同數(shù)目值增加時(shí)即有較少不同值時(shí)會(huì)怎樣?見(jiàn)如下代碼

      */

      DROP TABLE IndexTestTable
      GO

      CREATE TABLE IndexTestTable
      (
      Tid INT IDENTITY(1,1) NOT NULL,
      Status CHAR(10) NULL,
      Co3 CHAR(20) NOT NULL,
      Co4 CHAR(50) NOT NULL
      )
      GO

      DECLARE @intNum INT
      SET @intNum=0

      BEGIN TRAN
      WHILE @intNum<=1300
      BEGIN
      INSERT indexTestTable
      VALUES(CHAR(@intNum %26 +65),'test3','test4')
      SET @intNum=@intNum+1
      END
      COMMIT TRAN
      GO

      --不用索引查詢
      SELECT * FROM IndexTestTable WHIT(INDEX(0))
      WHERE Status='B'

      --創(chuàng)建聚集索引
      CREATE CLUSTERED INDEX icIndexTestTable
      ON IndexTestTable(Status)
      GO

      --使用索引查詢
      SELECT * FROM IndexTestTable WITH(INDEX(icIndexTestTable))
      WHERE Status='B'

      /*

      5,
          用戶很明顯地能看出,隨著表中行的數(shù)目和列中不同值的增長(zhǎng)。使用索引可以較大幅度提高效率,由此又引出另一個(gè)問(wèn)題,在何種情況下用何種索引更有效?上面列子已經(jīng)介紹了聚類(lèi)索引,大家都能看出在對(duì)于有較少不同植時(shí)使用聚類(lèi)索引是有很大幫助的,但當(dāng)不同值的數(shù)木增加并達(dá)到表中行的樹(shù)木時(shí)則應(yīng)該選非聚類(lèi)索引。此時(shí)使用非聚類(lèi)索在讀操作上和聚類(lèi)似索引并無(wú)
      二異,但在對(duì)表進(jìn)行寫(xiě)操作上的性能卻提高不少,如果用戶經(jīng)常從表中的一個(gè)或少是數(shù)幾個(gè)字段中檢索數(shù)據(jù),當(dāng)非聚集索引包含要檢索的所有字段時(shí)就會(huì)減少所需的讀操作,如果不是那么正如上面第二條所說(shuō)使用非聚集索引通常是鐘很差的選擇,下面這個(gè)列子說(shuō)明了在何時(shí)應(yīng)該使用聚集索引

      */

      DROP TABLE IndexTestTable
      GO

      CREATE TABLE IndexTestTable
      (
      Tid INT IDENTITY(1,1)NOT NULL,
      Status CHAR(20) NOT NULL
      )
      GO

      DECLARE @intCount INT
      SET @intCount=0

      BEGIN TRAN
      WHILE @intCount<=500
      BEGIN
      INSERT INTO IndexTestTable(Status) VALUES('test'+CONVERT(CHAR(6),@intCount))
      SET @intCount=@intCount+1
      END
      COMMIT TRAN
      GO

      --創(chuàng)建聚集索引
      CREATE CLUSTERED INDEX icIndexTestTable
      ON IndexTestTable(Tid)
      GO

      --創(chuàng)建非聚集索引
      CREATE INDEX inIndexTestTable
      ON IndexTestTable(Tid)
      GO

      --使用非聚集索引查詢
      SELECT Tid FROM IndexTestTable WITH(INDEX(inIndexTestTable))
      WHERE Tid BETWEEN 100 AND 500

      --使用聚集索引查詢
      SELECT Tid FROM IndexTestTable WITH(INDEX(icIndexTestTable))
      WHERE Tid BETWEEN 100 AND 500

      /*

          集索引包含絕大多數(shù)的檢索數(shù)據(jù),則只需要讀取很少的數(shù)據(jù)頁(yè)這種情況下非聚集索引要比聚集索引好,如果表的數(shù)據(jù)行很龐大效果會(huì)更加明顯。

      6,
          要說(shuō)明的是,索引雖有助于提高性能但不是索引越多越好,恰好相反過(guò)多的索引會(huì)導(dǎo)致系統(tǒng)低效。用戶在表中每加進(jìn)一個(gè)索引,維護(hù)索引集合就要做相應(yīng)的更新工作。  

       
       2003-11-25 11:49:45    SQL Server日期計(jì)算

         通常,你需要獲得當(dāng)前日期和計(jì)算一些其他的日期,例如,你的程序可能需要判斷一個(gè)月的第一天或者最后一天。你們大部分人大概都知道怎樣把日期進(jìn)行分割(年、月、日等),然后僅僅用分割出來(lái)的年、月、日等放在幾個(gè)函數(shù)中計(jì)算出自己所需要的日期!在這篇文章里,我將告訴你如何使用DATEADD和DATEDIFF函數(shù)來(lái)計(jì)算出在你的程序中可能你要用到的一些不同日期。
      在使用本文中的例子之前,你必須注意以下的問(wèn)題。大部分可能不是所有例子在不同的機(jī)器上執(zhí)行的結(jié)果可能不一樣,這完全由哪一天是一個(gè)星期的第一天這個(gè)設(shè)置決定。第一天(DATEFIRST)設(shè)定決定了你的系統(tǒng)使用哪一天作為一周的第一天。所有以下的例子都是以星期天作為一周的第一天來(lái)建立,也就是第一天設(shè)置為7。假如你的第一天設(shè)置不一樣,你可能需要調(diào)整這些例子,使它和不同的第一天設(shè)置相符合。你可以通過(guò)@@DATEFIRST函數(shù)來(lái)檢查第一天設(shè)置。

          為了理解這些例子,我們先復(fù)習(xí)一下DATEDIFF和DATEADD函數(shù)。DATEDIFF函數(shù)計(jì)算兩個(gè)日期之間的小時(shí)、天、周、月、年等時(shí)間間隔總數(shù)。DATEADD函數(shù)計(jì)算一個(gè)日期通過(guò)給時(shí)間間隔加減來(lái)獲得一個(gè)新的日期。要了解更多的DATEDIFF和DATEADD函數(shù)以及時(shí)間間隔可以閱讀微軟聯(lián)機(jī)幫助。

          使用DATEDIFF和DATEADD函數(shù)來(lái)計(jì)算日期,和本來(lái)從當(dāng)前日期轉(zhuǎn)換到你需要的日期的考慮方法有點(diǎn)不同。你必須從時(shí)間間隔這個(gè)方面來(lái)考慮。比如,從當(dāng)前日期到你要得到的日期之間有多少時(shí)間間隔,或者,從今天到某一天(比如1900-1-1)之間有多少時(shí)間間隔,等等。理解怎樣著眼于時(shí)間間隔有助于你輕松的理解我的不同的日期計(jì)算例子。

      【一個(gè)月的第一天】
          第一個(gè)例子,我將告訴你如何從當(dāng)前日期去這個(gè)月的最后一天。請(qǐng)注意:這個(gè)例子以及這篇文章中的其他例子都將只使用DATEDIFF和DATEADD函數(shù)來(lái)計(jì)算我們想要的日期。每一個(gè)例子都將通過(guò)計(jì)算但前的時(shí)間間隔,然后進(jìn)行加減來(lái)得到想要計(jì)算的日期。

          這是計(jì)算一個(gè)月第一天的SQL 腳本:
           SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)

          我們把這個(gè)語(yǔ)句分開(kāi)來(lái)看看它是如何工作的。最核心的函數(shù)是getdate(),大部分人都知道這個(gè)是返回當(dāng)前的日期和時(shí)間的函數(shù)。下一個(gè)執(zhí)行的函數(shù)DATEDIFF(mm,0,getdate())是計(jì)算當(dāng)前日期和“1900-01-01 00:00:00.000”這個(gè)日期之間的月數(shù)。記?。簳r(shí)期和時(shí)間變量和毫秒一樣是從“1900-01-01 00:00:00.000”開(kāi)始計(jì)算的。這就是為什么你可以在DATEDIFF函數(shù)中指定第一個(gè)時(shí)間表達(dá)式為“0”。下一個(gè)函數(shù)是DATEADD,增加當(dāng)前日期到“1900-01-01”的月數(shù)。通過(guò)增加預(yù)定義的日期“1900-01-01”和當(dāng)前日期的月數(shù),我們可以獲得這個(gè)月的第一天。另外,計(jì)算出來(lái)的日期的時(shí)間部分將會(huì)是“00:00:00.000”。

          這個(gè)計(jì)算的技巧是先計(jì)算當(dāng)前日期到“1900-01-01”的時(shí)間間隔數(shù),然后把它加到“1900-01-01”上來(lái)獲得特殊的日期,這個(gè)技巧可以用來(lái)計(jì)算很多不同的日期。下一個(gè)例子也是用這個(gè)技巧從當(dāng)前日期來(lái)產(chǎn)生不同的日期。

      【本周的星期一】
          這里我是用周(wk)的時(shí)間間隔來(lái)計(jì)算哪一天是本周的星期一。
           SELECT DATEADD(wk, DATEDIFF(wk,0,getdate()), 0)

      【一年的第一天】
          現(xiàn)在用年(yy)的時(shí)間間隔來(lái)顯示這一年的第一天。
           SELECT DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)

      【季度的第一天】
          假如你要計(jì)算這個(gè)季度的第一天,這個(gè)例子告訴你該如何做。
           SELECT DATEADD(qq, DATEDIFF(qq,0,getdate()), 0)

      【當(dāng)天的半夜】
          曾經(jīng)需要通過(guò)getdate()函數(shù)為了返回時(shí)間值截掉時(shí)間部分,就會(huì)考慮到當(dāng)前日期是不是在半夜。假如這樣,這個(gè)例子使用DATEDIFF和DATEADD函數(shù)來(lái)獲得半夜的時(shí)間點(diǎn)。
           SELECT DATEADD(dd, DATEDIFF(dd,0,getdate()), 0)

      【深入DATEDIFF和DATEADD函數(shù)計(jì)算】
          你可以明白,通過(guò)使用簡(jiǎn)單的DATEDIFF和DATEADD函數(shù)計(jì)算,你可以發(fā)現(xiàn)很多不同的可能有意義的日期。

          目前為止的所有例子只是僅僅計(jì)算當(dāng)前的時(shí)間和“1900-01-01”之間的時(shí)間間隔數(shù)量,然后把它加到“1900-01-01”的時(shí)間間隔上來(lái)計(jì)算出日期。假定你修改時(shí)間間隔的數(shù)量,或者使用不同的時(shí)間間隔來(lái)調(diào)用DATEADD函數(shù),或者減去時(shí)間間隔而不是增加,那么通過(guò)這些小的調(diào)整你可以發(fā)現(xiàn)和多不同的日期。

          這里有四個(gè)例子使用另外一個(gè)DATEADD函數(shù)來(lái)計(jì)算最后一天來(lái)分別替換DATEADD函數(shù)前后兩個(gè)時(shí)間間隔。

      【上個(gè)月的最后一天】
          這是一個(gè)計(jì)算上個(gè)月最后一天的例子。它通過(guò)從一個(gè)月的最后一天這個(gè)例子上減去3毫秒來(lái)獲得。有一點(diǎn)要記住,在Sql Server中時(shí)間是精確到3毫秒。這就是為什么我需要減去3毫秒來(lái)獲得我要的日期和時(shí)間。
           SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(mm,0,getdate()), 0))

          計(jì)算出來(lái)的日期的時(shí)間部分包含了一個(gè)Sql Server可以記錄的一天的最后時(shí)刻(“23:59:59:997”)的時(shí)間。

      【去年的最后一天】
          連接上面的例子,為了要得到去年的最后一天,你需要在今年的第一天上減去3毫秒。
           SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0))

      【本月的最后一天】
          現(xiàn)在,為了獲得本月的最后一天,我需要稍微修改一下獲得上個(gè)月的最后一天的語(yǔ)句。修改需要給用DATEDIFF比較當(dāng)前日期和“1900-01-01”返回的時(shí)間間隔上加1。通過(guò)加1個(gè)月,我計(jì)算出下個(gè)月的第一天,然后減去3毫秒,這樣就計(jì)算出了這個(gè)月的最后一天。這是計(jì)算本月最后一天的SQL腳本。
           SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(m,0,getdate())+1, 0))

      【本年的最后一天】
          你現(xiàn)在應(yīng)該掌握這個(gè)的做法,這是計(jì)算本年最后一天腳本
           SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate())+1, 0))。

      【本月的第一個(gè)星期一】
          好了,現(xiàn)在是最后一個(gè)例子。這里我要計(jì)算這個(gè)月的第一個(gè)星期一。這是計(jì)算的腳本。
           select DATEADD(wk, DATEDIFF(wk,0,dateadd(dd,6-datepart(day,getdate()),getdate())), 0)            
          在這個(gè)例子里,我使用了“本周的星期一”的腳本,并作了一點(diǎn)點(diǎn)修改。修改的部分是把原來(lái)腳本中“getdate()”部分替換成計(jì)算本月的第6天,在計(jì)算中用本月的第6天來(lái)替換當(dāng)前日期使得計(jì)算可以獲得這個(gè)月的第一個(gè)星期一。

      【總結(jié)】
          我希望這些例子可以在你用DATEADD和DATEDIFF函數(shù)計(jì)算日期時(shí)給你一點(diǎn)啟發(fā)。通過(guò)使用這個(gè)計(jì)算日期的時(shí)間間隔的數(shù)學(xué)方法,我發(fā)現(xiàn)為了顯示兩個(gè)日期之間間隔的有用歷法是有價(jià)值的。注意,這只是計(jì)算出這些日期的一種方法。要牢記,還有很多方法可以得到相同的計(jì)算結(jié)果。假如你有其他的方法,那很不錯(cuò),要是你沒(méi)有,我希望這些例子可以給你一些啟發(fā),當(dāng)你要用DATEADD和DATEDIFF函數(shù)計(jì)算你程序可能要用到的日期時(shí)。

       
       2003-11-25 12:11:33   

         在數(shù)據(jù)庫(kù)管理系統(tǒng)中,查詢是一項(xiàng)必不可少的功能。查詢功能是直接體現(xiàn)系統(tǒng)功能的一項(xiàng)重要指標(biāo)。查詢的方式主要有以下幾種:1固定字段的單一查詢;2可選擇字段的單一查詢;3限制若干個(gè)字段的多重查詢;4可任意選擇字段的多重查詢。前兩種也稱(chēng)為單條件查詢,后兩種稱(chēng)為多重(或多條件)查詢。在實(shí)際中,系統(tǒng)(實(shí)為程序員)提供給用戶的查詢方式以單條件查詢?yōu)槎?,即使提供了多條件方式,通常也只有兩或三個(gè)條件,因?yàn)榫帉?xiě)多重查詢是一項(xiàng)非常棘手且繁瑣的事情。僅為此,程序員吃盡了苦頭。實(shí)際上,利用表格Grid功能,就能輕松地實(shí)現(xiàn)多重查詢。本人以Delphi為例,介紹具體的實(shí)現(xiàn)方法,但這種思想,也同樣適合于其它的編程語(yǔ)言(如Visual Foxpro)。

          另外,為使程序方便“移植”, 本人把各功能模塊化,使其更具有通用性。

      程序主要按如下三個(gè)功能來(lái)實(shí)現(xiàn):
      ①設(shè)置DBGrid
      ②生成查詢條件(語(yǔ)句)
      ③執(zhí)行查詢

      具體步驟如下:
      ⑴新建一工程文件,取名為PDBGrid.dpr;
      ⑵給單元文件取名為UDBGrid.pas,在其相應(yīng)的表單(取名為frmDBGrid)中添加如下控件并編寫(xiě)相應(yīng)的代碼:

      控件名稱(chēng)
      主要屬性及值
      備注
      Table1
      DataBaseName(MyAlias)
      TableName
      (MyTable1.db)
      Active
      (false)
      查詢對(duì)象:數(shù)據(jù)集
      MyTable1.db為任意的表
      DataSource1
      DataSet(Table1)

      DBGrid1
      DataSource(DataSource1)

      顯示數(shù)據(jù)源
      Table2
      DataBaseName(MyAlias)
      TableName
      (CxComm.db)
      Active
      (false)

      記錄查詢條件的數(shù)據(jù)集
      (CxComm.db結(jié)構(gòu)下述)
      DataSource2
      DataSet(Table2)

      DBGrid2
      DataSource(DataSource2)

      提供查詢處理
      Query1
      DataBaseName(MyAlias)
      Active
      (false)

      保存和執(zhí)行SQL語(yǔ)句的數(shù)據(jù)集
      DataSource3
      DataSet
      (Query 1)

      DGrid3
      DataSource
      (DataSource3)

      顯示查詢結(jié)果
      Memo1
      Lines(<動(dòng)態(tài)賦值>)

      顯示及修改SQL語(yǔ)句
      Button1
      Caption(設(shè)置DBGrid)

      Click事件下述
      Button2
      Caption(生成查詢)

      Click事件下述
      Button3
      Caption(執(zhí)行查詢)

      Click事件下述

      其中
      Table2(記錄查詢條件的數(shù)據(jù)集)對(duì)應(yīng)的表CxComm.db的結(jié)構(gòu)定義如下:

      字段名
      項(xiàng)目
      關(guān)系
      實(shí)例
      邏輯
      類(lèi)型
      A(字符型)
      A(字符型)
      A(字符型)
      A(字符型)
      大小
      14
      5
      10
      6

      表單的FormActivate事件代碼如下:
      procedure TfrmDBGrid.FormActivate(Sender: TObject);
      begin
        if Table2.Active then Table2.Close;
        Table2.EmptyTable; //清空條件
        Table1.Open;
        Table2.Open;
      end;

      Button1(設(shè)置DBGrid)的Click事件代碼如下:
      procedure TfrmDBGrid.Button1Click(Sender: TObject);
      begin
        MySetDBGrid(Table1,DBGrid2); // MySetDBGrid為自定義過(guò)程
                                     //以Table1為數(shù)據(jù)源,DBGrid2為記錄篩選(查詢)條件的表格
      end;

      Button2(生成查詢)的Click事件代碼如下:
      procedure TfrmDBGrid.Button2Click(Sender: TObject);
      begin
        if MyCreate_SQL(Table1,Table2,Query1) //MyCreate_SQL為自定義函數(shù)
                                              //由指定數(shù)據(jù)來(lái)源表來(lái)生成SQL,存入Query1
        then begin
          Memo1.Lines.Clear;
          Memo1.Lines:=(Query1.SQL);
          Memo1.Modified:=false;
        end
      end;

      Button3(執(zhí)行查詢)的Click事件代碼如下:
      procedure TfrmDBGrid.Button3Click(Sender: TObject);
      begin
        with Query1,SQL do
        begin
          Close;
          if Memo1.Modified //用戶可修改SQL語(yǔ)句
          then SQL:=Memo1.Lines;
          try
            ExecSQL;
            Open;
          except //捕捉錯(cuò)誤并處理
            begin
              MessageBeep(0);
              Application.MessageBox('錯(cuò)誤的SQL語(yǔ)句!','確認(rèn)',MB_OK+MB_ICONSTOP);
              Close;
            end;
          end //try
        end;
      end; //執(zhí)行SQL

      自定義過(guò)程MySetDBGrid (設(shè)置DBGrid)的代碼如下:
      procedure TfrmDBGrid.MySetDBGrid(sTable:TTable;tjDBGrid:TDBGrid);
      //參數(shù)說(shuō)明:sTable為數(shù)據(jù)(包括字段,記錄)來(lái)源表
      // tjDBGrid為記錄篩選(查詢)條件的表格
      var i:byte;
      begin
        //設(shè)置查詢項(xiàng)目
        if not sTable.Active then sTable.Open;
        tjDBGrid.Columns[0].PickList.Clear;
        for i:=0 to sTable.FieldCount-1 do //記錄數(shù)(即字段數(shù))
        begin
          tjDBGrid.Columns[0].PickList.Add(sTable.Fields[i].FieldName);
        end; //for
        //設(shè)置關(guān)系(=,<>,>,>=,<,<=) 及邏輯(AND,OR)
        tjDBGrid.Columns[1].PickList.Text:='='+#13+'<>'+#13+'>'+#13+'>='+#13+'<'+#13+'<=';
        tjDBGrid.Columns[3].PickList.Text:='AND'+#13+'OR';
      end;//設(shè)置DBGrid

      自定義函數(shù)MyCreate_SQL (生成查詢)的代碼如下:
      function TfrmDBGrid.MyCreate_SQL(sTable,tjTable:TTable;tjQuery:TQuery):boolean;
      //參數(shù)說(shuō)明:sTable為數(shù)據(jù)(包括字段,記錄)來(lái)源表
      // tjTable為記錄篩選(查詢)條件的表
      // tjQuery記錄SQL語(yǔ)句
      var i:byte;
          lsDate:TDate; //檢測(cè)日期格式用
          sLj,sFilter,sFieldName:string; //分別表示:邏輯關(guān)系,篩選條件,字段名
      begin
        Result:=true;
        //生成"篩選條件"語(yǔ)句
        with tjQuery,SQL do
        begin
          Close;
          Clear;
          DatabaseName:=sTable.DatabaseName; //設(shè)置Query1的別名
          Add('Select * from '''+sTable.TableName+'''');
        end;
        with tjTable do //查詢(篩選)條件表
        begin
          if not Active then Open;
          if IsEmpty
          then begin
            Application.MessageBox('未選擇篩選條件!','確定',MB_OK+MB_ICONEXCLAMATION);
            Exit;
          end;
          tjQuery.SQL.Add(' Where ');//含有篩選條件
          sFilter:=''; //臨時(shí)記錄篩選條件
          First;
          for i:=0 to RecordCount-1 do
          begin
            sLj:=Fields[3].AsString; //邏輯關(guān)系A(chǔ)ND,OR
            //(字段名0>1實(shí)際值2)
            sFilter:=sFilter+'(';
            sFilter:=sFilter+Fields[0].AsString+Fields[1].AsString;
            sFieldName:=Fields[0].AsString; //取第1列的字段名
            case Table1.FieldByName(sFieldName).DataType of ftString:
            begin //字符型處理
              sFilter:=sFilter+''''+Fields[2].AsString+'''' //第2列為關(guān)系
            end;
            ftFloat, //浮點(diǎn)型處理
            ftAutoInc, //自增型
            ftSmallInt, //短整型
            ftInteger, //整型
            ftCurrency: begin //貨幣型
            sFilter:=sFilter+Fields[2].AsString;
          end;
          ftDate:
            begin //日期型處理
              try
                lsDate:=StrToDate(Fields[2].AsString);
                sFilter:=sFilter+''''+FormatDateTime('mm/dd/yyyy',StrToDate(Fields[2].AsString))+'''';
              except
                Application.MessageBox('錯(cuò)誤的日期格式!','確認(rèn)',MB_OK+MB_ICONSTOP);
                Result:=false; //返回錯(cuò)誤標(biāo)志
                break;
              end;//try 日期格式判斷
            end;
            //此處可增加對(duì)其它類(lèi)型數(shù)據(jù)的處理
            end;//case
            sFilter:=sFilter+')';
            if sLj<>''
            then begin
              if RecNo<>RecordCount //且"非最后行"的記錄
              then sFilter:=sFilter+Fields[3].AsString; //And|Or;
            end
            else break;
            Next
          end;
        end; //not IsEmpty(篩選)非空
        tjQuery.SQL.Add(sFilter); //保存查詢條件
      end; //處理篩選條件

      另外,需要進(jìn)行如下說(shuō)明:
      ...
      Type
      ...
      procedure MySetDBGrid(sTable:TTable;tjDBGrid:TDBGrid);
      function MyCreate_SQL(sTable,tjTable:TTable;tjQuery:TQuery):boolean;
      private
      { Private declarations }
      ...

          值得說(shuō)明的是,⑴為從一定程序上簡(jiǎn)化程序,邏輯關(guān)系只提供了AND和OR兩種,但為允許用戶修改SQL語(yǔ)句,如:在多條件之間增加括號(hào)來(lái)改變運(yùn)算順序等,使得查詢功能更加強(qiáng)大,因此增加了Memo控件;⑵在實(shí)際系統(tǒng)中,為方便用戶的操作,可增加幾個(gè)Button(按鈕),功能分別是對(duì)Table2的“增加”、“刪除”,這樣用戶界面會(huì)更友好些。
      利用這種方法來(lái)設(shè)置查詢,條件個(gè)數(shù)是無(wú)限制的,且在屏幕上不會(huì)占據(jù)太大的空間,程序員實(shí)現(xiàn)起來(lái)要簡(jiǎn)單得多了。

      軟件環(huán)境:中文Win98/中文Delphi5.0。

       
       2003-11-25 12:39:56    有關(guān)重復(fù)記錄的刪除

         有兩個(gè)意義上的重復(fù)記錄,一是完全重復(fù)的記錄,也即所有字段均重復(fù)的記錄,二是部分關(guān)鍵字段重復(fù)的記錄,比如Name字段重復(fù),而其他字段不一定重復(fù)或都重復(fù)可以忽略。

      1、對(duì)于第一種重復(fù),比較容易解決,使用
          select distinct * from tableName
      就可以得到無(wú)重復(fù)記錄的結(jié)果集。
         如果該表需要?jiǎng)h除重復(fù)的記錄(重復(fù)記錄保留1條),可以按以下方法刪除
          select distinct * into #Tmp from tableName
          drop table tableName
          select * into tableName from #Tmp
          drop table #Tmp
      發(fā)生這種重復(fù)的原因是表設(shè)計(jì)不周產(chǎn)生的,增加唯一索引列即可解決。

      2、這類(lèi)重復(fù)問(wèn)題通常要求保留重復(fù)記錄中的第一條記錄,操作方法如下假設(shè)有重復(fù)的字段為Name,Address,要求得到這兩個(gè)字段唯一的結(jié)果集
          select identity(int,1,1) as autoID, * into #Tmp from tableName
          select min(autoID) as autoID into #Tmp2 from #Tmp group by Name,autoID
          select * from #Tmp where autoID in(select autoID from #tmp2)
      最后一個(gè)select即得到了Name,Address不重復(fù)的結(jié)果集(但多了一個(gè)autoID字段,實(shí)際寫(xiě)時(shí)可以寫(xiě)在select子句中省去此列)

       
       2003-11-25 13:15:26    SQL SERVER 2000 數(shù)據(jù)庫(kù)備份與恢復(fù)單元

      unit BackRestoreSQLDB;
      {描述:SQL SERVER 2000 數(shù)據(jù)庫(kù)備份與恢復(fù)單元 ,本單元函數(shù)在SQL SERVER 2000 +Delphi7.0編譯通過(guò)
       時(shí)間:2003.09.15
       作者:chenshaizi
      }
      interface

      uses
        adodb, db;
      function repl_substr(sub_old, sub_new, s: string): string; //把sub_old換成sub_new,后面有用。
      function BackupSQLDataBase(connstr_sql, DatabaseName, Backup_FileName: string): Boolean; //數(shù)據(jù)庫(kù)備份函數(shù)
      //SQL數(shù)據(jù)數(shù)據(jù)庫(kù)備份,connstr_sql是ADO控件的connectionstring,DatabaseName是數(shù)據(jù)庫(kù)名稱(chēng),
      //Backup_FileName要備份到的目 標(biāo)文件
      function RestoreSQLDataBase(connstr_sql, DatabaseName, Restore_FileName: string): Boolean; //數(shù)據(jù)庫(kù)恢復(fù)函數(shù)
      //Restore_FileName以前備份的數(shù)據(jù)庫(kù)文件,
      implementation

      function repl_substr(sub_old, sub_new, s: string): string;
      var
        i: integer;
      begin
        repeat
          i := pos(sub_old, s);
          if i > 0 then
          begin
            delete(s, i, Length(sub_old));
            insert(sub_new, s, i);
          end;
        until i < 1;
        Result := s;
      end;

      function BackupSQLDataBase(connstr_sql, DatabaseName, Backup_FileName: string): Boolean;
      var
      //備份SQL數(shù)據(jù)庫(kù)SQL數(shù)據(jù)數(shù)據(jù)庫(kù)備份,connstr_sql是ADO控件的connectionstring,DatabaseName是數(shù)據(jù)庫(kù)名稱(chēng),
      //Backup_FileName要備份到的目標(biāo)文件
        aADOQuery: TADOQuery;
      begin
        try
          aADOQuery := TADOQuery.Create(nil);
          aADOQuery.Close;
          aADOQuery.ConnectionString := connstr_sql;
          aADOQuery.SQL.Clear;
          aADOQuery.SQL.Add('backup database ' + DatabaseName + ' to disk = ' + '''' + Backup_FileName + ''' with format');
          try
            aADOQuery.ExecSQL;
            Result := true;
          except
            Result := false;
            exit;
          end;
        finally
          aADOQuery.Free;
        end;
      end;

      function RestoreSQLDataBase(connstr_sql, DatabaseName, Restore_FileName: string): Boolean;
      var //數(shù)據(jù)庫(kù)恢復(fù)函數(shù),estore_FileName以前備份的數(shù)據(jù)庫(kù)文件
        aADOQuery: TADOQuery;
      begin
        try
          aADOQuery := TADOQuery.Create(nil);
          aADOQuery.Close; //恢復(fù)數(shù)據(jù)庫(kù)不能打開(kāi)數(shù)據(jù)庫(kù),要打開(kāi)系統(tǒng)數(shù)據(jù)庫(kù)master,把連接字符串如adoconnetion的connectionstring中的數(shù)據(jù)庫(kù)名稱(chēng)換成"master"數(shù)據(jù)庫(kù)
          aADOQuery.ConnectionString := repl_substr(DatabaseName, 'master', connstr_sql);
          aADOQuery.SQL.Clear;
          aADOQuery.SQL.Add('RESTORE DATABASE ' + DatabaseName + ' from disk = ' + '''' + Restore_FileName + '''');
          try
            aADOQuery.ExecSQL;
            Result := true;
          except
            Result := false;
            exit;
          end;
        finally
          aADOQuery.Free;
        end;
      end;
      end.

       
       2003-11-25 13:17:15    不用控件,通過(guò)ADO對(duì)象連接sqlserver數(shù)據(jù)庫(kù)

      關(guān)鍵詞:ADO連接sqlserver數(shù)據(jù)庫(kù)
       
      uses
       Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls,comobj, Db, ADODB;

      //要伸明comobj  下面為連接代碼:

      var
        adoc,ador:variant;
      begin
        adoc:=createoleobject('adodb.connection');
        adoc.open('Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=customer;Data Source=BERN');
        ador:=createoleobject('adodb.recordset');
        ador.activeconnection:=adoc;
        ador.CursorType:=ctDynamic;
        ador.open('select * from t_customer',adoc);  
      end;

       
       2003-11-25 13:28:58    存取JPEG文件到SQLSERVER數(shù)據(jù)庫(kù)【王大川(WDCZZH)】

      【關(guān)鍵詞】:JPEG圖片圖像數(shù)據(jù)庫(kù)  
          最近在CSDN上看到兩篇關(guān)于《DELPHI中存取JPEG文件到SQLSERVER》中的文章之后,覺(jué)得其中講述的方法雖然有可取之處,但頗費(fèi)時(shí),我這里有更簡(jiǎn)單的操作方法,而且安全可靠,不敢一人獨(dú)享,愿發(fā)布出來(lái)與大家共享。在Delphi7.0+Win2000+SqlServer 2000中測(cè)試通過(guò),運(yùn)行良好,現(xiàn)將思路、源碼公開(kāi)如下:

      【解決思路】:
      1、 關(guān)鍵在于將打開(kāi)的JPEG文件動(dòng)態(tài)轉(zhuǎn)換為T(mén)bitmap對(duì)象并顯示在Timage對(duì)象中;
      2、 將顯示的圖片提交到數(shù)據(jù)庫(kù)中。

      本例中在SQLSERVER2000中建立了一個(gè)試?yán)恚篹xam(xm char(10),photo image);
      程序源代碼:

      unit SavePic;

      interface

      uses
        Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, ExtDlgs, ExtCtrls, DBCtrls, Grids, DBGrids, DB, ADODB, Buttons,  StdCtrls,Jpeg;

      type
        TForm1 = class(TForm)
          SpeedButton1: TSpeedButton;
          ADOConnection1: TADOConnection;
          Table1: TADOTable;
          DataSource1: TDataSource;
          DBGrid1: TDBGrid;
          DBImage1: TDBImage;
          Image1: TImage;
          SpeedButton2: TSpeedButton;
          OpenPictureDialog1: TOpenPictureDialog;
          Label1: TLabel;
          Label2: TLabel;
          Edit1: TEdit;
          SpeedButton3: TSpeedButton;
          procedure SpeedButton2Click(Sender: TObject);
          procedure SpeedButton1Click(Sender: TObject);
          procedure SpeedButton3Click(Sender: TObject);
        private
          { Private declarations }
        public
          { Public declarations }
        end;

      var
        Form1: TForm1;

      implementation

      {$R *.dfm}

      procedure TForm1.SpeedButton2Click(Sender: TObject);
      var
        bmp1:TBitmap;
        jpg1:TJpegImage;
      begin
        OpenPictureDialog1.DefaultExt:=GraphicExtension(TJpegimage);
        if OpenPictureDialog1.Execute then
        begin
          bmp1:=TBitmap.Create;
          jpg1:=TJpegImage.Create;
          try
            jpg1.LoadFromFile(OpenPictureDialog1.FileName);
            bmp1.Assign(jpg1);
            Image1.Picture.Bitmap.Assign(bmp1);
          finally
            jpg1.Free;
            bmp1.Free;
          end;
        end;
      end;

      procedure TForm1.SpeedButton1Click(Sender: TObject);
      begin
        table1.Open;
        table1.insert;
        table1.fieldbyname('xm').asstring:=Edit1.Text;
        table1.FieldByName('photo').Assign(Image1.Picture);
        table1.post;
        table1.Refresh;
      end;

      end.

          以上就是將JPEG存取到SQLSERVER中的操作方法,本文在此僅是拋磚引玉,希望各位朋友舉一反三想出更多、更好、更實(shí)用的應(yīng)用技術(shù)。
       
      另外原來(lái)那兩篇《DELPHI中存取JPEG文件到SQLSERVER》暫時(shí)沒(méi)有找到。。。

       
       2003-11-25 16:41:42    多個(gè) Edit 的 SQL 查詢

      問(wèn):關(guān)于判斷的問(wèn)題:假如在form1里有Edit1、Edit2和Edit3,如果是查詢,有7種情況:
      (1)、當(dāng)Edit1不為空,而其它兩個(gè)為空:
      with query1 do
      begin
        close;
        sql.clear;
        sql.add('select * from fstao where field1=:field1');
        Parambyname('field1').AsString:=Edit1.text;
        Open;
      end;
      (2)、當(dāng)Edit2不為空,而其它兩個(gè)為空:
      with query1 do
      begin
        close;
        sql.clear;
        sql.add('select * from fstao where field2=:field2');
        Parambyname('field2').AsString:=Edit2.text;
        Open;
      end;
      (3)、當(dāng)Edit3不為空,而其它兩個(gè)為空:
      with query1 do
      begin
        close;
        sql.clear;
        sql.add('select * from fstao where field3=:field3');
        Parambyname('field3').AsString:=Edit3.text;
        Open;
      end;
      (4)、當(dāng)Edit1和Edit2不為空,Edit3為空:
      with query1 do
      begin
        close;
        sql.clear;
        sql.add('select * from fstao where field1=:field1 and field2=:field2');
        Parambyname('field1').AsString:=Edit1.text;
        Parambyname('field2').AsString:=Edit2.text;
        Open;
      end;
      (5)、當(dāng)Edit1和Edit3不為空,Edit2為空:
      with query1 do
      begin
        close;
        sql.clear;
        sql.add('select * from fstao where field1=:field1 and field3=:field3');
        Parambyname('field1').AsString:=Edit1.text;
        Parambyname('field3').AsString:=Edit2.text;
        Open;
      end;
      (6)、當(dāng)Edit2和Edit3不為空,Edit1為空:
      with query1 do
      begin
        close;
        sql.clear;
        sql.add('select * from fstao where field2=:field2 and field3=:field3');
        Parambyname('field2').AsString:=Edit1.text;
        Parambyname('field3').AsString:=Edit2.text;
        Open;
      end;
      (7)、當(dāng)Edit1、Edit2和Edit3都不為空:
      with query1 do
      begin
        close;
        sql.clear;
        sql.add('select * from fstao where field1=:field1 and field2=:field2 and
      field3=:field3');
        Parambyname('field2').AsString:=Edit1.text;
        Parambyname('field3').AsString:=Edit2.text;
        Parambyname('field1').AsString:=Edit2.text;
        Open;
      end;
          編程的時(shí)候,那么就逐個(gè)逐個(gè)判斷,有3個(gè)Edit就有7種情況,那么4個(gè)、5個(gè)Edit時(shí),那么分別有14種和25種情況,那就很麻煩,如果是逐個(gè)判斷的話那么就得寫(xiě)一兩萬(wàn)行代碼,而且很煩。我想請(qǐng)教有沒(méi)有更好的方法,比如自由判斷。數(shù)據(jù)庫(kù)為Oracle8。
      【答1】:你可以這樣做:
      query1.sql.add (' select * from table1 where ');
      if edit1.text<>'' then
      begin
        query1.sql.add ('field1:field1');
        Parambyname('field1').AsString:=Edit1.text;
      end;
      .......
      if edit9.text<>'' then
      begin
        query1.sql.add ('field9:field9');
        Parambyname('field9').AsString:=Edit9.text;
      end;
      ..............

      【答2】:我是這么干的:
      var
        SQLCondition:string;
        FirstConjunction:string;
      begin
        FirstConjunction := 'WHERE ';
        if Edit1.Text <> '' then
        begin
          SQLCondition := FirstConjunction + '(FieldName1="'+Edit1.Text + '")';
          FirstConjunction := 'AND ';
        end;
        if Edit2.Text <> '' then begin
          SQLCondition := FirstConjunction + '(FieldName2="'+Edit2.Text + '")';
          FirstConjunction := 'AND ';
        end;

      .......

        if Editn.Text <> '' then
        begin
          SQLCondition := FirstConjunction + '(FieldNamen="'+Editn.Text + '")';
          FirstConjunction := 'AND ';
        end;
        sql.clear;
        sql.Add('SELECT * FROM DATABASE');
        sql.Add(SQLCondition);
        open;

      【答3】:用不著這么麻煩吧...
      我是這么干的:
      begin
        sql.clear;
        sql.Add('SELECT * FROM DATABASE');
        if Edit1.Text <> '' then
          sql.Add('(FieldName1="'+Edit1.Text + '") and ';
        if Edit2.Text <> '' then
          sql.Add('(FieldName2="'+Edit2.Text + '")
      and ';

      .......

        if Edit9.Text <> ''
        then
          sql.Add('(FieldName9="'+Edit9.Text + '") and ';
        if Pos(sql.Lines[1],'and')>0
        then
          Delete(sql.Lines[1],Length(sql.Lines[1]-4),3);
        open;
      end;  

       
       2003-11-25 16:51:16    從 Foxpro 到 SQL Server 的數(shù)據(jù)轉(zhuǎn)移方法

         在計(jì)算機(jī)應(yīng)用系統(tǒng)的軟件升級(jí)改造過(guò)程中,我們經(jīng)常遇到這樣一個(gè)問(wèn)題:老系統(tǒng)的數(shù)據(jù)庫(kù)平臺(tái)與新系統(tǒng)不同。例如,老系統(tǒng)的數(shù)據(jù)庫(kù)平臺(tái)是 Foxpro, 而新系統(tǒng)的平臺(tái)是 SQL Server。 而且,我們需要把舊的數(shù)據(jù)庫(kù)應(yīng)用系統(tǒng)中的一些數(shù)據(jù)轉(zhuǎn)移到新系統(tǒng)來(lái)。但是因?yàn)樾吕舷到y(tǒng)在定義數(shù)據(jù)類(lèi)型、數(shù)據(jù)格式等方面的差異,就很難用人工錄入的方法來(lái)實(shí)現(xiàn)。因此,需要有一個(gè)能實(shí)現(xiàn)這種功能的程序。

          本文利用 Borland Delphi 實(shí)現(xiàn)了這個(gè)轉(zhuǎn)移過(guò)程。

          基本思想是:在一個(gè) Form 中,分別用兩個(gè) TDatabase 控件連接新老數(shù)據(jù)庫(kù)。并采用TTable、TDbGrid 作為數(shù)據(jù)轉(zhuǎn)移的中心,根據(jù) DbGrid 中的數(shù)據(jù)生成標(biāo)準(zhǔn)的 SQL 插入語(yǔ)句。這樣,就實(shí)現(xiàn)了從一個(gè)數(shù)據(jù)庫(kù)系統(tǒng)到另一個(gè)數(shù)據(jù)庫(kù)系統(tǒng)的數(shù)據(jù)轉(zhuǎn)移。在這里,采用 TTable、TDbGrid 作為數(shù)據(jù)轉(zhuǎn)移的中心是一個(gè)技巧,因?yàn)椋篢Table 的 Fields 屬性能指示出某字段的字段名稱(chēng)、數(shù)據(jù)類(lèi)型等,這為數(shù)據(jù)轉(zhuǎn)移過(guò)程中的 Insert 語(yǔ)句的生成及數(shù)據(jù)類(lèi)型轉(zhuǎn)換提供了依。

          下面的例子展示了從 Foxpro 到 SQL Server 的數(shù)據(jù)轉(zhuǎn)移方法。至于其他系統(tǒng)間的數(shù)據(jù)轉(zhuǎn)移,只要根據(jù)目標(biāo)系統(tǒng)的數(shù)據(jù)定義要求,修改相應(yīng)的 Insert 語(yǔ)句。

      ---- 程 序 代 碼 如 下:

      unit ConvertDBF;

      interface

      uses
       Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DBTables, Db, Grids, DBGrids;

      type
       TfrmConvertDB = class(TForm)
        btnOK: TButton;
        Label1: TLabel;
        db1: TDatabase;  {用于連接老數(shù)據(jù)庫(kù)系統(tǒng)}
        db2: TDatabase;  {用于連接新數(shù)據(jù)庫(kù)系統(tǒng)}
        dbg: TDBGrid;
        tblSource: TTable; {dbg的Datasource}
        qryInsert: TQuery;
         {用于存放生成的SQL Insert語(yǔ)句}
        srcSource: TDataSource;
        tblDest: TTable; {DBGrid1的Datasource}
        DBGrid1: TDBGrid;
        srcDest: TDataSource;
        edFromtbl: TEdit;
        Label2: TLabel;
        Label3: TLabel;
        edToTbl: TEdit;
        procedure btnOKClick(Sender: TObject);
       private
        { Private declarations }
       public
        { Public declarations }
       end;

      var
       frmConvertDB: TfrmConvertDB;

      implementation

      {$R *.DFM}

      procedure TfrmConvertDB.btnOKClick
       (Sender: TObject);
      var iField :integer;
      begin
       if ((edTotbl.text<>'') and (edFromtbl.text<>''))then begin
         tblSource.TableName:=edFromtbl.text;
                {指定TableName}
         tblDest.TableName:=edTotbl.text;
         with tblSource do begin
           Open; {打開(kāi)老系統(tǒng)的表}
           while EOF=FALSE do begin
             {逐條記錄處理}
             qryInsert.SQL.Clear;
             qryInsert.sql.Add('Insert into '+edTotbl.text + '(');
             for iField:=0 to dbg.FieldCount-1 do begin
               qryInsert.sql.add(dbg.Fields[iField].DisplayLabel);
               if iField<>dbg.FieldCount-1 then
                 qryInsert.sql.add(',');
             end;
             qryInsert.sql.add(') values(');
             for iField:=0 to dbg.FieldCount-1 do begin
          {進(jìn)行數(shù)據(jù)類(lèi)型轉(zhuǎn)換}
               if dbg.fields[iField].DataType=ftInteger then
                 qryInsert.sql.add(inttostr(dbg.fields[iField].asInteger));
               if dbg.fields[iField].DataType=ftFloat then
                 qryInsert.sql.add(floattostr(dbg.fields[iField].asFloat));
               if dbg.fields[iField].DataType=ftDate then
                 qryInsert.sql.add(''''+datetostr(dbg.fields[iField].asDateTime)+'''');
               if dbg.fields[iField].DataType=ftString then begin
                 if dbg.fields[iField].asString<>'' then
                   qryInsert.sql.add(''''+dbg.fields[iField].asString+'''')
                 else
                   qryInsert.sql.add('NULL');
               end;
               if iField<>dbg.FieldCount-1
               then qryInsert.sql.add(',');
             end;
             qryInsert.sql.add(')');
             qryInsert.ExecSQL;
                    {把數(shù)據(jù)插入到新系統(tǒng)的表中}
             next;
           end;
         end;
         tblDest.Close;
         tblDest.Open;;
         ShowMessage('  轉(zhuǎn)換完畢!   ');
       end
       else
        ShowMessage
        ('請(qǐng)輸入要插入數(shù)據(jù)的表的名稱(chēng)   ');
      end;

      end.

       
       2003-11-25 17:01:50    Delphi數(shù)據(jù)集過(guò)濾技巧

         當(dāng)我們?cè)诓僮鲾?shù)據(jù)集時(shí),往往需要對(duì)數(shù)據(jù)進(jìn)行篩選。例如:一個(gè)名為Customer的數(shù)據(jù)表,它具有 CustNo、CustName、Country、Address、Phone、State、TaxRate 等字段,如果只想查看國(guó)別為China或顧客號(hào)大于1000的顧客記錄,就需要對(duì)數(shù)據(jù)集進(jìn)行過(guò)濾。經(jīng)總結(jié),有下面這些過(guò)濾方法:

        一、利用Ttable和Tquery的Filter屬性
        1.在設(shè)計(jì)時(shí)設(shè)置Filter屬性
        例如,設(shè)置Filter為:Country=′China′
        然后改變Filtered屬性為T(mén)rue(注意,F(xiàn)iltered為T(mén)rue時(shí)過(guò)濾才有效)。則只能看到對(duì)應(yīng)的
      Country字段內(nèi)容為‘China’的記錄。
        設(shè)置Filter時(shí)可以使用的操作符有:<、>、<=、>=、=、<>、AND、OR、NOT。
        例如,設(shè)置Filter為:CustNo>=1000 and CustNo<=5000,則只能看到顧客號(hào)在1000與5000之間的顧客記錄。
        2.在程序運(yùn)行期間進(jìn)行動(dòng)態(tài)過(guò)濾
        要在程序運(yùn)行時(shí)改變Filter屬性,這包括兩種情況:
        (1)操作符右邊為常量,例如:
        Table1Filter:=′State′+′=′+′′′HI′′′;
        注意:字符串常量必須用三對(duì)單引號(hào)括起來(lái)。
        (2)操作符右邊不為常量,可能是通過(guò)一個(gè)變量指定的值,或由一輸入框給出的值。這時(shí)需要用到Format函數(shù)。其代碼形式為:
        Table1Filter:=Format(′State′+′=′+′′′%S′′′,[StateValue]);
        其中StateValue為已經(jīng)賦值的一個(gè)字符串變量,也可以為其他形式,例如:Edit1Text。

        二、用ApplyRange篩選數(shù)據(jù)集的記錄
        執(zhí)行下面這段代碼,將只能看到顧客號(hào)在1000至5000之間的顧客記錄。組成該例程的幾個(gè)過(guò)
      程為:ApplyRange,SetRangeStart,SetRangeEnd。
        Table1SetRangeStart;
        Table1[′CustNo′]:=1000;
        Table1SetRangeEnd;
        Table1[′CustNo′]:=5000;
        Table1ApplyRange;
        注意:該過(guò)程只適用于索引的字段。如果想基于非索引字段篩選,則不妨使用一點(diǎn)小花招:
      建立假索引。實(shí)現(xiàn)的方法為:
        Table1IndexFieldNames:=字段名;
        Delphi還提供了簡(jiǎn)單的調(diào)用SetRangeStart、SetRangeEnd和ApplyRange的方法,例如:Table1SetRange([Edit1Text],[Edit2Text]);

        三、用OnFilterRecord事件篩選
        OnFilterRecord事件允許按非鍵控字段建立篩選程序,例如:
        procedure TForm1Table1FilterRecord(DataSet:TDataSet;var Accept:Boolean);
        begin
        Accept:=DataSet[′State′]=′CA′;
        end;

        四、用Tquery控件的SQL語(yǔ)句
        1.SQL語(yǔ)句中不包含變量和參數(shù)
        Select*from Customer
        Where CustNo>=1000 and CustNo<=5000
        2.SQL語(yǔ)句中包含參數(shù)
        Select*from Customer
        Where CustNo>=:CustNo
        在運(yùn)行期間給參數(shù)CustNo賦值。
        3.SQL語(yǔ)句中包含變量
        這時(shí)向Tquery控件添加SQL語(yǔ)句的代碼應(yīng)當(dāng)這樣寫(xiě):
        Query1Close;
        Query1SQLClear;
        Query1SQLAdd(Format(′Select*from Customer′+′′+′ where State=′+′′′%S′′′,[StateValue]));
        Query1O(jiān)pen;
        在上面的四種方法中,第四種功能最強(qiáng)大,使用最靈活。  

       
       2003-11-25 17:06:12    建立臨時(shí)表

        數(shù)據(jù)輸入是開(kāi)發(fā)數(shù)據(jù)庫(kù)程序的必然環(huán)節(jié)。在Client/Server結(jié)構(gòu)中,客戶端可能要輸入一批數(shù)據(jù)后,再向服務(wù)器的后臺(tái)數(shù)據(jù)庫(kù)提交,這就需要在本地(客戶端)建立臨時(shí)數(shù)據(jù)表來(lái)存儲(chǔ)用戶輸入的數(shù)據(jù),待提交后,清除本地表數(shù)據(jù)。這種方法的好處是:提高輸入效率,減小網(wǎng)絡(luò)負(fù)擔(dān)。
       
         由于用戶一次輸入的數(shù)據(jù)量一般情況下較?。ú粫?huì)超過(guò)幾百條記錄),所以臨時(shí)表可以建立
      在內(nèi)存中,這樣處理速度較快。

        方法1:使用查詢控件(TQuery)
        第1步:在窗體上放上查詢控件(TQuery),設(shè)置好所連接的數(shù)據(jù)表。
        第2步:使TQuery. CachedUpdates=True;
             TQuery. RequestLive=True
        第3步:在原有的SQL語(yǔ)句后加入一條Where子語(yǔ)句,要求加入這條Where子語(yǔ)句后SQL查詢結(jié)果為空。
        例如:

        SELECT Biolife.″Species No″, Category, Common_Name, Biolife.″Species Name″,
      Biolife.″Length (cm)″, Length_In, Notes, Graphic
        FROM ″biolife.db″ Biolife
        where Biolife.Category=′A′ and Biolife.Category=′B′

        這樣臨時(shí)表就建立完成了。

        方法2:使用代碼創(chuàng)建臨時(shí)表
        代碼如下:

        function CreateTableInMemory(const AFieldDefs:TFieldDefs):
        TDataSet;
        var TempTable:TClientDataSet;
        begin
         TempTable:=nil;
         Result:=nil;
         if AFieldDefs<>nil then
         begin
          try
           TempTable:=TClientDataSet.Create(Application);
           TempTable.FieldDefs.Assign(AFieldDefs);
           TempTable.CreateDataSet;
           Result:=(TempTable as TDataSet);
          Except
           if TempTable<>nil then TempTable.Free;
           Result:=nil;
           raise;
          end
         end
        end;

        在程序中按如下方法使用:

        procedure TForm1.Button1Click(Sender: TObject);
        var ADataSet:TDataSet;
        begin
         ADataSet:=TDataSet.Create(Self);
         with ADataSet.FieldDefs do
         begin
           Add(′Name′,ftString,30,False);
           Add(′Value′,ftInteger,0,False);
         end;
         with DataSource1 do
         begin
           DataSet:=CreateTableInMemory(ADataSet.FieldDefs);
           DataSet.Open;
         end;
         ADataSet.Free;
        end;

        臨時(shí)表創(chuàng)建完成。

        方法1使用簡(jiǎn)單,但由于利用查詢控件,清空數(shù)據(jù)時(shí)需要查詢服務(wù)器后臺(tái)數(shù)據(jù)庫(kù),所以速度稍慢,而且不適用于臨時(shí)表中各個(gè)字段由數(shù)個(gè)數(shù)據(jù)表的字段拼湊而成的情況。方法2適用范圍廣、速度快,但需要編寫(xiě)代碼。(代碼中TFieldDefs的使用方法十分簡(jiǎn)單,見(jiàn)Delphi的聯(lián)機(jī)幫助)。  

       
       2003-11-25 17:08:31    Delphi中多庫(kù)關(guān)聯(lián)查詢

        在我們對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作時(shí),經(jīng)常用到TTable控件,但TTable只能同時(shí)對(duì)一個(gè)數(shù)據(jù)表進(jìn)行操
      作,而TQuery控件不僅具有TTable的多數(shù)功能,而且同時(shí)可對(duì)多個(gè)數(shù)據(jù)表進(jìn)行操作。不僅如此,
      TQuery控件還有更強(qiáng)大的數(shù)據(jù)庫(kù)查詢功能,可以同時(shí)對(duì)多個(gè)不同結(jié)構(gòu)的數(shù)據(jù)庫(kù)進(jìn)行關(guān)聯(lián)查詢,被
      查詢的數(shù)據(jù)庫(kù)可以是ODBC支持的任何一種類(lèi)型,當(dāng)然計(jì)算機(jī)中必須先安裝ODBC和BDC(Delphi的數(shù)
      據(jù)庫(kù)引擎),現(xiàn)舉例說(shuō)明。

        一、連接Paradox和dBASE進(jìn)行異庫(kù)查詢
        例如:Master.db和Customer.dbf分別為Paradox和dBASE的數(shù)據(jù)庫(kù),它們有一個(gè)公共字段
      CustNo。這時(shí)可輸入如下代碼:
        Query1.Close;
        Query1.DataBaseName:=′′;
        Query1.SQL.Clear;
        Query1.SQL.Add(′Select * from ″Master.db″ A,″Customer.dbf ″ B Where
      A.CustNo=B.CustNo′);{在同一行內(nèi)輸入}
        Query1.Open;
        注意:進(jìn)行多庫(kù)聯(lián)查時(shí),TQuery控件的DataBaseName屬性必須先置空,單引號(hào)內(nèi)不包含任何
      字符;A和B分別是Master.db和Customer.dbf的別名(引用別名可減少代碼長(zhǎng)度)。

        二、MS Access的多表聯(lián)查
        Access數(shù)據(jù)庫(kù)屬于多表集合數(shù)據(jù)庫(kù)(一個(gè)數(shù)據(jù)庫(kù)中包含多個(gè)數(shù)據(jù)表),所以,對(duì)兩個(gè)Access數(shù)
      據(jù)庫(kù)進(jìn)行查詢的方法就與上述有所不同。例如:我們有RSDA.mdb和ZFGjj.mdb兩個(gè)數(shù)據(jù)庫(kù),RSDA中包含人事檔案、在職職工目錄和離職職工目錄等數(shù)據(jù)表,ZFGjj通過(guò)公共字段“用戶號(hào)”與RSDA相連。如果我們從ZFGjj中提取一個(gè)用戶號(hào),需要從RSDA中得到擁有此用戶號(hào)的職工姓名,這時(shí)就必須用到TQuery的多表查詢。
        第一步 在ODBC中增加兩個(gè)數(shù)據(jù)源“ZFGjj”和“RSDA”。
        第二步 在BDE數(shù)據(jù)庫(kù)引擎中添加兩個(gè)數(shù)據(jù)庫(kù)列名“ZFGjj”和“RSDA”。
        第三步 在表單中增加兩個(gè)DataBase控件“DataBase1”和“DataBase2”,在AliasName屬性
      中分別選擇“ZFGjj”和“RSDA”,DataBaseName屬性中分別鍵入“ZFGjj”和“RSDA”,最后將
      KeepConnection和Connected屬性都設(shè)為“True”。

        現(xiàn)在可以輸入相應(yīng)的代碼了:
        Begin
          For I:=1 To 10 Do
          Begin
            Query1.Close;
            Query1.DataBaseName:=′′;
            Query1.Sq1.Clear;
            Query1.Sq1.Add(′Select A.七月,B.個(gè)人賬號(hào),B.用戶號(hào),C.姓名From“:ZFGjj:個(gè)人匯激部門(mén)表”A,“:ZFGjj:住房公積金明細(xì)表”B,“:RSDA:在職職工目錄”C Where(A.用戶號(hào)=B.封存=:ib)′);{在同一行輸入}
            Query1.Prepare;
            Query1.Params[0].DataType.=ftInteger;
            Query1.Params[1].DataType.=ftBoolean;
            Query1.Params[0].Asinteger:=ia[I];
            Query1.Params[1].Asboolean:=ib;
            Query1.Open;
          End;
        End;

        代碼中SQL語(yǔ)句必須在一行內(nèi)輸入,不能分行。SQL語(yǔ)句中使用了動(dòng)態(tài)參數(shù)“ia”和“ib”,
      Delphi會(huì)自動(dòng)按參數(shù)出現(xiàn)的順序?qū)⑺鼈兲砑釉赒uery1的Params屬性中并分配索引號(hào)分別為0和1,
      參數(shù)“ia”和“ib”應(yīng)在程序開(kāi)始時(shí)聲明其類(lèi)型并賦值。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類(lèi)似文章 更多