台灣最大程式設計社群網站
線上人數
2115
 
會員總數:246092
討論主題:189665
歡迎您免費加入會員
討論區列表 >> Oracle >> procedure問題
[]  
[我要回覆]
1
回應主題 加入我的關注話題 檢舉此篇討論 將提問者加入個人黑名單
procedure問題
價值 : 100 QP  點閱數:2676 回應數:8
樓主

真的有點難
高級專家
11127 36
6857 1436
發送站內信

我有兩個table

/*
create table COPLIST
(單別 VARCHAR2(10),
單號 VARCHAR2(11),
序號 VARCHAR2(4),
品號 VARCHAR2(10),
數量 NUMBER(18,0),
客戶 VARCHAR2(10))

create table logbb
(cc varchar(100));


INSERT INTO COPLIST(單別,單號,序號) VALUES('C103','0318','0001');
INSERT INTO COPLIST(單別,單號,序號) VALUES('C103','0318','0002');
INSERT INTO COPLIST(單別,單號,序號) VALUES('C103','0318','0003');
*/

我寫一個匿名個區塊 執行正常
/*
begin
declare
CURSOR cr IS
SELECT "序號","品號","數量","客戶" FROM COPLIST where "單別"='C103' AND "單號"='0318';
BEGIN
FOR crx IN cr LOOP
INSERT INTO logbb(cc) VALUES(crx."序號");
END LOOP;
end;
end;

*/

但把它改成procedure 卻不能成功編譯
/*

CREATE OR REPLACE PROCEDURE COPLISTP(
單別 in VARCHAR2(50),
單號 in VARCHAR2(50))
as

begin
declare
CURSOR cr IS
SELECT "序號","品號","數量","客戶" FROM COPLIST where "單別"=單別 AND "單號"=單號;
BEGIN
FOR crx IN cr LOOP
INSERT INTO logbb(cc) VALUES(crx."序號");
END LOOP;
end;
end;


*/


本篇文章發表於2013-03-18 10:44
1樓
不錯的參考

fantasy
捐贈 VP 給 fantasy 檢舉此回應
用Oracle不建議使用中文名單欄位名、參數名、變數名...

Client的NLS_Lang沒設對,程式就會出問題了...
本篇文章回覆於2013-03-18 17:40
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
2樓
作者回應

真的有點難
檢舉此回應
改成英文好像也不行 不知道是哪錯嚕?

create table COPS
(TA001 VARCHAR2(10),
TA002 VARCHAR2(11),
TA003 VARCHAR2(4),
TA004 VARCHAR2(10),
TA005 NUMBER(18,0),
TA006 VARCHAR2(10)) ;

create table logbb
(cc varchar(100));


INSERT INTO COPS("TA001","TA002","TA003") VALUES('C103','0318','0001');
INSERT INTO COPS("TA001","TA002","TA003") VALUES('C103','0318','0002');
INSERT INTO COPS("TA001","TA002","TA003") VALUES('C103','0318','0003');

以下這段 編譯還是錯了

CREATE OR REPLACE PROCEDURE COPLISTP(
VTA001 VARCHAR2(50),
VTA002 VARCHAR2(50))
as

begin
declare
CURSOR cr IS
SELECT "TA003","TA004","TA005","TA006" FROM COPLIST where "TA001"=VTA001 AND "TA002"=VTA002;
BEGIN
FOR crx IN cr LOOP
INSERT INTO logbb(cc) VALUES(crx."TA003");
END LOOP;
end;
end;




本篇文章回覆於2013-03-18 17:55
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
3樓
回應

花旗蔘
檢舉此回應
兩個error !
try~

1、VTA001、VTA002 不要指定精確度
ex:
CREATE OR REPLACE PROCEDURE COPLISTP(
VTA001 VARCHAR2, --*
VTA002 VARCHAR2 --*
)
as
......
......

2、另外你table name 寫錯了
ex:
begin
declare
CURSOR cr IS
SELECT "TA003","TA004","TA005","TA006" FROM COPLIST -->應是COPS
where "TA001"=VTA001 AND "TA002"=VTA002;
....
....


本篇文章回覆於2013-03-18 22:27
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
4樓
作者回應

真的有點難
檢舉此回應

我把它改成

CREATE OR REPLACE PROCEDURE COPss(
VTA001 VARCHAR2, --*
VTA002 VARCHAR2 --*
)
as
begin
declare
CURSOR cr IS
SELECT "TA003","TA004","TA005","TA006" FROM COPs where "TA001"=VTA001 AND "TA002"=VTA002;
BEGIN
FOR crx IN cr LOOP
INSERT INTO logbb(cc) VALUES(crx."TA003");
END LOOP;
end;
end;

編譯會過但
begin
copss('C103','0318');
end;

出現[Error] Execution (21: 7): ORA-06550: 第 2 行, 第 7 個欄位:
PLS-00103: 發現了符號 "COPSS" 當您等待下列事項之一發生時:
:= . ( @ % ;
符號 ":=" 取代了 "COPSS" 才可以繼續作業.

試了很多方法都不過 不知道如何解



本篇文章回覆於2013-03-19 16:03
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
5樓
作者回應

真的有點難
檢舉此回應
感謝大大
應該要

begin
copss('c103',0318);
end;
本篇文章回覆於2013-03-19 16:21
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
6樓
作者回應

真的有點難
檢舉此回應
但是我寫一個TRIGGER 去呼叫COPSS編譯過了但執行後

create or replace trigger coptrig
after update on cops
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
VTA001 VARCHAR2(50);
VTA002 VARCHAR2(50);
begin
SELECT :OLD."TA001" INTO VTA001 FROM DUAL;
SELECT :OLD."TA002" INTO VTA002 FROM DUAL;
copss(vTA001,vta002);
end;


UPDATE COPS SET TA005='1000' WHERE TA002='0318';
出現
ORA-04091: 表格 SYSTEM.COPS 正在變更中, 觸發程式/函數無法檢視它
ORA-06512: 在 "SYSTEM.COPSS", line 9
ORA-06512: 在 "SYSTEM.COPSS", line 11
ORA-06512: 在 "SYSTEM.COPTRIG", line 7
ORA-04088: 執行觸發程式 'SYSTEM.COPTRIG' 時發生錯誤







本篇文章回覆於2013-03-19 16:43
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
7樓
最有價值解答

花旗蔘
檢舉此回應
整段看下來你最近問的這兩個問題 核心都在 ORA-4091
其實我在你 "trigger + cursor問題"中的 #4
有提示過你了,
maybe you can try
"pragma autonomous_transaction"
google it for detail info.

你的business model 我不了解,總之就你的ISSUE來說
如果你要使用 你習慣的寫法 就是cursor那個
可使用 例1
1'使用pragma autonomous_transaction
EX:
CREATE OR REPLACE TRIGGER coptrig
AFTER UPDATE ON cops
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
declare
CURSOR cr IS
SELECT "TA003","TA004","TA005","TA006" FROM COPS where "TA001"= :NEW."TA001" AND "TA002"= :NEW."TA002";
pragma autonomous_transaction; --*
BEGIN
FOR crx IN cr LOOP
INSERT INTO logbb(cc)VALUES(crx."TA003");
commit; --*
END LOOP;
END;

注意 * 號部份.
另外 pragma autonomous_transaction的用法是 所謂的自主交易
也就是說你的 update 跟 trigger 所觸發的dml 是各自的兩個transaction
結論就是
A tx:update 資料 -->B tx :trigger 觸發 dml
今天即使A tx 被rollback了,B tx 不會連帶被rollback了.

2'我不清楚你的business model,但若針對 你問題的陳述來看,
提供個意見就是改用before update 的trigger,你可評估符合你需求否?

這樣寫 兩者納為一個transaction 處理

ex:
CREATE OR REPLACE TRIGGER coptrig
before UPDATE ON cops
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
INSERT INTO logbb(cc)VALUES(:new."TA003");
END;
本篇文章回覆於2013-03-20 13:50
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
8樓
作者回應

真的有點難
檢舉此回應
TO fantasy 花旗蔘版主

感謝你們一在提示終於搞定了
我有去研究"pragma autonomous_transaction"
可惜我太菜了看不懂
ORACLE 真是博大精深 我可能要海k文件了
再次感謝!
本篇文章回覆於2013-03-20 16:39
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
   
1

回覆
如要回應,請先登入.