Oracle UPDATE 语句

-- Start

我估计,只要是知道SQL 语句的人都会用UPDATE 语句,可是大部分人不知道UPDATE 语句有两种写法,首先,考虑下面的情况:

CREATE TABLE STUDENT
(
  ID       NUMBER(10),           ---学号
  NAME     VARCHAR2(20) NOT NULL,---姓名
  BIRTHDAY DATE                  ---生日
);

INSERT INTO STUDENT (ID,NAME,BIRTHDAY) VALUES (1,'张三',DATE '1991-01-01');
INSERT INTO STUDENT (ID,NAME,BIRTHDAY) VALUES (2,'李四',DATE '1991-01-01');
INSERT INTO STUDENT (ID,NAME,BIRTHDAY) VALUES (3,'王五',DATE '1990-01-01');

假设让你更新一下张三的生日,很简单,我们可以这么写:

UPDATE STUDENT SET BIRTHDAY=DATE '1991-1-5' WHERE NAME='张三';

除此之外,我们还可以这么写:

UPDATE
(
SELECT * FROM STUDENT WHERE NAME='张三'
)
SET BIRTHDAY=DATE '1991-1-5';

就上面这个例子而言,通常我们不会使用第二种写法,因为这种写法可读性不如第一种写法好,下面我们举一个用第一种方法办不到得例子,可是用第二种方法却非常简单(这是一个生产环境实际的例子,通常用在银行中,关于表定义,我做了简化),考虑如下情况:

CREATE TABLE TRANSACTION
(
CUSTOMERID VARCHAR2(10),---顾客号
SEQ NUMBER(9,0) NOT NULL,---流水号(每个顾客从1 开始)
PROCESSDATE TIMESTAMP,---处理日
AMOUNT NUMBER(10,2)---金额
);

对于上面表的流水号(SEQ)字段,每个顾客从 1开始,而且它的顺序,其实就是处理日(PROCESSDATE)排序后的顺序。细心的朋友可能已经发现,这样设计明显违反了表的第二范式,造成数据冗余。确实是这样的,为什么要这样设计呢?真实的原因我也不知道,只能问该系统的设计者。我猜测可能的原因是,系统的设计者将银行用的纸质报表直接转化为了数据库中的表,纸质报表有流水号(SEQ)字段是可以的,因为纸质报表我们无法排序,也不可能让会计去数每个顾客到底发生了多少交易,但是在数据库的表中,该字段则完全没有必要,因为我们可以通过对处理日(PROCESSDATE)排序后产生该结果。相反,如果设置流水号(SEQ)字段,就有可能因为这样那样的问题导致流水号(SEQ)和处理日(PROCESSDATE)排序结果不一致,这时候就要求我们更新流水号(SEQ),那么,我们该怎么更新呢?这个问题很好解决,通常我们会将查询结果排序后,更新其中的每一条记录。这样做是可以的,但是有点笨,我们能不能用一条语句来更新呢?答案是可以的,如下:

UPDATE
(
SELECT
TT.*,
ROW_NUMBER() OVER() AS RN
FROM
TRANSACTION AS TT WHERE CUSTOMERID=...
)
SET SEQ=RN;

怎么样,是不是很简单。如果你对上面语句的 ROW_NUMBER() OVER()还不熟悉,请参见:Oracle 分析函数

此外,如果是多表联合更新,用第一种方法会写出非常恶心的 SQL,用第二种方法确非常直观,下面是一个简单的例子。

-- 第一种写法
UPDATE JOBS J 
SET J.MIN_SALARY = (SELECT SALARY FROM EMPLOYEES E WHERE E.JOB_ID = J.JOB_ID)
WHERE J.JOB_ID IN (SELECT JOB_ID FROM EMPLOYEES WHERE EMPLOYEE_ID = 100);

--第二种写法
UPDATE 
(
  SELECT * FROM EMPLOYEES E, JOBS J WHERE E.JOB_ID = J.JOB_ID AND E.EMPLOYEE_ID = 100
) SET MIN_SALARY = SALARY;

怎么样,第一种写法是不是很难看懂它在干什么(what the hell),第二种写法是不是简单明了。

--更多参见:Oracle SQL 精萃

-- 声明:转载请注明出处

-- Last edited on 2015-08-11

-- Created by ShangBo on 2015-06-18

-- End


你可能感兴趣的:(oracle,sql,plsql)