分类: News

IT資訊新聞

  • 初學者,你應當如何學習C++以及編程

    Javascript是世界上最受誤解的語言,其實C++何嘗不是。坊間流傳的錯誤的C++學習方法一抓就是一大把。我自己在學習C++的過程中也走了許多彎路,浪費了不少時間。

    為什麼會存在這麼多錯誤認識?原因主要有三個,一是C++語言的細節太多。二是一些著名的C++書籍總在(不管有意還是無意)暗示語言細節的重要性和有趣。三是現代C++庫的開發哲學必須用到一些犄角旮旯的語言細節(但注意,是庫設計,不是日常編程)。這些共同塑造了C++社群的整體心態和哲學。

    單是第一條還未必能夠成氣候,其它語言的細節也不少(儘管比起C++起來還是小巫見大巫),就拿javascript來說,作用域規則,名字查找,closure,for/in,這些都是細節,而且其中還有違反直覺的。但許多動態語言的程序員的理念我猜大約是學到哪用到哪罷。但C++就不一樣了,學C++之人有一種類似於被暗示的潛在心態,就是一定要先把語言核心基本上吃透了才能下手寫出漂亮的程序。這首先就錯了。

    這個意識形成的原因在第二點,C++書籍。市面上的C++書籍不計其數,但有一個共同的缺點,就是講語言細節的書太多——《C++ gotchas》,《Effective C++》,《More Effective C++》,但無可厚非的是,C++是這樣一門語言:要拿它滿足現代編程理念的需求,尤其是C++庫開發的需求,還必須得關注語言細節,乃至於在C++中利用語言細節已經成了一門學問。比如C++模板在設計之初根本沒有想到模板元編程這回事,更沒想到C++模板系統是圖靈完備的,這也就導致了《Modern C++ Design》和《C++ Template Metaprogramming》的驚世駭俗。
    這些技術的出現為什麼驚世駭俗,打個比方,就好比是一塊大家都認為已經熟悉無比,再無秘密可言的土地上,突然某天有人挖到原來地下還蘊藏著最豐富的石油。在這之前的C++雖然也有一些細節,但也還算容易掌握,那可是C++程序員們的happy old times,因為C++的一切都一覽無餘,everything is figured out。然而《Modern C++ Design》的出世告訴人們,“瞧,還有多少細節你們沒有掌握啊。”於是C++程序員們久違的激情被重燃起來,奮不顧身的踏入細節的沼澤中。尤其是,模板編程將C++的細節進一步挖掘到了極致——我們幹嘛關心涉及類對象的隱式轉換的優先級高低?看看boost::is_base_of就可以知道有多詭異了。
    但最大的問題還在於,對於這些細節的關注還真有它合適的理由:我們要開發現代模板庫,要開發active library,就必須動用模板編程技術,要動用模板編程技術,就必須利用語言的犄角旮旯,enable_if,type_traits,甚至連早就古井無波的C宏也在亂世中重生,看看

    boost::preprocessor有多詭異就知道了,連C宏的圖靈完備性(預編譯期的)都被挖掘出來了。為什麼要做這些?好玩?標榜?都不是,開發庫的實際需求。但這也正是最大的悲哀了。在boost裡面因實際需求而動用語言細節最終居然能神奇的完成任務的最好教材就是
    boost::foreach,這個小設施對語言細節的發掘達到了驚天地泣鬼神的地步,不信你先試著自己去看看它的源代碼,再看看作者介紹它的文
    章吧。而boost::typeof也不甘其後——C++語言裡面有太多被“發現”而不是被“發明”的技術。難道最初無意設置這些語言規則的傢伙們都是oracles?

    因為沒有variadic templates,人們用宏加上缺省模板參數來實現類似效果。因為沒有concepts,人們用模板加上析構函數的細節來完成類似工作。因為沒有typeof,人們用模板元編程和宏加上無盡的細節來實現目標… C++開發者們的DIY精神不可謂不強。然而,如果僅僅是因為要開發優秀的庫,那麼涉及這些細節都還是情有可原的,至少在C++09出現並且編譯器廠商跟上之前,這些都還能說是不得已而為之。但我們廣大的C++程序員呢?大眾是容易被誤導的,我也曾經是。以為掌握了更多的語言細節就更牛,但實際卻是那些語言細節十有八九是平時編程用都用不到的。 C++中眾多的細節雖然在庫設計者手裡面有其用武之地,但普通程序員則根本無需過多關注,尤其是沒有實際動機的關注。一般性的編碼實踐準則,以及基本的編程能力和基本功,乃至基本的程序設計理論以及算法設計。才是真正需要花時間掌握的東西。學習最佳編碼實踐比學習C++更重要。看優秀的代碼也比埋頭用差勁的編碼方式寫垃圾代碼要有效。直接、清晰、了、KISS地表達意圖比玩編碼花招要重要…

    避免去過問任何語言細節,除非必要。這個必要是指在實際編程當中遇到問題,這樣就算需要過問細節,也是最省事的,懶惰者原則嘛。一個掌握了基本的編程理念並有較強學習能力的程序員在用一門陌生的語言編程時就算拿著那本語言的聖經從索引翻起也可以編出合格的程序來。十年學會編程不是指對每門語言都得十年,那一輩子才能學幾門語言哪,如果按字母順序學的話一輩子都別指望學到Ruby了;十年學習編程更不是指先把語言特性從粗到細全都吃透才敢下手編程,在實踐中提高才是最重要的。

    至於這種摳語言細節的哲學為何能在社群裡面呈野火燎原之勢,就是一個心理學的問題了。想像人們在論壇上討論問題時,一個對語言把握很細緻的人肯定能夠得到更多的佩服,而由於論壇上的問題大多是小問題,所以解決實際問題的真正能力並不能得到顯現,也就是說,知識型的人能夠得到更多佩服,後者便成為動力和仿效的砝碼。然而真正的編程能力是與語言細節沒關係的,熟練運用一門語言能夠幫你最佳表達你的意圖,但熟練運用一門語言絕不意味著要把它的邊邊角角全都記住。懂得一些常識,有了編程的基本直覺,遇到一些細節錯誤的時候再去查書,是最節省時間的辦法。

    C++的書,Bjarne的聖經《The C++ Programming Language》是高屋建瓴的。 《大規模C++程序設計》是挺務實的。 《Accelerated C++》是最佳入門的。 《C++ Templates》是僅作參考的。 《C++ Template Metaprogramming》是精力過剩者可以玩一玩的,普通程序員碰都別碰的。 《ISO.IEC C++ Standard 14882》不是拿來讀的。 Bjarne最近在做C++的教育,新書是絕對可以期待的。

    PS關於如何學習編程,g9的blog上有許多精彩的文章:這裡,這裡,這裡,這裡…實際上,我建議你去把g9老大的blog翻個底朝天:P

    再PS書單?我是遑於給出一個類似《C++初學者必讀》這種書單的。 C++的書不計其數,被公認的好書也不勝枚舉。只不過有些書容易給初學者造成一種錯覺,就是“學習C++就應該是這個樣子的”。比如有朋友提到的《高質量C/C++編程》,這本書有價值,但不適合初學者,初學者讀這樣的書容易一葉障目不見泰山。實際上,正確的態度是,細節是必要的。但細節是次要的。其實學習編程我覺得應該最先學習如何用偽碼表達思想呢,君不見《Introduction to Algorithm》裡面的代碼?《TAOCP》中的代碼?哦,對了它們是自己建立的語言,但這種僅教學目的的語言的目的就是為了避免讓寫程序的人一開始就忘了寫程序是為了完成功能,以為寫程序就是和語言細節作鬥爭了。 Bjarne說程序的正確性最重要,boost的編碼標準裡面也將正確性列在性能前面。此外,一旦建立了正確的學習編程的理念,其實什麼書(只要不是太垃圾的)都有些用處。都當成參考書,用的時候從目錄或索引翻,基本就對了。

    再再PS myan老大和g9老大都給出了許多精彩的見解。我不得不再加上一個P.S。具體我就不摘錄了,如果你讀到這裡,請務必往下看他們的評論。轉載者別忘了轉載他們的評論:-)許多朋友都問我同一個問題,到底要不要學習C++。其實這個問題問得很沒有意義。 “學C++”和“不學C++”這個二分法是沒意義的,為什麼?因為這個問題很表面,甚至很浮躁。重要的不是你掌握的語言,而是你掌握的能力,借用myan老大的話,“重要的是這個磨練過程,而不是結果,要的是你粗壯的腿,而不是你身上背的那袋鹽巴。 ”。此外學習C++的意義其實真的是醉翁之意不在酒,像C/C++這種系統級語言,在學習的過程中必須要涉及到一些底層知識,如內存管理、編譯連接系統、彙編語言、硬件體系結構等等等等知識(注意,這不包括過分犄角旮旯的語言枝節)。這些東西也就是所謂的內功了(其實最最重要的內功還是長期學習所磨練出來的自學能力)。對此大嘴Joel在《Joel On Software》裡面提到的漏洞抽象定律闡述得就非常漂亮。

    所以,答案是,讓你成為高手的並不是你掌握什麼語言,精通C++未必就能讓你成為高手,不精通C++也未必就能讓你成為低手。我想大家都不會懷疑g9老大如果要抄起C++做一個項目的話會比大多數自認熟練C++的人要做得漂亮。所以關鍵的不是語言這個表層的東西,而是底下的本質矛盾。當然,不是說那就什麼語言都不要學了,按照一種曹操的邏輯,“天下語言,唯imperative與declarative耳”。 C++是前者裡面最複雜的一種,支持最廣泛的編程範式。借用當初數學系入學大會上一個老師的話,“你數學都學了,還有什麼不能學的呢?”。學語言是一個途徑,如果你把它用來磨練自己,可以。如果你把它用來作為學習系統底層知識的鑰匙,可以。如果你把它用來作為學習如何編寫優秀的代碼,如何組織大型的程序,如何進行抽象設計,可以。如果掉書袋,光啃細節,我認為不可以(除非你必須要用到細節,像boost庫的coder們)。

  • 虛擬化項目實施前需考慮的十大問題

    利用虛擬化技術,把軟件從硬件當中抽取出來,創建靈活、動態的環境,這樣的好處很吸引人。不過能否成功實施該項技術則取決於所需技能、安全和管理工具以及業務驅動因素是否到位。因為,在有些情況下,虛擬化技術還沒有準備好,或者回報不夠明顯,因而不能立刻開始實施。虛擬化項目不應該倉促上馬。這是一個長期機會,如果企業把虛擬化當成是一項戰略,而不僅僅是一個項目,那樣更有可能獲得長遠效益。

    以下是啟動全企業虛擬化項目之前要問自己的幾個重要問題。

    1、你擁有支持虛擬化技術的技能嗎?

    EMA把缺少“相應技能”列為成功部署虛擬化技術面臨的最大障礙。這家研究公司聲稱,虛擬化技術還沒有到位的企業約有四分之三不具備支持這項技術的技能。 EMA建議:在採用這項技術之前,對員工進行培訓、確定需求、記下預期出現的變化,並且在小的試點環境裡對虛擬化技術進行試用。

    2、你對虛擬化技術可能帶來的人事紛爭做好準備了嗎?

    第二個隱藏困難也與人這個因素有關。 EMA認為,因為IT部門多年來存在於各自獨立的環境,IT主管試圖讓公司的主流用戶接受虛擬化技術時可能會面臨阻力。譬如說,有些部門可能不想共享服務器資源,正因為如此,EMA建議公司部署報告工具,顯示虛擬化技術如何有助於提升性能,或者因為可共享彼此的資源而至少不會損害各部門的利益。

    3、你有沒有考慮過相關風險?能不能承受?

    雖然虛擬化技術減少了支持多個系統及應用所需的物理資源的數量,但同時把更多的用戶和應用集中到了數量更少、更複雜的共享虛擬化環境下。正因為如此,硬件故障、人為錯誤、安全漏洞、規劃問題、支持問題及其他因素帶來的影響在虛擬化環境下會得到極大地放大。 EMA給出的建議就是:在虛擬化項目的每個階段,企業應當制訂詳細的業務連續性和災難恢復計劃。

    4、你的安全系統承受得了嗎?

    虛擬化技術會帶來更多的安全漏洞、惡意軟件及薄弱環節,數量之多超出了許多公司原先準備的應對能力——這主要是因為如今的技術還無法處理新的威脅。 EMA認為,借助現有工具,幾乎發現不了像虛擬機管理程序感染、rootkIT病毒以及惡意虛擬機這類安全問題。 IT主管必須像保護物理機器那樣來保護虛擬機,還要採取其他步驟來確保虛擬化環境得到保護。 EMA認為,發現、配置、變革管理及其他方面的技術和製度對發現針對虛擬化環境的惡意軟件變得更為關鍵。

    5、你的系統和應用與虛擬化技術兼容嗎?

    有些應用和系統與虛擬化技術之間缺乏良好的兼容性。譬如說,EMA提到的“具有對各種資源的高效利用、極大的需求峰值或者持續高利用率等特點”的應用。這家研究公司認為,直接與硬件進行聯繫的應用也會妨礙虛擬化項目的實施。

    6、你有沒有容量規劃措施?

    虛擬服務器散亂現像是部署的虛擬化技術超過現有容量所帶來的一個常見結果。 EMA建議,IT部門應當利用詳細的容量規劃措施,確保自己有足夠的軟硬件資源來支持所實施的虛擬化技術,並確保虛擬化技術不會失去控制。

    7、你的環境得到支持嗎?

    EMA認為,雖然許多流行的套裝應用軟件支持虛擬化技術,但還是有許多應用軟件不支持。這家研究機構建議,IT部門在部署虛擬化技術之前,應當調查哪些軟硬件平台得到支持、哪些需要升級。

    8、你的網絡支持虛擬化技術嗎?

    網絡和存儲可能會給數據中心的虛擬化技術帶來瓶頸。譬如說,專注於用戶的虛擬化技術(如應用虛擬化、桌面虛擬化或者應用流)在低帶寬連接上就無法使用。企業的IT管理人員可以試著利用廣域網優化技術或者限制系統映像數量過多,克服網絡和存儲帶來的局限性。

    9、你的管理系統能夠處理虛擬化環境嗎?

    雖然虛擬化技術減少了要管理的物理資源的數量,但也加大了整個環境的複雜性,還帶來了讓某些IT管理人員為之頭痛的管理問題。譬如,易於部署可能會帶來虛擬機數量過多,或者虛擬服務器散亂現象,這可能會導致管理難度大大提高。

    另外,添加的一層軟件加大了管理整個環境的複雜性。 EMA認為,在管理工具跟上虛擬化技術的步伐之前,成功的關鍵在於不但要有相應工具,還要有發現、性能管理、配置管理、補丁管理、服務級別管理、自動配置、災難恢復等其他方面嚴格的流程製度。

    10、虛擬化技術可以幫助你滿足業務目標嗎?

    也許在倉促實施虛擬化技術過程中最容易被忽視的因素就是,沒有把技術實施與具體的業務目標聯繫起來。為了評估虛擬化技術部署項目的成功,企業的IT部門必須在部署這項技術之前,先要知道所需要的結果。 EMA建議,IT管理人員應當為長遠的戰略成果做好規劃,不要使用虛擬化技術作為解決緊迫的棘手問題的權宜之計。譬如說,雖然許多公司認為節省成本是虛擬化技術的一個成果,但EMA認為情況往往並非如此。

    EMA認為: “總的來說,節省成本並非是總能得到的結果,實際上,減少成本(軟件、硬件和場地等方面的成本)是最不能指望的結果。譬如說,儘管服務器合併帶來的成本效益經常被吹噓,但它帶來的只是一次性的成本節省,而額外成本(特別是對軟件而言)往往相當大。”

  • SQL語法大全

    本部分內容
                SQL基礎
               中級SQL
               高級SQL
    第10章SQL基礎

                     本章內容
               
                      SQL介紹
                     使用SELECT語句從表中取數據
                     創建新表
                     字段屬性
                     向表中添加數據
                     刪除和修改表
             

        為了建立交互站點,你需要使用數據庫來存儲來自訪問者的信息。例如,你要建立一個職業介紹服務的站點,你就需要存儲諸如個人簡歷,所感興趣的工作等等這樣的信息。創建動態網葉也需要使用數據庫,如果你想顯示符合來訪者要求的最好的工作,你就需要從數據庫中取出這份工作的信息。你將會發現,在許多情況下需要使用數據庫。
        在這一章裡,你將學會怎樣使用“結構化查詢語言”(SQL〕來操作數據庫。SQL語言是數據庫的標準語言。在Active Sever Pages中,無論何時你要訪問一個數據庫,你就要使用SQL語言。因此,掌握好SQL對ASP編程是非常重要的。
         
        注意:
        你可以把“SQL”讀作“sequel”,也可以按單個字母的讀音讀作S-Q-L。兩種發音都是正確的,每種發音各有大量的支持者。在本書裡,認為“SQL”讀作“sequel”。

        通過這一章的學習,你將理解怎樣用SQL實現數據庫查詢,你將學會怎樣使用這種查詢從數據表中取出信息,最後,你將學會怎樣設計和建立自己的數據庫。
                
        注意:
        通過下面幾章對SQL的介紹,你將對SQL有足夠的了解,從而可以有效地使用Active Sever Pages。但是,SQL是一種複雜的語言,本書不可能包括它的全部細節。要全面掌握SQL語言,你需要學習在Microsoft SQL Sever中使用SQL。你可以到附近的書店去買一本Microsoft SQL Sever 6.5。

    SQL介紹:
        本書假設你是在SQL操作Microsoft SQL Sever的數據庫。你也可以用SQL操作許多其它類型的數據庫。 SQL是操作數據庫的標準語言。 (事實上,關於SQL語言有一個專門的ANSI標準〕

        注意:
        不要在你的站點上試圖用Microsoft Access代替Microsoft SQL Sever。 SQL Sever可以同時服務於許多用戶,如果你希望你的站點有較高的訪問率,MS Access是不能勝任的。

        在學習SQL的細節之前,你需要理解它的兩大特點。一個特點容易掌握,另一個掌握起來有點困難。
        第一個特點是所有SQL數據庫中的數據都存儲在表中。一個表由行和列組成。例如,下面這個簡單的表包括name和e-mail address:
         Name Email Address
         ………………………………………….. …………..
         Bill Gates billg@microsoft.com
         president Clinton president@whitehouse.com
         Stephen Walther swalther@somewhere.com
        這個表有兩列(列也稱為字段,域〕:Name和Email Address。有三行,每一行包含一組數據。一行中的數據組合在一起稱為一條記錄。
        無論何時你向表中添加新數據,你就添加了一條新記錄。一個數據表可以有幾十個記錄,也可以有幾千甚至幾十億個記錄。雖然你也許永遠不需要存儲十億個Email地址,但知道你能這樣做總是好的,也許有一天你會有這樣的需要。
        你的數據庫很有可能包含幾十個表,所有存儲在你數據庫中的信息都被存儲在這些表中。當你考慮怎樣把信息存儲在數據庫中時,你應該考慮怎樣把它們存儲在表中。
         SQL的第二個特點有些難於掌握。這種語言被設計為不允許你按照某種特定的順序來取出記錄,因為這樣做會降低SQL Sever取記錄的效率。使用SQL,你只能按查詢條件來讀取記錄。
        當考慮如何從表中取出記錄時,自然會想到按記錄的位置讀取它們。例如,也許你會嘗試通過一個循環,逐個記錄地掃描,來選出特定的記錄。在使用SQL時,你必須訓練自己,不要有這種思路。
        假如你想選出所有的名字是“Bill Gates”的記錄,如果使用傳統的編程語言,你也許會構造一個循環,逐個查看表中的記錄,看名字域是否是“Bill Gates”。
        這種選擇記錄的方法是可行的,但是效率不高。使用SQL,你只要說,“選擇所有名字域等於Bill Gates的記錄”,SQL就會為你選出所有符合條件的記錄。 SQL會確定實現查詢的最佳方法。
        建設你想取出表中的前十個記錄。使用傳統的編程語言,你可以做一個循環,取出前十個記錄後結束循環。但使用標準的SQL查詢,這是不可能實現的。從SQL的角度來說,在一個表中不存在前十個記錄這種概念。
        開始時,當你知道你不能用SQL實現某些你感覺應該能實現的功能,你會受到挫折。你也許會以頭撞牆甚至想寫惡毒的信件給SQL的設計者們。但後來你會認識到,SQL的這個特點不僅不是個限制,反而是其長處。因為SQL不根據位置來讀取記錄,它讀取記錄可以很快。
        綜上所述,SQL有兩個特點:所有數據存儲在表中,從SQL的角度來說,表中的記錄沒有順序。在下一節,你將學會怎樣用SQL從表中選擇特殊的記錄。

    使用SQL從表中取記錄。
         SQL的主要功能之一是實現數據庫查詢。如果你熟悉Internet引擎,那麼你已經熟悉查詢了。你使用查詢來取得滿足特定條件的信息。例如,如果你想找到有ASP信息的全部站點,你可以連接到Yahoo!並執行一個對Active Sever Pages的搜索。在你輸入這個查詢後,你會收到一個列表,表中包括所有其描述中包含搜索表達式的站點。
        多數Internet引擎允許邏輯查詢。在邏輯查詢中,你可以包括特殊的運算符如AND、OR和NOT,你使用這些運算符來選擇特定的記錄。例如,你可以用AND來限制查詢結果。如果你執行一個對Active Sever Pages AND SQL的搜索。你將得到其描述中同時包含Active Sever Pages和SQL的記錄。當你需要限制查詢結果時,你可以使用AND。
        如果你需要擴展查詢的結果,你可以使用邏輯操作符OR。例如,如果你執行一個搜索,搜索所有的其描述中包含Active Sever Pages OR SQL的站點,你收到的列表中將包括所有其描述中同時包含兩個表達式或其中任何一個表達式的站點。
        如果你想從搜索結果中排除特定的站點,你可以使用NOT。例如,查詢“Active Sever Pages ”AND NOT “SQL”將返回一個列表,列表中的站點包含Active Sever Pages,但不包含SQL。當必須排除特定的記錄時,你可以使用NOT。
        用SQL執行的查詢與用Internet搜索引擎執行的搜索非常相似。當你執行一個SQL查詢時,通過使用包括邏輯運算符的查詢條件,你可以得到一個記錄列表。此時查詢結果是來自一個或多個表。
         SQL查詢的句法非常簡單。假設有一個名為email_table的表,包含名字和地址兩個字段,要得到Bill Gates的e_mail地址,你可以使用下面的查詢:

         SELECT email from email_table WHERE name=”Bill Gates”

        當這個查詢執行時,就從名為email_table的表中讀取Bill Gates的e_mail地址。這個簡單的語句包括三部分:
         ■ SELECT語句的第一部分指名要選取的列。在此例中,只有email列被選取。當執行時,只顯示email列的值billg@microsoft.com。
         ■ SELECTT語句的第二部份指明要從哪個(些)表中查詢數據。在此例中,要查詢的表名為email_table 。
         ■最後,SELECT語句的WHERE子句指明要選擇滿足什麼條件的記錄。在此例中,查詢條件為只有name列的值為Bill Gates的記錄才被選取。
         Bill Gates很有可能擁有不止一個email地址。如果表中包含Bill Gates的多個email地址。用上述的SELECT語句可以讀取他所有的email地址。 SELECT語句從表中取出所有name字段值為Bill Gates的記錄的email字段的值。
        前面說過,查詢可以在查詢條件中包含邏輯運算符。假如你想讀取Bill Gates或Clinton總統的所有email地址,你可以使用下面的查詢語句:

         SELECT email FROM email_table WHERE name=”Bill Gates” OR
                                                        name=”president Clinton”

        此例中的查詢條件比前一個複雜了一點。這個語句從表email_table中選出所有name列為Bill Gates或president Clinton的記錄。如果表中含有Bill Gates或president Clinton的多個地址,所有的地址都被讀取。
         SELECT語句的結構看起來很直觀。如果你請一個朋友從一個表中為你選擇一組記錄,你也許以非常相似的方式提出你的要求。在SQL SELECT語句中,你“SELECT特定的列FROM一個表WHERE某些列滿足一個特定的條件”。
        下一節將介紹怎樣執行SQL查詢來選取記錄。這將幫助你熟悉用SELECT語句從表中取數據的各種不同方法。

    使用ISQL執行SELECT查詢
        當你安裝SQL Sever時,你同時安裝了一個叫作ISQL/w的應用程序。 ISQL/w允許你執行交互的SQL查詢。在把查詢包括到你的ASP網頁中之前,用ISQL/w對其進行測試是非常有用的。

        注意:
        在這本書的第一部份,你學習了怎樣安裝和配置Microsoft SQL Sever 。如果沒有安裝SQL Sever或者SQL Sever不能運行,請參閱第三章“安裝和使用SQL Sever”。

        選擇任務上SQL Sever程序組中的ISQL_w以啟動該程序。程序啟動時,首先會出現一個對話框,要求輸入服務器信息和登錄信息(見圖10.1)。在Sever框中,輸入你的SQL服務器的名字。如果服務器正運行在本地計算機上,服務器名字就是你計算機的名字。在登錄信息框中,輸入一個登錄帳號和密碼或選擇使用“可信連接”,然後單擊Connect按鈕。

        圖10。1

        注意:
        如果你將SQL Sever配置為使用完整安全或混合安全,那麼你可以使用可信連接。如果你使用標準安全,你則需要提供用戶帳號和密碼。要了解更多信息,參見第三章。

        如果一切正常,在你單擊連接按鈕後會出現一個查詢窗口,如圖10.2所示。 (如果有異常,請參考第三章)

            圖10.2

        在執行查詢之前,你需要選擇數據庫。安裝SQL Sever時你已為自己創建了一個數據庫,SQL Sever還有許多系統數據庫,如master,model,msdb,和tempdb。
        方便的是,SQL Sever帶有一個特殊的名為pubs的例子數據庫。庫pubs中包含供一個虛擬的出版商使用的各個表。文檔中所有的例子程序都是針對這個庫來設計的。本書中的許多例子也使用這個數據庫。
        在查詢窗口頂部的DB下拉框中選擇數據庫pubs,這樣你就選擇了數據庫。你所有的查詢都將針對這個庫中的各個表來執行。現在你可以執行你的第一個查詢了。這真讓人興奮!
        你的第一個查詢將針對一個名為autrors的表,表中包含所有為某個虛擬出版商工作的作者的相關數據。單擊查詢窗口並輸入以下的語句:

         SELECT phone FROM authors WHERE au_name=”Ringer”

        輸入完成後,單擊執行查詢按鈕(一個綠色三角形,看起來像VCR播放鍵)。單擊此按鈕後,任何出現在查詢窗口中的語句均會被執行。查詢窗口會自動變成結果顯示窗口,你可以看到查詢的結果(見圖10.3)。
        你看到的查詢結果也許與圖10.3所示的不同。在SQL Sever的不同版本中,庫pubs中的數據會有所不同。對SQL Sever 6.5來說,將會找到兩條記錄。結果顯示窗口中應顯示如下內容:
        
         phone
    ……………….
    801 826_0752
    801 826_0752
         (2 row(s) affected)

      
     
      圖10.3

        你所執行的SELECT語句從表authors中取出所有名字為Ringer的作者的電話號碼。你通過在WHERE子句中使用特殊的選擇條件來限制查詢的結果。你也可以忽略選擇條件,從表中取出所有作者的電話號碼。要做到這一點,單擊Query標籤,返回到查詢窗口,輸入以下的SELECT語句:

    SELECT Phone FROM authors
        這個查詢執行後,會取出表authors中的所有電話號碼(沒有特定的順序)。如果表authors中包含一百個電話號碼,會有一百個記錄被取出,如果表中有十億個電話號碼,這十億條記錄都會被取出(這也許需要一些時間)。
        表authrs的字段包括姓,名字,電話號碼,地址,城市,州和郵政編碼。通過在SELECT語句的第一部份指定它們,你可以從表中取出任何一個字段。你可以在一個SELECT語句中一次取出多個字段,比如:

         SELECT au_fname ,au_lname, phone FROM authors

        這個SELECT語句執行後,將取出這三個列的所有值。下面是這個查詢的結果的一個示例(為了節省紙張,只顯示查詢結果的一部分,其餘記錄用省略號代替):

         au_fname au_lname phone
         ………………………………………………………………………….
         Johnson White 408 496_7223
         Marjorie Green 415 986_7020
         Cheryl Carson 415 548_7723
         Michael O’Leary 408 286_2428
         …
         (23 row(s) affected)

        在SELECT語句中,你需要列出多少個字段,你就可以列出多少。不要忘了把字段名用逗號隔開。你也可以用星號(*)從一個表中取出所有的字段。這裡有一個使用星號的例子:

         SELECT * FROM authors

        這個SELECT語句執行後,表中的所有字段的值都被取出。你會發現你將在SQL查詢中頻繁使用星號。

        技巧:
        你可以使用星號來查看一個表的所有列的名字。要做到這一點,只需要在執行完SELECT語句後看一下查詢結果的列標題。

    操作多個表
        到現在為止,你只嘗試了用一句SQL查詢從一個表中取出數據。你也可以用一個SELECT語句同時從多個表中取出數據,只需在SELECT語句的FROM從句中列出要從中取出數據的表名稱即可:
            
         SELECT au_lname ,title FROM authors, titles

        這個SELECT語句執行時,同時從表authors和表titles中取出數據。從表authors中取出所有的作者名字,從表titles中取出所有的書名。在ISQL/w程序中執行這個查詢,看一下查詢結果。你會發現一些奇怪的出乎意料的情況:作者的名字並沒有和它們所著的書相匹配,而是出現了作者名字和書名的所有可能的組合,這也許不是你所希望見到的。
        出了什麼差錯?問題在於你沒有指明這兩個表之間的關係。你沒有通過任何方式告訴SQL如何把表和表關聯在一起。由於不知道如何關聯兩個表,服務器只能簡單地返回取自兩個表中的記錄的所有可能組合。
        要從兩個表中選出有意義的記錄組合,你需要通過建立兩表中字段的關係來關聯兩個表。要做到這一點的途徑之一是創建第三個表,專門用來描述另外兩個表的字段之間的關係。
        表authors有一個名為au_id的字段,包含有每個作者的唯一標識。表titles有一個名為title_id的字段,包含每個書名的唯一標識。如果你能在字段au_id和字段title_id之間建立一個關係,你就可以關聯這兩個表。數據庫pubs中有一個名為titleauthor的表,正是用來完成這個工作。表中的每個記錄包括兩個字段,用來把表titles和表authors關聯在一起。下面的SELECT語句使用了這三個表以得到正確的結果:

         SELECT au_name,title FROM authors,titles,titleauthor
                                 WHERE authors.au_id=titleauthor.au_id
                                  AND titles.title_id=titleauthor.title_id

        當這個SELECT語句執行時,每個作者都將與正確的書名相匹配。表titleauthor指明了表authors和表titles的關係,它通過包含分別來自兩個表的各一個字段實現這一點。第三個表的唯一目的是在另外兩個表的字段之間建立關係。它本身不包含任何附加數據。
        注意在這個例子中字段名是如何書寫的。為了區別表authors和表titles中相同的字段名au_id,每個字段名前面都加上了表名前綴和一個句號。名為author.au_id的字段屬於表authors,名為titleauthor.au_id的字段屬於表titleauthor,兩者不會混淆。
        通過使用第三個表,你可以在兩個表的字段之間建立各種類型的關係。例如,一個作者也許寫了許多不同的書,或者一本書也許由許多不同的作者共同完成。當兩個表的字段之間有這種“多對多”的關係時,你需要使用第三個表來指明這種關係。
        但是,在許多情況下,兩個表之間的關係並不復雜。比如你需要指明表titles和表publishers之間的關係。因為一個書名不可能與多個出版商相匹配,你不需要通過第三個表來指明這兩個表之間的關係。要指明表titles和表publishers之間的關係,你只要讓這兩個表有一個公共的字段就可以了。在數據庫pubs中,表titles和表publishers都有一個名為pub_id的字段。如果你想得到書名及其出版商的一個列表,你可以使用如下的語句:
         SELECT title,pub_name FROM titles,publishers
                                 WHERE titles.pub_id=publishers.pub_id

        當然,如果一本書是由兩個出版商聯合出版的,那麼你需要第三個表來代表這種關係。
        通常,當你予先知道兩個表的字段間存在“多對多”關係時,就使用第三個表來關聯這兩個表。反之,如果兩個表的字段間只有“一對一”或“一對多”關係,你可以使用公共字段來關聯它門。

    操作字段
        通常,當你從一個表中取出字段值時,該值與創建該表時所定義的字段名聯繫在一起。如果你從表authors中選擇所有的作者名字,所有的值將會與字段名au_lname相聯繫。但是在某些情況下,你需要對字段名進行操作。在SELECT語句中,你可以在缺省字段名後面僅跟一個新名字來取代它。例如,可以用一個更直觀易讀的名字Author Last Name來代替字段名au_lname:

         SELECT au_lname “Author Last Name” FROM authors

        當這個SELECT語句執行時,來自字段au_lname的值會與“Author Last Name”相聯繫。查詢結果可能是這樣:
             
           Author Last Name
           ……………………………………………………………………..
           White
           Green
           Carson
           O’Leary
           Straight
           …
           (23 row(s) affected)
     
    注意字段標題不再是au_lname,而是被Author Last Name所取代。
        你也可以通過執行運算,來操作從一個表返回的字段值。例如,如果你想把表titles中的所有書的價格加倍,你可以使用下面的SELECT語句:
        
         SELECT price*2 FROM titles

        當這個查詢執行時,每本書的價格從表中取出時都會加倍。但是,通過這種途徑操作字段不會改變存儲在表中的書價。對字段的運算只會影響SELECT語句的輸出,而不會影響表中的數據。為了同時顯示書的原始價格和漲價後的新價格,你可以使用下面的查詢:

    SELECT price “Original price”, price*2 “New price” FROM titles

        當數據從表titles中取出時,原始價格顯示在標題Original price下面,加倍後的價格顯示在標題New price下面。結果可能是這樣:
              
           original price new price
           ……………………………………………………………….
    19.99 39.98
    11.95 23.90
    2.99 5.98
    19.99 39.98

    (18 row(s) affected)
            
        你可以使用大多數標準的數學運算符來操作字段值,如加(+),減(-),乘(*)和除(/)。你也可以一次對多個字段進行運算,例如:

          SELECT price*ytd_sales “total revenue” FROM titles

        在這個例子中,通過把價格與銷售量相乘,計算出了每種書的總銷售額。這個SELECT語句的結果將是這樣的:
           
           total revenue
           ……………………………………………..
           81,859,05
           46,318,20
           55,978,78
           81,859,05
           40,619,68
           …
           (18 row(s) affected)
      
        最後,你還可以使用連接運算符(它看起來像個加號)來連接兩個字符型字段:

           SELECT au_fname+” “+au_lname “author name” FROM authors

        在這個例子中,你把字段au_fname和字段au_lname粘貼在一起,中間用一個逗號隔開,並把查詢結果的標題指定為author name。這個語句的執行結果將是這樣的:

            author names
            …………………………………………………………
            Johnson White
            Marjorie Green
            Cheryl Carson
           Michael O’Leary
           Dean Straight
           …
           (23 row(s) affected)
     
        可以看到,SQL為你提供了對查詢結果的許多控制。你應該在ASP編程過程中充分利用這些優點。使用SQL來操作查詢結果幾乎總是比使用有同樣作用的腳本效率更高。

    排序查詢結果
        本章的介紹中曾強調過,SQL表沒有內在的順序。例如,從一個表中取第二個記錄是沒有意義的。從SQL的角度看來,沒有一個記錄在任何其他記錄之前。
    然而,你可以操縱一個SQL查詢結果的順序。在缺省情況下,當記錄從表中取出時,記錄不以特定的順序出現。例如,當從表authors中取出字段au_lname時,查詢結果顯示成這樣:

            au_lname
            …………………………………….
            White
            Green
            Carson
            O’Leary
            Straight
            …
            (23 row(s) affected)
       
        看一列沒有特定順序的名字是很不方便的。如果把這些名字按字母順序排列,讀起來就會容易得多。通過使用ORDER BY子句,你可以強制一個查詢結果按升序排列,就像這樣:

         SELECT au_lname FROM authors ORDER BY au_lname

        當這個SELECT語句執行時,作者名字的顯示將按字母順序排列。 ORDER BY子句將作者名字按升序排列。
        你也可以同時對多個列使用ORDER BY子句。例如,如果你想同時按升序顯示字段au_lname和字段au_fname,你需要對兩個字段都進行排序:

         SELECT au_lname,au_fname FROM authors ORDER BY au_lname ,au_fname

        這個查詢首先把結果按au_lname字段進行排序,然後按字段au_fname排序。記錄將按如下的順序取出:

           au_lname au_fname
           …………………………………………………………………….
           Bennet Abraham
           Ringer Albert
           Ringer Anne
           Smith Meander
           …
           (23 row(s) affected)

        注意有兩個作者有相同的名字Ringer。名為Albert Ringer的作者出現名為Anne Ringer的作者之前,這是因為姓Albert按字母順序應排在姓Anne之前。
    如果你想把查詢結果按相反的順序排列,你可以使用關鍵字DESC。關鍵字DESC把查詢結果按降序排列,如下例所示:
         
            SELECT au_lname,au_fname FROM authors
                   WHERE au_lname=”Ringer” ORDER BY au_lname ,au_fname DESC

        這個查詢從表authors中取出所有名字為Ringer的作者記錄。 ORDER BY子句根據作者的名字和姓,將查詢結果按降序排列。結果是這樣的:

           au_lname au_fname
           ……………………………………………………………………………………….
           Ringer Anne
           Ringer Albert
           (2 row(s) affectec)

        注意在這個表中,姓Anne出現在姓Albert之前。作者名字按降序顯示。
    你也可以按數值型字段對一個查詢結果進行排序。例如,如果你想按降序取出所有書的價格,你可以使用如下的SQL查詢:

            SELECT price FROM titles ORDER BY price DESC

        這個SELECT語句從表中取出所有書的價格,顯示結果時,價格低的書先顯示,價格高的書後顯示。

        警告:
        不是特別需要時,不要對查詢結果進行排序,因為服務器完成這項工作要費些力氣。這意味著帶有ORDER BY子句的SELECT語句執行起來比一般的SELECT語句花的時間長。

    取出互不相同的記錄
        一個表有可能在同一列中有重複的值。例如,數據庫pubs的表authors中有兩個作者的名字是Ringer。如果你從這個表中取出所有的名字,名字Ringer將會顯示兩次。
        在特定情況下,你可能只有興趣從一個表中取出互不相同的值。如果一個字段有重複的值,你也許希望每個值只被選取一次,你可以使用關鍵字DISTINCT來做到這一點:

          SELCET DISTINCT au_lname FROM authors WHERE au_lname=”Ringer”

        當這個SELECT語句執行時,只返回一個記錄。通過在SELECT語句中包含關鍵字DISTINCT,你可以刪除所有重複的值。例如,假設有一個關於新聞組信息發布的表,你想取出所有曾在這個新聞組中發布信息的人的名字,那麼你可以使用關鍵字DISTINCT。每個用戶的名字只取一次——儘管有的用戶發布了不止一篇信息。
        警告:
        如同ORDER BY子句一樣,強制服務器返回互不相同的值也會增加運行開銷。福氣不得不花費一些時間來完成這項工作。因此,不是必須的時候不要使用關鍵字DISTINCT。

    創建新表
        前面說過,數據庫中的所有數據存儲在表中。數據表包括行和列。列決定了表中數據的類型。行包含了實際的數據。
        例如,數據庫pubs中的表authors有九個字段。其中的一個字段名為為au_lname,這個字段被用來存儲作者的名字信息。每次向這個表中添加新作者時,作者名字就被添加到這個字段,產生一條新記錄。
        通過定義字段,你可以創建一個新表。每個字段有一個名字和一個特定的數據類型(數據類型在後面的“字段類型”一節中講述),例如字段au_lname存儲的是字符型數據。一個字段也可以存儲其它類型的數據。
        使用SQL Sever,創建一個新表的方法是很多的。你可以可執行一個SQL語句或使用SQL事務管理器(SQL Enterprise Manager)來創建一個新表。在下一節裡,你將學會如何用SQL語句來創建一個新表。

    用SQL創建新表
        注意:
        如果你還沒有建立自己的數據庫,現在就跳回到第三章創建這個庫。你絕不能向master,tempdb或任何其他任何系統數據庫中添加數據。

        從SQL Sever程序組(在任務欄中)中啟動ISQL/w程序。出現查詢窗口後,從窗口頂部的下拉列表中選擇你在第三章所創建的數據庫。下一步,在查詢窗口中鍵入下面的SQL語句,單擊執行查詢按鈕,執行這個語句:

           CREATE TABLE guestbook (visitor VARCHAR(40),comments TEXT,entrydate
                                              DATETIME)

    如果一切正常,你會在結果窗口中看到如下的文字(如果出現異常,請參閱第三章):

           This command dit not return data ,and it did not return any rows

    祝賀你,你已經建立了你的第一個表!
        你所創建的表名為guestbook,你可以使用這個表來存儲來字你站點訪問者的信息。你是用REEATE TABLE語句創建的這個表,這個語句有兩部分:第一部份指定表的名子;第二部份是括在括號中的各字段的名稱和屬性,相互之間用逗號隔開。
        表guestbook有三個字段:visitor,comments和entrydate。 visitor字段存儲訪問者的名字,comments字段存儲訪問者對你站點的意見,entrydate字段存儲訪問者訪問你站點的日期和時間。
        注意每個字段名後面都跟有一個專門的表達式。例如,字段名comments後面跟有表達式TEXT。這個表達式指定了字段的數據類型。數據類型決定了一個字段可以存儲什麼樣的數據。因為字段comments包含文本信息,其數據類型定義為文本型。
        字段有許多不同的數據類型。下一小節講述SQL所支持的一些重要的數據類型。

    字段類型
        不同的字段類型用來存放不同類型的數據。創建和使用表時,更你應該理解五種常用的字段類型:字符型,文本型,數值型,邏輯性和日期型。

    字符型數據
        字符型數據非常有用。當你需要存儲短的字符串信息時,你總是要用到字符型數據。例如,你可以把從HTML form的文本框中蒐集到的信息放在字符型字段中。
        要建立一個字段用來存放可變長度的字符串信息,你可以使用表達式VARCHAR。考慮你前面創建的表guestbook:

          CREATE TABLE guestbook (visitor VARCHAR(40),comments TEXT,entrydate
                                              DATETIME)

        在這個例子中,字段visitor的數據類型為VARCHAR。注意跟在數據類型後面的括號中的數字。這個數字指定了這個字段所允許存放的字符串的最大長度。在這個例子中,字段visitor能存放的字符串最長為四十個字符。如果名字太長,字符串會被截斷,只保留四十個字符。
         VARCHAR類型可以存儲的字符串最長為255個字符。要存儲更長的字符串數據,可以使用文本型數據(下一節中講述)。
        另一種字符型數據用來存儲固定長度的字符數據。下面是一個使用這種數據類型的例子:

          CREATE TABLE guestbook (visitor CHAR(40),comments TEXT,entrydate
                                              DATETIME)

        在這個例子中,字段visitor被用來存儲四十個字符的固定長度字符串。表達式CHAR指定了這個字段應該是固定長度的字符串。
         VARCHAR型和CHAR型數據的這個差別是細微的,但是非常重要。假如你向一個長度為四十個字符的VARCHAR型字段中輸入數據Bill Gates。當你以後從這個字段中取出此數據時,你取出的數據其長度為十個字符——字符串Bill Gates的長度。
        現在假如你把字符串輸入一個長度為四十個字符的CHAR型字段中,那麼當你取出數據時,所取出的數據長度將是四十個字符。字符串的後面會被附加多餘的空格。
        當你建立自己的站點時,你會發現使用VARCHAR型字段要比CHAR型字段方便的多。使用VARCHAR型字段時,你不需要為剪掉你數據中多餘的空格而操心。
         VARCHAR型字段的另一個突出的好處是它可以比CHAR型字段佔用更少的內存和硬盤空間。當你的數據庫很大時,這種內存和磁盤空間的節省會變得非常重要。

    文本型數據
        字符型數據限制了字符串的長度不能超過255個字符。而使用文本型數據,你可以存放超過二十億個字符的字符串。當你需要存儲大串的字符時,應該使用文本型數據。
        這裡有一個使用文本型數據的例子:

         CREATE TABLE guestbook (visitor VARCHAR(40),comments TEXT,entrydate
                                              DATETIME)

        在這個例子中,字段comments被用來存放訪問者對你站點的意見。注意文本型數據沒有長度,而上一節中所講的字符型數據是有長度的。一個文本型字段中的數據通常要么為空,要么很大。
        當你從HTML form的多行文本編輯框(TEXTAREA)中收集數據時,你應該把收集的信息存儲於文本型字段中。但是,無論何時,只要你能避免使用文本型字段,你就應該不適用它。文本型字段既大且慢,濫用文本型字段會使服務器速度變慢。文本型字段還會吃掉大量的磁盤空間。
        警告:
        一旦你向文本型字段中輸入了任何數據(甚至是空值),就會有2K的空間被自動分配給該數據。除非刪除該記錄,否則你無法收回這部分存儲空間。

    數值型數據
         SQL Sever支持許多種不同的數值型數據。你可以存儲整數、小數、和錢數。
        通常,當你需要在表中的存放數字時,你要使用整型(INT)數據。 INT型數據的表數範圍是從-2,147,483,647到2,147,483,647的整數。下面是一個如何使用INT型數據的例子:

            CREATE TABLE visitlog (visitor VARCHAR(40),numvisits INT)

        這個表可以用來記錄你站點被訪問的次數。只要沒有人訪問你的站點超過2,147,483,647次,nubvisits字段就可以存儲訪問次數。
        為了節省內存空間,你可以使用SMALLINT型數據。 SMALLINT型數據可以存儲從-32768到32768的整數。這種數據類型的使用方法與INT型完全相同。
        最後,如果你實在需要節省空間,你可以使用TINYINT型數據。同樣,這種類型的使用方法也與INT型相同,不同的是這種類型的字段只能存儲從0到255的整數。 TINYINT型字段不能用來存儲負數。
        通常,為了節省空間,應該盡可能的使用最小的整型數據。一個TINYINT型數據只佔用一個字節;一個INT型數據佔用四個字節。這看起來似乎差別不大,但是在比較大的表中,字節數的增長是很快的。另一方面,一旦你已經創建了一個字段,要修改它是很困難的。因此,為安全起見,你應該預測以下,一個字段所需要存儲的數值最大有可能是多大,然後選擇適當的數據類型。
        為了能對字段所存放的數據有更多的控制,你可以使用NUMERIC型數據來同時表示一個數的整數部分和小數部分。 NUMERIC型數據使你能表示非常大的數——比INT型數據要大得多。一個NUMERIC型字段可以存儲從-1038到1038範圍內的數。 NUMERIC型數據還使你能表示有小數部分的數。例如,你可以在NUMERIC型字段中存儲小數3.14。
        當定義一個NUMERIC型字段時,你需要同時指定整數部分的大小和小數部分的大小。這裡有一個使用這種數據類型的例子:
         
            CREATE TABLE numeric_data (bignumber NUMERIC(28,0),
                                        fraction NUMERIC (5,4) )

        當這個語句執行時,將創建一個名為numeric_data的包含兩個字段的表。字段bignumber可以存儲直到28位的整數。字段fraction可以存儲有五位整數部分和四位小數部分的小數。
        一個NUMERIC型數據的整數部分最大隻能有28位,小數部分的位數必須小於或等於整數部分的位數,小數部分可以是零。
        你可以使用INT型或NUMERIC型數據來存儲錢數。但是,專門有另外兩種數據類型用於此目的。如果你希望你的網點能掙很多錢,你可以使用MONEY型數據。如果你的野心不大,你可以使用SMALLMONEY型數據。 MONEY型數據可以存儲從-922,337,203,685,477.5808到922,337,203,685,477.5807的錢數。如果你需要存儲比這還大的金額,你可以使用NUMERIC型數據。
         SMALLMONEY型數據只能存儲從-214,748.3648到214,748.3647的錢數。同樣,如果可以的話,你應該用SMALLMONEY型來代替MONEY型數據,以節省空間。下面的例子顯示瞭如何使用這兩種表示錢的數據類型:

           CREATE TABLE products (product VARCHAR(40),price MONEY,
                                    Discount_price SMALLMONEY)

        這個表可以用來存儲商品的折扣和普通售價。字段price的數據類型是MONEY,字段discount_price的數據類型是SMALLMONEY。

    存儲邏輯值
        如果你使用複選框(CHECKBOX)從網頁中蒐集信息,你可以把此信息存儲在BIT型字段中。 BIT型字段只能取兩個值:0或1。這裡有一個如何使用這種字段的例子:

         CREATE TABLE opinion (visitor VARCHAR(40),good BIT)

        這個表可以用來存放對你的網點進行民意調查所得的信息。訪問者可以投票表示他們是否喜歡你的網點。如果他們投YES,就在BIT型字段中存入1。反之,如果他們投NO,就在字段中存入0(在下一章裡,你將學會如何計算投票)。
        當心,在你創建好一個表之後,你不能向表中添加BIT型字段。如果你打算在一個表中包含BIT型字段,你必須在創建表時完成。

    存儲日期和時間
        當你建立一個網點時,你也許需要記錄在一段時間內的訪問者數量。為了能夠存儲日期和時間,你需要使用DATETIME型數據,如下例所示:

         CREATE TABL visitorlog( visitor VARCHAR (40), arrivaltime DATETIME ,
                                    departuretime DATETIME)

        這個表可以用來記錄訪問者進入和離開你網點的時間和日期。一個DATETIME型的字段可以存儲的日期範圍是從1753年1月1日第一毫秒到9999年12月31日最後一毫秒。
        如果你不需要覆蓋這麼大範圍的日期和時間,你可以使用SMALLDATETIME型數據。它與DATETIME型數據同樣使用,只不過它能表示的日期和時間範圍比DATETIME型數據小,而且不如DATETIME型數據精確。一個SMALLDATETIME型的字段能夠存儲從1900年1月1日到2079年6月6日的日期,它只能精確到秒。
         DATETIME型字段在你輸入日期和時間之前並不包含實際的數據,認識這一點是重要的。在下一章,你將學習怎樣使用大量的SQL函數來讀取和操作日期和時間(參見下面的“缺省值”一節)。你也可以在VBScript和JScript中使用日期和時間函數來向一個DATETIME型字段中輸入日期和時間。

    字段屬性
        上一節介紹瞭如何建立包含不同類型字段的表。在這一節中,你將學會如何使用字段的三個屬性。這些屬性允許你控制空值,缺省值和標識值。

    允許和禁止空值
        大多數字段可以接受空值(NULL)。當一個字段接受了空值後,如果你不改變它,它將一直保持空值。空值(NULL)和零是不同的,嚴格的說,空值表示沒有任何值。
    為了允許一個字段接受空值,你要在字段定義的後面使用表達式NULL。例如,下面的表中兩個字段都允許接受空值:
          
           CREATE TABLE empty (empty1 CHAR (40) NULL,empty2 INT NULL(
       
        注意:
         BIT型數據不能是空值。一個這種類型的字段必須取0或者1。

        有時你需要禁止一個字段使用空值。例如,假設有一個表存儲著信用卡號碼和信用卡有效日期,你不會希望有人輸入一個信用卡號碼但不輸入有效日期。為了強制兩個字段都輸入數據,你可以用下面的方法建立這個表:
          
           CREATE TABLE creditcards (creditcard_number CHAR(20) NOT NULL,
                                      Creditcard_expire DATETIME NOT NULL)
        注意字段定義的後面跟有表達式NOT NULL。通過包含表達式NOT NULL,你可以禁止任何人只在一個字段中插入數據,而不輸入另一個字段的數據。
        你將會發現,在你建設自己的網點過程中,這種禁止空值的能力是非常有用的。如果你指定一個字段不能接受空值,那麼當你試圖輸入一個空值時,會有錯誤警告。這些錯誤警告可以為程序調試提供有價值的線索。

    缺省值
        假設有一個存儲地址信息的表,這個表的字段包括街道、城市、州、郵政編碼和國家。如果你預計地址的大部分是在美國,你可以把這個值作為country字段的缺省值。
        為了在創建一個表時指定缺省值,你可以使用表達式DEFAULT。請看下面這個在創建表時使用缺省值的例子:
           
           CREATE TABLE addresses (street VARCHAR(60) NULL,
                                    city VARCHAR(40) NULL,
                                    state VARCHAR(20) NULL
                                    zip VARCHAR(20) NULL,
                                    country VARCHAR(30) DEFAULT ‘USA’)

        在這個例子中,字段country的缺省值被指定為美國。注意單引號的使用,引號指明這是字符型數據。為了給非字符型的字段指定缺省值,不要把該值擴在引號中:
        
           CREATE TABLE orders(price MONEY DEFAULT $38.00,
                                quantity INT DEFAULT 50,
                                 entrydate DATETIME DEFAULT GETDATE())

        在這個CREATE TABLE語句中,每個字段都指定了一個缺省值。注意DATETIME型字段entrydate所指定的缺省值,該缺省值是函數Getdate()的返回值,該函數返回當前的日期和時間。

    標識字段
        每個表可以有一個也只能有一個標識字段。一個標識字段是唯一標識表中每條記錄的特殊字段。例如,數據庫pubs中的表jobs包含了一個唯一標識每個工作標識字段:
        
           job_id job_desc
           …………………………………………………………….
    1 New Hire Job not specified
    2 Chief Executive officer
    3 Bushness Operations Manager
    4 Chief Financial Officier
    5 Publisher
     
        字段job_id為每個工作提供了唯一的一個數字。如果你決定增加一個新工作,新增記錄的job_id字段會被自動賦給一個新的唯一值。
        為了建立一個標識字段,你只需在字段定義後面加上表達式IDENTITY即可。你只能把NUMERIC型或INT型字段設為標識字段,這裡有一個例子:
      
            CREATE TABLE visitorID (theID NUBERIC(18) IDENTITY,name VARCHAR(40))
       
        這個語句所創建的表包含一個名為theid的標識字段。每當一個新的訪問者名字添加到這個表中時,這個字段就被自動賦給一個新值。你可以用這個表為你的站點的每一個用戶提供唯一標識。
        技巧:
        建立一個標示字段時,注意使用足夠大的數據類型。例如你使用TINYINT型數據,那麼你只能向表中添加255個記錄。如果你預計一個表可能會變得很大,你應該使用NUMERIC型數據。

        標識字段的存在會使你想嘗試許多不可能的事情。例如,你也許想利用標識字段來對記錄進行基於它們在表中位置的運算。你應該拋棄這種意圖。每個記錄的標識字段的值是互不相同的,但是,這並不禁止一個標識字段的標識數字之間存在間隔。例如,你永遠不要試圖利用一個表的標識字段來取出表中的前十個記錄。這種操作會導致失敗,比如說6號記錄和7號記錄根本不存在。

    使用SQL事務管理器創建新表
        你可以使用前面幾節所講的方法創建新表。但是,使用事務管理器創建新表會更容易。這一節介紹如何使用這個程序創建新表。
        從任務欄的SQL Sever程序組中選擇SQL Enterprise Manager,啟動該程序,你會看到如圖10.4所示的窗口。瀏覽服務管理器窗口中的樹形結構,選擇名為Database的文件夾。打開文件夾Database後,選擇你在第三章中所建立的數據庫。
        
    注意:
        如果你還沒有創建自己的數據庫,回到第三章創建它。你決不要向master,tempdb或任何其它系統數據庫中添加數據。
      
        在選擇了數據庫之後,你會看到一個名為Group/users的文件夾和一個名為objects的文件夾。打開文件夾objects,你會看到許多文件夾,其中一個名為Tables。用右鍵單擊文件夾Tables並選擇New table,就會出現如圖10.5所示的窗口。
        你可以使用Manager Tables窗口來創建一個新表。 Manager Tables窗口有7個列:Key,Column,Name,Datatype,Size,Nulls和Default。 Manager Tables窗口中的每一行標明表中一個字段的信息。

            圖10.4
                10.5

        要建立一個新表,你至少要輸入一行信息。在名為Column Name的列下面鍵入mycolumn。下一步,選擇Datatype列,並從下拉列表中選擇CHAR。當你在這兩個列中輸入信息後,窗口將是如圖10.6所示的樣子。

     圖10.6

        你已經建立了一個只有一個字段的簡單的表。單擊保存按扭保存這個新表。當要求你輸入新表的名字時,輸入mytable並單擊OK。現在這個表已經保存到了你的數據庫中。
    如果你打開服務管理器窗口中的文件夾Tables,你會看到你所建立的新表被列出。你可以雙擊該表的圖表來編輯它,這時Manager Tables窗口會重新出現,你可以增加新的字段並重新保存。
        用SQL事務管理器可以做的工作,你都可以用SQL語句來實現。但是,事務管理器使得建表過程變得更加簡單。

    向表中添加數據
        下一章將討論如何使用SQL向一個表中插入數據。但是,如果你需要向一個表中添加許多條記錄,使用SQL語句輸入數據是很不方便的。幸運的是,Microsoft SQL Sever帶有一個稱為Microsoft Query的客戶端應用程序,這個程序使得向表中添加數據變得容易了。
        啟動位於任務欄SQL Sever程序組中的Microsoft Query程序。從窗口頂部的菜單中選擇File|New Query。這時會顯示一個Select Data Source對話框(見圖10.7)。選擇你的數據源名字並單擊Use。
        
    圖10。7

        輸入你的登錄帳號和密碼後,程序要求你選擇一個表和一個數據庫。選擇你在上一節中所建立的表(mytable ),單擊按鈕Add,然後單擊按鈕Close關閉該對話框。
        在窗口的左上角會出現一個對話框,框中是取自表mytable的一列字段名。你可以雙擊任何一個字段,把它添加到主窗口中。如果你雙擊星號(*)字符,所有的字段都會被添加到主窗口中。
        如果你的表中有記錄,它們現在已經出現在主窗口的字段標題下面了。但是,因為你剛剛建立了這個表,表還是空的。要添加新記錄,選擇Records|Allow Editing,主窗口中就會出現一條新記錄。輸入一行數據完成這個記錄,就向表中添加了一條新記錄。
           
                    圖10。8

        當你轉到下一條新記錄時,你向上一條記錄中輸入的值會自動被保存。如果你需要,你可以用Microsoft Query向表中輸入幾百條記錄。

    刪除和修改表
        你應該在建立表之前仔細設計它們,因為你在改變一個已經存在的表時會受到很大的限制。例如,一旦已經建立了一個表,你就不能刪除表中的字段或者改變字段的數據類型。在這種情況你所能做的是刪除這個表,然後重頭開始(參見第十一章“中級SQL”中的“使用SQL創建記錄和表”一節)。
        要刪除一個表,你可以使用SQL語句DROP TABLE。例如,又從數據庫中徹底刪除表mytable,你要使用如下的語句:
        
            DROP TABLE mytable

        警告:
        使用DROP TABLE命令時一定要小心。一旦一個表被刪除之後,你將無法恢復它。

        當你建設一個站點時,你很可能需要向數據庫中輸入測試數據。而當你準備向世界提供你的網點時,你會想清空表中的這些測試信息。如果你想清除表中的所有數據但不刪除這個表,你可以使用TRUNCATE TABLE語句。例如,下面的這個SQL語句從表mytable中刪除所有數據:

             TRUNCATE TABLE mytable

        雖然你不能刪除和修改已經存在的字段,但你可以增加新字段。最容易的實現方法是使用SQL事務管理器中的Manager Tables窗口。你也可以使用SQL語句ALTER TABLE。下面是一個如何使用這種語句的例子:

          ALTER TABLE mytable ADD mynewcolumn INT NULL

        這個語句向表mytable中增加了一個新字段mynewcolumn。當你增加新字段時,你必須允許它接受空值,因為表中原來可能已經有了許多記錄。

    總結
        這一章向你介紹了SQL。使用SQL,你可以操作Microsoft SQL Sever數據庫。你已經學會了使用SELECT語句從數據庫中取出數據,你還學會了怎樣使用CREATE TABLE語句和SQL事務管理器來創建新表。最後,你學會瞭如何指明一系列重要的字段屬性。
    下一章將介紹如何使用索引來增強SQL查詢的操作。還將通過許多其它的SQL語句和函數,使你的SQL知識得到進一步擴充。

     

    第十一章中級SQL

                   本章內容
                    ■創建索引
                    ■SQL核心語句
                    ■集合函數
    ■其它常用的SQL表達式,
      函數,和過程

     

        第十章“SQL基礎”向你初步介紹了SQL。你學會瞭如何用SELECT語句進行查詢,你還學會瞭如何建立自己的表。在這一章裡,你將加深你的SQL知識。你將學習如何建立索引來加快查詢速度。你還將學會如果用更多的SQL語句和函數來操作表中的數據。

    建立索引
        假設你想找到本書中的某一個句子。你可以一頁一頁地逐頁搜索,但這會花很多時間。而通過使用本書的索引,你可以很快地找到你要搜索的主題。
        表的索引與附在一本書後面的索引非常相似。它可以極大地提高查詢的速度。對一個較大的表來說,通過加索引,一個通常要花費幾個小時來完成的查詢只要幾分鐘就可以完成。因此沒有理由對需要頻繁查詢的表增加索引。
        注意:
        當你的內存容量或硬盤空間不足時,也許你不想給一個表增加索引。對於包含索引的數據庫,SQL Sever需要一個可觀的額外空間。例如,要建立一個聚簇索引,需要大約1.2倍於數據大小的空間。要看一看一個表的索引在數據庫中所佔的空間大小,你可以使用系統存儲過程sp_spaceused,對象名指定為被索引的表名。

    聚簇索引和非聚簇索引
        假設你已經通過本書的索引找到了一個句子所在的頁碼。一旦已經知道了頁碼後,你很可能漫無目的翻尋這本書,直至找到正確的頁碼。通過隨機的翻尋,你最終可以到達正確的頁碼。但是,有一種找到頁碼的更有效的方法。
        首先,把書翻到大概一半的地方,如果要找的頁碼比半本書處的頁碼小,就書翻到四分之一處,否則,就把書翻到四分之三的地方。通過這種方法,你可以繼續把書分成更小的部分,直至找到正確的頁碼附近。這是找到書頁的非常有效的一種方法。
    SQL Sever的表索引以類似的方式工作。一個表索引由一組頁組成,這些頁構成了一個樹形結構。根頁通過指向另外兩個頁,把一個表的記錄從邏輯上分成和兩個部分。而根頁所指向的兩個頁又分別把記錄分割成更小的部分。每個頁都把記錄分成更小的分割,直至到達葉級頁。
        索引有兩種類型:聚簇索引和非聚簇索引。在聚簇索引中,索引樹的葉級頁包含實際的數據:記錄的索引順序與物理順序相同。在非聚簇索引中,葉級頁指向表中的記錄:記錄的物理順序與邏輯順序沒有必然的聯繫。
        聚簇索引非常象目錄表,目錄表的順序與實際的頁碼順序是一致的。非聚簇索引則更像書的標準索引表,索引表中的順序通常與實際的頁碼順序是不一致的。一本書也許有多個索引。例如,它也許同時有主題索引和作者索引。同樣,一個表可以有多個非聚簇索引。
        通常情況下,你使用的是聚簇索引,但是你應該對兩種類型索引的優缺點都有所理解。
        每個表只能有一個聚簇索引,因為一個表中的記錄只能以一種物理順序存放。通常你要對一個表按照標識字段建立聚簇索引。但是,你也可以對其它類型的字段建立聚簇索引,如字符型,數值型和日期時間型字段。
        從建立了聚簇索引的表中取出數據要比建立了非聚簇索引的表快。當你需要取出一定範圍內的數據時,用聚簇索引也比用非聚簇索引好。例如,假設你用一個表來記錄訪問者在你網點上的活動。如果你想取出在一定時間段內的登錄信息,你應該對這個表的DATETIME型字段建立聚簇索引。
        對聚簇索引的主要限制是每個表只能建立一個聚簇索引。但是,一個表可以有不止一個非聚簇索引。實際上,對每個表你最多可以建立249個非聚簇索引。你也可以對一個表同時建立聚簇索引和非聚簇索引。
        假如你不僅想根據日期,而且想根據用戶名從你的網點活動日誌中取數據。在這種情況下,同時建立一個聚簇索引和非聚簇索引是有效的。你可以對日期時間字段建立聚簇索引,對用戶名字段建立非聚簇索引。如果你發現你需要更多的索引方式,你可以增加更多的非聚簇索引。
        非聚簇索引需要大量的硬盤空間和內存。另外,雖然非聚簇索引可以提高從表中取數據的速度,它也會降低向表中插入和更新數據的速度。每當你改變了一個建立了非聚簇索引的表中的數據時,必須同時更新索引。因此你對一個表建立非聚簇索引時要慎重考慮。如果你預計一個表需要頻繁地更新數據,那麼不要對它建立太多非聚簇索引。另外,如果硬盤和內存空間有限,也應該限制使用非聚簇索引的數量。

    索引屬性
        這兩種類型的索引都有兩個重要屬性:你可以用兩者中任一種類型同時對多個字段建立索引(複合索引);兩種類型的索引都可以指定為唯一索引。
        你可以對多個字段建立一個複合索引,甚至是複合的聚簇索引。假如有一個表記錄了你的網點訪問者的姓和名字。如果你希望根據完整姓名從表中取數據,你需要建立一個同時對姓字段和名字字段進行的索引。這和分別對兩個字段建立單獨的索引是不同的。當你希望同時對不止一個字段進行查詢時,你應該建立一個對多個字段的索引。如果你希望對各個字段進行分別查詢,你應該對各字段建立獨立的索引。
        兩種類型的索引都可以被指定為唯一索引。如果對一個字段建立了唯一索引,你將不能向這個字段輸入重複的值。一個標識字段會自動成為唯一值字段,但你也可以對其它類型的字段建立唯一索引。假設你用一個表來保存你的網點的用戶密碼,你當然不希望兩個用戶有相同的密碼。通過強制一個字段成為唯一值字段,你可以防止這種情況的發生。

    用SQL建立索引
        為了給一個表建立索引,啟動任務欄SQL Sever程序組中的ISQL/w程序。進入查詢窗口後,輸入下面的語句:

            CREATE INDEX mycolumn_index ON mytable (myclumn)

        這個語句建立了一個名為mycolumn_index的索引。你可以給一個索引起任何名字,但你應該在索引名中包含所索引的字段名,這對你將來弄清楚建立該索引的意圖是有幫助的。
        注意:
        在本書中你執行任何SQL語句,都會收到如下的信息:
         This command did not return data,and it did not return any rows
    這說明該語句執行成功了。
    索引mycolumn_index對錶mytable的mycolumn字段進行。這是個非聚簇索引,也是個非唯一索引。 (這是一個索引的缺省屬性)
    如果你需要改變一個索引的類型,你必須刪除原來的索引並重建一個。建立了一個索引後,你可以用下面的SQL語句刪除它:

    DROP INDEX mytable.mycolumn_index

    注意在DROP INDEX語句中你要包含表的名字。在這個例子中,你刪除的索引是mycolumn_index,它是表mytable的索引。
    要建立一個聚簇索引,可以使用關鍵字CLUSTERED。 )記住一個表只能有一個聚簇索引。 (這裡有一個如何對一個表建立聚簇索引的例子:

    CREATE CLUSTERED INDEX mycolumn_clust_index ON mytable(mycolumn)

    如果表中有重複的記錄,當你試圖用這個語句建立索引時,會出現錯誤。但是有重複記錄的表也可以建立索引;你只要使用關鍵字ALLOW_DUP_ROW把這一點告訴SQL Sever即可:
     
    CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn)
                          WITH ALLOW_DUP_ROW

    這個語句建立了一個允許重複記錄的聚簇索引。你應該盡量避免在一個表中出現重複記錄,但是,如果已經出現了,你可以使用這種方法。
    要對一個表建立唯一索引,可以使用關鍵字UNIQUE。對聚簇索引和非聚簇索引都可以使用這個關鍵字。這裡有一個例子:

    CREATE UNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn)

    這是你將經常使用的索引建立語句。無論何時,只要可以,你應該盡量對一個對一個表建立唯一聚簇索引來增強查詢操作。
    最後,要建立一個對多個字段的索引──複合索引──在索引建立語句中同時包含多個字段名。下面的例子對firstname和lastname兩個字段建立索引:

    CREATE INDEX name_index ON username(firstname,lastname)

    這個例子對兩個字段建立了單個索引。在一個複合索引中,你最多可以對16個字段進行索引。

    用事務管理器建立索引
    用事務管理器建立索引比用SQL語句容易的多。使用事務管理器,你可以看到已經建立的索引的列表,並可以通過圖形界面選擇索引選項。
    使用事務管理器你可以用兩種方式建立索引:使用Manage Tables窗口或使用Manage Indexes窗口。
        要用Manage Tables窗口建立一個新索引,單擊按鈕Advanced Options(它看起來像一個前面有一加號的表)。這樣就打開了Advanced Options對話框。這個對話框有一部分標名為Primary Key(見圖11.1)。
     
    圖11。1

    要建立一個新索引,從下拉列表中選擇你想對之建立索引的字段名。如果你想建立一個對多字段的索引,你可以選擇多個字段名。你還可以選擇索引是聚簇的還是非聚簇的。在保存表信息後,索引會自動被建立。在Manage Tables窗口中的字段名旁邊,會出現一把鑰匙。
    你已經為你的表建立了“主索引”。主索引必須對不包含空值的字段建立。另外,主索引強制一個字段成為唯一值字段。
    要建立沒有這些限制的索引,你需要使用Manage Indexes窗口。從菜單中選擇Manage|Indexes,打開Manage Indexes窗口。在Manage Indexes窗口中,你可以通過下拉框選擇表和特定的索引。 (見圖11.2)。要建立一個新索引,從Index下拉框中選擇New Index.,然後就可以選擇要對之建立索引的字段。單擊按鈕Add,把字段加人到索引中。

    圖11。2

    你可以為你的索引選擇許多不同的選項。例如,你可以選擇該索引是聚簇的還是非聚簇的。你還可以指定該索引為唯一索引。設計好索引後,單擊按鈕Build,建立該索引。

    注意:
    唯一索引是指該字段不能有重複的值,而不是只能建立這一個索引。

    SQL核心語句
    在第十章,你學會瞭如何用SQL SELECT語句從一個表中取數據。但是,到現在為止,還沒有討論如何添加,修改或刪除表中的數據。在這一節中,你將學習這些內容。

    插入數據
    向表中添加一個新記錄,你要使用SQL INSERT語句。這裡有一個如何使用這種語句的例子:

          INSERT mytable (mycolumn) VALUES (‘some data’)

    這個語句把字符串’some data’插入表mytable的mycolumn字段中。將要被插入數據的字段的名字在第一個括號中指定,實際的數據在第二個括號中給出。
    INSERT語句的完整句法如下:

    INSERT [INTO] {table_name|view_name} [(column_list)] {DEFAULT VALUES |
                     Values_list | select_statement}

    如果一個表有多個字段,通過把字段名和字段值用逗號隔開,你可以向所有的字段中插入數據。假設表mytable有三個字段first_column,second_column,和third_column。下面的INSERT語句添加了一條三個字段都有值的完整記錄:

    INSERT mytable (first_column,second_column,third_column)
             VALUES (‘some data’,’some more data’,’yet more data’)

    注意:
    你可以使用INSERT語句向文本型字段中插入數據。但是,如果你需要輸入很長的字符串,你應該使用WRITETEXT語句。這部分內容對本書來說太高級了,因此不加討論。要了解更多的信息,請參考Microsoft SQL Sever的文檔。

    如果你在INSERT語句中只指定兩個字段和數據會怎麼樣呢?換句話說,你向一個表中插入一條新記錄,但有一個字段沒有提供數據。在這種情況下,有下面的四種可能:
    ■如果該字段有一個缺省值,該值會被使用。例如,假設你插入新記錄時沒有給字段third_column提供數據,而這個字段有一個缺省值’some value’。在這種情況下,當新記錄建立時會插入值’some value’。
    ■如果該字段可以接受空值,而且沒有缺省值,則會被插入空值。
    ■如果該字段不能接受空值,而且沒有缺省值,就會出現錯誤。你會收到錯誤信息:
    The column in table mytable may not be null.
    ■最後,如果該字段是一個標識字段,那麼它會自動產生一個新值。當你向一個有標識字段的表中插入新記錄時,只要忽略該字段,標識字段會給自己賦一個新值。

        注意:
        向一個有標識字段的表中插入新記錄後,你可以用SQL變量@@identity來訪問新記錄
    的標識字段的值。考慮如下的SQL語句:

          INSERT mytable (first_column) VALUES(‘some value’)

          INSERT anothertable(another_first,another_second)
              VALUES(@@identity,’some value’)

        如果表mytable有一個標識字段,該字段的值會被插入表anothertable的another_first字段。這是因為變量@@identity總是保存最後一次插入標識字段的值。
    字段another_first應該與字段first_column有相同的數據類型。但是,字段another_first不能是應該標識字段。 Another_first字段用來保存字段first_column的值。

    刪除記錄
    要從表中刪除一個或多個記錄,需要使用SQL DELETE語句。你可以給DELETE語句提供WHERE子句。 WHERE子句用來選擇要刪除的記錄。例如,下面的這個DELETE語句只刪除字段first_column的值等於’Delete Me’的記錄:
     
    DELETE mytable WHERE first_column=’Deltet Me’

    DELETE語句的完整句法如下:

            DELETE [FROM] {table_name|view_name} [WHERE clause]

    在SQL SELECT語句中可以使用的任何條件都可以在DELECT語句的WHERE子句中使用。例如,下面的這個DELETE語句只刪除那些first_column字段的值為’goodbye’或second_column字段的值為’so long’的記錄:

    DELETE mytable WHERE first_column=’goodby’ OR second_column=’so long’

    如果你不給DELETE語句提供WHERE子句,表中的所有記錄都將被刪除。你不應該有這種想法。如果你想刪除應該表中的所有記錄,應使用第十章所講的TRUNCATE TABLE語句。

    注意:
    為什麼要用TRUNCATE TABLE語句代替DELETE語句?當你使用TRUNCATE TABLE語句時,記錄的刪除是不作記錄的。也就是說,這意味著TRUNCATE TABLE要比DELETE快得多。

    更新記錄
    要修改表中已經存在的一條或多條記錄,應使用SQL UPDATE語句。同DELETE語句一樣,UPDATE語句可以使用WHERE子句來選擇更新特定的記錄。請看這個例子:

    UPDATE mytable SET first_column=’Updated!’ WHERE second_column=’Update Me!’

    這個UPDATE語句更新所有second_column字段的值為’Update Me!’的記錄。對所有被選中的記錄,字段first_column的值被置為’Updated!’。
    下面是UPDATE語句的完整句法:

    UPDATE {table_name|view_name} SET [{table_name|view_name}]
            {column_list|variable_list|variable_and_column_list}
            [,{column_list2|variable_list2|variable_and_column_list2}…
             [,{column_listN|variable_listN|variable_and_column_listN}]]
             [WHERE clause]

    注意:
    你可以對文本型字段使用UPDATE語句。但是,如果你需要更新很長的字符串,應使用UPDATETEXT語句。這部分內容對本書來說太高級了,因此不加討論。要了解更多的信息,請參考Microsoft SQL Sever的文檔。

        
    如果你不提供WHERE子句,表中的所有記錄都將被更新。有時這是有用的。例如,如果你想把表titles中的所有書的價格加倍,你可以使用如下的UPDATE語句:
    你也可以同時更新多個字段。例如,下面的UPDATE語句同時更新first_column,second_column,和third_column這三個字段:

    UPDATE mytable SET first_column=’Updated!’
                          Second_column=’Updated!’
                          Third_column=’Updated!’
                      WHERE first_column=’Update Me1’

    技巧:
    SQL忽略語句中多餘的空格。你可以把SQL語句寫成任何你最容易讀的格式。

    用SELECT創建記錄和表
    你也許已經註意到,INSERT語句與DELETE語句和UPDATE語句有一點不同,它一次只操作一個記錄。然而,有一個方法可以使INSERT語句一次添加多個記錄。要作到這一點,你需要把INSERT語句與SELECT語句結合起來,像這樣:

    INSERT mytable (first_column,second_column)
    SELECT another_first,another_second
    FROM anothertable
    WHERE another_first=’Copy Me!’

    這個語句從anothertable拷貝記錄到mytable.只有表anothertable中字段another_first的值為’Copy Me! ’的記錄才被拷貝。
    當為一個表中的記錄建立備份時,這種形式的INSERT語句是非常有用的。在刪除一個表中的記錄之前,你可以先用這種方法把它們拷貝到另一個表中。
    如果你需要拷貝整個表,你可以使用SELECT INTO語句。例如,下面的語句創建了一個名為newtable的新表,該表包含表mytable的所有數據:
     
    SELECT * INTO newtable FROM mytable

    你也可以指定只有特定的字段被用來創建這個新表。要做到這一點,只需在字段列表中指定你想要拷貝的字段。另外,你可以使用WHERE子句來限制拷貝到新表中的記錄。下面的例子只拷貝字段second_columnd的值等於’Copy Me!’的記錄的first_column字段。
     
    SELECT first_column INTO newtable
    FROM mytable
    WHERE second_column=’Copy Me!’

    使用SQL修改已經建立的表是很困難的。例如,如果你向一個表中添加了一個字段,沒有容易的辦法來去除它。另外,如果你不小心把一個字段的數據類型給錯了,你將沒有辦法改變它。但是,使用本節中講述的SQL語句,你可以繞過這兩個問題。
    例如,假設你想從一個表中刪除一個字段。使用SELECT INTO語句,你可以創建該表的一個拷貝,但不包含要刪除的字段。這使你既刪除了該字段,又保留了不想刪除的數據。
    如果你想改變一個字段的數據類型,你可以創建一個包含正確數據類型字段的新表。創建好該表後,你就可以結合使用UPDATE語句和SELECT語句,把原來表中的所有數據拷貝到新表中。通過這種方法,你既可以修改表的結構,又能保存原有的數據。

    集合函數
    到現在為止,你只學習瞭如何根據特定的條件從表中取出一條或多條記錄。但是,假如你想對一個表中的記錄進行數據統計。例如,如果你想統計存儲在表中的一次民意測驗的投票結果。或者你想知道一個訪問者在你的站點上平均花費了多少時間。要對錶中的任何類型的數據進行統計,都需要使用集合函數。
    Microsoft SQL支持五種類型的集合函數。你可以統計記錄數目,平均值,最小值,最大值,或者求和。當你使用一個集合函數時,它只返回一個數,該數值代表這幾個統計值之一。

    注意:
    要在你的ASP網頁中使用集合函數的返回值,你需要給該值起一個名字。要作到這一點,你可以在SELECT語句中,在集合函數後面緊跟一個字段名,如下例所示:

    SELECT AVG(vote) ‘the_average’ FROM opinion

    在這個例子中,vote的平均值被命名為the_average。現在你可以在你的ASP網頁的數據庫方法中使用這個名字。

    統計字段值的數目
    函數COUNT()也許是最有用的集合函數。你可以用這個函數來統計一個表中有多少條記錄。這裡有一個例子:

    SELECT COUNT(au_lname) FROM authors

    這個例子計算表authors中名字(last name)的數目。如果相同的名字出現了不止一次,該名字將會被計算多次。如果你想知道名字為某個特定值的作者有多少個,你可以使用WHERE子句,如下例所示:

    SELECT COUNT(au_lname) FROM authors WHERE au_lname=’Ringer’

    這個例子返回名字為’Ringer’的作者的數目。如果這個名字在表authors中出現了兩次,則次函數的返回值是2。
    假如你想知道有不同名字的作者的數目。你可以通過使用關鍵字DISTINCT來得到該數目。如下例所示:

    SELECT COUNT(DISTINCT au_lname) FROM authors

    如果名字’Ringer’出現了不止一次,它將只被計算一次。關鍵字DISTINCT決定了只有互不相同的值才被計算。
    通常,當你使用COUNT()時,字段中的空值將被忽略。一般來說,這正是你所希望的。但是,如果你僅僅想知道表中記錄的數目,那麼你需要計算表中所有的記錄─不管它是否包含空值。下面是一個如何做到這一點的例子:

    SELECT COUNT(*) FROM authors

    注意函數COUNT()沒有指定任何字段。這個語句計算表中所有記錄所數目,包括有空值的記錄。因此,你不需要指定要被計算的特定字段。
    函數COUNT()在很多不同情況下是有用的。例如,假設有一個表保存了對你站點的質量進行民意調查的結果。這個表有一個名為vote的字段,該字段的值要么是0,要么是1。0表示反對票,1表示贊成票。要確定贊成票的數量,你可以所有下面的SELECT語句:

    SELECT COUNT(vote) FROM opinion_table WHERE vote=1

    計算字段的平均值
    使用函數COUNT(),你可以統計一個字段中有多少個值。但有時你需要計算這些值的平均值。使用函數AVG(),你可以返回一個字段中所有值的平均值。
    假如你對你的站點進行一次較為複雜的民意調查。訪問者可以在1到10之間投票,表示他們喜歡你站點的程度。你把投票結果保存在名為vote的INT型字段中。要計算你的用戶投票的平均值,你需要使用函數AVG():

    SELECT AVG(vote) FROM opinion

    這個SELECT語句的返回值代表用戶對你站點的平均喜歡程度。函數AVG()只能對數值型字段使用。這個函數在計算平均值時也忽略空值。

    計算字段值的和
    假設你的站點被用來出售卡片,已經運行了兩個月,是該計算賺了多少錢的時候了。假設有一個名為orders的表用來記錄所有訪問者的定購信息。要計算所有定購量的總和,你可以使用函數SUM():

    SELECT SUM(purchase_amount) FROM orders

    函數SUM()的返回值代表字段purchase_amount中所有值的平均值。字段purchase_amount的數據類型也許是MONEY型,但你也可以對其它數值型字段使用函數SUM()。

    返回最大值或最小值
    再一次假設你有一個表用來保存對你的站點進行民意調查的結果。訪問者可以選擇從1到10的值來表示他們對你站點的評價。如果你想知道訪問者對你站點的最高評價,你可以使用如下的語句:

    SELECT MAX(vote) FROM opinion

    你也許希望有人對你的站點給予了很高的評價。通過函數MAX(),你可以知道一個數值型字段的所有值中的最大值。如果有人對你的站點投了數字10,函數MAX()將返回該值。
    另一方面,假如你想知道訪問者對你站點的的最低評價,你可以使用函數MIN(),如下例所示:

    SELECT MIN(vote) FROM opinion

    函數MIN()返回一個字段的所有值中的最小值。如果字段是空的,函數MIN()返回空值。

    其它常用的SQL表達式,函數,和過程
    這一節將介紹一些其它的SQL技術。你將學習如何從表中取出數據,其某個字段的值處在一定的範圍,你還將學習如何把字段值從一種類型轉換成另一種類型,如何操作字符串和日期時間數據。最後,你將學會一個發送郵件的簡單方法。

    通過匹配一定範圍的值來取出數據
    假設你有一個表用來保存對你的站點進行民意調查的結果。現在你想向所有對你的站點的評價在7到10之間的訪問者發送書面的感謝信。要得到這些人的名字,你可以使用如下的SELECT語句:

    SELECT username FROM opinion WHERE vote>6 and vote<11

    這個SELECT語句會實現你的要求。你使用下面的SELECT語句也可以得到同樣的結果:

    SELECT username FROM opinion WHERE vote BETWEEN 7 AND 10

    這個SELECT語句與上一個語句是等價的。使用哪一種語句是編程風格的問題,但你會發現使用表達式BETWEEN的語句更易讀。
    現在假設你只想取出對你的站點投了1或者10的訪問者的名字。要從表opinion中取出這些名字,你可以使用如下的SELECT語句:

    SELECT username FROM opinion WHERE vote=1 or vote

       這個SELECT語句會返回正確的結果,沒有理由不使用它。但是,存在一種等價的方式。使用如下的SELECT可以得到相同的結果:

    SELECT username FROM opinion WHERE vote IN (1,10)

    注意表達式IN的使用。這個SELECT語句只取出vote的值等於括號中的值之一的記錄。
    你也可以使用IN來匹配字符數據。例如,假設你只想取出Bill Gates或President Clinton的投票值。你可以使用如下的SELECT語句:

    SELECT vote FROM opinion WHERE username IN (‘Bill Gates’,’President Clinton’)

    最後,你可以在使用BETWEEN或IN的同時使用表達式NOT。例如,要取出那些投票值不在7到10之間的人的名字,你可以使用如下的SELECT語句:

    SELECT username FROM opinion WHERE vote NOT BETWEEN 7 and 10

    要選取那些某個字段的值不在一列值之中的記錄,你可以同時使用NOT和IN,如下例所示:

    SELECT vote FROM opinion
                 WHERE username NOT IN (‘Bill Gates’,’President Clinton’)

    你不是必須在SQL語句中使用BETWEEN或IN,但是,要使你的查詢更接近自然語言,這兩個表達式是有幫助的。

    轉換數據
    SQL Sever足夠強大,可以在需要的時候把大部分數值從一種類型轉換為另一種類型。例如,要比較SMALLINT型和INT型數據的大小,你不需要進行顯式的類型轉換。 SQL Sever會為你完成這項工作。但是,當你想在字符型數據和其它類型的數據之間進行轉換時,你的確需要自己進行轉換操作。例如,假設你想從一個MONEY型字段中取出所有的值,並在結果後面加上字符串“US Dollars”。你需要使用函數CONVERT(),如下例所示:

    SELECT CONVERT(CHAR(8),price)+’US Dollars’ FROM orders

    函數CONVERT()帶有兩個變量。第一個變量指定了數據類型和長度。第二個變量指定了要進行轉換的字段。在這個例子中,字段price被轉換成長度為8個字符的CHAR型字段。字段price要被轉換成字符型,才可以在它後面連接上字符串’US Dollars’。
    當向BIT型,DATETIME型,INT型,或者NUMERIC型字段添加字符串時,你需要進行同樣的轉換操作。例如,下面的語句在一個SELECT語句的查詢結果中加入字符串’The vote is’,該SELECT語句返回一個BIT型字段的值:

    SELECT ‘The vote is’+CONVERT(CHAR(1),vote) FROM opinion

    下面是這個語句的結果示例:

    The vote is 1
    The vote is 1
    The vote is 0
    (3 row(s) affected)

    如果你不進行顯式的轉換,你會收到如下的錯誤信息:
    Implicit conversion from datatype ‘varchar’ to ‘bit’ is not allowec.
    Use the CONVERT function to run this query.

    操作字符串數據
    SQL Sever有許多函數和表達式,使你能對字符串進行有趣的操作,包括各種各樣的模式匹配和字符轉換。在這一節中,你將學習如何使用最重要的字符函數和表達式。

    匹配通配符
    假設你想建立一個與Yahoo功能相似的Internet目錄。你可以建立一個表用來保存一系列的站點名稱,統一資源定位器(URL),描述,和類別,並允許訪問者通過在HTML form中輸入關鍵字來檢索這些內容。
    假如有一個訪問者想從這個目錄中得到其描述中包含關鍵字trading card的站點的列表。要取出正確的站點列表,你也許試圖使用這樣的查詢:

    SELECT site_name FROM site_directory WHERE site_desc=’trading card’

    這個查詢可以工作。但是,它只能返回那些其描述中只有trading card這個字符串的站點。例如,一個描述為We have the greatest collection of trading cards in the world!的站點不會被返回。
    要把一個字符串與另一個字符串的一部分相匹配,你需要使用通配符。你使用通配符和關鍵字LIKE來實現模式匹配。下面的語句使用通配符和關鍵字LIKE重寫了上面的查詢,以返回所有正確站點的名字:
     
    SELECT SITE_name FROM site_directory
                      WHERE site_desc LIKE ‘%trading cark%’

        在這個例子中,所有其描述中包含表達式trading card的站點都被返回。描述為We have the greatest collection of trading cards in the world!的站點也被返回。當然,如果一個站點的描述中包含I am trading cardboard boxes online ,該站點的名字也被返回。
    注意本例中百分號的使用。百分號是通配符的例子之一。它代表0個或多個字符。通過把trading card括在百分號中,所有其中嵌有字符串trading card的字符串都被匹配。
    現在,假設你的站點目錄變得太大而不能在一頁中完全顯示。你決定把目錄分成兩部分。在第一頁,你想顯示所有首字母在A到M之間的站點。在第二頁,你想顯示所有首字母在N到Z之間的站點。要得到第一頁的站點列表,你可以使用如下的SQL語句:

    SELECT site_name FROM site_directory WHERE site_name LIKE ‘[AM]%’

    在這個例子中使用了表達式[AM],只取出那些首字母在A到M之間的站點。中括號([])用來匹配處在指定範圍內的單個字符。要得到第二頁中顯示的站點,應使用這個語句:

    SELECT site_name FROM site_directory
                      WHERE site_name LIKE ‘[N-Z]%’

    在這個例子中,括號中的表達式代表任何處在N到Z之間的單個字符。
    假設你的站點目錄變得更大了,你現在需要把目錄分成更多頁。如果你想顯示那些以A,B或C開頭的站點,你可以用下面的查詢來實現:
     
    SELECT site_name FROM site_directory WHERE site_name LIKE ‘[ABC]%’

    在這個例子中,括號中的表達式不再指定一個範圍,而是給出了一些字符。任何一個其名字以這些字符中的任一個開頭的站點都將被返回。
    通過在括號內的表達式中同時包含一個範圍和一些指定的字符,你可以把這兩種方法結合起來。例如,用下面的這個查詢,你可以取出那些首字母在C到F之間,或者以字母Y開頭的站點:

    SELECT site_name FROM site_directory WHERE site_name LIKE ‘[C-FY]%’

    在這個例子中,名字為Collegescape和Yahoo的站點會被選取,而名字為Magicw3的站點則不會被選取。
    你也可以使用脫字符(^)來排除特定的字符。例如,要得到那些名字不以Y開頭的站點,你可以使用如下的查詢:

    SELECT site_name FROM site_directory WHERE site_name LIKE ‘[^Y]%’

    對給定的字符或字符範圍均可以使用脫字符。
    最後,通過使用下劃線字符(_),你可以匹配任何單個字符。例如,下面這個查詢返回每一個其名字的第二個字符為任何字母的站點:

    SELECT site_name FROM site_directory WHERE site_name LIKE ‘M_crosoft’

    這個例子既返回名為Microsoft的站點,也返回名為Macrosoft的站點。但是,名字為Moocrosoft的站點則不被返回。與通配符’%’不同,下劃線只代表單個字符。

    注意:
    如果你想匹配百分號或下劃線字符本身,你需要把它們括在方括號中。如果你想匹配連字符(-),應把它指定為方括號中的第一個字符。如果你想匹配方括號,應把它們也括在方括號中。例如,下面的語句返回所有其描述中包含百分號的站點:

         SELECT site_name FROM site_directory WHERE site_desc LIKE ‘%[%]%’
    匹配發音
    Microsoft SQL有兩個允許你按照發音來匹配字符串的函數。函數SOUNDEX()給一個字符串分配一個音標碼,函數DIFFERENCE()按照發音比較兩個字符串。當你不知道一個名字的確切拼寫,但多少知道一點它的發音時,使用這兩個函數將有助於你取出該記錄。
    例如,如果你建立一個Internet目錄,你也許想增加一個選項,允許訪問者按照站點名的發音來搜索站點,而不是按名字的拼寫。考慮如下的語句:

    SELECT site_name FROM site_directory
                      WHERE DIFFERENCE(site_name , ‘Microsoft’>3

    這個語句使用函數DEFFERENCE()來取得其名字的發音與Microsoft非常相似的站點。函數DIFFERENCE()返回一個0到4之間的數字。如果該函數返回4,表示發音非常相近;如果該函數返回0,說明這兩個字符串的發音相差很大。
    例如,上面的語句將返回站點名Microsoft和Macrosoft。這兩個名字的發音與Microsoft都很相似。如果你把上一語句中的大於3改為大於2,那麼名為Zicrosoft和Megasoft的站點也將被返回。最後,如果你只需要差別等級大於1即可,則名為Picosoft和Minisoft的站點也將被匹配。
    要深入了解函數DIFFERENCE()是如何工作的,你可以用函數SOUNDEX()來返回函數DIFFERENCE()所使用的音標碼。這裡有一個例子:

    SELECT site_name ‘site name’,SOUNDEX(site_name) ‘sounds like’

    這個語句選取字段site_name的所有數據及其音標碼。下面是這個查詢的結果:

    site name sounds like
    ……………………………………………………………….
    Yahoo Y000
    Mahoo M000
    Microsoft M262
    Macrosoft M262
    Minisoft M521
    Microshoft M262
    Zicrosoft Z262
    Zaposoft Z121
    Millisoft M421
    Nanosoft N521
    Megasoft M221
    Picosoft P221
    (12 row(s) affected)

    如果你仔細看一下音標碼,你會注意到音標碼的第一個字母與字段值的第一個字母相同。例如,Yahoo和Mahoo的音標碼只有第一個字母不同。你還可以發現Microsoft和Macrosoft的音標碼完全相同。
    函數DIFFERENDE()比較兩個字符串的第一個字母和所有的輔音字母。該函數忽略任何元音字母(包括y),除非一個元音字母是一個字符串的第一個字母。
    不幸的是,使用SOUNDEX()和DIFFERENCE()有一個欠缺。 WHERE子句中包含這兩個函數的查詢執行起來效果不好。因此,你應該小心使用這兩個函數。

    刪除空格
    有兩個函數,TTRIM()和LTRIM(),可以用來從字符串中剪掉空格。函數LTRIM()去除應該字符串前面的所有空格;函數RTRIM()去除一個字符串尾部的所有空格。這裡有一個任何使用函數RTRIM()的例子:

    SELECT RTRIM(site_name) FROM site_directory

    在這個例子中,如果任何一個站點的名字尾部有多餘的空格,多餘的空格將從查詢結果中刪去。
    你可以嵌套使用這兩個函數,把一個字符串前後的空格同時刪去:

    SELECT LTRIM(RTRIM(site_name) FROM site_directory

    你會發現,在從CHAR型字段中剪掉多餘的空格時,這兩個函數非常有用。記住,如果你把一個字符串保存在CHAR型字段中,該字符串會被追加多餘的空格,以匹配該字段的長度。用這兩個函數,你可以去掉無用的空格,從而解決這個問題。

    操作日期和時間
    日期和時間函數對建立一個站點是非常有用的。站點的主人往往對一個表中的數據何時被更新感興趣。通過日期和時間函數,你可以在毫秒級跟踪一個表的改變。

    返回當前日期和時間
    通過函數GETDATE(),你可以獲得當前的日期和時間。例如,語句SELECT GETDATE()返回如下的結果:
    ……………………………..
         NOV 30 1997 3:29AM
    (1 row(s) affected)

    顯然,如果你將來使用這個函數,你得到的日期將比這個時間晚,或者梗早。
    函數GETDATE()可以用來作為DATEDIME()型字段的缺省值。這對插入記錄時保存當時的時間是有用的。例如,假設有一個表用來保存你站點上的活動日誌。每當有一個訪問者訪問到你的站點時,就在表中添加一條新記錄,記下訪問者的名字,活動,和進行訪問的時間。要建立一個表,其中的記錄包含有當前的日期和時間,可以添加一個DATETIME型字段,指定其缺省值為函數GETDATE()的返回值,就像這樣:

    CREATE TABLE site_log (
            username VARCHAR(40),
            useractivity VARCHAR(100),
            entrydate DATETIME DEFAULT GETDATE())

    轉換日期和時間
    你也許已經註意到,在上一節的例子中,函數GETDATE()的返回值在顯示時只顯示到秒。實際上,SQL Sever內部時間可以精確到毫秒級(確切地說,可以精確到3.33毫秒)。
    要得到不同格式的日期和時間,你需要使用函數CONVERT()。例如,當下面的這個語句執行時,顯示的時間將包括毫秒:

    SELECT CONVERT(VARCHAR(30),GETDATE(),9)

    注意例子中數字9的使用。這個數字指明了在顯示日期和時間時使用哪種日期和時間格式。當這個語句執行時,將顯示如下的日期和時間:
    …………………………………..
    Nov 30 1997 3:29:55:170AM
    (1 row(s) affected)

    在函數CONVERT()中你可以使用許多種不同風格的日期和時間格式。表11.1顯示了所有的格式。

    表11.1日期和時間的類型
    類型值標準輸出
        0 Default mon dd yyyy hh:miAM
        1 USA mm/dd/yy
        2 ANSI yy.mm.dd
        3 British/French dd/mm/yy
        4 German dd.mm.yy
        5 Italian dd-mm-yy
        6 – dd mon yy
        7 – mon dd,yy
        8 – hh:mi:ss
    9 Default + milliseconds–mon dd yyyy
    hh:mi:ss:mmmAM(or )
        10 USA mm-dd-yy
        11 JAPAN yy/mm/dd
        12 ISO yymmdd
        13 Europe Default + milliseconds–dd mon yyyy
                                            hh:mi:ss:mmm(24h)
        14 – hh:mi:ss:mmm(24h)

       類型0,9,和13總是返回四位的年。對其它類型,要顯示世紀,把style值加上100。類型13和14返回24小時時鐘的時間。類型0,7,和13返回的月份用三位字符表示(用Nov代表November).

    對錶11.1中所列的每一種格式,你可以把類型值加上100來顯示有世紀的年(例如,00年將顯示為2000年)。例如,要按日本標準顯示日期,包括世紀,你應使用如下的語句:

    SELECT CONVERT(VARCHAR(30),GETDATE(),111)

        在這個例子中,函數CONVERT()把日期格式進行轉換,顯示為1997/11/30

    抽取日期和時間
    在許多情況下,你也許只想得到日期和時間的一部分,而不是完整的日期和時間。例如,假設你想列出你的站點目錄中每個站點被查詢的月份。這時你不希望完整的日期和時間把網頁弄亂。為了抽取日期的特定部分,你可以使用函數DATEPART(),像這樣:

    SELECT site_name ‘Site Name’,
    DATEPART(mm,site_entrydate) ‘Month Posted’ FROM site_directory

    函數DATEPART()的參數是兩個變量。第一個變量指定要抽取日期的哪一部分;第二個變量是實際的數據。在這個例子中,函數DATEPART()抽取月份,因為mm代表月份。下面是這個SELECT語句的輸出結果:

    Site Name Month Posted
    ………………………………………………………………
    Yahoo 2
    Microsoft 5
    Magicw3 5
    (3 row(s) affected)

        Month Posted列顯示了每個站點被查詢的月份。函數DATEPART()的返回值是一個整數。你可以用這個函數抽取日期的各個不同部分,如表11.2所示。

    表11.2日期的各部分及其簡寫
    日期部分簡寫值
    year yy 1753–9999
    quarter qq 1–4
    month mm 1–12
    day of year dy 1–366
    day dd 1–31
    week wk 1–53
    weekday dw 1–7(Sunday–Saturday)
    hour hh 0–23
    minute mi 0–59
    second ss 0–59
    milisecond ms 0–999

    當你需要進行日期和時間的比較時,使用函數DATEPART()返回整數是有用的。但是,上例中的查詢結果(2,5)不是十分易讀。要以更易讀的格式得到部分的日期和時間,你可以使用函數DATENAME(),如下例所示:
     
    SELECT site_name ‘Site Name’
    DATENAME(mm,site_entrydate) ‘Month Posted’
    FROM site_directory

    函數DATENAME()和函數DATEPART()接收同樣的參數。但是,它的返回值是一個字符串,而不是一個整數。下面是上例該用DATENAME()得到的結果:

    Site Name Month Postec
    ………………………………………………………………….
    Yahoo February
    Microsoft June
    Magicw3 June
    (3 row(s) affected)

    你也可以用函數DATENAE()來抽取一個星期中的某一天。下面的這個例子同時抽取一周中的某一天和日期中的月份:

    SELECT site_name ‘Site Name’,
    DATENAME(dw,site_entrydate)+ ‘-’ + DATENAME(mm,site_entrydate)
              ‘Day and Month Posted’ FORM site_directory

    這個例子執行時,將返回如下的結果:

    Site Name Day and Month Posted
    ………………………………………………………………………
    Yahoo Friday – February
    Microsoft Tuesday – June
    Magicw3 Monday – June
    (3 row(s) affected)

    返回日期和時間範圍
    當你分析表中的數據時,你也許希望取出某個特定時間的數據。你也許對特定的某一天中――比如說2000年12月25日――訪問者在你站點上的活動感興趣。要取出這種類型的數據,你也許會試圖使用這樣的SELECT語句:

    SELECT * FROM weblog WHERE entrydate=”12/25/20000”

    不要這樣做。這個SELECT語句不會返回正確的記錄――它將只返回日期和時間是12/25/2000 12:00:00:000AM的記錄。換句話說,只有剛好在午夜零點輸入的記錄才被返回。

    注意:
    在本節的討論中,假設字段entrydate是DATETIME型,而不是SMALLDATETIME型。本節的討論對SMALLDATETIME型字段也是適用的,不過SMALLDATETIME型字段只能精確到秒。

    問題是SQL Sever將用完整的日期和時間代替部分日期和時間。例如,當你輸入一個日期,但不輸入時間時,SQL Sever將加上缺省的時間“12:00:00:000AM”。當你輸入一個時間,但不輸入日期時,SQL Sever將加上缺省的日期“Jan 1 1900”。
    要返回正確的記錄,你需要適用日期和時間範圍。有不止一種途徑可以做到這一點。例如,下面的這個SELECT語句將能返回正確的記錄:

    SELECT * FROM weblog
    WHERE entrydate>=”12/25/2000” AND entrydate<”12/26/2000”

    這個語句可以完成任務,因為它選取的是表中的日期和時間大於等於12/25/2000 12:00:00:000AM並小於12/26/2000 12:00:00:000AM的記錄。換句話說,它將正確地返回2000年聖誕節這一天輸入的每一條記錄。
    另一種方法是,你可以使用LIKE來返回正確的記錄。通過在日期表達式中包含通配符“%”,你可以匹配一個特定日期的所有時間。這裡有一個例子:

    SELECT * FROM weblog WHERE entrydate LIKE ‘Dec 25 2000%’

    這個語句可以匹配正確的記錄。因為通配符“%”代表了任何時間。
    使用這兩種匹配日期和時間範圍的函數,你可以選擇某個月,某一天,某一年,某個小時,某一分鐘,某一秒,甚至某一毫秒內輸入的記錄。但是,如果你使用LIKE來匹配秒或毫秒,你首先需要使用函數CONVERT()把日期和時間轉換為更精確的格式(參見前面“轉換日期和時間”一節)。

    比較日期和時間
    最後,還有兩個日期和時間函數對根據日期和時間取出記錄是有用的。使用函數DATEADD()和DATEDIFF(),你可以比較日期的早晚。例如,下面的SELECT語句將顯示表中的每一條記錄已經輸入了多少個小時:

    SELECT entrydate ‘Time Entered’
    DATEDIFF(hh,entrydate,GETDATE()) ‘Hours Ago’ FROM weblog

    如果當前時間是2000年11月30號下午6點15分,則會返回如下的結果:

    Time Entered Hours Ago
    …………………………………………………..
    Dec 30 2000 4:09PM 2
    Dec 30 2000 4:13PM 2
    Dec 1 2000 4:09PM 698
    (3 row(s) affected)

    函數DADEDIFF()的參數是三個變量。第個變量指定日期的某一部分。在這個例子中,是按小時對日期進行比較,(要了解日期各部分的詳細內容,請參考表11.2)在日期2000年11月1日和2000年11月30日的指定時間之間有689個小時。另外兩個參數是要進行比較的時間。為了返回一個正數,較早的時間應該先給。
    函數DATEADD()把兩個日期相加。當你需要計算截止日期這一類的數據時,這個函數是有用處的。例如,假設訪問者必須先註冊才能使用你的站點。註冊以後,他們可以免費使用你的站點一個月。要確定什麼時候他們的免費時間會用完,你可以使用如下的SELECT語句:

    SELECT username ‘User Name’,
    DATEADD(mm,1,firstvisit_date) ‘Registration Expires’
    FROM registration_table

    函數DATEADD()的參數有三個變量。第一個變量代表日期的某一部分(參見表11.2),這個例子用到了代表月份的mm。第二個變量指定了時間的間隔――在本例中是一個月。最後一個變量是一個日期,在這個例子中,日期是取自DATETIME型字段firstvisit_date.假設當前日期是June 30,2000,這個語句將返回如下的內容:

    User Name Registration Expires
    ……………………………………………………………………………
    Bill Gates Jul 30 2000 4:09PM
    President Clinton Jul 30 2000 4:13PM
    William Shakespeare Jul 1 2000 4:09PM
    (3 row(s) affected)

    注意:
    與你預料的相反,使用函數DATEADD()把一個日期加上一個月,它並不加上30天。這個函數只簡單地把月份值加1。這意味著在11月註冊的人將比在2月註冊的人多得到2天或3天的時間。要避免這個問題,你可以用函數DATEADD()直接增加天數,而不是月份。

    發送郵件
    你可以用SQL Sever發送簡單的e_mail信息。要做到這一點,你需要在你的系統中安裝郵件服務器,如Microsoft Exchange Sever(參見第四章“Exchange Active Sever,Index Sever,和NetShow”)。你還需要配置SQL Sever以識別郵件服務器。
    要讓SQL Sever能識別郵件服務器,啟動事務管理器並從菜單中選擇Sever|SQL Mail|Configue,這時會出現一個如圖11.3所示的對話框。輸入你在郵件服務器中註冊的用戶名和口令,然後單擊OK。

    注意:
    如果你使用Microsoft Exchange Sever,配置SQL Sever的過程將會大大不同。你需要在同一個(域)用戶帳號下運行Microsoft SQL Sever和Exchange Sever。你還需要在安裝了SQL Sever的機器上安裝Exchange Cliect並給這個帳號創建一個一個配置文件。完成這些之後,你就可以在SQL Mail Configuration對話框中輸入該配置文件的名字。
     
    圖11。3

    在發送郵件之前,你要先啟動SQL Mail。從菜單中選擇Sever|SQL Mail|Start。如果你的郵件服務器配置正確,並且你輸入了正確的用戶名和口令,則SQL Mail會成功啟動。

    注意:
    你可以把SQL Sever配置為自動啟動郵件服務。要做到這一點,在Set Sever Optons對話框(從菜單中選擇Sever|SQL Sever|Configure)中選擇Auto Start Mail Client即可。

    要發送一個郵件,你可以使用名為xp_sendmail的擴展存儲過程。這裡有一個如何使用這個過程的例子:

    master..xp_sendmail “president@whitehouse.gov”,”Hello Mr. President”

    這個過程調用向e_mail地址president@whitehouse.gov發送一個簡單的email信息:“Hello Mr. President”。你可以用任何其它的email地址和信息取代上例中相應的內容,但是,你所發送的信息不能超過255個字符長度。
        當你想隨時了解你的站點數據庫的狀態時,存儲過程xp_sendmail是有用處的。例如,你可以向一個頁面管理程序發送信息。如果你的站點出了什麼問題,你馬上就可以知道。下一章將講述更多有關存儲過程的內容。

    總結
    這一章加深了你的SQL知識。你學會瞭如何建立索引,使你的查詢速度更快。你還學會瞭如何插入,刪除和更新一個表中的數據,如何使用集合函數得到一個表中數據的統計信息。最後,你學會了許多有價值的表達式,函數和過程,用來操作字符串,日期和時間及郵件。
    下一章將進一步加深你對Microsoft SQL Sever的掌握。你將學習如何用SQL來進行程序設計,如何建立存儲過程,觸發器和執行計劃。更另人興奮的是,你將學會讓SQL Sever自動創建網頁的一個簡單方法。

  • Cisco最近公佈了一項新的專家級網絡設計認證——CCDE

    CCDE 專家級網絡設計認證

     思科網站原文:

    Program Updates – 1/22/08
    Cisco Announces New “Expert” Network Design Certification Program
    Cisco is announcing an expansion of its Network Design certification track to include a Network Design Expert designation,

    the Cisco Certified Design Expert (CCDE). The CCDE certification is a certification that identifies those with expert-

    level knowledge and skills in Infrastructure Design. CCDE is parallel to CCIE in terms of difficulty, and expertise. It

    emphasizes network design principles and theory at the Layer 3 level or Routing layer and recognizes expertise of

    designers that have the knowledge to assess network business requirements and can translate them into technical

    specifications to be incorporated into successful designs.

    The new Expert program is modeled after the industry leading CCIE program with a “qualification” and subsequent

    “practical” exam. Currently, the qualification exam is available worldwide at any Pearson VUE testing center. The

    practical exam is still in development and is expected to be released later this year.

    For more information visit the CCDE page

    來源:www.itcert.org

  • 如何加強Linux操作系統安全的配置說明

    眾所周知,網絡安全是一個非常重要的課題,而服務器是網絡安全中最關鍵的環節。 Linux被認為是一個比較安全的Internet服務器,作為一種開放源代碼操作系統,一旦Linux系統中發現有安全漏洞,Internet上來自世界各地的志願者會踴躍修補它。然而,系統管理員往往不能及時地得到信息並進行更正,這就給黑客以可乘之機。相對於這些系統本身的安全漏洞,更多的安全問題是由不當的配置造成的,可以通過適當的配置來防止。下面就簡單列出以下幾點,以供大家參考:

    1、用防火牆關閉不須要的任何端口,別人PING不到服務器,威脅自然減少了一大半

    防止別人ping的方法:

    1)命令提示符下打

    echo 1> /proc/sys/net/ipv4/icmp_ignore_all

    2)用防火牆禁止(或丟棄)icmp包

    iptables -A INPUT -p icmp -j DROP

    3)對所有用ICMP通訊的包不予響應

    比如PING TRACERT

    2、更改SSH端口,最好改為10000以上,別人掃描到端口的機率也會下降

    vi /etc/ssh/sshd_config

    將PORT改為1000以上端口

    同時,創建一個普通登錄用戶,並取消直接root登錄

    useradd ‘username’

    passwd ‘username’

    vi /etc/ssh/sshd_config

    在最後添加如下一句:

    PermitRootLogin no #取消root直接遠程登錄

    3、刪除系統臃腫多餘的賬號: userdel adm userdel lp userdel sync userdel shutdown userdel halt userdel news userdel uucp userdel operator userdel games userdel gopher userdel ftp如果你不允許匿名FTP,就刪掉這個用戶帳號groupdel adm groupdel lp groupdel news groupdel uucp groupdel games groupdel dip groupdel pppusers

    4、更改下列文件權限,使任何人沒有更改賬戶權限: chattr +i /etc/passwd chattr +i /etc/shadow chattr +i /etc/group chattr +i /etc/gshadow

    5、chmod 600 /etc/xinetd.conf

    6、關閉FTP匿名用戶登陸

  • 怎样學習C語言

    很多人對學習c語言感到無從下手,經常問我同一個問題:究竟怎樣學習c語言?我是一個教師,已經開發了很多年的程序,和很多剛剛起步的人一樣,學習的第一個計算機語言就是c語言。經過這些年的開發,我深深的體會到c語言對於一個程序設計人員多麼的重要,如果不懂c語言,你想寫底層程序這幾乎聽起來很可笑,不懂c語言,你想寫出優秀高效的程序,這簡直就是天方夜譚。為什麼c語言如此重要呢?

        第一:c語言語法結構很簡潔精妙,寫出的程序也很高效,很便於描述算法,大多數的程序員願意使用c語言去描述算法本身,所以,如果你想在程序設計方面有所建樹,就必須去學它。

        第二:c語言能夠讓你深入系統底層,你知道的操作系統,哪一個不是c語言寫的?所有的windows,unix,linux,mac,os/2,沒有一個里外的,如果你不懂c語言,怎麼可能深入到這些操作系統當中去呢?更不要說你去寫它們的內核程序了。

        第三:很多新型的語言都是衍生自c語言,c++,java,c#,j#,perl……哪個不是呢?掌握了c語言,可以說你就掌握了很多門語言,經過簡單的學習,你就可以用這些新型的語言去開發了,這個再一次驗證了c語言是程序設計的重要基礎。還有啊,多說一點:即使現在招聘程序員,考試都是考c語言,你想加入it行業,那麼就一定要掌握好c語言。

        那麼究竟怎樣學習c語言呢?

         1.工欲善其事,必先利其器

        這裡介紹幾個學習c語言必備的東東:

        一個開發環境,例如turbo c 2.0,這個曾經佔據了dos時代開發程序的大半個江山。但是現在windows時代,用turbo c有感覺不方面,編輯程序起來很吃力,並且拖放,更沒有函數變量自動感應功能,查詢參考資料也不方便。建議使用visual c++,這個東西雖然比較大塊頭,但是一旦安裝好了,用起來很方便。

        一本學習教程,現在c語言教材多如牛毛,但推薦大家使用《c語言程序設計》譚浩強主編第二版清華大學出版社,此書編寫的很適合初學者,並且內容也很精到。

        除此以外,現在有很多輔助學習的軟件,畢竟現在是window時代了,學習軟件多如牛毛,不像我們當初學習,只有讀書做題這麼老套。我向大家推荐一個“集成學習環境(c語言)”,裡邊的知識點總結和例程講解都非常好,還有題庫測試環境,據說有好幾千題,甚至還有一個windows下的trubo c,初學者甚至不用裝其它的編譯器,就可以練習編程了,非常適合初學者。還有一個“c語言學習系統”軟件,不過感覺只是一個題庫系統,如果你覺得題做的不夠,不妨也可以試試。

         2.葵花寶典

        學習計算機語言最好的方法是什麼?答曰:讀程序。

        沒錯,讀程序是學習c語言入門最快,也是最好的方法。如同我,現在學習新的j#,c#等其他語言,不再是抱著書本逐行啃,而是學習它們的例程。當然,對於沒有學過任何計算機語言的初學者,最好還是先閱讀教程,學習完每一章,都要認真體會這一章的所有概念,然後不放過這一章中提到的所有例程,然後仔細研讀程序,直到每一行都理解了,然後找幾個編程題目,最好是和例程類似的或一樣的,自己試圖寫出這段已經讀懂的程序,不要以為例程你已經讀懂了,你就可以寫出和它一樣的程序,絕對不一定,不相信你就試一試吧,如果寫不出來,也不要著急,回過頭來再繼續研究例程,想想自己為什麼寫不出來,然後再去寫這段程序,反反复复,直到你手到擒來為止,祝賀你,你快入門了。

         3.登峰造極

        寫程序的最高境界其實就是掌握各種解決問題的手段(數據結構)和解決問題的方法(算法)。

        是不是寫出底層程序就是程序設計高手呢?非也,寫底層程序,無非是掌握了硬件的結構,況且硬件和硬件還不一樣,要給一個芯片寫驅動程序,無非就是掌握這塊芯片的各種寄存器及其組合,然後寫值讀值,僅此而已。這不過是熟悉一些io函數罷了。那麼怎樣才算精通程序設計呢?怎樣才能精通程序設計呢?舉個例子:你面前有10個人,找出一個叫“張三”的人,你該怎麼辦?第一種方法:直接對這10個人問:“誰叫張三”。第2種方法:你挨個去問“你是不是張三?”,直到問到的這個人就是張三。第三種方法:你去挨個問一個人“你認不認識張三,指給我看”。不要小看這個問題,你說當然會選第一種方法,沒錯恭喜你答對了,因為這個方法最快,效率最高,但是在程序設計中找到解決問題的最優方法和你用的手段卻是考驗一個程序員程序設計水平的重要標誌,而且是不容易達到的。剛才這個問題類似於數據結構和算法中的:map數據結構,窮舉查找和折半查找。所以掌握好數據結構和一些常用算法,是登峰造極的必然之路。最後給大家推薦嚴尉敏的《數據結構》清華大學出版社,希望每一個想成為程序設計高手的人研讀此書。

  • IT認證的應該注意事項

    1、明確考證的目的

    現在許多大學生考證主要是迫於工作的壓力,往往會簡單認為多一個證書等於是多了一項謀生的資本,而且證書還能幫助自己獲得比其他人高得多的待遇和地位,於是這些人往往會去片面地追求一紙證書,而根本就不會把自己的認證考試和自己的特長以及目前所從事的工作結合起來,他們往往會參加一些社會上舉辦的什麼“考證速成班”,通過死記硬背的突擊方法來獲取一張可能對工作能力毫無助益的證書。

    而有的大學生或者是已工作的中青年考證主要是為自己“充電”,提高自己的自身素質和知識層次,以便為自己將來的職業重新進行規劃打基礎。這些人有一個共同的特點就是對自己所學的專業和大學學習心中底氣不足,希望能通過多參加各種專業認證教育來彌補自己的知識層次和技術水平,這些人往往是為了獲取真正的知識,會十分注重認證考試的能力和實力。

    2、正確認識證書的價值

    在一般人的心目中,IT證書是個人能力和才華的書面證明,IT證書多意味著本領高、能力強,或許在過去的就業模式下,IT證書的多少可能會影響到求職的成功,然而在當今追求實際效益的今天,IT證書在求職中到底又能起到多大作用呢?

    一些老闆和人事專員說,擁有電腦技術、軟件程序或操作系統證書,並不能保證你獲得一份工作,因為持證者所學知識可能足以通過考試,但卻無法應付工作。因此,我們可以這樣來評價IT證書的作用:如果你有工作經驗,證書就很有價值,它的確能表明你熟悉程序員或網絡工程師應該掌握的東西。
    有的人對現在的人才市場狀況不太了解,總是想當然地認為證書就是求職的通行證,於是可能會去參加什麼速成班,拿到證書之後就去進軍自己所希望的行當,可到頭來只能是一場空。因此如果你是這種想法的話,那最好得換一下腦筋。當然,話又得說回來,如果你確實對某些行業感興趣並希望到那些行業中去工作時,可能也會去參加一些專業培訓班來提高自己的能力,最後也有可能勝任新行業的工作。

    3、要注重培訓過程和內容

    正確認識到證書的價值以後,相信眾多的大學生肯定明白參加認證培訓不僅僅是交點錢、再死記硬背一些考試題目那麼簡單。

    大學生一定要端正學習態度,不要走為了應付考試去背題目這樣的捷徑。具體表現在應該先認真學習認證培訓所要求的理論知識,並按照任課教師制定的各項考核任務來指導安排自己的學習計劃和學習步驟,在參加完培訓之後,應立即進行知識的學習和課堂知識的反思,這能加強記憶效果,真正吸收課堂的講課內容,同時,在條件允許的情況下,多參加一些網上的交流和論壇,將對大家的學習和項目管理能力的提高有很大的幫助;其次在培訓過程中,每一位參加認證培訓的大學生要能完成一份符合《培訓與考試大綱》要求、並能體現個性和創造性的作業設計;再有就是在過程式考核與作業設計過程中,只記成功,不記失敗,理論考核通過以後再繼續進行實踐操作的加強和鞏固。

    4、注重實際操作技能

    IT認證培訓不僅僅是理論上學習,它更強調的是實際操作技能的培訓。因此大學生應該先註重能力和經驗的積累。在去正式考證之前,先從低級職位做起,利用晚上時間再去讀證書。用人單位可能更喜歡已在業內開始工作的應聘者,而不是雖有證書但仍在非相關領域工作的求職者。因此培訓與考試都應該圍繞“技能”這一主題展開的,主要表現在:大學生在每一階段的學習培訓中,都應該給自己制定一個與理論培訓內容相適應的技能培訓目標,例如根據理論知識點來製定相關的技能操作要點;其次,要提高實際操作技能的水平的話,惟有不斷地上機實踐操作,一般情況下要將自己的上機操作時間控制在整個認證培訓時間的70%這一數字上。

    5、正確給自己定位

    目前IT認證考試的種類很多,如何選擇還需三思而後行。

    大家應該首先明白,每種證書考試培訓費和考試費從數十元到上千元不等,如果每一種認證考試都參加的話,顯然在經濟上是不能承受的,況且大學生自己也沒有足夠的經歷和時間去應對每一種認證培訓。因此正確的做法就是根據自己的實際情況,來選擇合適的一個或者幾個認證考試來參加;例如根據自己日後可能從事的工作來選擇,或者根據社會所迫切需要的人才要求來選擇,也可以根據自己的個人愛好以及在學校所學習的專業要求來選擇。總之,自己所選擇的認證考試,要對自己的將來工作要有幫助,否則獲得的認證證書再多,如果日後根本就使用不到,就會白白浪費了大學時期寶貴的專業學習和訓練機會。

    6、正確選定培訓機構

    面對各式各樣的培訓機構,大家變得有點無從選擇,那到底該如何選擇培訓機構呢?

    首先,應該看培訓機構的師資力量,IT認證培訓畢竟是知識含量要求很高的培訓,培訓講師水平的高低會給培訓帶來直接的影響;因此,在參加認證考前培訓班時,對培訓機構的老師應重點考察老師是否具有豐富的實踐操作技能,因為認證培訓是一門實踐性極強的學科,必須由實際操作技能豐富的老師講解,才能比較透徹和深入;另外還要看他是否有豐富的講課經驗和水平,有的老師滿腹經綸,但講課水平不高,這種培訓會浪費大家的時間和金錢。

    其次,要選擇影響比較大的培訓機構。辦學條件也是影響培訓效果的一個重要因素。如果沒有擬真度較高的環境,其教學與實踐將會脫節。因此,在參加培訓前不妨到培訓現場看一看,實地考察一番。最後應該看一下培訓機構對培訓課程的安排是否得當。

    7、要有持續學習的準備

    不少人認為在獲取認證資格證書後,就可以躺在證書上吃老本了,這種認識是非常錯誤的。因為IT技術本身進步就非常快,在校時學習的IT內容可能是屬於熱門實用的IT技能,但是到了自己參加工作後,將有新的IT技術不斷湧現,先前獲取的證書可能一點用也沒有了了,所以在參加認證考試時一定要做好持續學習的思想準備。

    8、切忌盲目認證

    不少人由於不能正確認識證書的價值,今天看到這個證書熱門就去參加這個認證培訓班,明天看到另外一種證書吃香了,又趕快報名參加另外一種培訓班。其實,不同的認證證書代表了培訓機構、用人單位和考證者對市場不同的理解。大家應該保持一份冷靜和成熟,在參加報名認證考試之前,一定要詳細了解該證書的適合人群、面向的市場領域、含金量之後,再去選擇那些適合自己的認證考試,切記不要盲目趕潮。 (來源:網絡)

  • PEARSON VUE考試中心介紹

    PEARSON VUE

    公司概覽
      
    Pearson是一家大型的跨國傳媒公司,在教育、出版和商務信息領域內,一直居於世界領先地位。
      
    PEARSON於2001年在倫敦和紐約的證券交易所掛牌上市。並於同年,銷售額超過了61億美元,利潤達6.22億美元!
    Pearson VUE
      
    PEARSON VUE是PEARSON EDUCATION旗下從事電子化考試的服務機構,它致力於依靠快捷的互聯網絡,先進的計算機技術及優質的服務,為您提供安全、可靠且實用的國際認證考試和安全職業執照及認證程序。考試將通過全美200家公司運行的PEARSON職業認證中心和全球3400家VUE授權認證中心進行。範圍覆蓋了美國、澳洲、日本、印度、荷蘭、中國等地區和國家。
      
    目前通過Pearson VUE傳輸考試的公司有:Microsoft, Cisco, CompTIA, IBM, Novell, NCLES, NASD,英國教師培訓機構,美國大學等等。

    Pearson VUE是全球著名的考試中心之一。陝圖時代是Pearson VUE授權考試中心,可進行多種IT考試。