我在上一篇文章(https://stackoverflow.com/questions/16520216/ora-01843-not-a-valid-month)中提到了这个问题,但从那时起它发生了变化,我认为最好从一开始就让它更清楚。
在运行从客户表中删除客户的过程时,我收到此错误。
BEGIN
customers.remove_customer('17023');
END;
然而,当我从customers表中删除一个客户时触发了一个触发器,这就是我认为问题所在,这里是触发器的代码:
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;
现在,当我删除未在placement_order表中获取记录的客户时,记录被删除了,尝试删除在placement_order表中有记录的客户时会出现错误消息。因此,我认为错误发生在触发器中,因为触发器只是在previous_order表中有记录时才将值插入到previous_customer表中。但我仍然不明白为什么我收到错误信息?
客户表上没有其他触发器。 放置的订单表上没有其他触发器,previous_employee
也没有customers表的结构是:
"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
placement_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
以及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;
答案 0 :(得分:4)
DELIVERY_DATE
是VARCHAR2(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
类型 - 您确实应该 - 您必须假设其中的数据采用标准格式,并且在这种情况下,你可以(正如Bob所说)按照你自己的条件强制进行转换:
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
可能就足够了。