Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Базы данных
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 11.08.2011, 20:14
nicht nicht вне форума
Прохожий
 
Регистрация: 18.05.2011
Сообщения: 17
Репутация: 12
По умолчанию Автоинкремент в InterBase

с базами данных только разбираться начал, поэтому извиняюсь за простой вопрос. Как с помощью генератора и триггера делать автоинкрементные поля я понял, только вот если триггер стоит на before insert и пользователь ввел некорректные данные, то из-за ошибки запись в базу не добавится, а значение генератора все равно увеличится. Можно ли как-то в триггере (или как по другому) перед инкрементом генератора проверять корректность вводимых данных. Заранее спасибо
Ответить с цитированием
  #2  
Старый 12.08.2011, 10:18
dnkSW dnkSW вне форума
Прохожий
 
Регистрация: 12.08.2011
Сообщения: 4
Репутация: 10
По умолчанию

Цитата:
Сообщение от nicht
и пользователь ввел некорректные данные, то из-за ошибки запись в базу не добавится
Ну а ты попробуй введи некорректные данные и запись не сохраниться , а генератор увеличится , и какая проблема? Главное чтобы в автоинкрементном поле ID (например) было уникальное значение. А то, что они(значения ID) идут не подряд... это не проблема!
Ответить с цитированием
  #3  
Старый 12.08.2011, 10:38
Аватар для Viajero
Viajero Viajero вне форума
Активный
 
Регистрация: 14.06.2011
Адрес: РБ
Сообщения: 214
Версия Delphi: Delphi 7 FB 2.5
Репутация: 5849
По умолчанию

Значение генератора увеличивается при вызове генератора а не триггера. Тут возможно несколько вариантов. Можно сделать несколько триггеров на одну таблицу. Можно сделать несколько генераторов. Можно проверки делать в программе, и даже генератор из программы вызывать, (FIBPLUS например может так делать). Смотря что вам важнее. Можно сделать автоинкремент непрерывный, если предполагается только один пользователь. Но если база многопользовательская, то возникнут проблемы. Вот здесь очень хорошо всё описано:
http://www.delphisources.ru/forum/sh...0&postcount=19
__________________
- Товарищ прапорщик!!! Остановите поезд!!! - Поезд СТОЙ! РАЗ! ДВА!
Ответить с цитированием
  #4  
Старый 12.08.2011, 13:45
nicht nicht вне форума
Прохожий
 
Регистрация: 18.05.2011
Сообщения: 17
Репутация: 12
По умолчанию

Цитата:
генератор увеличится , и какая проблема?
В принципе, да, я прикинул, что Integer'a на хватит явно не на один год . Но все же интересно, можно ли как-нибудь самому проверять в триггере корректность введенных данных. А по книге Хелен Борри я как раз и начал свое изучение Firebird/InterBase. Спасибо!
Ответить с цитированием
  #5  
Старый 12.08.2011, 15:05
Аватар для Viajero
Viajero Viajero вне форума
Активный
 
Регистрация: 14.06.2011
Адрес: РБ
Сообщения: 214
Версия Delphi: Delphi 7 FB 2.5
Репутация: 5849
По умолчанию

Цитата:
Но все же интересно, можно ли как-нибудь самому проверять в триггере корректность введенных данных
Так триггеры в основном для этого и предназначены. А на одну таблицу Firebird позволяет несколько триггеров before insert навесить, только с порядком следования желательно не запутаться. При некорректных данных триггер может передать сообщение программе или вызвать исключение, для обработки специальные компонетнты есть.
__________________
- Товарищ прапорщик!!! Остановите поезд!!! - Поезд СТОЙ! РАЗ! ДВА!

Последний раз редактировалось Viajero, 12.08.2011 в 16:01.
Ответить с цитированием
  #6  
Старый 20.08.2011, 00:09
chainik chainik вне форума
Начинающий
 
Регистрация: 30.06.2008
Сообщения: 140
Репутация: 8882
По умолчанию

проблема известная.
Действительно при неверном вводе номер, выделенный триггером, пропадает и в нумерации появляются пропуски (после накладной № 100 следующая накладная имеет №102.) Это происходит потому что генератор работает вне транзакции и поэтому назад не откатывается.
Объясни своим юзерам что так работает абсолютно любая БД. Это вопрос безопасности. Первичный ключ никогда не должен повторяться.

Но проблему можно решить.
1 способ. Анализируешь введенные данные и записываешь в БД только если они корректны. Поскольку здесь нельзя переводить БД в состояние INSERT то нельзя использовать компоненты связанные с БД (Вместо DBEdit надо использовать Edit и тд)
2 способ. Делаешь в БД процедуру которая возвращает максимальный номер, например SELECT MAX(Num_Nakladn) FROM Table_Nakladn
далее программно его инкрементируешь и записываешь всю строку в БД
Но при многопользовательской работе могут быть проблемы
3. Можно еще заняться извращениями и программно изменять значение генератора, но проблем будет еще больше.
Ответить с цитированием
  #7  
Старый 21.08.2011, 16:02
Аватар для Viajero
Viajero Viajero вне форума
Активный
 
Регистрация: 14.06.2011
Адрес: РБ
Сообщения: 214
Версия Delphi: Delphi 7 FB 2.5
Репутация: 5849
По умолчанию

Цитата:
Действительно при неверном вводе номер, выделенный триггером, пропадает и в нумерации появляются пропуски (после накладной № 100 следующая накладная имеет №102.)
Цитата:
Можно еще заняться извращениями и программно изменять значение генератора, но проблем будет еще больше.
Никто не заставляет привязывать номер именно к ключу. Ключ вообще рекумендуется делать суррогатный и не показывать его пользователям. А для номера накладной можно сделать отдельное поле и генерировать его отдельным генератором и триггером AFTER INSERT. (т е номер накладной целесообразно формировать после транзакции)
__________________
- Товарищ прапорщик!!! Остановите поезд!!! - Поезд СТОЙ! РАЗ! ДВА!
Ответить с цитированием
  #8  
Старый 21.08.2011, 21:14
chainik chainik вне форума
Начинающий
 
Регистрация: 30.06.2008
Сообщения: 140
Репутация: 8882
По умолчанию

В общем, получается что-то вроде этого
Код:
/*****************************************************
    База данных программы Nikonov
    по заказу Никонова
******************************************************/


SET AUTODDL ON;
SET ECHO ON;
OUTPUT isql.txt;

CONNECT 'test.fdb'
USER 'sysdba' PASSWORD 'masterkey';
DROP DATABASE;
COMMIT;

SET NAMES WIN1251;
SET SQL DIALECT 3;
CREATE DATABASE 'test.fdb'
USER 'sysdba' PASSWORD 'masterkey'
DEFAULT CHARACTER SET WIN1251;
COMMIT;

CONNECT 'test.fdb'
USER 'sysdba' PASSWORD 'masterkey';





/***************************************************
        Список операторов
****************************************************/
CREATE TABLE Nakladn (
    NN INTEGER NOT NULL,              /*первичный ключ*/
    NumNakladn INTEGER NOT NULL UNIQUE,    /* номер накладной */
    Fam VARCHAR(20) NOT NULL,           /* фамилия */
    Doljn VARCHAR(20),           /* должность */
    PRIMARY KEY(NN)
    );


CREATE GENERATOR Nakladn_NN_GEN;
SET GENERATOR Nakladn_NN_GEN TO 0;
CREATE GENERATOR Nakladn_Num_GEN;
SET GENERATOR Nakladn_Num_GEN TO 0;


SET TERM !;

/**********************************************
    Процедуры и функции
***********************************************/

/**********************************************
    Генераторы первичных ключей
***********************************************/
    CREATE TRIGGER Nakladn_trig FOR Nakladn
ACTIVE BEFORE INSERT
AS
BEGIN
NEW.NN=GEN_ID(Nakladn_NN_GEN,1);
END!

    CREATE TRIGGER Nakladn_Num_trig FOR Nakladn
ACTIVE AFTER INSERT
AS
BEGIN
  UPDATE Nakladn
  SET
  NumNakladn=GEN_ID(Nakladn_Num_GEN,1)
  WHERE (NN=NEW.NN);
END!




/***********************************************
        Начальная инициализация
************************************************/
SET TERM ;!

COMMIT;

Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 10:10.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025