【DB2学习文档之七】SQL for DB2
作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/
1.SQL的數據操作語言data manipulation language (DML)
參見Beginning SQL Queries: From Novice to Professional, by Clare Churcher (Apress, 2008)
2.Select語句
這個語句是DB2中最簡單也最復雜的語句,它包含六部分:
select :列出列名或相關結構。
from :描述從何處得到需要的數據并指出多個目標怎樣被結合在一起。
where:像謂語那樣描述條件。
group:描述非聚合數據在聚合數據之前是怎樣被處理的。
having:可選項、相當于where語句,作為一個對group中生成的組判斷的準則。
order:提供排序需求。
那我怎么知道從哪個表去取數據呢?
系統提供了以下表單進行查詢:
SYSTABLES SYSIBM Information about all tables in the database
SYSINDEXES SYSIBM Information about the indexes on all tables
SYSVIEWS SYSIBM Information on all views in the database
.....類似的結構
系統還提供了以下一些視圖進行查詢:
TABLES SYSCAT Information about all tables in the database
INDEXES SYSCAT Information about the indexes on all tables
VIEWS SYSCAT Information on all views in the database
PROCEDURES SYSCAT Information on all stored procedures in the database
FUNCTIONS SYSCAT Information on all functions in the database
select * from sysibm.systables可以進行查看。注意這個操作不要在CLP中進行,否則會十分郁悶,原因是CLP的屏幕有限,而信息太多。
諸如select name, creator, colcount from sysibm.systables這樣的命令可以在CLP中執行。
我們可以對表單的輸出進行訂制:
select name, creator, colcount as "No of Columns", abs(npages*4*1024) as "Bytes" from sysibm.systables
where怎么使用?
where就像一個過濾器grep那樣進行過濾:select name, creator from sysibm.systables where creator = 'FUZZY'
group怎么使用?
例如你想在sample中知道每個部門給員工發的薪水的總和,你怎樣告訴SUM你想對每個部門進行分別的累加呢?使用group進行就可以。
select workdept, sum(salary) as newsalary from employee group by workdept
having怎么使用?
類比where,這是對group進行的數據進行了grep。例如:
select workdept, sum(salary) DeptSal from employee group by workdept having sum(salary) > 100000
這就確定了1000000以上的薪金總和的部門了。注意這里使用having語句時,盡管我們進行了重命名,但是還是使用以前的名字salary進行重命名。
order怎么使用 ?
order來指定根據哪一列元素進行排序,例如:
select workdept, sum(salary) DeptSal from employee group by workdept having sum(salary) > 100000 order by workdept
Select的三種規模較大的語句:joins, subqueries, unions
1.Joins
使用比較、處理和使用,將不同表的相關數據結合起來,例如:
select e.firstnme, e.lastname, d.deptname, d.location from employee e inner join department d on e.workdept = d.deptno
其中e和d對數據庫名稱進行了簡化,關于inner join在這里我們回顧一下數據庫相關的三個小概念:
內聯:
a inner join b on a.id=b.id
查兩張表都有的id記錄
左外聯:
a left join b on a.id=b.id
只要表a有記錄,表b沒有記錄的
右外聯:
a right join b on a.id=b.id
只要表b有記錄,表a沒有記錄的
2.Subqueries
是一種嵌套方式,它可以被用來進行更加復雜的where或者having,可以當做一個虛擬表或視圖給from使用。例如:
select firstnme, surname from employee where empno in (select mgrno from department)
3. union
就是維恩圖中的集合相并,集合相交為Intersect,集合做差集是Except,在這些操作后加上all則會保留原來的集合中的元素而不會像默認進行的那樣將重復的去掉。例如:
Select firstnme from employee where salary < style="FONT-WEIGHT: bold" size="4">3.使用DB2的注冊表
DB2提供了許多特殊值幫助你完成類似得到當前時間、日期等的信息,例如:
select current timestamp from sysibm.sysdummy1
使用注冊表的好處我們可以舉一個例子進行說明:
我們在Sample數據庫的Employee這個表中加入莫扎特的好朋友Jimi Hendrix(此人不是那個著名的電吉他手),語句如下:
Insert into employee(empno, firstnme, lastname, hiredate, edlevel)Values('222222', 'Jimi', 'Hendrix', current date, 16)
其中我們使用了current date寄存器進行了設定了雇傭的時間,這比我們自己手動設置靠譜許多。
我們可以試著看看這個值是不是就是現在的時間:
---------------------------------
db2 => values current time
1--------15:56:451 條記錄已選擇。
-------------------------
沒錯!
更多的關于時間寄存器和其應用在IBM的Developerworks上有:
http://www.ibm.com/developerworks/data/library/techarticle/0211yip/0211yip3.html
除了時間寄存器外,我們在這列出所有的寄存器,希望你能用好它:
CLIENT ACCTNG
CLIENT APPLNAME
CLIENT USERID
CLIENT WRKSTNNAME
CURRENT DBPARTITIONNUM
CURRENT PATH
CURRENT SCHEMA
CURRENT SERVER
CURRENT TIME
CURRENT TIMESTAMP
CURRENT TIMEZONE
CURRENT USER
Current query optimization
SESSION USER
SYSTEM USER
USER
?
1.新建一個表的基本方法:
Create table nomination
(
nominationID INTEGER Not Null,
nominee char(6) Not Null,
nominator char(6) Not Null,
reason VARCHAR(250),
nomdate date Not Null
)
格式如下:column_name data_type constraint_details
注意列名稱不能大于30,并且你如果不指定限制信息則我們允許null。
這個看似簡單的操作后邊隱藏著兩個值得注意的地方:
第一個是所有的存儲需求都要去檢驗是不是滿足,第二個是權限檢驗。關于權限,你必須是這個數據庫實例的SYSADM組,或者該數據庫的DBADM組,或者是在該數據庫中有CREATETAB權限并且在合適的表空間中使用。當然這些都可能暫時不是我們考慮的,否則我們就瘋掉了…
表的名字由字母開頭,不能包含非法字符,不大于128個單字,在一個schema中名字是唯一的。schema類似于一個命名空間,你要是不顯示指定schema的話那么就使用你連接數據庫時使用的ID作為Schema。
要是你有數據建模的背景,那么你就知道在一個給定的實體的一系列屬性上應該定義一個或者多個屬性為唯一標識。在定義主鍵上,SQL語句有如下的兩種形式:
Create table nomination
(
nominationID BIGINT Not Null Primary Key,
nominee char(6) Not Null,
nominator char(6) Not Null,
reason VARCHAR(250),
nomdate date Not Null
)
或者
Create table nomination
(
nominationID BIGINT Not Null,
nominee char(6) Not Null,
nominator char(6) Not Null,
reason VARCHAR(250),
nomdate date Not Null,
Primary Key (nominationID)
)
而改變主鍵則使用下面的命令:
db2 => alter table nomination add primary key (nominationid)
2.外鍵的設置和處理
而主鍵則必須與另一種限制一起使用:外鍵(參照完整性限制)。例如:
第一個表是國家的表,包含世界上所有的國家。而第二個表是城市表,我們注意country_ID 和country_no是連接兩個表的列。
其中country_no就是所謂外鍵(也叫做參照約束,Referential Constraints),用于指向父表中的主鍵 ,由于這種關系,country_no列不能有一個在country_ID 中不存在的值。外鍵的數據類型必須與父表的主鍵類型兼容。
CREATE TABLE country (
?????? country_ID????? INT???????? NOT NULL PRIMARY KEY,
?????? country_Name??? VARCHAR(30)?? NOT NULL,
?????? continent_Name? CHAR(15)
?????? )
CREATE TABLE city (
?????? city_ID???????? INT?????????? NOT NULL PRIMARY KEY,
?????? city_name??? VARCHAR(30)?? NOT NULL,
?????? country_no????? INT?????????? REFERENCES country,
?????? population????? INT
?????? )
在nomination那個例子中,我們引入一個表,Category,并且改變nomination這個表去以Category為一個約束。我們先把Category表建立起來,
我們根據這個需求建立表單為:
那么我們就可以創建表單了:
Create table category
(
CategoryID INTEGER Not Null Primary Key,
CateogryName VARCHAR(50) Not Null,
Eligibility VARCHAR(250)
)
首先我們要加入一列,categoryid
db2 => alter table nomination
add column categoryid integer not null
這個時候會出現以下的錯誤:
SQL0193N? In an ALTER TABLE statement, the column "CATEGORYID" has been
specified as NOT NULL and either the DEFAULT clause was not specified or was
specified as DEFAULT NULL.? SQLSTATE=42601
這其中的原因是如果你使用ALTER TABLE命令強行加入一個NOT NULL 參數,DB2會認為你可能是對一個已經存在的列進行操作,但實際上DB2這個玩意也不會去檢查。我們只需在后邊加上一個默認值,DB2就會放行。
db2 => alter table nomination
add column categoryid integer not null default 1
我們現在利用這個列對兩個表進行連接,指向Category表。
db2 => alter table nomination add foreign key CategoryExists (categoryid)
references category (categoryid)
這樣我們就建立了聯系,不過像其他數據庫那樣,DB2對于這些連接表的量也提供了一些on change規則。我們可以使用:
我們先刪掉剛建立的外鍵:
db2 => alter table nomination drop constraint CategoryExists
我們再次建立,使用on delete rules對一旦刪除了父表的參照約束,數據庫怎么處理進行了約束:
db2 => alter table nomination add foreign key CategoryExists (categoryid)
references category (categoryid) on delete restrict
on delete選項后邊可以跟如下參數,我們使用color和object兩個表進行說明:
cascade: 一旦刪除任何父表的外鍵,則將刪除所有與其匹配的子表的行。
SET NULL: 一旦刪除父表的外鍵,則將子表中相關的值設置為null,但該行保留。
no action: 字面上的意思是不會試圖去解決任何沖突。實際上是子記錄所以無法刪除該記錄,在下邊的這個例子中Delete 操作直接failed了。
restrict: 若子表中還有父表中的參照約束,則刪除動作會failed。
注意到這個與no action貌似沒有任何區別,那是因為兩個表之間的關系不足以說明問題,而且只有在及個別的情況下會導致區別,那么我們舉這樣一個例子:
T2是T3的父表,delete rule設置為CASCADE。
T1也是T3的父表,delete rule設置為:
1)RESTRICT:那么在T3中有任何一個子行有T1的參照約束的話,任何刪除T1或者T2中參照約束的刪除操作都會failed(SQLSTATE 23001)。也就是說,這個具有最高的優先級執行權限,在CASCADE生效之前起作用。
2)NO ACTION:當刪除T2中的參照約束時,由于T2和T3是CASCADE,那么T3的相關行也可能 會被刪除(之所以說“可能” 意思是:當刪除T2的參照約束不足以將T3中與T1相關的行全部刪除,那么也會出錯。)。也就是說,它是在其他約束的動作之后執行的rule。
除了on delete規則,我們還可以設置為on update規則,當父表中的參照約束有更改的時候起作用。
ON UPDATE RESTRICT :對這個更改進行約束。
ON UPDATE NO ACTION:更新操作會成功,父表的值會根據操作改變,子表不變
我們在更改這樣的約束規則時沒有一個命令能直接更改,只能先刪掉相關外鍵后重建外鍵。
上一節介紹了參照約束,這一節我們介紹另外一個約束以及解約束。
1.檢查約束:
一旦在表上定義了表檢查約束,每個UPDATE和INSERT語句都會引起限制或約束的檢查。如果違反了約束條件,數據記錄將不被插入或更新,并且會返回一條SQL錯誤信息。
基本的語法是:Check (columncolumn-constraints)
例如我們創建如下的表格:
Create table nomination
(
nominationID BIGINT Not Null Primary Key,
nominee char(6) Not Null,
nominator char(6) Not Null,
reason VARCHAR(250),
nomdate date Not Null,
categoryid INTEGER Not Null,
check (nominee != nominator),
Foreign Key CategoryExists (categoryid)
references category (categoryid) on delete restrict
)
當然我們還可以對現存的表單加入檢查約束:
db2 => alter table nomination add constraint
NoSelfNomination check (nominee != nominator)
2.解約束和約束延期(Disabling Constraints and Constraint Deferral)
我們可以使用not enforced來建立解約束,使這個約束不生效。我們先將上一個部分建立的檢查約束刪除:
db2 => alter table nomination drop constraint NoSelfNomination
然后再建立解約束:
db2 => alter table nomination add constraint
NoSelfNomination check (nominee != nominator) not enforced
你可能比較納悶為什么這么做,簡單的說,這個可以把你的數據庫性能提升上去,在某些時候使用enable query optimization 和 disable query optimization。我們在后邊會學習到。這里有個小小的演示:
我們還是先將剛才建立的解約束刪除:
db2 => alter table nomination drop constraint NoSelfNomination
使用上邊提到的那個東東建立解約束:
db2 => alter table nomination add constraint
NoSelfNomination check (nominee != nominator)
not enforced enable query optimization
這樣我們就告訴DB2,我們不使用這個約束,但是在查詢時使用這個約束進行性能優化。
例如,我們這樣查詢:Select * from nomination where nominee = nominator
DB2就會先看看這個解約束,這個解約束告訴我們這個是不可能發生的(雖然這個約束并沒有enforced),那么DB2就不會去查表了(其實這并不一定反映真實的情況,所以要慎用這個解約束功能),性能也自然得到了優化。
DB2提供了當有一行插入的時候自動在某一列添加值的功能,可以使用所謂identity rules,簡單點的比如某個數值的遞增填入該列中,當然也有很復雜的。使用這個一般是用作識別碼的,當做定義表格的主鍵。generated語法則可以自定義你想怎么產生這個值的策略。
語法如下:
column definition generated {always | by default}
as {identity identity rules | using your rules}
我們先刪掉上次我們建立的表格:
db2 => drop table nomination
然后再創建一個表格:
Create table nomination
(
nominationID BIGINT Not Null Primary Key generated always as identity,
nominee char(6) Not Null,
nominator char(6) Not Null,
reason VARCHAR(250),
nomdate date Not Null,
categoryid INTEGER Not Null,
check (nominee != nominator) not enforced enable query optimization,
Foreign Key CategoryExists (categoryid)
references category (categoryid) on delete restrict
)
注意黑體字,以后我們就不能使用insert或者update來顯式的指定它的值了。
而DB2中的identity也提供了多種策略,具體的可以去查DB2手冊,我們舉例如下:
我們先刪掉上次我們建立的表格:
db2 => drop table category
然后建立表單
Create table category
(
CategoryID INTEGER Primary Key? Generated Always as Identity
(Start With 1 Increment by 1 minvalue 0 maxvalue 999999999
no cycle cache 5 no order),
CateogryName VARCHAR(50) Not Null,
Eligibility VARCHAR(250)
)
黑體字中identity中的語句你都能在DB2的手冊中查到,都是自然語言一看就懂了。
有時候你并不只想去做數字的填充,你可能還想處理一些字母,那么下邊這個轉換大寫的例子就是給你的:
db2 => alter table category add column
UpperCatName VARCHAR(50) generated always as (upper(CategoryName))
關于這些在DB2的文檔里都有具體說明。
1.表空間作為表的邏輯存儲單元,有三種:
in:你可以指定一個表單的普通數據存放在哪個常規表空間中。
Index:你也可以指定一個獨立的常規表空間存儲index。
Long:你還可以分配一個大的表空間存儲一個表單中大的對象。
2.語法:
Create table tablename
(various column names and attributes)
[in tablespace-name]
[Index in tablespace-name]
[Long in tablespace-name]
3.實例:
Create table AwardWinner
(AwardWinnerID integer Primary Key Generated Always as Identity
(Start With 1 Increment by 1),
DateWon Date Not Null,
TotalVotes Integer Not Null,
Picture BLOB)
in userspace1
Index in userspace1
Long in picturelobs
?
1.create table ... as select ...方法:
我們可以使用select方法從源表單中選擇性的構建新表單的列,例如:
db2 => Create table EmployeeCopy
as (select firstnme, lastname from employee)
definition only
create table 的時候不同時進行數據插入。那個關鍵字就是指“只定義無數據 ",也就是沒有數據導入。
2.create table ... like ...方法:
用于建立一個完全相同列的表。
語法如下:
CREATE TABLE [TableName ] LIKE [SourceTable ]
<[INCLUDING | EXCLUDING] COLUMN DEFAULTS>
<[INCLUDING | EXCLUDING] IDENTITY COLUMN ATTRIBUTES>
這樣創建的表格是和SourceTable有相同的列(names, data types, and nullability characteristics)(也同樣不導入數據),如果你不使用EXCLUDING COLUMN DEFAULTS,任何定義在源表單中的默認約束都會生效。需要注意的是其他的屬性不會被復制進新的表單中,所有UNIQUE約束、參照性約束、觸發器或者索引都不會復制的。
db2 =>create table EmployeeCopy3 like EmployeeCopy2
including column defaults
excluding identity column attributes
你要是想導入數據,一般是在控制中心中執行類似如下的語句:
CREATE TABLE ADDRESS2 LIKE ADDRESS
INSERT INTO ADDRESS2 SELECT * FROM ADDRESS
?
?
作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/
總結
以上是生活随笔為你收集整理的【DB2学习文档之七】SQL for DB2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 加载GIF动态图
- 下一篇: 通达信公式-当天成交量不大于百日均成交量