Конференция "Базы" » Почему вставляются пустые поля? [D7, FireBird 2.0]
 
  • macrodens © (01.02.10 16:15) [0]
    Всем доброго времени суток.

    Работаю с 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.
  • Diplomat © (01.02.10 16:41) [1]
    По видимому в поле Name, должно быть указано значение по умолчанию.
  • Ega23 © (01.02.10 16:47) [2]

    > однако при выполнении SQL запроса через компоненты ADO или
    > IBX запись с пустым полем спокойно вставляется


    Код запроса в студию.
  • 12 © (01.02.10 16:48) [3]
    Во. Спасибо.
    хм..

    >> почему все-таки вставляются записи с пустыми полями при not null
    прикольно еще тут написано
    http://alexey-rouban.livejournal.com/11984.html
    дома потестю..
  • macrodens © (01.02.10 16:52) [4]
    И что даст это значение по умолчанию?
    Мне нужно что бы при вставке записи осуществлялась проверка поля, что оно не пустое, и желательно что бы проверку осуществлял сервер базы данных.

    Единственное пока что я понял, что пустая строка ('') не равна null
  • Ega23 © (01.02.10 16:56) [5]

    > Единственное пока что я понял, что пустая строка ('') не
    > равна null


    Именно так. По крайней мере - в FireBird.
  • Ega23 © (01.02.10 16:57) [6]

    > Мне нужно что бы при вставке записи осуществлялась проверка
    > поля, что оно не пустое, и желательно что бы проверку осуществлял
    > сервер базы данных.


    Create table test (fld varchar(32) not null default '');

  • macrodens © (01.02.10 16:59) [7]
    Код запроса в студию.

    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, то исключение срабатывает.
  • macrodens © (01.02.10 17:06) [8]
    to Ega23 ©   (01.02.10 16:57) [6]
    проверка все равно не осуществляется
  • macrodens © (01.02.10 17:10) [9]
    поставил default=null и все заработало!!!
  • macrodens © (01.02.10 17:32) [10]
    ан нет не заработало.... :-(
  • macrodens © (01.02.10 18:06) [11]
    пришлось написать тригер по инсерту и апдейту и там проверять...
  • Виталий Панасенко(дом) (01.02.10 18:17) [12]
    строка '' и null - разные вещи..
  • Виталий Панасенко(дом) (01.02.10 18:20) [13]
    при значении 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;
    будет ругаться, как ты и предположил
  • Anatoly Podgoretsky © (01.02.10 19:27) [14]
    > Ega23  (01.02.2010 16:57:06)  [6]

    Откуда возьмется пустое поле, раз есть default значение.
  • macrodens © (02.02.10 09:24) [15]
    to Виталий Панасенко(дом)   (01.02.10 18:20) [13]

    при таком подходе можно в базе вообще не объявлять что поле должно быть не пустым, а выполнять проверки на уровне приложения.
    А это будет достаточно грамоздким решением, если в таблице будет 10-15 непустых полей.
    Я считаю, что обработка все же должна происходить на уровне сервера (драйвера) БД, а в приложении уже отслеживать исключения, потому как сторонний разработчик приложения под эту БД может и не знать какие поля должны заполняться обязательно - а это  может привести к нарушению актуальности данных.
    Пока решил вопрос на уровне тригера, который срабатывает на вставку и обновление данных, выглядит так:
    if (new.Name='') then new.name=null
    может конечно и не самый лучший вариант, но в приложение возвращается исключение с именем поля.
  • Sergey13 © (02.02.10 09:29) [16]
    > [15] macrodens ©   (02.02.10 09:24)
    > при таком подходе можно в базе вообще не объявлять что поле
    > должно быть не пустым, а выполнять проверки на уровне приложения.

    > Я считаю, что обработка все же должна происходить на уровне
    > сервера (драйвера) БД

    Одно другому не мешает, а только дополняет. На сервере - последний рубеж обороны, в приложении превентивные меры.
  • macrodens © (02.02.10 10:15) [17]
    На сервере - последний рубеж обороны

    если этот "рубеж" работает...
  • Ega23 © (02.02.10 10:24) [18]

    > может и не знать какие поля должны заполняться обязательно
    > - а это  может привести к нарушению актуальности данных.


    ХП со значениями по-умолчанию.
  • macrodens © (02.02.10 10:28) [19]
    ХП со значениями по-умолчанию.

    а если это поле с уникальным значением?
  • Ega23 © (02.02.10 10:33) [20]
    Уникальное значение генерится на клиенте????
    Впрочем, извращения всякие бывают.
    В этом случае на поле unique index, а по-умолчанию - не знаю, чё там. Чё-нибудь.
    Словишь тот же exception.
  • Медвежонок Пятачок © (02.02.10 11:39) [21]
    Откуда возьмется пустое поле, раз есть default значение.

    а откуда возьмется дефолт значение, если с клиента идет инсерт в котором есть это поле?
  • Anatoly Podgoretsky © (02.02.10 12:18) [22]
    > Медвежонок Пятачок  (02.02.2010 11:39:21)  [21]

    От туда, не может быть в этом случае пустого поля. Он вставяет не пустое поле.
  • Медвежонок Пятачок © (02.02.10 12:48) [23]
    У него в тексте инсерта поле присутствует.
    При этом независимо от того, что именно туда вставляется, дефолт констрэйнт на сервере не сработает.
    Он сработал бы и вставил дефолт значение, если бы в инсерте было бы опущено это поле.

    то есть скажем всего в таблице есть три поля f1,f2,f3
    и для f3 создано дефолт значение.

    то при insert into table (f1,f2,f3) values (:f1,:f2,:f3)

    дефолтное значение никогда не попадет в таблицу (имеется ввиду что оно механизмами дефолт-констрейнта не попадет туда)
  • Sergey13 © (02.02.10 13:36) [24]
    > [17] macrodens ©   (02.02.10 10:15)
    > если этот "рубеж" работает...

    Ну так проверить это можно только запросом

    select * from table
    where Not_Null_Field is null

  • macrodens © (02.02.10 14:24) [25]
    to Sergey13 ©   (02.02.10 13:36) [24]
    И что это даст?
    речь идет о вставке значения.
    и если Not_Null_Field в делфе ='' то твой запрос ничего не даст, потому что в firebird'е ''<>null.
    один способ я уже нашел и описал его в macrodens ©   (02.02.10 09:24) [15].
    и при его работе приложение ловит exception.
    Слава бога с unique index изобретать велосипед не пришлось, работает как надо.
  • Sergey13 © (02.02.10 14:36) [26]
    > [25] macrodens ©   (02.02.10 14:24)
    > И что это даст?

    Это даст уверенность в работоспособности "последних рубежей".
    Эти "рубежи" и не обещают нормальности данных в этом поле.

    А твой велосипед, ИМХО, заключался в Parameters.ParamValues['c1;c2;']
    честно говоря впервые увидел такое.
    Если бы присваивалось по одному параметру с проверкой на пустоту едита, то и "проблемы" бы не было.
    Непонятно зачем вообще формировать запрос и параметры и дергать сервак, если заранее известно, что запрос не пройдет.
  • Виталий Панасенко(дом) (02.02.10 14:44) [27]
    ты так и не понял, хотя сам в (25) и написал.. строка с нулевой длинной и значение "пусто"(null) - это разные вещи... в Edit1.Text просто НЕТУ ТАКОГО ЗНАЧЕНИЯ, КАК NULL ! там м.б. все, что угодно! строка с нулевой длинной '', в 2 гига.. все,  кроме NULL...+, как вариант АДО "помогает". при использовании нативных компонент и DBAware визуальных такой проблемы не возникает.. возможно, проблема во второй части
  • macrodens © (03.02.10 09:32) [28]
    А твой велосипед, ИМХО, заключался в Parameters.ParamValues['c1;c2;']

    да не в этом "велосипед". Оно понятно, что можно проверить все нужные поля вообще еще до формирования запроса.
    Можно обращаться к параметрам и через ParamByName - эти два способа формирования запросов описываются во многих книжках. Дело то собственно не в этом.
    Суть собственно в том, что бы в базу не заносилось пустое значение, а до момента вставки данных может произойти что угодно -и вот это то собственно и надо отслеживать.
    Непонятно зачем вообще формировать запрос и параметры и дергать сервак, если заранее известно, что запрос не пройдет.

    Запрос как раз отлично проходит.

    ты так и не понял, хотя сам в (25) и написал.. строка с нулевой длинной и значение "пусто"(null)
    Да это-то как раз я уже понял и именно за счет этого и сделал проверку в тригере. И тем самым проблема решилась
  • Ega23 © (03.02.10 10:30) [29]

    > Суть собственно в том, что бы в базу не заносилось пустое
    > значение, а до момента вставки данных может произойти что
    > угодно -и вот это то собственно и надо отслеживать.


    Поставь not null, делов-то.
  • Sergey13 © (03.02.10 10:46) [30]
    > [29] Ega23 ©   (03.02.10 10:30)

    Так он поставил, но от пустой строки, которая <> NULL это не спасает. А спастись хочется.
    Но от этого ИМХО программно не спасешься. Юзеры расчухают, что можно поставить например точку в эдит и "ругаться не будет".
    Намного дейсвеннее будет писать логин юзера, сделавшего последнее изменение, автоматом в тригере и наказывать периодически "шибко умных".
  • newbie (11.02.10 07:20) [31]
    В файрберде же ХП вроде есть?
    Тогда какие проблемы, я не пойму - создается ХП для инсерта, в которой пишутся все необходимые проверки, и ее уже вызывай в клиенте.

    P.S. Хотя не вижу смысла в том, чтобы ловить ввод строк вида ''. Пускай себе пишут чо хотят, все равно ошибки при вводе будут.
 
Конференция "Базы" » Почему вставляются пустые поля? [D7, FireBird 2.0]
Есть новые Нет новых   [134435   +33][b:0.001][p:0.001]