2016-01-18 2 views
0

меня написать функцию PL/SQL, который принимает входной сигнал в формате XML для следующей таблице:Как обрабатывать последовательность в вставке из XMLTable?

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 как инкрементная последовательность (на данный момент я сохраняю ее нулевой, так как я не знаю, как поместить последовательность в предложение 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 является вставка 4 значений столбцов в таблице 5 столбцов, так как колонны MED_RECORDNO будет принимать значение из последовательности MED_RECORDNO_SEQ с использованием TRIGGER MED_RECORDNO_TRIGGER.

Я ничего не знаю об этом. Если вы когда-либо испытывали такие вещи, то, пожалуйста, поделитесь своей идеей.

ответ

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 с значением последовательности. По крайней мере, пока вы не сделаете столбец MED_RECORDNO не нулевым, и вы, вероятно, захотите, если это первичный ключ.


Кстати, если вы на 11g или выше Ваш триггер может назначить последовательность прямо на НОВОЙ pseudorecord:

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 проверка означает, что вы иногда хотите, чтобы значение, которое будет указано ; это плохая идея, поскольку введенные вручную значения могут конфликтовать с значениями последовательностей, либо давая вам дубликаты, либо исключительное/первичное ключевое исключение.

+0

Спасибо вам большое @Alex Poole, он работает правильно. Я сохранил MED_RECORDNO в качестве первичного ключа. Останется ли он основным ключом после добавления последовательности? Я просто CREATE SEQUENCE MED_RECORDNO_SEQ; на несохраненном рабочем листе на sql-проявителе, так же сохраняется ли эта последовательность или я должен ее создавать каждый раз? Где я могу найти эту последовательность в sql-разработчике. Наконец, мне всегда нужно поддерживать порядок в столбцах imputs [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] будет работать без заказа? Спасибо – user5005768

+1

Столбцы должны быть в том же порядке в этих двух частях инструкции; они не должны совпадать с порядком в реальной таблице; или порядок предложения столбца XMLTable - вы также можете иметь больше столбцов в том, что не используется. Последовательность создается один раз; запросите представление 'user_sequences', чтобы увидеть его, или если вы расширяете соединение в SQL Developer, есть раздел для последовательностей. Первичный ключ и последовательность независимы - только триггер соединяет их. –

+0

Спасибо @Alex Poole.Also я хочу знать: могу ли я использовать ту же последовательность и один и тот же триггер для всех таблиц, чтобы поддерживать их порядковый номер строки в таблице. В противном случае для слишком большого числа таких таблиц мне нужно определить новую последовательность и новый триггер для каждого из них. Спасибо – user5005768

Смежные вопросы