某天,羣裏突然冒出一個道友詢問oracle的面試題,特此記錄一下
一系列過程:
第一步建表:
DROP TABLE serv;
DROP TABLE terminal;
CREATE TABLE serv(
serv_id NUMBER(10),
prod_id NUMBER(10),
user_type VARCHAR2(30),
terminal_name VARCHAR2(20)
)
tablespace ORAC_DATA
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 11M
next 1M
minextents 1
maxextents unlimited
);
COMMENT ON TABLE serv IS '用戶資料表';
COMMENT ON COLUMN serv.serv_id IS '用戶標識';
COMMENT ON COLUMN serv.prod_id IS '產品標識';
COMMENT ON COLUMN serv.user_type IS '用戶類型';
COMMENT ON COLUMN serv.terminal_name IS '終端類型';
CREATE TABLE terminal(
serv_id NUMBER(10),
terminal_name VARCHAR2(20)
)
tablespace ORAC_DATA
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 11M
next 1M
minextents 1
maxextents unlimited
);
COMMENT ON TABLE terminal IS '終端類型臨時表';
COMMENT ON COLUMN terminal.serv_id IS '用戶標識';
COMMENT ON COLUMN terminal.terminal_name IS '終端類型';
第二步,插入數據
我採用的手工添加,所用的方法如下
oracle 直接更新查詢結果
SELECT * FROM serv FOR UPDATE;
SELECT * FROM terminal FOR UPDATE;
serv 表結果如下:
terminal 表結果如下
第三步,創建存儲過程如下:
--創建存儲過程
CREATE OR REPLACE PROCEDURE sp_terminal
IS
BEGIN
--更新serv表 方法一
UPDATE serv s SET s.terminal_name = (
SELECT
CASE
WHEN s.PROD_ID = 1 AND s.USER_TYPE = 'A' THEN '固話'
WHEN s.PROD_ID = 1 AND s.USER_TYPE = 'B' THEN '小靈通'
WHEN S.PROD_ID = 2 THEN '寬帶'
WHEN S.USER_TYPE = 'C' THEN 'CDMA'
ELSE '-1'
END terminal_name
FROM SERV S1
WHERE S1.PROD_ID = S.PROD_ID AND S1.USER_TYPE = S.USER_TYPE
) WHERE EXISTS (
SELECT NULL FROM SERV S1
WHERE S1.PROD_ID = S.PROD_ID AND S1.USER_TYPE = S.USER_TYPE
);
COMMIT;
--更新serv表 方法二
UPDATE SERV S --用戶資料表
SET S.TERMINAL_NAME=(SELECT
CASE WHEN S.PROD_ID = 1 AND S.USER_TYPE='A' THEN '固話'
WHEN S.PROD_ID = 1 AND S.USER_TYPE='B' THEN '小靈通'
WHEN S.PROD_ID = 2 THEN '寬帶'
WHEN S.USER_TYPE='C' THEN 'CDMA'
ELSE '-1'
END AS TERMINAL_NAME
FROM TERMINAL T --終端類型臨時表
WHERE S.SERV_ID=T.SERV_ID)
WHERE EXISTS (SELECT 1
FROM TERMINAL T1 WHERE S.SERV_ID=T1.SERV_ID);
COMMIT;
--更新terminal表 方法一
UPDATE terminal T SET T.TERMINAL_NAME = (
SELECT
s1.TERMINAL_NAME
FROM SERV S1
INNER JOIN terminal T1
ON S1.SERV_ID = t1.SERV_ID
WHERE t1.SERV_ID = t.SERV_ID
) WHERE EXISTS (
SELECT
s1.TERMINAL_NAME
FROM SERV S1
INNER JOIN terminal T1
ON S1.SERV_ID = t1.SERV_ID
WHERE t1.SERV_ID = t.SERV_ID
);
COMMIT;
--更新terminal表 方法二
UPDATE terminal T SET T.TERMINAL_NAME = (
SELECT
CASE
WHEN s.PROD_ID = 1 AND s.USER_TYPE = 'A' THEN '固話'
WHEN s.PROD_ID = 1 AND s.USER_TYPE = 'B' THEN '小靈通'
WHEN S.PROD_ID = 2 THEN '寬帶'
WHEN S.USER_TYPE = 'C' THEN 'CDMA'
ELSE '-1'
END terminal_name
FROM SERV S
WHERE t.SERV_ID = s.SERV_ID
) WHERE EXISTS (
SELECT
CASE
WHEN s.PROD_ID = 1 AND s.USER_TYPE = 'A' THEN '固話'
WHEN s.PROD_ID = 1 AND s.USER_TYPE = 'B' THEN '小靈通'
WHEN S.PROD_ID = 2 THEN '寬帶'
WHEN S.USER_TYPE = 'C' THEN 'CDMA'
ELSE '-1'
END terminal_name
FROM SERV S
WHERE t.SERV_ID = s.SERV_ID
);
COMMIT;
--------------
END sp_terminal;
後面,其他道友提出此種方法不適合數據量很大的情況,提出了一些方法,也記錄在次
處於禮貌這裏將聊天內容截圖,僅僅展示相關文字
數據量大的話,這種更新就掛了。
buck into for all
數量大 採用 數組 批量更新
弄成分批提交。
引用塊內容
bulk collect into for all