簡介
SQL全稱是“結構化查詢語言(Structured Query Language)”,最早的是IBM的聖約瑟研究實驗室為其關係資料庫管理系統SYSTEM R開發的一種查詢語言,它的前身是SQUARE語言。SQL語言結構簡潔,功能強大,簡單易 學,所以自從IBM公司1981年推出以來,SQL語言,得到了廣泛的套用。如今無論是像Oracle ,Sybase,Informix,SQL server這些大型的資料庫管理系統,還是像Visual Foxporo,PowerBuilder這些微機上常用的資料庫開發系統,都支持SQL語言作為查詢語言。語言介紹
SQL是高級的非過程化程式語言,允許用戶在高層數據結構上工作。他不要求用戶指定對數據的存放方法,也不需要用戶了解具體的數據存放方式,所以具有完全不同底層結構的不同資料庫系統可以使用相同的SQL語言作為數據輸入與管理的接口。它以記錄集合作為操縱對象,所有SQL語句接受集合作為輸入,返回集合作為輸出,這種集合特性允許一條SQL語句的輸出作為另一條SQL語句的輸入,所以SQL語言可以嵌套,這使他具有極大的靈活性和強大的功能,在多數情況下,在其他語言中需要一大段程式實現的一個單獨事件只需要一個SQL語句就可以達到目的,這也意味著用SQL語言可以寫出非常複雜的語句。
SQL同時也是資料庫檔案格式的擴展名。
SQL語言包含4個部分:
數據定義(DDL)語言(如CREATE, DROP,ALTER等語句)
數據操縱(DML)語言(INSERT, UPDATE, DELETE語句)
數據查詢語言(SELECT語句)
數據控制語言(如GRANT,REVOKE,COMMIT, ROLLBACK等語句)
SQL(STructured Query Language)是一種資料庫查詢和程式設計語言,用於存取資料以及查詢、更新和管理關聯式資料庫系統。美國國家標準局(ANSI)與國際標準化組織(ISO)已經制定了 SQL 標準。ANSI 是一個美國工業和商業集團組織,發展美國的商務和通訊標準。ANSI 同時也是 ISO 和 International Electrotechnical Commission(IEC)的成員之一。ANSI 發布與國際標準組織相應的美國標準。1992年,ISO 和 IEC 發布了 SQL 的國際標準,稱為 SQL-92。ANSI 隨之發布的相應標準是 ANSI SQL-92。ANSI SQL-92 有時被稱為 ANSI SQL。儘管不同的關聯式資料庫使用的 SQL 版本有一些差異,但大多數都遵循 ANSI SQL 標準。SQL Server 使用 ANSI SQL-92 的擴展集,稱為 T-SQL,其遵循 ANSI 制定的 SQL-92 標準。
SQL 語言包括兩種主要程式設計語言類別的陳述式: 資料定義語言 (DDL)與資料操作語言 (DML)。下面介紹這兩類語言。
DDL
DDL 用於定義和管理物件,例如資料庫、資料表以及檢視表( 第18章 將會解釋何謂檢視表)。DDL 陳述式通常包括每個物件的CREATE、ALTER 以及 DROP 命令。舉例來說,CREATE TABLE、ALTER TABLE 以及 DROP TABLE 這些陳述式便可以用來建立新資料表、修改其屬性(如新增或刪除資料行)、刪除資料表等,下面我們會一一介紹。
CREATE TABLE 陳述式
使用 DDL 在 MyDB 資料庫建立一個名為 Customer_Data 的範例資料表,本章後面的例子我們會使用到這個資料表。如前所述,CREATE TABLE 陳述式可以用來建立資料表。這個範例資料表被定義成四個資料行,如下所示:
Use MyDB
CREATE TABLE Customer_Data
(customer_id SMALLINT,
first_name char(20),
last_name char(20),
phone char(10))
GO
這個陳述式能產生 Customer_Data 資料表,這個資料表會一直是空的直到資料被填入資料表內。
ALTER TABLE 陳述式
ALTER TABLE 陳述式用來變更資料表的定義與屬性。在下面的例子中,我們利用 ALTER TABLE 在已經存在的 Customer_Data 資料表中新增 middle_initial 資料行。
ALTER TABLE Customer_Data
ADD middle_initial char(1)
GO
現在資料表的定義包括了五個資料行,而不是之前的四個資料行。
DROP TABLE 陳述式
DROP TABLE 陳述式用來刪除資料表定義以及所有的資料、索引、觸發程式、條件約束以及資料表的許可權。要刪除我們的 Customer_Data 資料表,可利用下列命令:
DROP TABLE Customer_Data
GO
DML
DML 利用 INSERT、SELECT、UPDATE 及 DELETE 等陳述式來操作資料庫物件所包含的資料。
INSERT 陳述式
INSERT 陳述式用來在資料表或檢視表中插入一列資料。例如,如果要在Customer_Data 資料表中新增一個客戶,可使用類似以下的 INSERT 陳述式:
INSERT INTO Customer_Data
(customer_id, first_name, last_name, phone)
VALUES (777, "Frankie", "Stein", "4895873900")
請注意 SQL 陳述式中第二行的資料行名稱清單,清單上資料行名稱的次序決定了資料數值將被放在哪個資料行。舉例來說,第一個資料數值將被放在清單列出的第一個資料行 customer_id、第二個資料數值放在第二個資料行,依此類推。由於我們在建立資料表時,定義資料資料行填入數值的次序與現在相同,因此我們不必特意指定欄位名稱。我們可以用以下的 INSERT 陳述式代替:
INSERT INTO Customer_Data
VALUES (777, "Frankie", "Stein", "4895873900")
注意
如果使用這種形式的 INSERT 陳述式,但被插入的數值次序上與建立資料表時不同,數值將被放入錯誤的資料行。如果資料的型別與定義不符,則會收到一個錯誤訊息。
UPDATE 陳述式
UPDATE 陳述式用來更新或改變一列或多列中的值。例如,一位名稱為 Frankie Stein 的客戶想要在記錄中改變他的姓氏為 Franklin,可使用以下 UPDATE 陳述式:
UPDATE Customer_Data
SET first_name = "Franklin"
WHERE last_name = "Stein" and customer_id= 777
我們在 WHERE 子句中加入 customer_id 的項目來確定其他名稱為 Stein 的客戶不會被影響-只有customer_id為777的客戶,姓氏會有所改變。
說明
當您使用 UPDATE 陳述式時,要確定在 WHERE 子句提供充分的篩選條件,如此才不會不經意地改變了一些不該改變的資料。
DELETE 陳述式
DELETE 陳述式用來刪除資料表中一列或多列的資料,您也可以刪除資料表中的所有資料列。要從 Customer_Data 資料表中刪除所有的列,您可以利用下列陳述式:
DELETE FROM Customer_Data
或
DELETE Customer_Data
資料表名稱前的 FROM 關鍵字在 DELETE 陳述式中是選擇性的。除此之外,這兩個陳述式完全相同。
要從 Customer_Data 資料表中刪除 customer_id 資料行的值小於100的列,可利用下列陳述式:
DELETE FROM Customer_Data
WHERE customer_id < 100
SELECT 陳述式用來檢索資料表中的資料,而哪些資料被檢索由列出的資料行與陳述式中的 WHERE 子句決定。例如,要從之前建立的 Customer_Data 資料表中檢索 customer_id 以及 first_name 資料行的資料,並且只想取出每列中 first_name 資料行值為 Frankie 的資料,那麼可以利用以下的 SELECT 陳述式:
SELECT customer_id, first_name FROM Customer_Data
WHERE first_name = "Frankie"
如果有一列符合 SELECT 陳述式中的標準,則結果將顯示如下:
customer_id first_name
------------- ------------
777 Frankie
五種數據類型
簡要描述一下SQL中的五種數據類型:字元型,文本型,數值型,邏輯型和日期型字元型
varchar VS CHAR
VARCHAR型和CHAR型數據的這個差別是細微的,但是非常重要。他們都是用來儲存字元串長度小於255的字元。
假如你向一個長度為四十個字元的VARCHAR型欄位中輸入數據BIll GAtES。當你以後從這個欄位中取出此數據時,你取出的數據其長度為十個字元——字元串Bill Gates的長度。 現在假如你把字元串輸入一個長度為四十個字元的CHAR型欄位中,那么當你取出數據時,所取出的數據長度將是四十個字元。字元串的後面會被附加多餘的空格。
當你建立自己的站點時,你會發現使用VARCHAR型欄位要比CHAR型欄位方便的多。使用VARCHAR型欄位時,你不需要為剪掉你數據中多餘的空格而操心。
VARCHAR型欄位的另一個突出的好處是它可以比CHAR型欄位占用更少的記憶體和硬碟空間。當你的資料庫很大時,這種記憶體和磁碟空間的節省會變得非常重要
文本型
TEXT
使用文本型數據,你可以存放超過二十億個字元的字元串。當你需要存儲大串的字元時,應該使用文本型數據。
注意文本型數據沒有長度,而上一節中所講的字元型數據是有長度的。一個文本型欄位中的數據通常要么為空,要么很大。
當你從HTML fORM的多行文本編輯框(TEXTAREA)中收集數據時,你應該把收集的信息存儲於文本型欄位中。但是,無論何時,只要你能避免使用文本型欄位,你就應該不適用它。文本型欄位既大且慢,濫用文本型欄位會使伺服器速度變慢。文本型欄位還會吃掉大量的磁碟空間。
一旦你向文本型欄位中輸入了任何數據(甚至是空值),就會有2K的空間被自動分配給該數據。除非刪除該記錄,否則你無法收回這部分存儲空間。
數值型
SQL支持許多種不同的數值型數據。你可以存儲整數 INT 、小數 NUMERIC、和錢數 MONEY。
INT VS SMALLINT VS TINYINT
他們的區別只是字元長度:
INT型數據的表數範圍是從-2,147,483,647到2,147,483,647的整數
SMALLINT 型數據可以存儲從-32768到32768的整數
TINYINT 型的欄位只能存儲從0到255的整數,不能用來儲存負數
通常,為了節省空間,應該儘可能的使用最小的整型數據。一個TINYINT型數據只占用一個位元組;一個INT型數據占用四個位元組。這看起來似乎差別不大,但是在比較大的表中,位元組數的增長是很快的。另一方面,一旦你已經創建了一個欄位,要修改它是很困難的。因此,為安全起見,你應該預測以下,一個欄位所需要存儲的數值最大有可能是多大,然後選擇適當的數據類型。
NUMERIC
為了能對欄位所存放的數據有更多的控制,你可以使用NUMERIC型數據來同時表示一個數的整數部分和小數部分。NUMERIC型數據使你能表示非常大的數——比INT型數據要大得多。一個NUMERIC型欄位可以存儲從-1038到1038範圍內的數。NUMERIC型數據還使你能表示有小數部分的數。例如,你可以在NUMERIC型欄位中存儲小數3.14。
當定義一個NUMERIC型欄位時,你需要同時指定整數部分的大小和小數部分的大小。如:MUNERIC(23,0)
一個 NUMERIC型數據的整數部分最大只能有28位,小數部分的位數必須小於或等於整數部分的位數,小數部分可以是零。
MONEY VS SMALLMONEY
你可以使用 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型數據,以節省空間。
邏輯型
BIT
如果你使用複選框( CHECKBOX)從網頁中蒐集信息,你可以把此信息存儲在BIT型欄位中。BIT型欄位只能取兩個值:0或1。
當心,在你創建好一個表之後,你不能向表中添加 BIT型欄位。如果你打算在一個表中包含BIT型欄位,你必須在創建表時完成。
日期型
DATETIME VS SMALLDATETIME
一個 DATETIME型的欄位可以存儲的日期範圍是從1753年1月1日第一毫秒到9999年12月31日最後一毫秒。
如果你不需要覆蓋這么大範圍的日期和時間,你可以使用SMALLDATETIME型數據。它與DATETIME型數據同樣使用,只不過它能表示的日期和時間範圍比DATETIME型數據小,而且不如DATETIME型數據精確。一個SMALLDATETIME型的欄位能夠存儲從1900年1月1日到2079年6月6日的日期,它只能精確到秒。
DATETIME型欄位在你輸入日期和時間之前並不包含實際的數據,認識這一點是重要的。
常用語句
--語句功能
--數據操作
SELECT--從資料庫表中檢索數據行和列
INSERT--向資料庫表添加新數據行
DELETE--從資料庫表中刪除數據行
UPDATE--更新資料庫表中的數據
--數據定義
CREATETABLE--創建一個資料庫表
DROPTABLE--從資料庫中刪除表
ALTERTABLE--修改資料庫表結構
CREATEVIEW--創建一個視圖
DROPVIEW--從資料庫中刪除視圖
CREATEINDEX--為資料庫表創建一個索引
DROPINDEX--從資料庫中刪除索引
CREATEPROCEDURE--創建一個存儲過程
DROPPROCEDURE--從資料庫中刪除存儲過程
CREATETRIGGER--創建一個觸發器
DROPTRIGGER--從資料庫中刪除觸發器
CREATESCHEMA--向資料庫添加一個新模式
DROPSCHEMA--從資料庫中刪除一個模式
CREATEDOMAIN--創建一個數據值域
ALTERDOMAIN--改變域定義
DROPDOMAIN--從資料庫中刪除一個域
--數據控制
GRANT--授予用戶訪問許可權
DENY--拒絕用戶訪問
REVOKE--解除用戶訪問許可權
--事務控制
COMMIT--結束當前事務
ROLLBACK--中止當前事務
SETTRANSACTION--定義當前事務數據訪問特徵
--程式化SQL
DECLARE--為查詢設定游標
EXPLAN--為查詢描述數據訪問計畫
OPEN--檢索查詢結果打開一個游標
FETCH--檢索一行查詢結果
CLOSE--關閉游標
PREPARE--為動態執行準備SQL語句
EXECUTE--動態地執行SQL語句
DESCRIBE--描述準備好的查詢
SQL發展歷史
1970: E.J. Codd 發表了關係資料庫理論(relational database theory); 1974-79: IBM 以Codd的理論為基礎開發了“sequel”,並重命名為"SQL"; 1979: Oracle 發布了商業版SQL 1981-84: 出現了其他商業版本,分別來自 IBM(DB2),Data General(DG/SQL),Relational Technology(ingres); SQL/86:ANSI 跟 ISO的第一個標準; SQL/89:增加了引用完整性(referential integrity); SQL/92(aka SQL2):被資料庫管理系統(DBMS)生產商廣發接受; 1997+:成為動態網站(Dynamic web content)的後台支持; SQL/99:Core level跟其他8種相應的level,包括遞歸查詢,程式跟流程控制,基本的對象(object)支持包括oids; SQL/2003:包含了XML相關內容,自動生成列值(column values); 2005-09-30:“Data is the next generation inside...SQL is the new HTML”! Tim O'eilly提出了Web 2.0理念,稱數據將是核心,SQL將成為“新的HTML"; SQL/2006:定義了SQL與XML(包含XQuery)的關聯套用; 2006:Sun公司將以SQL基礎的資料庫管理系統嵌入Java V6
功能介紹
SQL 面向資料庫執行查詢;SQL 可從資料庫取回數據;SQL 可在資料庫中插入新的記錄;SQL 可更新資料庫中的數據;SQL 可從資料庫刪除記錄;SQL 可創建新資料庫;SQL 可在資料庫中創建新表;SQL 可在資料庫中創建存儲過程;SQL 可在資料庫中創建視圖;SQL 可以設定表、存儲過程和視圖的許可權。
SQL 是一種標準 - 但是...
SQL 是一門 ANSI 的標準計算機語言,用來訪問和運算元據庫系統。SQL 語句用於取回和更新資料庫中的數據。SQL 可與資料庫程式協同工作,比如 MS Access、DB2、Informix、MS SQL Server、Oracle、Sybase 以及其他資料庫系統。SQL語句結構不幸地是,存在著很多不同版本的 SQL 語言,但是為了與 ANSI 標準相兼容,它們必須以相似的方式共同地來支持一些主要的關鍵字(比如 SELECT、UPDATE、DELETE、INSERT、WHERE 等等)。 注釋:除了 SQL 標準之外,大部分 SQL 資料庫程式都擁有它們自己的私有擴展!
精妙語句介紹
說明:複製表(只複製結構,源表名:a新表名:b)SQL:select*intobfromawhere1<>1
說明:拷貝表(拷貝數據,源表名:a目標表名:b)
SQL:insertintob(a,b,c)selectd,e,ffromb;
說明:顯示文章、提交人和最後回復時間
SQL:selecta.title,a.username,b.adddatefromtablea,(selectmax(adddate)adddatefromtablewheretable.title=a.title)b
說明:外連線查詢(表名1:a表名2:b)
SQL:selecta.a,a.b,a.c,b.c,b.d,b.ffromaLEFTOUTJOINbONa.a=b.c
說明:日程安排提前五分鐘提醒
SQL:select*from日程安排wheredatediff('minute',f開始時間,getdate())>5
說明:兩張關聯表,刪除主表中已經在副表中沒有的信息
SQL:deletefrominfowherenotexists(select*frominfobzwhereinfo.infid=infobz.infid
說明:--
SQL:
SELECTA.NUM,A.NAME,B.UPD_DATE,B.PREV_UPD_DATE
FROMTABLE1,
(SELECTX.NUM,X.UPD_DATE,Y.UPD_DATEPREV_UPD_DATE
FROM(SELECTNUM,UPD_DATE,INBOUND_QTY,STOCK_ONHAND
FROMTABLE2
WHERETO_CHAR(UPD_DATE,'YYYY/MM')=TO_CHAR(SYSDATE,'YYYY/MM'))X,
(SELECTNUM,UPD_DATE,STOCK_ONHAND
FROMTABLE2
WHERETO_CHAR(UPD_DATE,'YYYY/MM')=
TO_CHAR(TO_DATE(TO_CHAR(SYSDATE,'YYYY/MM')¦¦'/01','YYYY/MM/DD')-1,'YYYY/MM')Y,
WHEREX.NUM=Y.NUM(+)
ANDX.INBOUND_QTY+NVL(Y.STOCK_ONHAND,0)<>X.STOCK_ONHANDB
WHEREA.NUM=B.NUM
說明:--
SQL:
select*fromstudentinfowherenotexists(select*fromstudentwherestudentinfo.id=student.id)and系名稱=""&strdepartmentname&""and專業名稱=""&strprofessionname&""orderby性別,生源地,聯考總成績
說明:
從資料庫中去一年的各單位電話費統計(電話費定額賀電化肥清單兩個表來源)
SQL:
SELECTa.userper,a.tel,a.standfee,TO_CHAR(a.telfeedate,'yyyy')AStelyear,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'01',a.factration))ASJAN,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'02',a.factration))ASFRI,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'03',a.factration))ASMAR,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'04',a.factration))ASAPR,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'05',a.factration))ASMAY,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'06',a.factration))ASJUE,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'07',a.factration))ASJUL,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'08',a.factration))ASAGU,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'09',a.factration))ASSEP,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'10',a.factration))ASOCT,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'11',a.factration))ASNOV,
SUM(decode(TO_CHAR(a.telfeedate,'mm'),'12',a.factration))ASDEC
FROM(SELECTa.userper,a.tel,a.standfee,b.telfeedate,b.factration
FROMTELFEESTANDa,TELFEEb
WHEREa.tel=b.telfax)a
GROUPBYa.userper,a.tel,a.standfee,TO_CHAR(a.telfeedate,'yyyy')
說明:四表聯查問題:
SQL:select*fromaleftinnerjoinbona.a=b.brightinnerjoincona.a=c.cinnerjoindona.a=d.dwhere.....
說明:得到表中最小的未使用的ID號
SQL:
SELECT(CASEWHENEXISTS(SELECT*FROMHandlebWHEREb.HandleID=1)THENMIN(HandleID)+1ELSE1END)asHandleID
FROMHandle
WHERENOTHandleIDIN(SELECTa.HandleID-1FROMHandlea)
varkw;kw="|MySQL|";vartemptemp=kw.split("|")document.write("
Tag:");for(i=0;i");