SQLite: Значения по умолчанию для новой записи
Модератор: Модераторы
- Unvictis
- новенький
- Сообщения: 48
- Зарегистрирован: 17.07.2015 17:59:12
- Откуда: Kokshetau, Kazakshtan
- Контактная информация:
SQLite: Значения по умолчанию для новой записи
Здравствуйте комрады! Подолжаю своё погружения в мир великого и могучего Lazarus и SQLite. При добавлении новой записи в таблицу с помощью оператора SQLQuery.Insert в таблицу добавляется абсолютно пустая запись, хотя в БД прописаны значения по умолчанию для некоторых полей (.. DEFAULT 15 например) или по крайней мере эти данные по умолчанию не вставляются в запись до метода SQLQuery.Post. Нельзя ли как-нибудь сделать, что-бы при добавлении данных (SQLQuery.Insert) данные по умолчанию вставлялись сразу-же?
Допускаю что проблема в коде sql - написано типа insert from table (AAAA, BBBB) values (:AAAA, :BBBB) или как там в либе (?,?), так вот, DEFAULT присваиваются полям только в случае их ОТСУТСТВИЯ, в данном случае ни для AAAA ни для BBBB они не подставятся а возьмутся NULLы.
а вот если так - insert from table (AAAA) values (:AAAA) то для BBBB DEFAULT подставится.
Добавлено спустя 6 минут 21 секунду:
далее, есть высокоуровневые либы доступа к базам, которые самостоятельно считывают, из описателя таблиц, значения по умолчанию и, в случае передачи в параметрах NULLов, подставляют их, чем вы там пользуетесь? посмотрите на предмет настроек.
а вот если так - insert from table (AAAA) values (:AAAA) то для BBBB DEFAULT подставится.
Добавлено спустя 6 минут 21 секунду:
далее, есть высокоуровневые либы доступа к базам, которые самостоятельно считывают, из описателя таблиц, значения по умолчанию и, в случае передачи в параметрах NULLов, подставляют их, чем вы там пользуетесь? посмотрите на предмет настроек.
Unvictis писал(а):При добавлении новой записи в таблицу с помощью оператора SQLQuery.Insert...
Полагаю (может быть напрасно
Предлагаю, вдобавок к сказанному предыдущим оратором, перед 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
- Контактная информация:
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.
Unvictis писал(а):в почти в любой современной СУБД значения для полей по умолчанию можно (и я думаю что это правильный метод) установить на этапе проектирования БД (опция DEFAULT в описании поля) и в дальнейшем совсем не трудно изменить.
Здесь проблема в другом - при редактировании\вставке записи Вы посылаете все поля со значениями в БД, поэтому у неё нет абсолютно никакого повода применять значение DEFAULT. Если хотите, чтобы БД применяла значение DEFAULT Вам нужно отказаться от редактирования\вставки записей через DBGrid, т.е. посредством редактирования уже полученного набора данных из БД. Заведите отдельную форму для редактирования\вставки и формируйте команду INSERT по условию непустого поля редактирования. А потом посылайте её с помощью Connection.ExecuteDirect().
Вам необходимо прежде чем садиться писать код сначала продумать и описать архитекетуру Вашей программы, т.е. начинать надо с проектирования, а не программирования.
Unvictis писал(а):Поясните, как это?
1. Для редактирования\вставки у Вас должна быть своя, отдельная форма, где каждое поле типа TEdit соответствует одному полю редактируемой таблицы в БД.
2. Вводите две строковых переменных, куда будете собирать названия полей и их значения.
3. Для вставки новой записи Вы, прежде чем вставить название поля и его значение, проверяете не пустое ли оно (If Edit.Text!='' Then). Если не пустое, то добавляете к первой переменной название поля, а ко второй - его значение. В самом конце формируете из этих двух переменных команду INSERT.
3. Для редактирования Вы эти же поля предварительно заполняете значениями из текущей строки SQLQuery, а потом проверяете, не изменилось ли значение. Для этого прекрасно подходит событие TEdit.OnChange - в нём просто ставите метку, что такое-то поле изменилось. Когда все изменения внесены, по этим меткам собираете команду UPDATE.
alexs
Можно и DB, но у меня идея другая - вводить данные с помощью запроса и только в те поля, в которые реально существуют данные. А с DB-компонентами мы можем прийти к тому же результату от которого хотели уйти - т.е. вставки в поля БД пустых значений, если при добавлении новой записи в DB-компонент не вставлено какое-то значение.
Можно и DB, но у меня идея другая - вводить данные с помощью запроса и только в те поля, в которые реально существуют данные. А с DB-компонентами мы можем прийти к тому же результату от которого хотели уйти - т.е. вставки в поля БД пустых значений, если при добавлении новой записи в DB-компонент не вставлено какое-то значение.
- Unvictis
- новенький
- Сообщения: 48
- Зарегистрирован: 17.07.2015 17:59:12
- Откуда: Kokshetau, Kazakshtan
- Контактная информация:
Я мыслю, что реальной вставки записи в БД после процедуры TSQLQuery.Insert не происходит, да даже и после TSQLQuery.Post тоже. Поэтому и остаётся неназначенным автоинкрементное поле, и не вставляются значения по умолчанию (мои догадки). Сегодня попробую реализовать вставку в таблицу посредством SQL-запроса, а затем выбор добавленной записи - думаю должно сработать, хотя тоже попахивает костылём.
Unvictis
Вот смотрите:
- когда у Вас выполнилась процедура SQLQuery.Insert, у Вас вставилась пустая строка в тот набор данных, который Вы получили из БД. Там пока нет данных, всё пусто.
- Вы занесли свои данные в пустую строку и чтобы зафиксировать изменение в наборе данных (обращаю внимание - том, который только в Вашей программе), применяете процедуру SQLQuery.Post. До Post все ваши данные были во временном кэше, после Post они переехали в набор данных. В самой БД их ещё нет и она даже не знает, что Вы у себя натворили.
- Чтобы перенести новую строку с данными в БД, необходимо применить процедуру SQLQuery.ApplyUpdates. Эта процедура передаёт в БД все поля, которые есть в Вашем наборе данных, вне зависимости есть ли там данные или нет.
Поэтому подобный метод, как и вообще редактирование данных в SQLQuery, имеет смысл, только в том случае, если Вы редактируете все без исключения поля или у этих полей в БД нет значений по умолчанию и занесение в них пустых значений не является критичным фактором.
Вот смотрите:
- когда у Вас выполнилась процедура SQLQuery.Insert, у Вас вставилась пустая строка в тот набор данных, который Вы получили из БД. Там пока нет данных, всё пусто.
- Вы занесли свои данные в пустую строку и чтобы зафиксировать изменение в наборе данных (обращаю внимание - том, который только в Вашей программе), применяете процедуру SQLQuery.Post. До Post все ваши данные были во временном кэше, после Post они переехали в набор данных. В самой БД их ещё нет и она даже не знает, что Вы у себя натворили.
- Чтобы перенести новую строку с данными в БД, необходимо применить процедуру SQLQuery.ApplyUpdates. Эта процедура передаёт в БД все поля, которые есть в Вашем наборе данных, вне зависимости есть ли там данные или нет.
Поэтому подобный метод, как и вообще редактирование данных в SQLQuery, имеет смысл, только в том случае, если Вы редактируете все без исключения поля или у этих полей в БД нет значений по умолчанию и занесение в них пустых значений не является критичным фактором.
- alexs
- долгожитель
- Сообщения: 4069
- Зарегистрирован: 15.05.2005 23:17:07
- Откуда: г.Ставрополь
- Контактная информация:
Vadim писал(а):вставки в поля БД пустых значений, если при добавлении новой записи в DB-компонент не вставлено какое-то значение.
1. На уровне формы сделайте проверку на заполненность полей.
2. Написать запрос на вставку/изменение только тех полей, которые реально могут меняться в данной ситуации.
PS
На мой взгляд - пустых значений в БД вообще быть не должно. NULL - зло. И разработчик должен стараться исключать ситуации с хранением пустых значений.
alexs писал(а):На мой взгляд - пустых значений в БД вообще быть не должно. NULL - зло. И разработчик должен стараться исключать ситуации с хранением пустых значений.
У топикстартера в самой БД уже предусмотрены DEFAULT-значения. Он хочет чтобы именно они были задействованы.
- alexs
- долгожитель
- Сообщения: 4069
- Зарегистрирован: 15.05.2005 23:17:07
- Откуда: г.Ставрополь
- Контактная информация:
Штатные DB компоненты не умеют работать с DefaultExpression
Zeos - вроде может.
А вообще - если оператору даёшь вводить данные - так пусть он их вводит. А если позволяешь вносить пустые данные - то может это поле вообще не нужно?
В своё время мне надоело писать обработчики в форме на заполненность полей - в RxFPC написал компоненту, которая именно и занимается этим.
Zeos - вроде может.
А вообще - если оператору даёшь вводить данные - так пусть он их вводит. А если позволяешь вносить пустые данные - то может это поле вообще не нужно?
В своё время мне надоело писать обработчики в форме на заполненность полей - в RxFPC написал компоненту, которая именно и занимается этим.
- Unvictis
- новенький
- Сообщения: 48
- Зарегистрирован: 17.07.2015 17:59:12
- Откуда: Kokshetau, Kazakshtan
- Контактная информация:
alexs писал(а):Штатные DB компоненты не умеют работать с DefaultExpression
Zeos - вроде может.
А вообще - если оператору даёшь вводить данные - так пусть он их вводит. А если позволяешь вносить пустые данные - то может это поле вообще не нужно?
В своё время мне надоело писать обработчики в форме на заполненность полей - в RxFPC написал компоненту, которая именно и занимается этим.
Всё ради удобства, логичности и максимальной производительности программы. Чтож, вопрос остаётся открытым, пока воспользуюсь костылями.
Добавлено спустя 2 минуты 2 секунды:
Не хочется продолжать быдлокодить
