[бд] вставить уникальную запись с проверкой
1-й способ надо использовать
тогда нужно блокировать таблицу на запись
в принципе можно давать констрейнтам разумные имена и искать их в тексте ошибки
большинство СУБД в тексте ошибки пишет название нарушенного констрейнта.
Ну собственно, о чём и речь.
>в принципе можно давать констрейнтам разумные имена и искать их в тексте ошибки
>большинство СУБД в тексте ошибки пишет название нарушенного констрейнта.
Этот грязный хак мне уже несколько неместных отцов предлагали.
Неужели всё так запущено?
таблица будет автоматически блокироваться на запись,если другая транзакция использует оператор insert
так меньше всего гемора и приемлемое качество
второй способ - это хак, и последствия будут долго аукаться.
и последствия будут долго аукатьсяПочему?
Именно, потому что это сильно не стандартный способ.
И изменения, которое вроде бы даже не связанное с этим (смена базы, смена провайдера, смена языка и т.д.) - будут ронять в том числе и это место.
Такое стоит делать - если ты померил, и выяснил, что это действительно дает выигрыш в два раза - и тебе действительно это жизненно необходимо.
И изменения, которое вроде бы даже не связанное с этим (смена базы, смена провайдера, смена языка и т.д.) - будут ронять в том числе и это место.Но, грубо говоря - мы пытаемся вставить строку, нам говорят "не получилось"... как на это повлияет "смена базы, смена провайдера, смена языка и т.д."? Если при этом то поле всё равно будет уникальным...
И вообще, какой тогда смысл делать уникальным то поле - если мы всё равно ручками каждый раз это проверять будем?
потому что вот это "не получилось" - сильно зависит от базы, провайдера, языка
> И вообще, какой тогда смысл делать уникальным то поле - если мы всё равно ручками каждый раз это проверять будем?
только для того, чтобы иметь гарантию - что в базе лежат всегда хорошие данные.
ps
Использовать вот такие эффекты в программах - это все равно, что идти по краю обрыва ориентируясь на то, чувствует плечо ограду или нет (а не на реальный край).
потому что вот это "не получилось" - сильно зависит от базы, провайдера, языкаНо "получилось" ведь нам в любом случае не скажут?
Скажут тебе - вместо того, что ты ожидал, например, упал коннект до базы - твои действия?
понял
И изменения, которое вроде бы даже не связанное с этим (смена базы, смена провайдера, смена языка и т.д.) - будут ронять в том числе и это место.и часто приходится переходить?
а даже если пришлось, то "это место" должно быть одно и тогда проблем особых не возникнет.
Обозвать его типа "транслятор ошибок" и положить во внешнем файле наподобии словаря с регэкспами - тогда переход на новую СУБД обойдется даже без пересобирания исходников.
а открывать лишние блокирующие транзакции - это может сильно помешать, если пользователей будет много...
если пишется - промышленное ПО (в котором и так обычно хватает подводных камней то ну его нафиг.
в дипломном проекте можно генитально относится к работе под нагрузкой.
ps
Систему в целом - стоит далее по максимуму прозрачную, опирающуюся на стандартные технологии, и стандартное поведение.
и только далее, когда есть уже четкое понимание, что именно не устраивает, можно вставлять оптимизирующие хаки, при чем обязательно с profiler-ом в руках.
pps
скорость можно купить за деньги
надежность, гибкость, прозрачность - чисто за деньги уже не купишь.
где гемор-то? я не пойму...
гемор - это вставлять селекты перед каждой проверкой уникальности (читай дублирование структуры СУБД)
Вот это и есть гибкость/прозрачность.
этот запрос с ошибкой про-upgrade-ить до группового запроса (когда сразу хочеться вставить несколко записей)?поясни
в чем вопрос? какая разница сколько записей ты вставлял, когда произошла ошибка?
гемор (вернее, ошибка архитектуры) - это использовать в качестве идентификатора последовательный счетчик.
гемор (вернее, ошибка архитектуры) - это использовать в качестве идентификатора последовательный счетчик.аргументируй.
GUID лучше?
Пример:
хотим загрузить инфу из некоей базы с такой же таблицей в новую базу в аналогичную таблицу.
тока не все субды умеет по нему правильно индексировать
конечно, лучше. т.к. он все-таки глобально уникальный, что позволяет использовать в том числе и децентрализованные(слабоцентрализованную) архитектуру и механизмы (например, отложенная загрузка)
по оригинальным условиям задачи - предлагалось вставлять по одной записи.
на это ты предложил решение - которое ловит ошибку.
Что будет, если захочеться вставлять в базу не по одной записи, а, например, сразу скопом?
придется менять полностью решение? возвращаясь к транзакционности, select-у и т.д.?
Ничего не будет. А почему должно что-то измениться? Инсерт выдаст эксепшен на одной из строк, откатит изменения и вернет имя нарушенного ограничения. Задача выяснить, какая именно запись не вставилась, тут стоять не может потому что либо ты вставляешь под одной и тогда знаешь, которая упала, либо ты проверяешь все скопом и втавляешь все скопом.
Если стоит задача найти существующие записи - то это совсем другая история и без select'а не обойтись, но вопрос автора треда звучит совсем по-другому.
insert into my_table (select @x where not exists (select id from my_table where id = @x
Оставить комментарий
Josy
Пусть имеется таблица в базе данных. Пусть [для простоты] она содержит единственный столбец типа int, для которого задано ограничение уникальности. В неё забито какое-то множество записей (т.е. различных чисел).Дано очередное число. Нужно проверить, есть ли уже такая запись в таблице, если есть - выдать какое-то сообщение, если её нет - добавить, и выдать другое сообщение. Вопрос такой - как это правильно сделать? У меня получилось родить 2 варианта:
1. Сначала select'ом проверяем, есть ли такое значение в таблице. Если нет, делаем insert.
2. Делаем сразу insert, если возникает ошибка нарушения ограничения - значит, такое число уже было в таблице.
Вариант 2, видимо, во всех смыслах правильнее (быстрее, действие атомарно и т.д.). Кроме того, он и удобнее - например, если моё приложение работает с таблицей в базе через что-нибудь типа ADO Recordset, не надо плодить какие-то лишние сущности для выполнения проверочного селекта.
Проблема в том, что непонятно, как сколько-нибудь перененосимым способом при нарушении ограничения эту ошибку перехватывать. Разные СУБД реагируют на нарушение ограничения по-разному, а когда это пролезает по всем уровням обёрток до ADO, то вообще получается не пойми что. То есть фактически можно лишь только написать обработчик, который переватывает ВСЕ ошибки, что плохо. Можно с этим как-нибудь разумно забороться?