Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
2-1296731036
student22
2011-02-03 14:03
2011.05.15
WebSnap


15-1296586073
cross
2011-02-01 21:47
2011.05.15
Стоит ли покупать MacBook


2-1297326626
Максон
2011-02-10 11:30
2011.05.15
как открыть вордовский документ с помощью OpenDialog


15-1296682513
Ацтекг
2011-02-03 00:35
2011.05.15
SvcOS RS: Обзор сервиса удаленного администрирования через браузе


15-1296654628
int64
2011-02-02 16:50
2011.05.15
Как попасть на RSDN.ru?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский