2013-05-13 44 views
0

我在上一篇文章(https://stackoverflow.com/questions/16520216/ora-01843-not-a-valid-month)中提出過這個問題,但從那時起它就發生了變化,我認爲最好從頭開始更清楚一點。爲什麼我得到ORA-01843:不是有效的月份錯誤?

運行過程從客戶表中刪除客戶時,我收到此錯誤。

BEGIN 
customers.remove_customer('17023'); 
END; 

然而,當我刪除客戶表中的客戶一個觸發器觸發這是我認爲問題在於,這裏是觸發代碼:

create or replace TRIGGER CUSTOMER_AD 
    BEFORE DELETE ON CUSTOMER 
    REFERENCING OLD AS OLD 
    FOR EACH ROW 
DECLARE 
pragma autonomous_transaction; 
nPlaced_order_count NUMBER; 
BEGIN 
SELECT COUNT(*) 
INTO nPlaced_order_count 
FROM PLACED_ORDER p 
WHERE p.FK1_CUSTOMER_ID = :OLD.CUSTOMER_ID; 
IF nPlaced_order_count > 0 THEN 
INSERT into previous_customer 
(customer_id, 
first_name, 
last_name, 
address) 
VALUES 
(:old.customer_id, 
:old.first_name, 
:old.last_name, 
:old.address); 
END IF; 
END CUSTOMER_AD; 

現在,當我刪除客戶誰沒有記錄在已放置的訂單表中記錄被刪除正常,當試圖刪除在已訂購的訂單表中有記錄的客戶時會出現錯誤消息。因此,我認爲錯誤發生在觸發器中,因爲如果觸發器只在prede_customer表中插入值,那麼它們在place_order表中有記錄。但我仍然不明白爲什麼我會收到我的錯誤消息?

客戶表上沒有其他觸發器。 的放置順序表上有沒有其他觸發器和既不確實的previous_employee

爲客戶表中的結構是:

"CUSTOMER_ID" VARCHAR2(40) NOT NULL ENABLE, 
"FIRST_NAME" VARCHAR2(30), 
"LAST_NAME" VARCHAR2(30), 
"ADDRESS" VARCHAR2(30) 
CONSTRAINT "PK_CUSTOMER" PRIMARY KEY ("CUSTOMER_ID") ENABLE 

爲placed_order結構是:

"ORDER_ID" NUMBER(*,0) NOT NULL ENABLE, 
"ORDER_DATE" VARCHAR2(15), 
"DELIVERY_DATE" VARCHAR2(15), 
"FK1_CUSTOMER_ID" VARCHAR2(40) NOT NULL ENABLE, 
CONSTRAINT "PK_PLACED_ORDER" PRIMARY KEY ("ORDER_ID") ENABLE 

ALTER TABLE "PLACED_ORDER" ADD CONSTRAINT "FK1_PLACED_ORDER_TO_CUSTOMER" FOREIGN KEY ("FK1_CUSTOMER_ID") 
     REFERENCES "CUSTOMER" ("CUSTOMER_ID") ON DELETE CASCADE ENABLE 

和結構for previous_customer是:

"CUSTOMER_ID" VARCHAR2(40), 
"FIRST_NAME" VARCHAR2(30), 
"LAST_NAME" VARCHAR2(30), 
"ADDRESS" VARCHAR2(30) 

任何人都知道爲什麼我得到錯誤消息ORA-01843?

程序代碼是:

PROCEDURE remove_customer (customer_id VARCHAR2) IS 
    ordersCount pls_integer; 
BEGIN 
    select count(*) into ordersCount 
    from placed_order 
    where fk1_customer_id = remove_customer.customer_id 
    and delivery_date > sysdate; 
IF ordersCount > 0 
THEN 
DBMS_OUTPUT.PUT_LINE ('Customer currently has a order been delivered and cant be deleted'); 
ELSE 
DELETE FROM customer 
WHERE customer.customer_id = remove_customer.customer_id; 
total_customers := total_customers - 1; 
END IF; 
END; 
+1

您顯示的內容沒有解釋錯誤。查找試圖將一列'placed_order.delivery_date'和'placed_order.order_date'解析爲實際日期或日期時間對象的代碼。 – 2013-05-13 15:50:47

+0

爲什麼你認爲觸發是問題的根源?如果在任何表格或代碼中沒有「DATE」列,觸發器導致錯誤的可能性很小。爲什麼觸發器是一個自主事務?這幾乎肯定是一個錯誤。雖然它可能不是這個特定bug的來源。 – 2013-05-13 15:51:17

+0

如果觸發器是問題,那麼只需運行...刪除客戶id = ...應該得到同樣的問題。可以? – Dave 2013-05-13 16:02:31

回答

4

DELIVERY_DATEVARCHAR2(15)。你的程序包括:

and delivery_date > sysdate; 

...這將導致該表中的delivery_date值隱式轉換爲date類型的基礎上,NLS_DATE_FORMAT的會話。如果你有一個'日期'在那裏不是那種格式,那麼你會得到這個錯誤。例如,如果您的NLS_DATE_FORMAT爲mm/dd/yyyy,就像您在上一個問題中所說的那樣,並且您之前在表格中將日期存儲爲dd/mm/yyyy,例如, '13/05/2013',那麼它會從隱式轉換中得到這個錯誤。

它可能有點間歇;如果客戶沒有placed_order的數據,那麼將沒有日期(試圖)轉換。

所以這與觸發器無關。無論如何,觸發似乎毫無意義。你爲什麼不在這個程序中插入previous_customer?你可以這樣做:

ELSE 
    INSERT INTO previous_customer(customer_id, first_name, last_name, address) 
    SELECT customer_id, first_name, last_name, address) 
    FROM customer 
    WHERE customer_id = remove_customer.customer_id; 

    DELETE FROM customer 
    WHERE customer.customer_id = remove_customer.customer_id; 

    total_customers := total_customers - 1; 
END IF; 

...並放棄和忘記觸發器。

正因如此,您不應該在文本字段中存儲日期。 如果您不能將placed_order字段更改爲DATE類型 - 而且您確實應該 - 您必須假定它們中的數據是標準格式,並且在這種情況下,您只能與()鮑勃說)迫使你自己的條件轉換:

and to_date(delivery_date, 'dd/mm/yyyy') > sysdate 

...其中`DD/MM/YYYY」,是指已用於填充文本字段的日期格式。如果它有一個時間分量,我想它的長度可能,則包括在面具太:

and to_date(delivery_date, 'dd/mm/yyyy HH24:MI:SS') > sysdate 

...雖然明明說現在太久了varchar2(15)場,誰知道你是什麼在那裏。

您是否確實是指> sysdate?在項目實際交付時它是否填充,還是顯示預計交付日期?錯誤很奇怪,並沒有說清楚,如果只有還沒有交付的訂單才能刪除,或者已經有任何交付的訂單,在這種情況下delivery_date is not null可能就足夠了。

+0

BRAVO !!!!!並詛咒你,紅色男爵...... :-) – 2013-05-13 16:27:58

+1

因此,說明爲什麼人們需要發佈*所有*相關的代碼,而不僅僅是它的一部分。通常情況下,他們認爲拋出錯誤的位並非如此。 – APC 2013-05-13 16:28:13

+0

所以你認爲它會工作,如果我改變日期的格式與sysdate相同。因爲看着這個放置在記錄表格中的記錄的格式是DD/MM/YYYY,而你說我需要它們是mm/dd/yyyy嗎? – 2013-05-13 16:28:39

相關問題