Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.05.15;
Скачать: CL | DM;

Вниз

проверка вводимого значения   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.007 c
15-1296130623
Knight
2011-01-27 15:17
2011.05.15
Права доступа и тормоза в 1с...


15-1296212454
qazxsw
2011-01-28 14:00
2011.05.15
Быстрый вывод пикселей на канву


2-1296731036
student22
2011-02-03 14:03
2011.05.15
WebSnap


2-1296925416
UnnamedUser
2011-02-05 20:03
2011.05.15
Размер файла на сервере


2-1296797621
И. Павел
2011-02-04 08:33
2011.05.15
Шаблон