我已经编写了一个PL / SQL函数,它以XML格式输入 下表:
TABLE: TBL_MEDICAL_CENTER_BILLS
Name Null Type
------------- -------- -------------
MED_RECORDNO NOT NULL NUMBER
MED_EMPID NVARCHAR2(10)
MED_BILL_HEAD NVARCHAR2(20)
MED_DATE DATE
MED_AMOUNT FLOAT(126)
这是功能代码:
FUNCTION save_medical_center_bills(medical_bill_data NVARCHAR2 ) RETURN clob IS ret clob;
xmlData XMLType;
v_code NUMBER;
v_errm VARCHAR2(100);
BEGIN
xmlData:=XMLType(medical_bill_data);
INSERT INTO TBL_MEDICAL_CENTER_BILLS SELECT x.* FROM XMLTABLE('/medical_center_bill'
PASSING xmlData
COLUMNS MED_RECORDNO NUMBER PATH 'MED_RECORDNO' default null,
MED_EMPID NVARCHAR2(11) PATH 'employee_id',
MED_BILL_HEAD NVARCHAR2(20) PATH 'bill_head' ,
MED_DATE DATE PATH 'effective_date',
MED_AMOUNT FLOAT PATH 'bill_amount'
) x;
ret:=to_char(sql%rowcount);
COMMIT;
RETURN '<result><status affectedRow='||ret||'>success</status></result>';
EXCEPTION
WHEN OTHERS THEN
v_code := SQLCODE;
v_errm := SUBSTR(SQLERRM, 1, 100);
DBMS_OUTPUT.PUT_LINE (v_code || ' ' || v_errm);
-- '<result><status>Error</status> <error_message>'|| 'Error Code:' || v_code || ' ' || 'Error Message:' || v_errm ||'</error_message> </result>';
RETURN '<result><status>Error</status> <error_message>'|| 'Error Message:' || v_errm ||'</error_message> </result>';
END save_medical_center_bills;
但是,我希望将表的第一列MED_RECORDNO
保持为递增序列(此时我保持为null,因为我不知道如何将序列放在XMLTable子句中)和其余的
输入[MED_EMPID,MED_BILL_HEAD,MED_DATE,MED_AMOUNT]将从传递给函数的XML中获取。
我创建了一个序列和一个触发器,以便为该表格列MED_RECORDNO
增加此序列:
CREATE SEQUENCE MED_RECORDNO_SEQ;
create or replace TRIGGER MED_RECORDNO_TRIGGER
BEFORE INSERT ON TBL_MEDICAL_CENTER_BILLS FOR EACH ROW
WHEN (new.MED_RECORDNO is null)
DECLARE
v_id TBL_MEDICAL_CENTER_BILLS.MED_RECORDNO%TYPE;
BEGIN
SELECT MED_RECORDNO_seq.nextval INTO v_id FROM DUAL;
:new.MED_RECORDNO := v_id;
END;
如您所见,我的XMLTable在5列表中插入4个列值,因为列MED_RECORDNO
将使用MED_RECORDNO_SEQ
从序列TRIGGER MED_RECORDNO_TRIGGER
获取其值。
我不知道这样做的任何事情。如果您曾经历过这样的事情,那么请分享您的想法。
答案 0 :(得分:1)
我在之前的回答中暗示了这一点。您应该在要插入的表中指定列的名称;这是一个很好的做法,即使你正在填充所有这些,因为如果表结构发生变化(或环境不同),它将避免意外,并且更容易发现像列或值的顺序错误。
INSERT INTO TBL_MEDICAL_CENTER_BILLS (MED_EMPID, MED_BILL_HEAD, MED_DATE, MED_AMOUNT)
SELECT x.MED_EMPID, x.MED_BILL_HEAD, x.MED_DATE, x.MED_AMOUNT
FROM XMLTABLE('/medical_center_bill'
PASSING xmlData
COLUMNS MED_EMPID NVARCHAR2(11) PATH 'employee_id',
MED_BILL_HEAD NVARCHAR2(20) PATH 'bill_head' ,
MED_DATE DATE PATH 'effective_date',
MED_AMOUNT FLOAT PATH 'bill_amount'
) x;
您拥有的插入实际上应该有效(如果表中的列顺序匹配);触发器仍将使用序列值替换从XMLTable获取的null值。至少,直到你使MED_RECORDNO列不为空,并且你可能想要它是否是主键。
顺便提一下,如果您使用11g或更高级别,您的触发器可以将序列直接分配给新的伪记录:
create or replace TRIGGER MED_RECORDNO_TRIGGER
BEFORE INSERT ON TBL_MEDICAL_CENTER_BILLS
FOR EACH ROW
BEGIN
:new.MED_RECORDNO := MED_RECORDNO_seq.nextval;
END;
when null
检查意味着您有时希望允许指定值;这是一个坏主意,因为手动插入的值可能会与序列值发生冲突,无论是给出重复项还是唯一/主键异常。