我使用以下代码创建了现有数据库(I_Customer)的副本:
CREATE TABLE N_CUSTOMER AS SELECT * FROM I_CUSTOMER;
我创建了下表,它将作为修改N_Customer表的日志:
CREATE TABLE CUSTOMER_CHANGELOG
( cust_no NUMBER(5),
cust_name VARCHAR2(20),
contact VARCHAR2(20),
log_date DATE);
我还创建了(在堆栈成员的帮助下)下面的触发器,它将在编辑N_Customer表后触发,并将一些特定字段(新旧)写入Customer_Changelog表:
CREATE OR REPLACE
TRIGGER customer_up_tr
AFTER UPDATE ON n_customer
FOR EACH ROW
WHEN (OLD.contact <> 1 AND NEW.contact = 1 OR OLD.cust_name <> 1 AND NEW.cust_name = 1)
BEGIN
INSERT INTO customer_changelog (cust_no, cust_name, contact, log_date) VALUES (:OLD.cust_no, :OLD.cust_name, :OLD.contact, sysdate);
INSERT INTO customer_changelog (cust_no, cust_name, contact, log_date) VALUES (:NEW.cust_no, :NEW.cust_name, :NEW.contact, sysdate);
END;
现在,当我使用以下代码编辑N_Customer表时:
UPDATE N_CUSTOMER
SET cust_name = 'Peter Davis', contact = 'Sam Bogdanovich'
WHERE cust_no = 2338;
我收到此错误:
UPDATE N_CUSTOMER
*
ERROR at line 1:
ORA-01722: invalid number
现在我的数据类型等都匹配,所以我不确定是什么原因造成的。
非常感谢任何想法。
答案 0 :(得分:1)
问题在于触发器的这一行:
(OLD.contact <> 1 AND NEW.contact = 1 OR OLD.cust_name <> 1 AND NEW.cust_name = 1)
Contact和cust_name字段是VARCHAR2,但触发器将它们与数字进行比较。
这个简单的示例将失败并出现相同的错误:
SELECT 1 FROM DUAL
WHERE 'abc' <> 1;
答案 1 :(得分:0)
表达式OLD.contact <> 1
正在将字符列contact
与数字进行比较(这也称为“将苹果与橙子进行比较”)。
因为将数字转换为字符是不明确的(可以转换为'01',
'001'...) Oracle will do it the other way round and convert the character value to a number (because that is non-amgigous
'01',
'001'will both result in the number
1 `)。
您显然在contact
列中有非数字值(根据列的名称及其数据类型预期),转换失败。
简单的规则是:
将字符文字用于数字的字符和数字文字。 1
是一个数字。 '1'
是一个字符文字。
说了这么多,你需要改变这一行:
OLD.contact <> 1 AND NEW.contact = 1 OR OLD.cust_name <> 1 AND NEW.cust_name = 1
到
OLD.contact <> '1' AND NEW.contact = '1' OR OLD.cust_name <> '1' AND NEW.cust_name = '1'