-
Всем доброго времени суток.
Работаю с Firebird 2.0
Через IBExpert создал базу и в ней табличку с полями
ID (integer) - not null autoinc (тригер)
Name (varchar(96) - not null
Pole1 (varchar(96)
если я в IBExpert пытаюсь добавить запись не заполнив поле Name - все ок - срабатывет исключение,
однако при выполнении SQL запроса через компоненты ADO или IBX запись с пустым полем спокойно вставляется, а в IBExpert потом при редактировании этой записи (поле Name не трогаем) исключение уже не возникает.
Подскажите почему все-таки вставляются записи с пустыми полями при not null и как сделать что бы обработка все же происходила?
Пробовал спросить у гугля и яндекса, увидел только вопрос с похожей ситуацией в MySQL.
-
По видимому в поле Name, должно быть указано значение по умолчанию.
-
> однако при выполнении SQL запроса через компоненты ADO или
> IBX запись с пустым полем спокойно вставляется
Код запроса в студию.
-
-
И что даст это значение по умолчанию?
Мне нужно что бы при вставке записи осуществлялась проверка поля, что оно не пустое, и желательно что бы проверку осуществлял сервер базы данных.
Единственное пока что я понял, что пустая строка ('') не равна null
-
> Единственное пока что я понял, что пустая строка ('') не
> равна null
Именно так. По крайней мере - в FireBird.
-
> Мне нужно что бы при вставке записи осуществлялась проверка
> поля, что оно не пустое, и желательно что бы проверку осуществлял
> сервер базы данных.
Create table test (fld varchar(32) not null default '');
-
Код запроса в студию.
adoconnection1.BeginTrans;
with ADOQuery1 do
begin
SQL.clear;
SQL.add('INSERT INTO MYTABLE (NAME, POLE1) VALUES (:C1, :C2)');
Parameters.ParamValues['c1;c2;']:=VarArrayOf(Edit1.test, Edit2.text);
ExecSQL;
end;
adoconnection1.CommitTrans;
запрос проходит и запись вставляется даже при Edit1.text=''
если вместо него указать null, то исключение срабатывает.
-
to Ega23 © (01.02.10 16:57) [6]
проверка все равно не осуществляется
-
поставил default=null и все заработало!!!
-
ан нет не заработало.... :-(
-
пришлось написать тригер по инсерту и апдейту и там проверять...
-
строка '' и null - разные вещи..
-
при значении edit1.text='' строка и будет вставляться... потому как см.. выше.. перепиши так:
adoconnection1.BeginTrans;
with ADOQuery1 do
begin
SQL.clear;
if edit1.text<>'' then
begin
SQL.add('INSERT INTO MYTABLE (NAME, POLE1) VALUES (:C1, :C2)');
Parameters.ParamValues['c1;c2;']:=VarArrayOf(Edit1.test, Edit2.text);
end
else
begin
SQL.add('INSERT INTO MYTABLE (POLE1) VALUES (:C1)');
Parameters.ParamValues['c1']:=VarArrayOf( Edit2.text);
end;
ExecSQL;
end;
adoconnection1.CommitTrans;
будет ругаться, как ты и предположил
-
> Ega23 (01.02.2010 16:57:06) [6]
Откуда возьмется пустое поле, раз есть default значение.
-
to Виталий Панасенко(дом) (01.02.10 18:20) [13]
при таком подходе можно в базе вообще не объявлять что поле должно быть не пустым, а выполнять проверки на уровне приложения.
А это будет достаточно грамоздким решением, если в таблице будет 10-15 непустых полей.
Я считаю, что обработка все же должна происходить на уровне сервера (драйвера) БД, а в приложении уже отслеживать исключения, потому как сторонний разработчик приложения под эту БД может и не знать какие поля должны заполняться обязательно - а это может привести к нарушению актуальности данных.
Пока решил вопрос на уровне тригера, который срабатывает на вставку и обновление данных, выглядит так:
if (new.Name='') then new.name=null
может конечно и не самый лучший вариант, но в приложение возвращается исключение с именем поля.
-
> [15] macrodens © (02.02.10 09:24)
> при таком подходе можно в базе вообще не объявлять что поле
> должно быть не пустым, а выполнять проверки на уровне приложения.
> Я считаю, что обработка все же должна происходить на уровне
> сервера (драйвера) БД
Одно другому не мешает, а только дополняет. На сервере - последний рубеж обороны, в приложении превентивные меры.
-
На сервере - последний рубеж обороны
если этот "рубеж" работает...
-
> может и не знать какие поля должны заполняться обязательно
> - а это может привести к нарушению актуальности данных.
ХП со значениями по-умолчанию.
-
ХП со значениями по-умолчанию.
а если это поле с уникальным значением?
-
Уникальное значение генерится на клиенте????
Впрочем, извращения всякие бывают.
В этом случае на поле unique index, а по-умолчанию - не знаю, чё там. Чё-нибудь.
Словишь тот же exception.
-
Откуда возьмется пустое поле, раз есть default значение.
а откуда возьмется дефолт значение, если с клиента идет инсерт в котором есть это поле?
-
> Медвежонок Пятачок (02.02.2010 11:39:21) [21]
От туда, не может быть в этом случае пустого поля. Он вставяет не пустое поле.
-
У него в тексте инсерта поле присутствует.
При этом независимо от того, что именно туда вставляется, дефолт констрэйнт на сервере не сработает.
Он сработал бы и вставил дефолт значение, если бы в инсерте было бы опущено это поле.
то есть скажем всего в таблице есть три поля f1,f2,f3
и для f3 создано дефолт значение.
то при insert into table (f1,f2,f3) values (:f1,:f2,:f3)
дефолтное значение никогда не попадет в таблицу (имеется ввиду что оно механизмами дефолт-констрейнта не попадет туда)
-
>
[17] macrodens © (02.02.10 10:15)
> если этот "рубеж" работает...
Ну так проверить это можно только запросом
select * from table
where Not_Null_Field is null
-
to Sergey13 © (02.02.10 13:36) [24]
И что это даст?
речь идет о вставке значения.
и если Not_Null_Field в делфе ='' то твой запрос ничего не даст, потому что в firebird'е ''<>null.
один способ я уже нашел и описал его в macrodens © (02.02.10 09:24) [15].
и при его работе приложение ловит exception.
Слава бога с unique index изобретать велосипед не пришлось, работает как надо.
-
> [25] macrodens © (02.02.10 14:24)
> И что это даст?
Это даст уверенность в работоспособности "последних рубежей".
Эти "рубежи" и не обещают нормальности данных в этом поле.
А твой велосипед, ИМХО, заключался в Parameters.ParamValues['c1;c2;']
честно говоря впервые увидел такое.
Если бы присваивалось по одному параметру с проверкой на пустоту едита, то и "проблемы" бы не было.
Непонятно зачем вообще формировать запрос и параметры и дергать сервак, если заранее известно, что запрос не пройдет.
-
ты так и не понял, хотя сам в (25) и написал.. строка с нулевой длинной и значение "пусто"(null) - это разные вещи... в Edit1.Text просто НЕТУ ТАКОГО ЗНАЧЕНИЯ, КАК NULL ! там м.б. все, что угодно! строка с нулевой длинной '', в 2 гига.. все, кроме NULL...+, как вариант АДО "помогает". при использовании нативных компонент и DBAware визуальных такой проблемы не возникает.. возможно, проблема во второй части
-
А твой велосипед, ИМХО, заключался в Parameters.ParamValues['c1;c2;']
да не в этом "велосипед". Оно понятно, что можно проверить все нужные поля вообще еще до формирования запроса.
Можно обращаться к параметрам и через ParamByName - эти два способа формирования запросов описываются во многих книжках. Дело то собственно не в этом.
Суть собственно в том, что бы в базу не заносилось пустое значение, а до момента вставки данных может произойти что угодно -и вот это то собственно и надо отслеживать.
Непонятно зачем вообще формировать запрос и параметры и дергать сервак, если заранее известно, что запрос не пройдет.
Запрос как раз отлично проходит.
ты так и не понял, хотя сам в (25) и написал.. строка с нулевой длинной и значение "пусто"(null)
Да это-то как раз я уже понял и именно за счет этого и сделал проверку в тригере. И тем самым проблема решилась
-
> Суть собственно в том, что бы в базу не заносилось пустое
> значение, а до момента вставки данных может произойти что
> угодно -и вот это то собственно и надо отслеживать.
Поставь not null, делов-то.
-
> [29] Ega23 © (03.02.10 10:30)
Так он поставил, но от пустой строки, которая <> NULL это не спасает. А спастись хочется.
Но от этого ИМХО программно не спасешься. Юзеры расчухают, что можно поставить например точку в эдит и "ругаться не будет".
Намного дейсвеннее будет писать логин юзера, сделавшего последнее изменение, автоматом в тригере и наказывать периодически "шибко умных".
-
В файрберде же ХП вроде есть?
Тогда какие проблемы, я не пойму - создается ХП для инсерта, в которой пишутся все необходимые проверки, и ее уже вызывай в клиенте.
P.S. Хотя не вижу смысла в том, чтобы ловить ввод строк вида ''. Пускай себе пишут чо хотят, все равно ошибки при вводе будут.