То, что вы натолкнулись, - это классическое исключение «mutating table». В ROW-триггере Oracle не позволяет вам запускать запрос к таблице, для которой задан триггер, поэтому это SELECT
против TABLE1 в DELETING
части триггера вызывает эту проблему.
Существует несколько способов обойти это. Возможно, лучшим в этой ситуации является использование составного триггера, который будет выглядеть примерно так:
CREATE OR REPLACE TRIGGER TABLE1_NUM_TRG
FOR INSERT OR DELETE ON TABLE1
COMPOUND TRIGGER
TYPE NUMBER_TABLE IS TABLE OF NUMBER;
tblTABLE2_IDS NUMBER_TABLE;
BEFORE STATEMENT IS
BEGIN
tblTABLE2_IDS := NUMBER_TABLE();
END BEFORE STATEMENT;
AFTER EACH ROW IS
BEGIN
IF INSERTING THEN
UPDATE TABLE2 t2
SET t2.TABLE2NUM = :new.NUM
WHERE t2.ID = :new.TABLE2_ID;
ELSIF DELETING THEN
tblTABLE2_IDS.EXTEND;
tblTABLE2_IDS(tblTABLE2_IDS.LAST) := :new.TABLE2_ID;
END IF;
END AFTER EACH ROW;
AFTER STATEMENT IS
BEGIN
IF tblTABLE2_IDS.COUNT > 0 THEN
FOR i IN tblTABLE2_IDS.FIRST..tblTABLE2_IDS.LAST LOOP
UPDATE TABLE2 t2
SET t2.TABLE2NUM = (SELECT NUM
FROM (SELECT t1.NUM
FROM TABLE1 t1
WHERE t1.TABLE2_ID = tblTABLE2_IDS(i)
ORDER BY modification_date DESC)
WHERE ROWNUM = 1)
WHERE t2.ID = tblTABLE2_IDS(i);
END LOOP;
END IF;
END AFTER STATEMENT;
END TABLE1_NUM_TRG;
Составной триггер позволяет каждой временной точке (BEFORE STATEMENT
, BEFORE ROW
, AFTER ROW
и AFTER STATEMENT
) для обработки. Обратите внимание, что точки синхронизации всегда вызывается в указанном порядке. Когда выполняется соответствующий оператор SQL (т.е. INSERT INTO TABLE1
или DELETE FROM TABLE1
) и запускается этот триггер, первая выбранная точка синхронизации будет BEFORE STATEMENT
, а код в обработчике BEFORE STATEMENT
будет выделять PL / SQL чтобы держать кучу чисел. В этом случае номера, которые должны быть сохранены в таблице PL / SQL, будут значениями TABLE2_ID из таблицы 1. (Вместо таблицы, например, массива используется таблица PL / SQL, поскольку таблица может содержать различное количество значений, а если мы использовали массив, нам нужно заранее знать, сколько чисел нам нужно хранить. Мы не можем заранее знать, сколько строк будет зависеть от конкретного оператора, поэтому мы используем таблицу PL / SQL). Когда достигнута точка времени AFTER EACH ROW
, и мы обнаруживаем, что обрабатываемый оператор является INSERT, триггер просто идет вперед и выполняет необходимое UPDATE в TABLE2, так как это не вызовет проблемы. Однако, если выполняется DELETE, триггер сохраняет TABLE1.TABLE2_ID в таблицу PL / SQL, выделенную ранее. Когда окончательная точка времени AFTER STATEMENT
окончательно достигнута, таблица PL / SQL, распределенная ранее, повторяется, и для каждого найденного TABLE2_ID выполняется соответствующее обновление.
Поделитесь и наслаждайтесь.
Он доступен в SDK начиная с API 11 - http://developer.android.com/reference/android/widget/NumberPicker.html
Немного поздно, но для всех, кто заинтересован, http://code.google.com/p/android-wheel/ - хорошая реализация.
Может быть полезно:
http://groups.google.com/group/android-developers/browse_thread/thread/65da9820998fddc9
Я только что выпустил код, который делает именно то, что вы хотите. Посмотрите на мой пользовательский элемент управления, NumberPicker, который можно увидеть здесь: http://www.technologichron.net/?p=42