Форум: "Начинающим";
Текущий архив: 2011.05.15;
Скачать: [xml.tar.bz2];
Вниз
проверка вводимого значения Найти похожие ветки
← →
kxft78 © (2011-02-03 12:46) [0]Господа подскажите, дело не хитрое но "прогуглив" пол дня так ничего и не нашел дельного.
Ситуация:
При выполнении sql скрипта (insert строки), необходимо сделать проверку на наличие содержимого поля в справочной таблице и если его там нет то обругать юзера.
сделал просто - select field from spr_table where field="edit.text"
затем
perem1:= AOQuery.FieldValues["field"];
если в запросе пусто то я соответственно получаю ошибку о невозможности присвоения строковой переменной значения null.
И все хорошо если не одно но... необходимо обругать юзера по русски и указать где он напортачил.
Пытался через try ...except наткнулся на грабли что после обработки исключения он благополучно выполняет дальнейший код, а мне это не надо!
← →
Сергей М. © (2011-02-03 12:51) [1]try
..
except
on e:ESomeKnownException do begin
raise EMyExceprion.Create("Юзер, ты тупорылый !");
end;
end;
← →
И. Павел © (2011-02-03 12:52) [2]if AOQuery.bof and AOQuery.eof then ShowMessage("Ах ты гад! Ты что только что ввел!?");
← →
Anatoly Podgoretsky © (2011-02-03 13:03) [3]IsNull/IsEmpty
← →
kxft78 © (2011-02-03 13:06) [4]все не то.
Мне необходимо чтобы после обругания юзера дальнейший код не выполнялся...
← →
И. Павел © (2011-02-03 13:07) [5]if AOQuery.bof and AOQuery.eof then
begin
ShowMessage("Ах ты гад! Ты что только что ввел!? Теперь все вводи заново!");
Abort;
end;
← →
kxft78 © (2011-02-03 13:10) [6]Сергей М твой пример работает как надо, спасибо!
чет я совсем плохой стал....
← →
И. Павел © (2011-02-03 13:11) [7]А блоки перехвата ошибок в коде, где есть abort стройте так, чтобы исключение EAbort ими не обрабатывалось:
except
on EAbort do abort;
on Exception do
...
← →
Ega23 © (2011-02-03 13:11) [8]
> if AOQuery.bof and AOQuery.eof
Это называетсяDataSet.IsEmpty
> все не то.
> Мне необходимо чтобы после обругания юзера дальнейший код
> не выполнялся...
Если делать идеально, то все проверки должны происходить в одной транзакции со вставкой. Ибо никто не даёт гарантии, что ты проверил 6 полей из 10, проверяешь 7-е, а Вася Пупкин в это время не обновляет 1-е.
Я в таких случаях стараюсь логику на сторону СУБД вынести и хранимку пишу.
← →
И. Павел © (2011-02-03 13:13) [9]> Это называется DataSet.IsEmpty
Нет. IsEmpty работает не так, и поэтому не исключено, что может не работать вместе с RecordCount.
← →
Ega23 © (2011-02-03 13:18) [10]
> IsEmpty работает не так, и поэтому не исключено, что может
> не работать вместе с RecordCount
Гы, ну тебя за язык никто не тянул, давай объясняй, чего не так в
function TDataSet.IsEmpty: Boolean;
begin
Result := FActiveRecord >= FRecordCount;
end;
и как оно может работать "не так" вместе с RecordCount.
← →
kxft78 © (2011-02-03 13:22) [11]И. Павел тоже спасибо, сижу выбирая как бы лучше сделать, мне кажется решение Сергея более правильно чтоли. Или в моем случае все равно? а проверяю я перед инсертом всей строки целиком, так что ситуации с Пупкиным я думаю не будет :)
← →
И. Павел © (2011-02-03 13:24) [12]> Гы, ну тебя за язык никто не тянул, давай объясняй, чего
> не так в
И вас за язык тоже никто не тянул (хотя последнее время у меня складывается обратное впечатление):
>The number of rows indicated might be less than the total number of rows in a table.
>This can happen when the rows retrieved as a recordset
>for a dataset component are a conditional subset of the table.
Например RecordCount = -1 и тогда для того, чтобы база была не пустой, FactiveRecord должен быть меньше или равен -2.
← →
Ega23 © (2011-02-03 13:26) [13]
> а проверяю я перед инсертом всей строки целиком, так что
> ситуации с Пупкиным я думаю не будет :)
Время между проверкой и инсертом есть? Есть.
Принцип ACID кто-то уже отменил? Нет.
Вероятность "влезания" между проверкой и инсертом есть? Есть.
"Я думаю не будет" - доверительный источник информации? Ну тут каждый ССЗБ.
По уму всё делается в рамках единой транзакции.
← →
kxft78 © (2011-02-03 13:26) [14]Смотрю нешуточный спор разгорелся :)
Может под шумок подскажет кто идею как проверку такую сделать совсем уж красиво на уровне субд, триггер например :)
← →
И. Павел © (2011-02-03 13:27) [15]> мне кажется решение Сергея более правильно чтоли
Пожалуй, так и есть. ИМХО ошибки удобно выводить наружу, а не подчищать в месте возникновения, чтобы при желании однотипно обрабатывать: например, если у вас таких блоков будет несколько.
← →
kxft78 © (2011-02-03 13:29) [16]
>
> Время между проверкой и инсертом есть? Есть.
> Принцип ACID кто-то уже отменил? Нет.
> Вероятность "влезания" между проверкой и инсертом есть?
> Есть.
> "Я думаю не будет" - доверительный источник информации?
> Ну тут каждый ССЗБ.
> По уму всё делается в рамках единой транзакции.
>
Полностью согласен, но с таблицей работает на инсерт работает 5 юзеров, согласитесь вероятность такого ничтожно мала....
← →
Ega23 © (2011-02-03 13:30) [17]
> Например RecordCount = -1
Это не "например". Читай и переводи внимательно.
> должен быть меньше или равен -2.
должен быть меньше или равен -1, учи арифметику.
Вся эта свистопляска с RecordCount - это сколько данных получено на данный момент. У тебя "подсос" данных может идти по-факту.
Но если ты (в текущий момент) получил 0 записей, то и ActiveRecord чему равно будет?
← →
kxft78 © (2011-02-03 13:31) [18]Ega23 я новичок, не ругайте сильно, лучше подскажите примерчик где подсмотреть в котором все по уму сделано ;)
← →
Ega23 © (2011-02-03 13:33) [19]
> Полностью согласен, но с таблицей работает на инсерт работает
> 5 юзеров, согласитесь вероятность такого ничтожно мала..
Это всё зависит от ТЗ. Если мала - ну значит мала. Если можно наплевать - ну и хорошо. В изначальном вопросе ТЗ не было озвучено.
Вариантов решений - море (зависит от используемой СУБД).
Триггер, хранимая процедура, блокировка таблицы.
← →
Ega23 © (2011-02-03 13:35) [20]
> Ega23 я новичок, не ругайте сильно, лучше подскажите примерчик
> где подсмотреть в котором все по уму сделано ;)
Да к тебе претензий нет никаких.
Что касаемо примерчика, то сначала тебе нужно СУБД указать.
← →
И. Павел © (2011-02-03 13:35) [21]> [17] Ega23 © (03.02.11 13:30
> должен быть меньше или равен -1, учи арифметику.
IsEmpty = -1 >= -1 = true - т.е. база пустая. Кому арифметику нужно учить?
По поводу ситуации, когда RecordCount = -1: они бывают. Не верите - экспериментируйте с курсором и т.д. Мне сейчас лень новый проект создавать и что-то доказывать...
> Ega23 я новичок, не ругайте сильно, лучше подскажите примерчик
> где подсмотреть в котором все по уму сделано ;)
Боюсь что ничто (пожалуй, на всякий случай, чтобы опять не возник спор, уточню: кроме кода Ega32) не совершенно в этом мире...
← →
Anatoly Podgoretsky © (2011-02-03 13:36) [22]
> Нет. IsEmpty работает не так
Именно так и работает, только он и нафиг нужен, для проверки пустых значений.
← →
Anatoly Podgoretsky © (2011-02-03 13:38) [23]> Ega23 (03.02.2011 13:30:17) [17]
Джентельмен верит на слово, у тут мне поперла карта.
← →
Ega23 © (2011-02-03 13:42) [24]
> IsEmpty = -1 >= -1 = true - т.е. база пустая. Кому арифметику
> нужно учить?
Не база пустая, а рекордсет в данный момент - пуст. Нету там никаких записей.
По какой причине - без разницы. Может у него вообще не было подключения к источнику данных. Может текст запросаselect * from sysobjects where 0=1
Нету на клиенте записей. Нету.
> По поводу ситуации, когда RecordCount = -1: они бывают.
А я это где-то отрицал?
> Боюсь что ничто не совершенно в этом мире...
Пересадка рук позволит выйти из депрессии.
← →
И. Павел © (2011-02-03 13:56) [25]> Пересадка рук позволит выйти из депрессии.
Ну я же уточнил, что вы - исключение :)
> учи арифметику.
> Не база пустая, а рекордсет в данный момент - пуст. Нету
> там никаких записей.
> А я это где-то отрицал?
Т.е. этими репликами вы отрицаете, что -1 >= -1 = true?
← →
Ega23 © (2011-02-03 14:22) [26]
> Т.е. этими репликами вы отрицаете, что -1 >= -1 = true?
Давай так сделаем. Приведи пример, когда я могу к TDataSet обратиться через FieldByName и получить вразумительное значение, но при этом TDataSet.IsEmpty = True.
Приведёшь пример - я извинюсь, публично.
← →
Ega23 © (2011-02-03 14:28) [27]З.Ы. (вдогонку)
приватное поле TDataSet.FRecordCount и свойство TDataSet.RecordCount с виртуальным геттером GetRecordCount - разные вещи. Если чё.
← →
И. Павел © (2011-02-03 14:40) [28]> [26] Ega23 © (03.02.11 14:22)
Ну сомневаюсь я в том факте, что IsEmpty будет на 100% работать при RecordCount = -1. Ведь тогда или FActiveRecord должен быть <= -2, либо FRecordCount не быть равным RecordCount. Я тоже раньше использовал IsEmpty а потом решил перестраховаться, чтобы не искать в случае чего ошибку в таком неожиданном месте. Может быть IsEmpty всегда будет работать правильно (чем более что [22]), но (eof) and (bof) уж точно не подведет. Короче я не знаю, как ведет себя FRecordCount, а протрассировать до этой функции в Delphi7 не получается.
По поводу поисков - нет ни желания ни времени. Вот если бы альтернативы IsEmpty не было, тогда стоило бы в ней полностью разбираться.
В общем, я больше спорить не хочу. В моем текущем проекте хватает геморроя без IsEmpty а время я уже потратил много.
PS: но если кто-нибудь мне объяснит, в чем секрет IsEmpty и почему она работает (и всегда ли работает?) при RecordCount = -1 и ActiveRecord = 0 - буду очень благодарен, т.к. все же любопытно.
← →
12 © (2011-02-03 14:41) [29]FK-PK ключи,
> необходимо сделать проверку на наличие содержимого поля
> в справочной таблице и если его там нет то обругать
и СУБД сделает за тебя
останется только ловить нарушение соотв. constrat`a
если конечн осекретная СУБД поддерживает такое
← →
Ega23 © (2011-02-03 14:43) [30]З.З.Ы.
ИМХО, DB.pas вообще образец корявости в, казалось бы, вылизанном коде. Всё-таки описание абстрактных классов, должно быть хорошо выверено.
Ан нет, встречаем перлы типа
procedure TDataLink.UpdateRange;
var
Min, Max: Integer;
begin
Min := DataSet.FActiveRecord - FBufferCount + 1;
.....
end;
Оно поняно, что так можно в рамках одного юнита. Но как хитрых потомков того же DataLink писать - вот тут большой затык.
← →
И. Павел © (2011-02-03 14:44) [31]> [27] Ega23 © (03.02.11 14:28)
А это действительно аргумент.
Но т.к. по FRecordCount документации нет. Остается либо штудировать код, либо гадать, когда он отстает от свойства. Если кто-нибудь найдет - пишите, т.к. интересно.
← →
И. Павел © (2011-02-03 14:48) [32]> с виртуальным геттером
Выходит, что FRecordCount знает, сколько записей, а потомок, пеализовавший GetRecordCount - нет. Тогда зачем они его переопределили?...
← →
Ega23 © (2011-02-03 14:51) [33]
> либо FRecordCount не быть равным RecordCount.
Вот. Наконец-то.
Смотрим внимательно:
TDataSet = class(TComponent, IProviderSupport)
private
FFields: TFields;
.....
FRecordCount: Integer;
т.е. - приватное поле.
TDataSet = class(TComponent, IProviderSupport)
public
......
property RecordCount: Integer read GetRecordCount;
Публичное read-only свойство с геттером.
TDataSet = class(TComponent, IProviderSupport)
protected
......
function GetRecordCount: Integer; virtual;
протектед-геттер.
ну и наконец:function TDataSet.GetRecordCount: Longint;
begin
Result := -1;
end;
И функции IsEmpty глубоко начхать, каким макаром в ADODB перекрыт GetRecordCount и какое значение он вернул.
← →
Ega23 © (2011-02-03 15:00) [34]
> Выходит, что FRecordCount знает, сколько записей, а потомок,
> пеализовавший GetRecordCount - нет. Тогда зачем они его
> переопределили?...
А это потому, что вот так вот DB.pas написан.
FRecordCount - исключительно внутренний счётчик базового TDataSet.
Есть и ещё перлы. Например - DataSet.DisableControls/DataSet.EnableControls
Всё честно, по DisableControls события не передаются всем TDataSource, которые подключены к НД. А вот по EnableControls - идёт DataChanged.
Но нет никакой гарантии, что за это время НД могли изменить. Добавить туда записей, модифицировать, что-то удалить. Переоткрыть, в конце-концов.
Для DBEdit - не беда, берём активную запись и отображаем.
Для DBGrid - отображаем ровно то, что есть на экране, на остальное наплевать.
А вот для TDBTree - уже ой. Тебе всю иерархию знать надо, мало ли, ты ветки местами поменял. И считай приходится заново перестраивать.
ИМХО, уже только этой причины было достаточно для отсутствия "стандартного" TDBTreeView.
← →
И. Павел © (2011-02-03 15:01) [35]> TDataSet = class(TComponent, IProviderSupport)
> private
> FFields: TFields;
> .....
> FRecordCount: Integer;
Он приватный :) И, похоже, именно для того, чтобы его не тронули не умеющие определять число строк потомки.
Похоже, что вы правы. Не удивительно, что в справке про IsEmpty нет такого же предостережения, как про RecordCount. Борландовцы как то умудрились реализовать IsEmpty на самом низком уровне!
← →
kxft78 © (2011-02-03 15:04) [36]Выходил не надолго
> Это всё зависит от ТЗ. Если мала - ну значит мала. Если
> можно наплевать - ну и хорошо. В изначальном вопросе ТЗ
> не было озвучено.Вариантов решений - море (зависит от используемой
> СУБД).Триггер, хранимая процедура, блокировка таблицы.
СУБД oracle10g xe, наплевать можно но не хочется :) хочется по уму и красиво.
надо проверить вводимое значение на совпадением со значением в некой таблице, если его там нет то обматерить и не дать сделать insert.
Вероятно правильней всего в такой ситуации будет использовать триггер before update?
Накидаете грамотный и красивый пример на plsql + отлов в дельфях - будет ОГРОМНОЕ ВАМ СПАСИБО :)
← →
Ega23 © (2011-02-03 15:07) [37]
> И, похоже, именно для того, чтобы его не тронули не умеющие
> определять число строк потомки.
Да, но при этом в том же DB.pas:procedure TDataLink.UpdateRange;
var
Min, Max: Integer;
begin
Min := DataSet.FActiveRecord - FBufferCount + 1;
if Min < 0 then Min := 0;
Max := DataSet.FRecordCount - FBufferCount;
...
В общем, я бы не рекомендовал DB.pas как образцово-показательный код. :)
← →
Ega23 © (2011-02-03 15:09) [38]
> триггер before update?
Скорее, before insert
> Накидаете грамотный и красивый пример на plsql + отлов в
> дельфях
Не силён в Оракле. Может там есть какое-нибудь изящное решение.
Для MSSQL я бы хранимку написал.
← →
kxft78 © (2011-02-03 15:12) [39]Пардон ошибся, before insert конечно.
Есть гуру оракла? :)
← →
Anatoly Podgoretsky © (2011-02-03 15:38) [40]> Ega23 (03.02.2011 14:51:33) [33]
Это виртуальный метод, могбы быть даже абстрактным, его перекрытие в
наследнике обязательно.
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.05.15;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.004 c