SQLite: Значения по умолчанию для новой записи

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Ответить
Аватара пользователя
Unvictis
новенький
Сообщения: 48
Зарегистрирован: 17.07.2015 17:59:12
Откуда: Kokshetau, Kazakshtan
Контактная информация:

SQLite: Значения по умолчанию для новой записи

Сообщение Unvictis »

Здравствуйте комрады! Подолжаю своё погружения в мир великого и могучего Lazarus и SQLite. При добавлении новой записи в таблицу с помощью оператора SQLQuery.Insert в таблицу добавляется абсолютно пустая запись, хотя в БД прописаны значения по умолчанию для некоторых полей (.. DEFAULT 15 например) или по крайней мере эти данные по умолчанию не вставляются в запись до метода SQLQuery.Post. Нельзя ли как-нибудь сделать, что-бы при добавлении данных (SQLQuery.Insert) данные по умолчанию вставлялись сразу-же?
sts
энтузиаст
Сообщения: 548
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Сообщение sts »

Допускаю что проблема в коде sql - написано типа insert from table (AAAA, BBBB) values (:AAAA, :BBBB) или как там в либе (?,?), так вот, DEFAULT присваиваются полям только в случае их ОТСУТСТВИЯ, в данном случае ни для AAAA ни для BBBB они не подставятся а возьмутся NULLы.
а вот если так - insert from table (AAAA) values (:AAAA) то для BBBB DEFAULT подставится.

Добавлено спустя 6 минут 21 секунду:
далее, есть высокоуровневые либы доступа к базам, которые самостоятельно считывают, из описателя таблиц, значения по умолчанию и, в случае передачи в параметрах NULLов, подставляют их, чем вы там пользуетесь? посмотрите на предмет настроек.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Unvictis писал(а):При добавлении новой записи в таблицу с помощью оператора SQLQuery.Insert...

Полагаю (может быть напрасно :-) ), что речь идёт о работе через DBGrid.

Предлагаю, вдобавок к сказанному предыдущим оратором, перед Post проверять значения в полях, чтобы они не были пустыми строками:

Код: Выделить всё

//Перед Post
procedure TForm1.SQLQueryBeforePost(DataSet: TDataSet);
begin
  If DataSet.FieldByName('Имя_поля').AsString='' Then
    DataSet.FieldByName('Имя_поля').AsНужныйТип=ЗначениеПоУмолчанию;
end;

Или отказаться от редактирования\Вставки записей через DBGrid в пользу собственной формы.
Аватара пользователя
Unvictis
новенький
Сообщения: 48
Зарегистрирован: 17.07.2015 17:59:12
Откуда: Kokshetau, Kazakshtan
Контактная информация:

Сообщение Unvictis »

Vadim писал(а):
Unvictis писал(а):При добавлении новой записи в таблицу с помощью оператора SQLQuery.Insert...

Полагаю (может быть напрасно :-) ), что речь идёт о работе через DBGrid.

Предлагаю, вдобавок к сказанному предыдущим оратором, перед Post проверять значения в полях, чтобы они не были пустыми строками:

Код: Выделить всё

//Перед Post
procedure TForm1.SQLQueryBeforePost(DataSet: TDataSet);
begin
  If DataSet.FieldByName('Имя_поля').AsString='' Then
    DataSet.FieldByName('Имя_поля').AsНужныйТип=ЗначениеПоУмолчанию;
end;

Или отказаться от редактированияВставки записей через DBGrid в пользу собственной формы.

Большое спасибо, метод конечно рабочий - я и сам о нём думал, но дело в том что в почти в любой современной СУБД значения для полей по умолчанию можно (и я думаю что это правильный метод) установить на этапе проектирования БД (опция DEFAULT в описании поля) и в дальнейшем совсем не трудно изменить. А вот для того, что-бы поменять эти данные в программе придётся её либо перекомпилировать, либо хранить данные по умолчанию в отдельной таблице/файле настроек. Полагаю, что это костыли, и есть Труъ-решение :).

Добавлено спустя 5 минут:
sts писал(а):Допускаю что проблема в коде sql - написано типа insert from table (AAAA, BBBB) values (:AAAA, :BBBB) или как там в либе (?,?), так вот, DEFAULT присваиваются полям только в случае их ОТСУТСТВИЯ, в данном случае ни для AAAA ни для BBBB они не подставятся а возьмутся NULLы.
а вот если так - insert from table (AAAA) values (:AAAA) то для BBBB DEFAULT подставится.

Добавлено спустя 6 минут 21 секунду:
далее, есть высокоуровневые либы доступа к базам, которые самостоятельно считывают, из описателя таблиц, значения по умолчанию и, в случае передачи в параметрах NULLов, подставляют их, чем вы там пользуетесь? посмотрите на предмет настроек.

Пользуюсь стандартными компонентами Lazarus'a: SDLdb, и визуальными с вкладки "Data Controls". Для добавления новой записи использую метод SQLQuery.Insert.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Unvictis писал(а):в почти в любой современной СУБД значения для полей по умолчанию можно (и я думаю что это правильный метод) установить на этапе проектирования БД (опция DEFAULT в описании поля) и в дальнейшем совсем не трудно изменить.

Здесь проблема в другом - при редактировании\вставке записи Вы посылаете все поля со значениями в БД, поэтому у неё нет абсолютно никакого повода применять значение DEFAULT. Если хотите, чтобы БД применяла значение DEFAULT Вам нужно отказаться от редактирования\вставки записей через DBGrid, т.е. посредством редактирования уже полученного набора данных из БД. Заведите отдельную форму для редактирования\вставки и формируйте команду INSERT по условию непустого поля редактирования. А потом посылайте её с помощью Connection.ExecuteDirect().
Вам необходимо прежде чем садиться писать код сначала продумать и описать архитекетуру Вашей программы, т.е. начинать надо с проектирования, а не программирования. ;-)
Аватара пользователя
Unvictis
новенький
Сообщения: 48
Зарегистрирован: 17.07.2015 17:59:12
Откуда: Kokshetau, Kazakshtan
Контактная информация:

Сообщение Unvictis »

Vadim писал(а):формируйте команду INSERT по условию непустого поля редактирования

Поясните, как это?
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Unvictis писал(а):Поясните, как это?

1. Для редактирования\вставки у Вас должна быть своя, отдельная форма, где каждое поле типа TEdit соответствует одному полю редактируемой таблицы в БД.
2. Вводите две строковых переменных, куда будете собирать названия полей и их значения.
3. Для вставки новой записи Вы, прежде чем вставить название поля и его значение, проверяете не пустое ли оно (If Edit.Text!='' Then). Если не пустое, то добавляете к первой переменной название поля, а ко второй - его значение. В самом конце формируете из этих двух переменных команду INSERT.
3. Для редактирования Вы эти же поля предварительно заполняете значениями из текущей строки SQLQuery, а потом проверяете, не изменилось ли значение. Для этого прекрасно подходит событие TEdit.OnChange - в нём просто ставите метку, что такое-то поле изменилось. Когда все изменения внесены, по этим меткам собираете команду UPDATE.
Аватара пользователя
alexs
долгожитель
Сообщения: 4069
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

Vadim
А почему не использовать для редактирования данных DB компоненты?
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

alexs
Можно и DB, но у меня идея другая - вводить данные с помощью запроса и только в те поля, в которые реально существуют данные. А с DB-компонентами мы можем прийти к тому же результату от которого хотели уйти - т.е. вставки в поля БД пустых значений, если при добавлении новой записи в DB-компонент не вставлено какое-то значение.
Аватара пользователя
Unvictis
новенький
Сообщения: 48
Зарегистрирован: 17.07.2015 17:59:12
Откуда: Kokshetau, Kazakshtan
Контактная информация:

Сообщение Unvictis »

Я мыслю, что реальной вставки записи в БД после процедуры TSQLQuery.Insert не происходит, да даже и после TSQLQuery.Post тоже. Поэтому и остаётся неназначенным автоинкрементное поле, и не вставляются значения по умолчанию (мои догадки). Сегодня попробую реализовать вставку в таблицу посредством SQL-запроса, а затем выбор добавленной записи - думаю должно сработать, хотя тоже попахивает костылём.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Unvictis
Вот смотрите:
- когда у Вас выполнилась процедура SQLQuery.Insert, у Вас вставилась пустая строка в тот набор данных, который Вы получили из БД. Там пока нет данных, всё пусто.
- Вы занесли свои данные в пустую строку и чтобы зафиксировать изменение в наборе данных (обращаю внимание - том, который только в Вашей программе), применяете процедуру SQLQuery.Post. До Post все ваши данные были во временном кэше, после Post они переехали в набор данных. В самой БД их ещё нет и она даже не знает, что Вы у себя натворили.
- Чтобы перенести новую строку с данными в БД, необходимо применить процедуру SQLQuery.ApplyUpdates. Эта процедура передаёт в БД все поля, которые есть в Вашем наборе данных, вне зависимости есть ли там данные или нет.
Поэтому подобный метод, как и вообще редактирование данных в SQLQuery, имеет смысл, только в том случае, если Вы редактируете все без исключения поля или у этих полей в БД нет значений по умолчанию и занесение в них пустых значений не является критичным фактором.
Аватара пользователя
alexs
долгожитель
Сообщения: 4069
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

Vadim писал(а):вставки в поля БД пустых значений, если при добавлении новой записи в DB-компонент не вставлено какое-то значение.

1. На уровне формы сделайте проверку на заполненность полей.
2. Написать запрос на вставку/изменение только тех полей, которые реально могут меняться в данной ситуации.
PS
На мой взгляд - пустых значений в БД вообще быть не должно. NULL - зло. И разработчик должен стараться исключать ситуации с хранением пустых значений.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

alexs писал(а):На мой взгляд - пустых значений в БД вообще быть не должно. NULL - зло. И разработчик должен стараться исключать ситуации с хранением пустых значений.

У топикстартера в самой БД уже предусмотрены DEFAULT-значения. Он хочет чтобы именно они были задействованы.
Аватара пользователя
alexs
долгожитель
Сообщения: 4069
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

Штатные DB компоненты не умеют работать с DefaultExpression
Zeos - вроде может.

А вообще - если оператору даёшь вводить данные - так пусть он их вводит. А если позволяешь вносить пустые данные - то может это поле вообще не нужно?
В своё время мне надоело писать обработчики в форме на заполненность полей - в RxFPC написал компоненту, которая именно и занимается этим.
Аватара пользователя
Unvictis
новенький
Сообщения: 48
Зарегистрирован: 17.07.2015 17:59:12
Откуда: Kokshetau, Kazakshtan
Контактная информация:

Сообщение Unvictis »

alexs писал(а):Штатные DB компоненты не умеют работать с DefaultExpression
Zeos - вроде может.

А вообще - если оператору даёшь вводить данные - так пусть он их вводит. А если позволяешь вносить пустые данные - то может это поле вообще не нужно?
В своё время мне надоело писать обработчики в форме на заполненность полей - в RxFPC написал компоненту, которая именно и занимается этим.

Всё ради удобства, логичности и максимальной производительности программы. Чтож, вопрос остаётся открытым, пока воспользуюсь костылями.

Добавлено спустя 2 минуты 2 секунды:
Не хочется продолжать быдлокодить :)
Ответить