Страница 1 из 1

SQLite3

СообщениеДобавлено: 15.07.2018 15:43:34
arriah
Привет всем,

Никогда не разрабатывал базы данных с нуля, в основном работал на готовых. Но теперь понадобилось это сделать.
Вроде со всем разобрался, но остались некоторые воспросы. Суть в том, что надо создать грамотную структуру БД.

БД должна состоять из трех таблиц
Организация
Автомобили
Водители

У одной организации может быть несколько автомобилей - с этим понятно, организовываем связь один ко многим
За каждым водителем может быть закреплен 1 автомобиль, или на каждом автомобиле может быть только один водитель - вот в этом вопросе возникают сложности, ибо автомобиль может быть просто без водителя, типа стоит в парке и не работает.

Вот как мне организовать базу данных с внешними ключами и ненарушить целостность БД, чтобы выполнялись следующие условия:

1. Водителя можно удалить из базы данных
2. Водителя можно пересадить с одной машины на другую
3. Автомобиль можно перенести из одной организации в другую
4. Автомобиль может быть удален

Пока сделать такую структуру:
Код: Выделить всё
CREATE TABLE firms (
   FirmsID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
   FirmsIndex VARCHAR (255) NOT NULL,
   FirmsAddress VARCHAR (255) NOT NULL,
   FirmsOGRN VARCHAR (255) NOT NULL,
   FirmsINN VARCHAR (255) NOT NULL,
   FirmsPhone VARCHAR (255) NOT NULL,
   FirmsDisp VARCHAR (50),
   Cars_ID INTEGER NOT NULL,
   FOREIGN KEY (Cars_ID) REFERENCES cars(CarsID));

CREATE TABLE cars (
   CarsID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
   CarsName VARCHAR (50) NOT NULL,
   CarsNumber VARCHAR (50) NOT NULL,
   CarsLic VARCHAR (50) NOT NULL,
   CarsGrant VARCHAR (50) NOT NULL,
   Drivers_ID INTEGER NULL,
   FOREIGN KEY (Drivers_ID) REFERENCES drivers (DriversID));

CREATE TABLE drivers (
   DriversID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
   DriversFIO VARCHAR (100) NOT NULL,
   DriversPrava VARCHAR (50) NOT NULL);


Но что-то мне подсказывает что я сделал что-то неправильно, особенно с внешними ключами.
И как правильно в моем случае связывать машину с водителем или водителя с машиной?

В идеале должно работать так:
Механик выбирает из списка водителя и видит инфу о машине и организации, за которой закреплена машина.
Начальник колонны имеет право цволить водителя, закрепить машину за другой организацией и удалить машину.

Re: SQLite3

СообщениеДобавлено: 16.07.2018 08:17:30
Снег Север
FOREIGN KEY в вашем случае приведет к тому, что при удалении записи из firms автоматически удалятся все связанные записи из cars и, соответственно, из drivers. Вам надо предусмотреть в коде аппликации, чтобы перед удалением изменить привязку автомобиля и водителя к другой записи, если удаление недопустимо. Можно придумать также встроенные процедуры и триггеры, чтобы по максимуму переложить работу на движок
SQLite. Что вам удобнее - решайте сами.

И, надеюсь, вы помните, что SQLite - это, принципиально, однопользовательская БД? А то есть любители ладить многопользовательские велосипеды на ее основе, а это не есть гуд. :)

Re: SQLite3

СообщениеДобавлено: 16.07.2018 08:35:17
Vadim
arriah
Попробуйте начать разработку БД с того, что на самом обычном русском языке, самым обычным текстом написать:
- какие данные должны храниться и, соответственно, обрабатываться;
- процедуры обработки данных. Начинаете с исходных данных и что в результате должно получиться.
Повторюсь - никакого программирования, SQL и прочей лабуды, всё обычным текстом. Хорошо бы с рисунками. Ни в коем случае не должно быть неоднозначности в интерпретации тех или иных данных.
Это называется - разработка бизнес-логики. После этого структура БД и приложения можно с лёгкостью перевести на что угодно. ;-)

Добавлено спустя 6 минут 14 секунд:
arriah писал(а):И как правильно в моем случае связывать машину с водителем или водителя с машиной?

В том коде, что Вы представили, содержаться так называемые справочные данные, т.е. это у Вас справочные таблицы, откуда берутся правильные данные. А вот рабочие таблицы, которые хранят суть работы с данными, у Вас полностью отсутствуют. Правильные связи, с отслеживанием актуальности данных, Вы будете устанавливать между справочными и рабочими таблицами. На текущий момент у Вас рабочие таблицы отсутствуют, следовательно, над спецификациями связей можно думать хоть до морковкиного заговения - всё равно ничего не получится. ;-)

Добавлено спустя 3 минуты 1 секунду:
Снег Север
Не пугайте ребёнка множественностью пользователей. Ему бы просто с БД разобраться... :-D

Re: SQLite3

СообщениеДобавлено: 22.07.2018 16:08:02
arriah
Спасибо всем за ответы, очень помогли :)
Но вот столкнулся с другой проблемкой, кого винить я хз :)

Не могу понять, почему не вносятся изменения в базу данных при использовании DBGrid и DBNavigator?
Софтина работает только через SQLQuery.
Сделал отдельную форму для редактирование таблиц.
На форму закинул DataSource, TSqlite3DataSet, DBNavigator.
При открытии формы устанавливаются соответствующие свойства для DataSet.
В DBGrid.AutoEdit:=True
ReadOnly везде False
dgEditing тоже True;

Форма открывается, записи показываются, кнопки на навигаторе работают исправно, но засада в том, что изменения не сохраняются. Ни при удалении записи, ни при редактировании, ни при вставке, хотя галочку на навигаторе нажимаю :).

Решил проверить:
при открытии таблицы указал DataSet.Edit,
На событие OnClick кнопки повесил:
DataSet.Post;
DataSet.ApplyUpdate;
Внес изменения в базу, жму на кнопку и ловлю ошибку с сообщение что мол БД не находится ни в режиме редактирования, ни в режиме добавления...

Я что-то не так делаю или это такие глюки? Проверил бы на дельфях, но лениво скачивать и ставить.

по сути, вариант с навигатором должен работать, но почему то не работает.

И небольшой вопросик про DBGrid. Сейчас у меня примерно так:
Код: Выделить всё
  DBGrid1.Columns.Clear;
  DBGrid1.Columns.Add.FieldName:='DriversFIO';
  DBGrid1.Columns.Add.FieldName:='DriversLic';
  DBGrid1.Columns.Add.FieldName:='DriversCar';
  DBGrid1.Columns[0].Title.Caption:='ФИО';
  DBGrid1.Columns[1].Title.Caption:='Номер в/у';
  DBGrid1.Columns[2].Title.Caption:='Автомобиль';

Вобщем добавляю столбец в таблицу и даю ему осмысленное название.
А можно ли как-то добавить это в одну строчку типа:
Add.FieldName['DriversFIO'].Title.Caption:='ФИО';

Re: SQLite3

СообщениеДобавлено: 22.07.2018 23:18:45
pupsik
Вроде со всем разобрался
....
Ни при удалении записи, ни при редактировании, ни при вставке, хотя галочку на навигаторе нажимаю
и т.п....

Есть вики. Там всё описано. Запросы надо добавить что бы работало.

БД должна состоять из трех таблиц
судя по описанию... из 4-х...

Re: SQLite3

СообщениеДобавлено: 23.07.2018 08:58:07
Снег Север
С SQLite3Connection связать SQLTransaction и выставить у него caCommitRetaining. У SQLQuery в опциях поставить [sqoAutoApplyUpdates].

Re: SQLite3

СообщениеДобавлено: 23.07.2018 17:48:28
arriah
Снег Север писал(а):С SQLite3Connection связать SQLTransaction и выставить у него caCommitRetaining. У SQLQuery в опциях поставить [sqoAutoApplyUpdates].

А при чем SQLQuery?
У меня набор данных через SQLite3Dataset.

Re: SQLite3

СообщениеДобавлено: 23.07.2018 19:00:25
Снег Север
arriah писал(а):У меня набор данных через SQLite3Dataset.
А я не знаю, что это. Знаю, что то, что в моем примере - работает идеально и не только в тесте. Не устраивает - разбирайтесь сами.

Re: SQLite3

СообщениеДобавлено: 23.07.2018 19:32:52
arriah
Снег Север писал(а):А я не знаю, что это. Знаю, что то, что в моем примере - работает идеально и не только в тесте

Да ну? Прям-таки идеально?
Это ваш пример, при удалении записи:
error.PNG

Re: SQLite3

СообщениеДобавлено: 24.07.2018 08:19:06
Снег Север
Эта ошибка при удалении через навигатор возникает от того, что в таблице не назначен primary key. Назначьте его на поле id и всё заработает.
Но всегда лучше удалять записи самостоятельно, вызовом SQL.

Re: SQLite3

СообщениеДобавлено: 25.07.2018 17:25:02
arriah
Снег Север писал(а):Эта ошибка при удалении через навигатор возникает от того, что в таблице не назначен primary key. Назначьте его на поле id и всё заработает.
Но всегда лучше удалять записи самостоятельно, вызовом SQL.

Я понял из-за чего ошибка :) Это так, тролинг по поводу "идеальности". Ничего личного)
Проблем удаления через запросы SQL нет, но хотелось сделать без запросов, через DataSet,
Сделал пробный проект в дельфи - там работает. а в лазаре не хочет. Вобщем сделал через SQLQuery, чтобы не копаться в причинах, но природу ошибки хотелось бы познать.

Вот тут http://www.cyberforum.ru/delphi-database/thread1631920.html описана моя проблема, правда для дельфи. И там вопрос решился пересозданием всего с нуля.
Вобщем странное поведение...

Re: SQLite3

СообщениеДобавлено: 25.07.2018 18:10:32
Снег Север
arriah, это был у меня досстаточно давний тестовый пример, в котором я проверял совсем другие вещи. Но в программах, которые я делаю по работе, я никогда не использую ни навигатор, ни редактирования в гридах, ни вставку/удаление по усмотрению датасетов. Слишком много проблем с этим выскакивает в неожиданных местах. Гриды - только для быстрого просмотра, вставки - через формы с контролами редактирования конкретных полей, все измения - только самостоятельно формируемыми SQL-ми. Немного более громоздко, зато полный конроль.

Re: SQLite3

СообщениеДобавлено: 26.07.2018 06:45:13
arriah
Снег Север писал(а):arriah, Гриды - только для быстрого просмотра, вставки - через формы с контролами редактирования конкретных полей, все измения - только самостоятельно формируемыми SQL-ми. Немного более громоздко, зато полный конроль.

Полностью согласен :)