0

我在上一篇文章(https://stackoverflow.com/questions/16520216/ora-01843-not-a-valid-month)中问过这个问题,但从那以后它发生了变化,我认为这样做会更好从一开始就更清楚。

我在运行从客户表中删除客户的过程时收到此错误。

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;

现在,当我删除一个在placed_order 表中没有记录的客户时,该记录被删除了,当尝试删除一个在placed_order 表中有记录的客户时会出现错误消息。因此,我认为错误发生在触发器中,因为触发器仅将值插入到 previous_customer 表中,前提是它们在placed_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

放置订单的结构是:

"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;
4

1 回答 1

4

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

and delivery_date > sysdate;

...这将导致表中的值根据会话的 NLS_DATE_FORMATdelivery_date隐式转换为类型。date如果您有一个不是该格式的“日期”,那么您将收到此错误。例如,如果您的 NLS_DATE_FORMATmm/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可能就足够了。

于 2013-05-13T16:24:52.063 回答