免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2078 | 回复: 1
打印 上一主题 下一主题

SQL快速进阶---表格的处理 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-05-30 11:05 |只看该作者 |倒序浏览
表格是数据库中储存资料的基本架构。在绝大部份的情况下,数据库厂商不可能知道您需要如何储存您的资料,所以通常您会需要自己在数据库中建立表格。虽然许多数据库工具可以让您在不需用到 SQL 的情况下建立表格,不过由于表格是一个最基本的架构,我们决定包括 CREATE TABLE 的语法在这个网站中。

在我们跳入 CREATE TABLE 的语法之前,我们最好先对表格这个东西有些多一点的了解。表格被分为栏位 (column) 及列位 (row)。每一列代表一笔资料,而每一栏代表一笔资料的一部份。举例来说,如果我们有一个记载顾客资料的表格,那栏位就有可能包括姓、名、地址、城市、国家、生日...等等。当我们对表格下定义时,我们需要注明栏位的标题,以及那个栏位的资料种类。

那,资料种类是什么呢?资料可能是以许多不同的形式存在的。它可能是一个整数 (例如 1),、一个实数(例如 0.55)、一个字串 (例如 'sql')、一个日期/时间 (例如 '2000-JAN-25 03:22:22')、或甚至是 以二进法 (binary) 的状态存在。当我们在对一个表格下定义时,我们需要对每一个栏位的资料种类下定义。(例如 '姓' 这个栏位的资料种类是 char(50)━━代表这是一个 50 个字符的字串)。我们需要注意的一点是不同的数据库有不同的资料种类,所以在对表格做出定义之前最好先参考一下数据库本身的说明。

CREATE TABLE 的语法是:

CREATE TABLE "表格名"
("栏位 1" "栏位 1 资料种类",
"栏位 2" "栏位 2 资料种类",
... )

若我们要建立我们上面提过的顾客表格,我们就打入以下的 SQL:

CREATE TABLE customer
(First_Name char(50),
Last_Name char(50),
Address char(50),
City char(50),
Country char(25),
Birth_Date date)


视观表 (Views) 可以被当作是虚拟表格。它跟表格的不同是,表格中有实际储存资料,而视观表是建立在表格之上的一个架构,它本身并不实际储存资料。

建立一个视观表的语法如下:

CREATE VIEW "VIEW_NAME" AS "SQL 语句"

"SQL 语句" 可以是任何一个我们在这个教材中有提到的 SQL。

来看一个例子。假设我们有以下的表格:

TABLE Customer
(First_Name char(50),
Last_Name char(50),
Address char(50),
City char(50),
Country char(25),
Birth_Date date)



若要在这个表格上建立一个包括 First_Name, Last_Name, 和 Country 这三个栏位的视观表,我们就打入,

CREATE VIEW V_Customer
AS SELECT First_Name, Last_Name, Country
FROM Customer

现在,我们就有一个叫做 V_Customer 的视观表:

View V_Customer
(First_Name char(50),
Last_Name char(50),
Country char(25))


我们也可以用视观表来连接两个表格。在这个情况下,使用者就可以直接由一个视观表中找出她要的资讯,而不需要由两个不同的表格中去做一次连接的动作。假设有以下的两个表格: Store_Information 表格 store_name Sales Date
Los Angeles $1500 Jan-05-1999
San Diego $250 Jan-07-1999
Los Angeles $300 Jan-08-1999
Boston $700 Jan-08-1999

Geography 表格 region_name store_name
East Boston
East New York
West Los Angeles
West San Diego



我们就可以用以下的指令来建一个包括每个地区 (region) 销售额 (sales) 的视观表:

CREATE VIEW V_REGION_SALES
AS SELECT A1.region_name REGION, SUM(A2.Sales) SALES
FROM Geography A1, Store_Information A2
WHERE A1.store_name = A2.store_name
GROUP BY A1.region_name

这就给我们有一个名为 V_REGION_SALES 的视观表。这个视观表包含不同地区的销售哦。如果我们要从这个视观表中获取资料,我们就打入,

SELECT * FROM V_REGION_SALES

结果:

REGION SALES
East $700
West $2050


索引 (Index) 可以帮助我们从表格中快速地找到需要的资料。举例来说,假设我们要在一本园艺书中找如何种植青椒的讯息。若这本书没有索引的话,那我们是必须要从头开始读,直到我们找到有关种直青椒的地方为止。若这本书有索引的话,我们就可以先去索引找出种植青椒的资讯是在哪一页,然后直接到那一页去阅读。很明显地,运用索引是一种有效且省时的方式。

从资料库表格中寻找资料也是同样的原理。如果一个表格没有索引的话,资料库系统就需要将整个表格的资料读出 (这个过程叫做'table scan')。若有适当的索引存在,资料库系统就可以先由这个索引去找出需要的资料是在表格的什么地方,然后直接去那些地方抓资料。这样子速度就快多了。

因此,在表格上建立索引是一件有利于系统效率的事。一个索引可以涵盖一或多个栏位。建立索引的语法如下:
CREATE INDEX "INDEX_NAME" ON
"TABLE_NAME" (COLUMN_NAME)
现在假设我们有以下这个表格,

TABLE Customer
(First_Name char(50),
Last_Name char(50),
Address char(50),
City char(50),
Country char(25),
Birth_Date date)



若我們要在 Last_Name 這個欄位上建一個索引,我們就打入以下的指令,

CREATE INDEX IDX_CUSTOMER_LAST_NAME
ON CUSTOMER (LAST_NAME)
索引的命名并没有一个固定的方式。通常会用的方式是在名称前加一个字首,例如 "IDX_" ,来避免与资料库中的其他物件混淆。另外,在索引名之内包括表格名及栏位名也是一个好的方式。

请读者注意,每个资料库会有它本身的 CREATE INDEX 语法,而不同资料库的语法会有不同。因此,在下指令前,请先由资料库使用手册中确认正确的语法。


在表格被建立在资料库中后,我们常常会发现,这个表格的结构需要有所改变。常见的改变如下:

加一个栏位
删去一个栏位
改变栏位名称
改变栏位的资料种类
以上列出的改变并不是所有可能的改变。ALTER TABLE 也可以被用来作其他的改变,例如改变主键定义。

ALTER TABLE 的语法如下:
ALTER TABLE "table_name“
[改变方式]
[改变方式]中的详细写法会依我们想要达到的目标而有所不同,如下:
~加一个栏位:ADD ”栏位1“ ”栏位1资料种类"
~删去一个栏位:DROP ”栏位1“
~改变栏位名称:CHANGE ”原本栏位名” "新栏位名" "新栏位名资料种类"
~改变栏位的资料种类:MODIFY "栏位1" ”新资料种类"
以下我们用在CREATE TABLE 一页建出的 customer 表格来当作例子:

customer 表格 栏位名称 资料种类
First_Name char(50)
Last_Name char(50)
Address char(50)
City char(50)
Country char(25)
Birth_Date date
第一,我们要加入一个叫做 "gender" 的栏位。这可以用以下的指令达成:
ALTER TABLE customer add gender char(1)
这个指令执行后的表格架构是:

customer 表格 栏位名称 资料种类
First_Name char(50)
Last_Name char(50)
Address char(50)
City char(50)
Country char(25)
Birth_Date date
Gender char(1)


接下来,我们要把 "Address" 栏位改名为 "Addr"。这可以用以下的指令达成:
ALTER TABLE customer change Address Addr char(50);
这个指令执行后的表格架构是:

customer 表格 栏位名称 资料种类
First_Name char(50)
Last_Name char(50)
Addr char(50)
City char(50)
Country char(25)
Birth_Date date
Gender char(1)


再来,我们要将 "Addr" 栏位的资料种类改为 char(30)。这可以用以下的指令达成:
ALTER TABLE customer MODIFY Addr char(30);
这个指令执行后的表格架构是:

customer 表格 栏位名称 资料种类
First_Name char(50)
Last_Name char(50)
Addr char(30)
City char(50)
Country char(25)
Birth_Date date
Gender char(1)
最后,我们要删除 "Gender" 栏位。这可以用以下的指令达成:
ALTER TABLE customer DROP Gender;
这个指令执行后的表格架构是:

customer 表格 栏位名称 资料种类
First_Name char(50)
Last_Name char(50)
Addr char(30)
City char(50)
Country char(25)
Birth_Date date

主键 (Primary Key) 中的每一笔资料都是表格中的唯一值。换言之,它是用来独一无二地确认一个表格中的每一行资料。主键可以是原本资料内的一个栏位,或是一个人造栏位 (与原本资料没有关系的栏位)。主键可以包含一或多个栏位。当主键包含多个栏位时,称为组合键 (Composite Key)。

主键可以在建置新表格时设定 (运用 CREATE TABLE 语句),或是以改变现有的表格架构方式设定 (运用 ALTER TABLE)。

以下举几个在建置新表格时设定主键的方式:

MySQL:
CREATE TABLE Customer
(SID integer,
  Last_Name varchar(30),
  First_Name varchar(30),
   PRIMARY KEY (SID));
ORACLE:
CREATE TABLE Customer
(SID interger PRIMARY KEY,
  Last_Name varchar(30),
First_Name varchar(30));

以下则是以改变现有表格架构来设定主键的方式:
MySQL:
ALTER TABLE Customer ADD PRIMARY KEY (SID);

Oracle:
ALTER TABLE Customer ADD PRIMARY KEY (SID);

SQL Server:
ALTER TABLE Customer ADD PRIMARY KEY (SID);

请注意,在用ALTER TABLE语句来添加主键之前,我们需要确认被用来当做主键的栏位是设定为 『NOT NULL』 ;也就是说,那个栏位一定不能没有资料。


外来键是一个(或数个)指向另外一个表格主键的栏位。外来键的目的是确定资料的参考完整性(referential integrity)。换言之,只有被准许的资料值才会被存入资料库内。

举例来说,假设我们有两个表格:一个 CUSTOMER 表格,里面记录了所有顾客的资料;另一个 ORDERS 表格,里面记录了所有顾客订购的资料。在这里的一个限制,就是所有的订购资料中的顾客,都一定是要跟在 CUSTOMER 表格中存在。在这里,我们就会在 ORDERS 表格中设定一个外来键,而这个外来键是指向 CUSTOMER 表格中的主键。这样一来,我们就可以确定所有在 ORDERS 表格中的顾客都存在 CUSTOMER 表格中。换句话说,ORDERS表格之中,不能有任何顾客是不存在于 CUSTOMER 表格中的资料。

这两个表格的结构将会是如下:

CUSTOMER 表格 栏位名 性质
SID 主键
Last_Name  
First_Name  


ORDERS 表格 栏位名 性质
Order_ID 主键
Order_Date  
Customer_SID 外来键
Amount  


在以上的例子中,ORDERS 表格中的 customer_SID 栏位是一个指向 CUSTOMERS 表格中 SID 栏位的外来键。

以下列出几个在建置 ORDERS 表格时指定外来键的方式:

MySQL:
CREATE TABLE ORDERS
(Order_ID integer,
Order_Date date,
Customer_SID integer,
Amount double,
Primary Key (Order_ID),
Foreign Key (Customer_SID) references CUSTOMER(SID));

Oracle:
CREATE TABLE ORDERS
(Order_ID integer primary key,
Order_Date date,
Customer_SID integer references CUSTOMER(SID),
Amount double);

SQL Server:
CREATE TABLE ORDERS
(Order_ID integer primary key,
Order_Date datetime,
Customer_SID integer references CUSTOMER(SID),
Amount double);

以下的例子则是藉着改变表格架构来指定外来键。这里假设 ORDERS 表格已经被建置,而外来键尚未被指定:

MySQL:
ALTER TABLE ORDERS
ADD FOREIGN KEY (customer_sid) REFERENCES CUSTOMER(sid);

Oracle:
ALTER TABLE ORDERS
ADD (CONSTRAINT fk_orders1) FOREIGN KEY (customer_sid) REFERENCES CUSTOMER(sid);

SQL Server:
ALTER TABLE ORDERS
ADD FOREIGN KEY (customer_sid) REFERENCES CUSTOMER(sid);


有时候我们会决定我们需要从数据库中清除一个表格。事实上,如果我们不能这样做的话,那将会是一个很大的问题,因为数据库管理师 (Database Administrator -- DBA) 势必无法对数据库做有效率的管理。还好,SQL 有提供一个 DROP TABLE的语法来让我们清除表格。 DROP TABLE 的语法是:

DROP TABLE "表格名"

我们如果要清除在SQL CREATE 中建立的顾客表格,我们就打入:

DROP TABLE customer.


有时候我们会需要清除一个表格中的所有资料。要达到者个目的,一种方式是我们在 SQL DROP 那一页 看到的 DROP TABLE 指令。不过这样整个表格就消失,而无法再被用了。另一种方式就是运用 TRUNCATE TABLE 的指令。在这个指令之下,表格中的资料会完全消失,可是表格本身会继续存在。 TRUNCATE TABLE 的语法为下:

TRUNCATE TABLE "表格名"

所以,我们如果要清除在 SQL Create 那一页建立的顾客表格之内的资料,我们就打入:

TRUNCATE TABLE customer.



我们已经学到了将如何把资料由表格中取出。但是这些资料是如果进入这些表格的呢? 这就是这一页 (INSERT INTO) 和下一页 (UPDATE) 要讨论的。

基本上,我们有两种作法可以将资料输入表格中内。一种是一次输入一笔,另一种是一次输入好几笔。 我们先来看一次输入一笔的方式。

依照惯例,我们先介绍语法。一次输入一笔资料的语法如下:

INSERT INTO "表格名" ("栏位1", "栏位2", ...)
VALUES ("值1", "值2", ...)

假设我们有一个架构如下的表格:

Store_Information 表格
Column Name  Data Type  
store_name  char(50)  
Sales  float  
Date  datetime  


而我们要加以下的这一笔资料进去这个表格:在 January 10, 1999,Los Angeles 店有 $900 的营业额。我们就打入以下的 SQL 语句:

INSERT INTO Store_Information (store_name, Sales, Date)
VALUES ('Los Angeles', 900, 'Jan-10-1999')

第二种 INSERT INTO 能够让我们一次输入多笔的资料。跟上面刚的例子不同的是,现在我们要用 SELECT 指令来指明要输入表格的资料。如果您想说,这是不是说资料是从另一个表格来的,那您就想对了。一次输入多笔的资料的语法是:

INSERT INTO "表格1" ("栏位1", "栏位2", ...)
SELECT "栏位3", "栏位4", ...
FROM "表格2"

以上的语法是最基本的。这整句 SQL 也可以含有 WHERE、 GROUP BY、 及 HAVING 等子句,以及表格连接及别名等等。

举例来说,若我们想要将 1998 年的营业额资料放入 Store_Information 表格,而我们知道资料的来源是可以由 Sales_Information 表格取得的话,那我们就可以打入以下的 SQL:

INSERT INTO Store_Information (store_name, Sales, Date)
SELECT store_name, Sales, Date
FROM Sales_Information
WHERE Year(Date) = 1998

在这里,我用了 SQL Server 中的函数来由日期中找出年。不同的数据库会有不同的语法。 举个例来说,在 Oracle 上,您将会使用 WHERE to_char(date,'yyyy')=1998。



我们有时候可能会需要修改表格中的资料。在这个时候,我们就需要用到 UPDATE 指令。这个指令的语法是:

UPDATE "表格名"
SET "栏位1" = [新值]
WHERE {条件}

最容易了解这个语法的方式是透过一个例子。假设我们有以下的表格:

Store_Information 表格
store_name  Sales  Date  
Los Angeles  $1500  Jan-05-1999  
San Diego  $250  Jan-07-1999  
Los Angeles  $300  Jan-08-1999  
Boston  $700  Jan-08-1999  


我们发现说 Los Angeles 在 01/08/1999 的营业额实际上是 $500,而不是表格中所储存的 $300,因此我们用以下的 SQL 来修改那一笔资料:

UPDATE Store_Information
SET Sales = 500
WHERE store_name = "Los Angeles"
AND Date = "Jan-08-1999"

现在表格的内容变成:

Store_Information 表格
store_name  Sales  Date  
Los Angeles  $1500  Jan-05-1999  
San Diego  $250  Jan-07-1999  
Los Angeles  $500  Jan-08-1999  
Boston  $700  Jan-08-1999  


在这个例子中,只有一笔资料符合 WHERE 子句中的条件。如果有多笔资料符合条件的话,每一笔符合条件的资料都会被修改的。

我们也可以同时修改好几个栏位。这语法如下:

UPDATE "表格"
SET "栏位1" = [值1], "栏位2" = [值2]
WHERE {条件}

在某些情况下,我们会需要直接由数据库中去除一些资料。这可以藉由 DELETE FROM 指令来达成。它的语法是:

DELETE FROM "表格名"
WHERE {条件}

以下我们用个实例说明。假设我们有以下这个表格:

Store_Information 表格
store_name  Sales  Date  
Los Angeles  $1500  Jan-05-1999  
San Diego  $250  Jan-07-1999  
Los Angeles  $300  Jan-08-1999  
Boston  $700  Jan-08-1999  


而我们需要将有关 Los Angeles 的资料全部去除。在这里我们可以用以下的 SQL 来达到这个目的:

DELETE FROM Store_Information
WHERE store_name = "Los Angeles"

现在表格的内容变成:

Store_Information 表格
store_name  Sales  Date  
San Diego  $250  Jan-07-1999  
Boston  $700  Jan-08-1999

论坛徽章:
0
2 [报告]
发表于 2008-05-30 11:58 |只看该作者
在这一页中,我们列出所有SQL 指令的语法。若要更详尽的说明,参看之前的相关SQL快速进阶主题。

这一页的目的是提供一个简洁的 SQL 语法做为读者参考之用。
Select
SELECT "栏位" FROM "表格名"

Distinct
SELECT DISTINCT "栏位"
FROM "表格名"

Where
SELECT "栏位"
FROM "表格名"
WHERE "condition"

And/Or
SELECT "栏位"
FROM "表格名"
WHERE "简单条件"
{[AND|OR] "简单条件"}+

In
SELECT "栏位"
FROM "表格名"
WHERE "栏位" IN ('值1', '值2', ...)

Between
SELECT "栏位"
FROM "表格名"
WHERE "栏位" BETWEEN '值1' AND '值2'

Like
SELECT "栏位"
FROM "表格名"
WHERE "栏位" LIKE {模式}

Order By
SELECT "栏位"
FROM "表格名"
[WHERE "条件"]
ORDER BY "栏位" [ASC, DESC]

Count
SELECT COUNT("栏位")
FROM "表格名"

Group By
SELECT "栏位1", SUM("栏位2")
FROM "表格名"
GROUP BY "栏位1"

Having
SELECT "栏位1", SUM("栏位2")
FROM "表格名"
GROUP BY "栏位1"
HAVING (栏位)

Create Table
CREATE TABLE "表格名"
("栏位 1" "栏位 1 资料种类",
"栏位 2" "栏位 2 资料种类",
... )

Drop Table
DROP TABLE "表格名"

Truncate Table
TRUNCATE TABLE "表格名"

Insert Into
INSERT INTO "表格名" ("栏位1", "栏位2", ...)
VALUES ("值1", "值2", ...)

Update
UPDATE "表格名"
SET "栏位1" = [新值]
WHERE {条件}

Delete From
DELETE FROM "表格名"
WHERE {条件}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP