![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Быстрая проверка существования записи в Oracle
Ломброзо © (2007-03-25 14:19:00)Как известно, В MSSQL оператор EXISTS может использоваться как скалярная функция, которая возвращает булевый результат, и её можно использовать для быстрой проверки существования записи по условию, как то:
IF EXISTS(SELECT * FROM CUSTOMERS WHERE NAME = @NAME) THEN ....
В Oracle такая фича не работает и я выкручиваюсь через подсчёт числа записей:
DECLARE
iCNT NUMBER;
BEGIN
SELECT COUNT(ID) INTO iCNT FROM CUSTOMERS WHERE NAME = :NAME;
IF iCNT = 0 THEN ...
Есть ли в оракле какой-нибудь заменитель сей громоздкой конструкции?
evvcom (2007-03-27 14:45:00) [1]> [29] ANB © (27.03.07 14:32)
> Но неочевидно все все равно.
АбЫдна...
Еще как вариант, по тексту навставлять Step := Step + 1; и в exception запись в лог в том числе и Step. Извращений много разных. :)
ANB (2007-03-27 14:32:00) [2]
> А 10-ку на этот счет не тестил пока.
Я тестил. Тока теперь там еще одну функцию добавили для выгребания стека. Разобраться, что сломалось, помудохавшись, можно. Но неочевидно все все равно.
evvcom (2007-03-27 14:22:00) [3]> [27] ANB © (27.03.07 12:01)
> И так обернуть каждый оператор ?
А это уж, как душе угодно. :)
> А вот обработка исключений в оракле имеет некоторые проблемы,
> т.к. до 10-ки при перехвате их портился стек ошибок. И
> разобраться, где именно произошли проблемы, довольно тяжело.
Вот, видимо, из-за этого и родилась у меня такая идея. А 10-ку на этот счет не тестил пока.
ANB (2007-03-27 12:01:00) [4]
> evvcom © (27.03.07 10:36) [26]
И так обернуть каждый оператор ?
Предварительные проверки, имхо, имеют смысл именно из-за простоты их реализации. Но база все равно должна быть закрыта от мусора ограничениями.
А вот обработка исключений в оракле имеет некоторые проблемы, т.к. до 10-ки при перехвате их портился стек ошибок. И разобраться, где именно произошли проблемы, довольно тяжело.
evvcom (2007-03-27 10:36:00) [5]> [23] Ломброзо © (27.03.07 00:18)
> мне ничего не говорит о том, по какой причине и в каком
> месте случилась ошибка
а кто тебе мешает написать:
<procedure>
beginБудет тебе и место и смысл
...
begin
...
exception
...
end;
...
begin
...
exception
...
end;
...
begin
...
exception
...
end;
...
exception
...
end;
Ломброзо (2007-03-27 01:27:00) [6]Да ладно, select for update я уже освоил на твёрдую тройку и запытал в конкурирующей среде :) Вполне устраивает.
Petr V. Abramov (2007-03-27 00:40:00) [7]> Не боинг, но всё же.
так бы и ветку озаглавил, хрен вас медиков, поймешь, спросишь в реанимации анекдот, так говорят: "у нас все про покойников" :)))) увы, из жизни....
> Ломброзо ©
че те не устаривает в стандартном подходе Oracle? щас объясним, че ты в нем не понимаешь или workaround придумаем.
Ломброзо (2007-03-27 00:18:00) [8]Блин, ну я уже объяснял, зачем. Мне, например, прежде чем в транзакции перенести данные, полученные от некоего девайса, в медкарту, нужно порядка сотни параметров в десятке процедур проверить, причем таким образом, чтобы человек со средним медицинским образованием в обморок не падал при виде непонятных английских слов. То есть буквально на каждый неверный чих нужно выдавать внятное сообщение на русском языке с объяснением причин ошибки и инструкцией во избежание. Как это технически реализовать - плеваться ли из хранимок кодами ошибок в сервер приложений, который их транслирует в текстовые, или прямо из ХП ексепшн кидать - непринципиально.
Вот такой код (с)
when others then
if sqlcode = 1 then
-- тут в автономной транзакции запиши куда-нить оригинальный sqlerrm
raise_application_error(-2001, 'сам дурак и никаких имен таблиц' );
else
raise;
end if;
- мне ничего не говорит о том, по какой причине и в каком месте случилась ошибка, если отключить Debug info и не смотреть стек.
Разумеется, в проверке тех предусловий, которые проверяются в том числе и констрейнтами, ручками, есть некоторое неудобство, но тут предметная область такая. Не боинг, но всё же.
Petr V. Abramov (2007-03-26 23:31:00) [9]имелось в виду, когда констрайнта нет и он моделируется кодом, что стронгли не рекомендуется в документации.
Petr V. Abramov (2007-03-26 23:15:00) [10]> ANB © (26.03.07 17:11) [17]
> А в 10% сработает констрайнт. При чем тут random
если есть констрайнт, то получим исключение по факту инсерта. хоть и проверяли, что "нету".
будут и более гадкие ситуациии, при delete в другой транзакции, без exception
> А в 10% сработает констрайнт. При чем тут random
а нахрена писанина, если все ошибочные ситуации этими "10%" и описываются?
Val (2007-03-26 18:23:00) [11]я, наверное.
ANB (2007-03-26 18:20:00) [12]
> "незначительной" разницы между блокировочником и версионником
Эээ. А кто тут версионник ? Про IB/FB разговора вроде не было . . .
Val (2007-03-26 18:09:00) [13]Честно говоря, я бы попытался сделать вставку и обработать исключение, а не выборку, а затем обработку условия и вставку, которая может не произойти по вышеописанным причинам.
p.s. топик возник, думается, как тут говорили, из-за "незначительной" разницы между блокировочником и версионником ;)
ANB (2007-03-26 17:11:00) [14]
> Petr V. Abramov © (26.03.07 13:51) [16]
А в 10% сработает констрайнт. При чем тут random ?
Petr V. Abramov (2007-03-26 13:51:00) [15]> минимум 90% случаев они обрабатывают.
тогда можно не писать никаких проверок, а проверять резльтат random.
ANB (2007-03-26 13:05:00) [16]Практически все проверки, выполняемые до DML могут оказаться ложными к моменту собственно изменения данных. Что, однако, не снижает их полезности, т.к. минимум 90% случаев они обрабатывают.
Вывод - если операция не критична по скорости и не лень эти проверки писать - то есть смысл таки их написать. Но при этом не забывать об ограничениях.
Все имхо.
evvcom (2007-03-26 12:06:00) [17]А что после
> IF iCNT = 0 THEN ...
? От этого зависит красота решения. А то "вставят, не вставят" :) Каков вообще смысл проверки?
Evgeny V (2007-03-26 09:38:00) [18]
> roottim © (26.03.07 09:20) [12]
Добавить INTO и перевести в PL/SQL не проблема думаю
Ну если надо строго 1 или 0, то можно и такие варианты
Первый с COUNT, хоть и COUNT, но считать не более одной записи...
SELECT COUNT(*) from (SELECT 1 FROM dual where exists(select sernum from myshema.avl_sensor where dk > SYSDATE-1))
Второй вариант
select nvl(
(select 1 from adm.avl_sensor
where dk > SYSDATE-1
and rownum<=1),0) from dual
roottim (2007-03-26 09:20:00) [19]у тебя нет into, речь ведь о pl/sql
а посему влетит exception no_data_found который обработать надо...
посему тот же результат без гемороя можно получить обернув его
select
nvl((SELECT 1 FROM dual where exists(select 1 from myshema.avl_sensor where dk > SYSDATE-1), 0) f_exists
into
v_result
from
dual
Evgeny V (2007-03-26 07:48:00) [20]В Оракле например -
SELECT 1 FROM dual where exists(select sernum from myshema.avl_sensor where dk > SYSDATE-1)
Есть запись - получим 1, нет -получим NULL
В свое время узнал это от Шевченко Игоря и Внука:-)